2018年11月
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30  

Amazonウィジェット

  • お気に入り
  • 書籍ランキング

AdSense

  • 広告
無料ブログはココログ

« C言語 厄介なバグ第一位 不定値のリード | トップページ | <続>C言語で作るシューティングゲーム »

2018年10月20日 (土)

C言語で作るシューティングゲーム

まずは動画をどうぞ。




最初はC言語の練習のつもりで書いてきたのだが、ずいぶん長い間続けてきたプロジェクトなので、このブログでも記事を書くことにした。

~自作ゲーム歴~

最初にゲームを自作したのは、エクセルマクロだった。

理由は、絵を出すのが簡単でデバッガもついていたから。
当時は主にPICマイコンで遊んでいて、あまりC言語は使っていなかった。

PICのプログラムを書くのはもっぱらアセンブリ言語で、いきなりそれで書こうとすると大儀だった。そこで、いったんエクセルマクロを使ってモックアップのプログラムを書き、デバッグもしてからアセンブリ言語に書き直す。ということをやっていた。

そんな中Vectorなどのフリーソフト界隈で、エクセルでテトリスを作っている人がいると聞いて、自分もチャレンジしてみたのが始まり。

エクセルマクロは意外とスムーズに動き、ブロックの出現とスクロールまではそれなりに実装できた。しかしどこまでだったか、ブロックを並べて消すところで詰まってしまった気がする。

たしか、配列を使って動かせるブロック、積んだブロックを番号を書き込んで管理していたのだが、それらの管理が上手くいかなくなったのだと思う。




それからしばらくゲームを作ることはなかったのだが、仕事か何かでC++で書かれた小さなツールのコードを見かけて興味を持ち、再チャレンジしようとこれならわかるC++という本を買って読んだ。

この本に出合うまで、C++は謎の言語であった。
C++のクラスというものがどういうもので、どのように活用するのかがやさしい例でまとめられており、すぐにC++の虜になった。

C++といえばオブジェクト指向が売りで、何かとオブジェクト指向で書きたがっていた。それは、画像処理やWindowsアプリの作り方に関する本がC++やJavaで書かれていたからである。

今思えば、ちょっと画像処理するだけならオブジェクト指向など使わなくてもベタのC言語でバイナリいじればいいやんというノリなのだが、どうしてもGUIを作ってみたかった。その頃は空っぽのウィンドウが出ただけでも大層感動したものである。そのせいで、「簡単にできる」とか「これでマスター」のような本をせっせと買い漁り、余計にわからなくなるという迷宮をさまよった。基礎をおろそかにしていると技術は身につかないものである。

C++の本を読み進めるうちに、C++を使いたいというよりも、クラスという機能がC言語の構造体とよく似ていると感じた。構造体なんて基本情報処理の資格を取るためにやったきりご無沙汰していたのだが、よくできた機能であることがわかった。

これならわかるC++と一緒に買ったのが、C言語ポインタ完全制覇である。
この本のおかげで今があるといってもいいくらい、大変お世話になった。

この本が特別なのは、C文法におけるポインタの宣言の仕方に欠点があることを突いていることと、宣言された内容を1ステップずつ解釈する方法を詳細に説明してある点である。

qsortやSIGINTなどのライブラリ関数は、複雑なポインタ型のオンパレードであり、それを読みこなせないと使うことができない。これらを初めてひも解いてくれたのがこの本だった。
ようやくC言語について理解が深まると、関数ポインタというのがC++のクラスにある、メンバ関数とよく似ているように見えてきた。


結局二冊の良書に巡り合ったことで、ゲームを作るためにC++をやらなくても、C言語だけで作れそうな気がしてきたのである。

さて自作ゲーム歴に話を戻そう。

これまでゲームなどのグラフィックを使うものはC++を使ってオブジェクト指向で書くもの。と思い込んでいたのだが、グラフィックのライブラリを使うだけならCの文法だけ知っていれば十分であった。

実際に調べてみるとDXライブラリというものがあり、これを使えばC言語でもゲームがつくれることがわかった。

不慣れなC++で、いちいちググりながら書いていても回り道であり、純粋なプログラミングの楽しみとは離れているように感じた。ググらずに持っている知識だけでガンガン書いてみたくなった。
そうして始まったのがシューティングゲーム作りだった。
その時一番やりたいと思ったゲームがゼビウスだった。

小学校のときにファミコンソフトで所持していたのだが、中学に入るときに親に強制的に剥奪されてしまったので、それ以来できなかったのである。前にも後にもゼビウスは最高峰のゲームであった。
ゼビウスの特徴は、敵が空中と地上に分かれて攻めてくるところ。
空を飛ぶ敵にはBボタンで機銃を浴びせ、地上の砲台にはAボタンで爆弾を投下する。

爆弾が命中するときが爽快で、4つなど固まって建造されている砲台のど真ん中に当たると、4ついっぺんに破壊することができる。破壊した後は穴ぼこのようなものが開くなど、ファミコンにしては妙にリアルだった。

機銃も連打すればするほど弾が出るので、敵がたくさん出てくるときは必至で連射した。
十字キーとB連打で手がつったが、シューティングの爽快感を抜群に体現していた。




~最初の一歩~
最初はDXライブラリのサイトを見ながら、スプライトやフレームレートの仕組みを学習していった。APIの仕様だけでなく、その関数をどのように使うのか。どんな応用ができるかということが丁寧に説明されていた。

スプライトのことがわかったので、ペイントブラシでスライムを落書きし、4コマのアニメーションにして背景の前に表示してみた。きれいにキャラクタが表示されると、初めてウィンドウを出したとき以上に感動した。

矢印キーで上下左右に動かしたり、背景前景を作ってキャラクタを隠れさせたりするのも面白かった。背景をスクロールさせると、いよいよゲームらしくなった。


絵を表示するのが面白くて、ゼビウスに似せて書いた絵をアニメーションさせてどんどん追加していった。しかし絵を表示させるのは簡単でも、当たり判定やら当たった後爆発させて消えるとか、爆弾の後の穴を残すといった処理は難儀した。フラグやグローバル変数を連発すると、あっという間にウ〇コードが完成してしまった。



さすがにこれはまずいと思い、ゲームのベースになるものを探すことにした。
ゲームエンジンで色々調べると、タスクリストというものを見つけた。


タスクリストは、TNKSOFTというサイトで大変わかりやすく説明されていた。オブジェクト指向でゲームエンジンを作るということがテーマにはなっていたものの、Cでも応用が可能で、コーディングの実際を学ぶことができた。

このサイトにこのタイミングで出会ったからこそ、うまくいったのだと思う。
じっくり読んで解釈したものを、自分で考えてC言語で書き直す作業をしたのがよかった。C++で書いてあるものをあちこちのサイトから摘まみながらやろうとしていたら、文法でつまずいて駄目だったろう。



他の言語で書かれたコードを、同じことができるように書きたい言語で置き換えるという作業は、有効な学習手段だと思う。その言語の持つ得意・不得意分野が見えてくる。

各部分が何をしているかをよく読むことになるので、頭にも残りやすい。それに全くほかの言語で同じパターンを書きたいときも何も見ずに書き出せる。実際Processing(Java)でゲームを作ったときも、この時の知識がフル活用できた。




タスクリストを導入してから、開発は加速度的に進んだ。
キャラクタ毎にパラメータや関数をまとめて扱い、タスクとしてタスクリストに組み込むという一連の流れができたことで、全体的な構造がわかりやすくなった。

タスクリストをソートして、処理すべきタスクを頭出しする仕組みも導入した。これによりプレイヤーと敵弾。プレイヤー弾と敵。などそれぞれの条件に沿って当たり判定を作ることができた。



一番苦しんだのは背景のスクロールだった。
背景を表示する処理自体は絵を貼るだけなのだが、画面のスクロールに従って新しいマップ画像をロードし切れ目のないように継ぎ足して表示するのが難しい。

すでに表示した画像のY座標が画面高さまで移動したとき、次の画像を画面外に貼る。という処理を書いていくのであるが、条件がゴチャゴチャとなって面倒だった。



if文は考えたことを直接書きやすいので、入り組んだロジックでもそのまま表現できてしまう。それがif文の罠のように思う。

どの条件を見ればすっきりするのか、最初にロジックを整理して書かないとやっぱりだめだ。


背景は32x32のマス目に、緑、黄、青、深緑の4色を塗り分けたチップを配置することで再現した。いきなりチップの番号を指定すると、どんなマップになるか想像しづらいので、エクセルで絵を配置してからチップ番号に置き換えるという手法を取った。

チップのパターンは真ん中の対角線を色の境界とした単純な物。色の組み合わせと対角線の向きで組み合わせを作った。

Photo


正しく表示されると最初のうちは楽しかったが、エクセルに打ち込み→テキストで入力→コンパイル→表示確認とステップが多く、なかなか手間のかかる作業だった。

※マップの製作については別の動画をアップしているのでよろしければ・・・。




効果音も実装すると、それなりに本家に似たゲームが完成した。タイトル画面を表示し、画面遷移も実装した。半ば強引に進めたので弾を撃ちまくるとメモリリークで落ちることもあったが、一応一通りの機能は動いた。初めて作ったにしては大作だった。


しかしながら、ゲームとしての面白さは本家には敵わなかった。

敵キャラの種類もすべてを再現したわけではなく、ワッカのやつと、一発撃って逃げるやつ。あとは砲台とかピラミッドのやつを数種類であった。
この時はこれが精いっぱいであった。

本当は中ボスとか、道に沿って動く移動砲台とか、そもそも大ボスが出てこないと話にならないのだ。



何はともあれ、
とりあえず一通り動いたので、初めて動画を投稿した。
Unityがある時代にわざわざエンジンから自作し、しかもCだけでチマチマ書くというのは、それなりに珍しいかなと思ったのと、C++やJavaに無理して手を出さなくても、地道にやればできるということを表明したかったのかも。

投稿したときは、再生回数が伸びるのかソワソワしたけれど、初めていいねコメントをもらったときはとても感動した。今まで家でゴソゴソやってるだけだったけれど、作ったものが日の目を見たのはうれしかった。


« C言語 厄介なバグ第一位 不定値のリード | トップページ | <続>C言語で作るシューティングゲーム »

C言語」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/518723/67293185

この記事へのトラックバック一覧です: C言語で作るシューティングゲーム:

« C言語 厄介なバグ第一位 不定値のリード | トップページ | <続>C言語で作るシューティングゲーム »