SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

japan.internet.com翻訳記事

さまざまな言語に対応するゲームプラットフォーム「Simple DirectMedia Layer」

スペースインベーダー似のゲームで巡るSDLの世界

RunGame()関数

 メインのロジックループは、もちろんすべてRunGame()内にあります。この関数は約200行から成るので、全体を一度に見るには長すぎます。そこで、SDLの機能を説明しながら、いくつかの重要なセクションを取り上げることにします。コードを省略した部分は、コメント中の省略記号(...)で示します。

301 void RunGame(void)
302 {
303    int i, j;
304    SDL_Event event;
305    Uint8 *keys;
306
307    /* Paint the background */
308    numupdates = 0;
309    for ( i=0; i<screen->w; i += background->w ) {
310       SDL_Rect dst;
311
312       dst.x = i;
313       dst.y = 0;
314       dst.w = background->w;
315       dst.h = background->h;
316       SDL_BlitSurface(background, NULL, screen, &dst);
317    }
318    SDL_UpdateRect(screen, 0, 0, 0, 0);

 最初のセクション(301~318行目)では、SDL_BlitSurface()を使用して背景色のスライスをスクリーンバッファに順次blit転送し、SDL_UpdateRect()を使用して再描画をセットアップしているだけです。

319
320    /* Initialize the objects */
321    // . . .
333    CreateAlien();
334    DrawObject(&aliens[0]);
335    UpdateScreen();
336
337    while ( player.alive ) {
338       /* Wait for the next frame */
339       WaitFrame();
340
341       /* Poll input queue, run keyboard loop */
342       while ( SDL_PollEvent(&event) ) {
343          if ( event.type == SDL_QUIT )
344             return;
345       }
346       keys = SDL_GetKeyState(NULL);
347
348       /* Erase everything from the screen */
349       // . . .
366       /* Decrement the lifetime of the explosions */
367       // . . .
373       /* Create new aliens */
374       if ( (rand()%ALIEN_ODDS) == 0 ) {
375          CreateAlien();
376       }
377
378       /* Create new shots */
379       if ( ! reloading ) {
380          if ( keys[SDLK_SPACE] == SDL_PRESSED ) {
381             for ( i=0; i<MAX_SHOTS; ++i ) {
382                if ( ! shots[i].alive ) {
383                   break;
384                }
385             }
386             if ( i != MAX_SHOTS ) {
387                shots[i].x = player.x +
388                   (player.image->w-shots[i].image->w)/2;
389                   shots[i].y = player.y -
390                      shots[i].image->h;
391                   shots[i].alive = 1;
392                   Mix_PlayChannel(SHOT_WAV,
393                      sounds[SHOT_WAV], 0);
394             }
395          }
396       }

 これは、RunGame()ループ内の入力管理を行う部分です。

 一見シンプルに見えるSDL_PollEvent()は、イベントに関する情報を含んだSDL_Eventオブジェクトを返します。ここでSDL_QUITという特殊な値を使用して、ESCキーが押されているかどうかを確認します。

 これは純粋にキーボード操作だけでプレイするゲームなので、SDL_GetKeyState()を使用すれば必要な情報をすべて入手できます。PCのキーボードは複数のキーを同時に押せるよう設計されているので、結果は配列として返されます。この配列ではSDLK_SPACEのようなキーボードコード値がインデックスとして使われます(SDLK_SPACEはスペースバーを表します)。

397        reloading = (keys[SDLK_SPACE] == SDL_PRESSED);
398
399       /* Move the player */
400       //. . .
415       /* Move the aliens and the shots */
416       // . . .
443
444       /* Detect collisions */
445          for ( j=0; j<MAX_SHOTS; ++j ) {
446          for ( i=0; i<MAX_ALIENS; ++i ) {
447          if ( shots[j].alive && aliens[i].alive &&
448                Collide(&shots[j], &aliens[i]) ) {
449             aliens[i].alive = 0;
450             explosions[i].x = aliens[i].x;
451             explosions[i].y = aliens[i].y;
452             explosions[i].alive = EXPLODE_TIME;
453             Mix_PlayChannel(EXPLODE_WAV,
454                sounds[EXPLODE_WAV], 0);
455             shots[j].alive = 0;
456             break;
457          }
458       }
459    }

 ここではMix_PlayChannel()に注目してください。これを使用することで、適切な状況で砲撃音を追加します。

 このゲームでは3つのチャンネルを同時に使用し、音楽、砲撃音、爆発音をそれぞれ独立したチャンネルで扱います。なぜなら、そのときどきの状況によって、最大3つのサウンドを同時に再生する必要があるからです。独立したチャンネルを用意しておかないと、あるサウンドから別のサウンドへの切り替えをひっきりなしに行うことになり、サウンドトラックがぶつ切れになってしまいます。

 話が前後しますが、これらのサウンドは次のような呼び出しで読み込んでおきます。

127    sounds[MUSIC_WAV] = Mix_LoadWAV(DATAFILE("music.wav"));

 それでは、コードの続きに戻りましょう。

474       // . . .
475       /* Draw the aliens, shots, player, and explosions */
476       for ( i=0; i<MAX_ALIENS; ++i ) {
477          if ( aliens[i].alive ) {
478             DrawObject(&aliens[i]);
479          }
480       }
481       // . . .
494       UpdateScreen();
495
496       /* Loop the music */
498       if ( ! Mix_PlayingMusic() ) {
499          Mix_PlayMusic(music, 0);
500       }
506
507       /* Check for keyboard abort */
508       if ( keys[SDLK_ESCAPE] == SDL_PRESSED ) {
509          player.alive = 0;
510       }
511    }
512
513    /* Wait for the player to finish exploding */
514    while ( Mix_Playing(EXPLODE_WAV) ) {
515       WaitFrame();
516    }
517    Mix_HaltChannel(-1);
518    return;
519 }
520

 本稿では、すべての処理について細かく説明したわけではありません。たとえば特に触れませんでしたが、UpdateScreen()は、表示するビットマップのリストを反復処理して画面へのblit転送を行う関数です。これらのコードの詳細については、ソースコードを見てください。

まとめ

 500行あまりのコードで実装された昔懐かしい2Dシューティングゲームに音楽とリアルタイムプレイを組み合わせただけですが、SDLの素晴らしさはわかっていただけたのではないでしょうか。もちろん、この同じコードから、WindowsやLinuxをはじめ、さまざまなプラットフォームで実行可能なアプリケーションをコンパイルできます。本稿では、SDLの表面を少し触ってみただけにすぎません。興味のある方は、ぜひ実際に使ってみてください。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
japan.internet.com翻訳記事連載記事一覧

もっと読む

この記事の著者

japan.internet.com(ジャパンインターネットコム)

japan.internet.com は、1999年9月にオープンした、日本初のネットビジネス専門ニュースサイト。月間2億以上のページビューを誇る米国 Jupitermedia Corporation (Nasdaq: JUPM) のニュースサイト internet.comEarthWeb.com からの最新記事を日本語に翻訳して掲載するとともに、日本独自のネットビジネス関連記事やレポートを配信。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

Victor Volkman(Victor Volkman)

1980年代末から『C/C++ Users Journal』などのプログラミング雑誌に記事を執筆。ミシガン工科大学を卒業し、WashtenawコミュニティカレッジCIS学部の諮問委員会のメンバーを務める。『C/C++ Treasure Chest』など数々の書籍の編集者であり、Loving Healing Pressのオーナーでもある。オープンソースのツールやライブラリについての相談、お問い合わせはsysop@HAL9K.comまで。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/2524 2008/06/05 00:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー