同人ゲーム『東方Project』がきっかけでゲームを作り始め、その勢いでIT業界に来てしまった私がラクス Advent Calendar 2016の17日目を担当いたします。
昨日は @kiimisato さんの『ベトナムオフショア開発』でした。
#はじめに(本記事の方向性)
土曜日なので箸休め的な読み物になれば良いなと思いながら書きます。(と思っていたのですが、記事を書き上げてから読み直すと結構な長編になってました……)
本記事では「ゲーム作りを通してオブジェクト指向プログラミングを学ぶ」をテーマに色々書いていきます。
ジャンルとしては弾幕シューティングゲームを作って行きます。
必要な知識としては
・C++の基本的な文法
・ポインタの考え方(概要程度で大丈夫です)
・※あると便利:高校数学ⅡB程度の数学力(高次関数、三角関数、ラジアン、ベクトル、軌跡等)
などになると思います。
#ゲーム作りでプログラミングは学べるのか?
この業界に入る前あるいは入りたての頃はきっと誰しも「ゲーム作りでプログラミングの勉強したら楽しく学べるんじゃね?」的なことを一度は考えるかと思います。
私の結論から言うと半分間違い、半分正解だと思います。
まず、0からゲームを作るというのは想像以上にマゾい作業で「楽しい」と思える段階に入る前に多くの人が挫折します。
実際私も東方Projectに憧れてC++を始めましたが、少なくとも3~4回は挫折しています。
あとゲームプログラミングはその特殊性故に実務で使うようなアルゴリズムが身につくかと問われると正直微妙です。
しかし、それでも
・プログラミング言語の文法
・オブジェクト指向の考え方
・ある現象をプログラミング的考え方に変換する手法
・デザインパターン少々
と言ったプログラミングをする上で普遍的に役立つノウハウを身につけることはできるので、興味と根気があれば挑戦してみることをオススメします。
特にIT業界に入ることを考えているor入ってから経験の浅い方でゲーム作りに興味がある方には強くすすめます。少なくとも私はゲーム作りをしていたお陰でスムーズにプログラミングが身につきました。
ということで、以降は実際のゲーム作りに関する内容に入っていきます。
#ゲームを作る手段の選択(開発環境のDL)
個人でゲームを作る手段今は色々ありますね。
Unity、UnrealEngine、RPGツクールシリーズ、cocos2d-x等々パッと思いつくだけでも本当に色々と。
これらは非常に強力なツールでネット上の画像素材やプラグイン素材等を組み合わせるだけで簡単に高品質なゲームを作れてしまいます。
が、プログラミングの勉強となるとちょっと話は変わってきて、上記のツール達はどれもデフォルトでリッチな機能を備えていることに加え、有志の方々が拡張機能をたくさん公開しているのでコードを書くことなくそれなり以上のゲームが作れてしまいます。
(拡張機能まで自作する場合はC#、C++、Ruby、JavaScript等のコードを書くことになります。これであればプログラミングを学ぶことができます)
今回は「ゲーム作りを通してオブジェクト指向プログラミングを学ぶ」ということをがテーマなので
・なるべく多くコードを書く
・でもオブジェクト指向の本質から外れるようなコードは書かない
という観点で開発環境を考えたところ、開発OSはWindows、言語は「C++とDXライブラリ(DirectX)」が良いと思ったのでこの環境で開発します。
######!!注意!!
本記事ではあくまでも「プログラミング学習のためにゲームを作る」ので「ゲームとして映える・面白いもの」を作りたい場合は上で挙げたツールを使うことを強くおすすめします。
自作も可能だとは思いますが要求される労力と知識が半端ないです。(あと、ぶっちゃけるとゲーム自体のアルゴリズムよりもゲームエフェクトのプログラム勉強した方がウケます)
IDEはVisualStudio Community 2015を使用します。
ダウンロード:https://www.visualstudio.com/ja/vs/community/
C++には画面に画像やポリゴンを描画したり音楽を流したりと言った機能はないのでその部分はDirectXを使うこととします。
しかし、DirectXは初期化処理のコードからして数十行に及ぶ意味不明コードで、それを理解することは本記事の趣旨から外れるため今回はDXライブラリというDirectXのグロテスクな部分を隠蔽してくれる便利なライブラリを使います。
DXライブラリダウンロード:http://dxlib.o.oo7.jp/dxdload.html
次は環境構築と一番最初のプログラムを作ります。
#環境構築~Hello World
最初にごめんなさいをしておきます。
オブジェクト指向の記事を名乗りつつ実際にオブジェクト指向っぽくなるのはもう少し先になります。
あ、環境構築はDXライブラリ初心者の心を折りにくる難関その1です。
文句を言っても仕方ないのでVisualStudioのインストールとDXライブラリ本体の解凍が終わったらこちらの手順通りに設定を行いましょう。
この手順はDXライブラリを使う上で避けて通れない道なのでできれば自力で行っていただきたいのですが、どうしても面倒な場合は私がプロジェクトテンプレートを用意したのでご利用くださいませ。
###プロジェクトテンプレートの使い方
①ダウンロードしたVS_DxLibTemplate.zipを『C:\Users\{ユーザー名}\Documents\Visual Studio 2015\Templates\ProjectTemplates』に配置する。
②DXライブラリ本体を解凍し、パスが『C:\DxLib_VC』となるように配置する。
③VisualStudioのメニューバーから『ファイル』→『新規作成』→『プロジェクト』を選ぶ。
④『新しいプロジェクト』ウィンドウが開くので『インストール済み』→『テンプレート』→『Visual C++』を選ぶ。
⑤一番下に『VS_DxLibTemplate』が出ているはずなので選択し、プロジェクトの名前と場所を設定し『OK』を押す。
それぞれの方法で環境構築していただき『デバッグ』→『デバッグの開始』をすることで最初のプログラムが動いたはずなのでソースコードを見ながら解説を少々。
と言ってもほとんどテンプレート内のコメントに書いてある通りです。
#include "DxLib.h" // ←DXライブラリの機能を使うために必ず書きます。DxLib.hの中には各種定数や関数の宣言が書かれています。
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) // ←定型。ここが処理スタート地点以上のことは考える必要ありません。というか私もわかりません。
{
ChangeWindowMode(TRUE); // ←ウィンドウモードに設定。設定しないと全画面表示になります。
SetGraphMode(640, 480, 32); // ←ウィンドウの大きさと色情報を指定。32bitカラーにします。
if( DxLib_Init() == -1 ) // ←DXライブラリ初期化処理。必ず書きます。初期化中に何らかのエラーが発生すると返値が-1になるのでその場合は以降の処理を行いません。
{
return -1 ; // エラーが起きたら直ちに終了
}
int Cr = GetColor(255, 255, 255); // ←これから描画する文字の色をあらかじめ指定しておきます。引数は左から順にRGBでカラーを指定しています。
DrawString(240, 240 - 32, "今日も一日頑張るぞい!", Cr); // ←ウィンドウ内X座標、Y座標を指定し、指定した文字列を指定した色で描画します。
WaitKey() ; // ←何かキーが入力されるまで待ちます。
DxLib_End() ; // ←DXライブラリ使用の終了処理。こちらも必ず書きます。
return 0 ; // ソフトの終了
}
どのプログラミング言語でも最初は"Hello World"から始まるのでそれに倣ってみました。
この後からはいよいよゲームプログラミングらしくなっていきます。
#ゲームプログラムの基本的な構造
まずゲーム画面とはそもそもどういう仕組みで画面の中の物を動かしているかを軽く説明します。
非常に簡単に言えばゲーム画面とは『紙芝居またはパラパラ漫画を超高速で繰り返している』というのが答えになります。
図で表すとこんな感じ。
・ゲームの処理自体は画面を2つ持っている。
・プレイヤーに見えている画面を『表画面』、見えていない画面を『裏画面』という。
・プレイヤーが見ているのは描画完了した画面のみ。
・どちらか片方は常に1/60秒後の画面を描画している。
・画面の表裏は1/60秒ごとに切り替えられる。
・一般的なPCディスプレイを使った場合約1/60秒ごとに画面の更新を行わなくてはいけないので非常に処理速度を求められる。
それでは実際に画面を動かします。DXライブラリを使うととても簡単です。
まず、今回使用する画像をこちらからDLしてください。
解凍してできたdatフォルダはプロジェクトフォルダの直下に配置してください。(画像内の赤枠のフォルダです)
あと、念のためdatフォルダ内の階層構造を確認してください。(dat/imgやdat/font等になっていれば正解。dat/dat/imgやdat/dat/font等の場合は解凍ソフトが余計なフォルダを作っています)
次に先ほどのMain.cppを以下のように書き換えることで画像が回転しながら左右に動くプログラムになります。
それではまたソースコードを見ながら解説していきます。
#include "DxLib.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
ChangeWindowMode(TRUE);
SetGraphMode(640, 480, 32);
if (DxLib_Init() == -1)
{
return -1;
}
SetDrawScreen(DX_SCREEN_BACK); // ←画面の描画先として裏画面を指定。
SetDrawMode(DX_DRAWMODE_BILINEAR); // ←バイリニア補完をかけて画像を描画。これを指定しないと画像を拡大・縮小・回転させた際にフチの部分がギザギザになります。
//SetDrawBlendMode(DX_BLENDMODE_ADD, 255); // ←画像を描画する際加算モードで描画する。加算モードで描画すると画像が光っているような効果を与えられます。今回は使用しません。
double x = 20.0; // ←画像を表示する際のX座標。
int dx = 1; // ←画面内の画像が1フレームにつき何ピクセル動くかを指定。
int GrHandle[11]; // ←画像格納用ハンドル。メモリに読み込んだ画像はこのポインタを経由して使用します。
int type = 4; // ←画面にどの画像を表示するか。下のswitch文の分岐条件に使用。
switch (type){
case 0:
LoadDivGraph("dat/img/bullet/b7.png", 11, 11, 1, 18, 18, GrHandle);
break;
case 1:
LoadDivGraph("dat/img/bullet/b7_lo.png", 11, 11, 1, 22, 40, GrHandle);
break;
case 2:
LoadDivGraph("dat/img/bullet/b15.png", 11, 11, 1, 18, 18, GrHandle);
break;
case 3:
LoadDivGraph("dat/img/bullet/b7_mid.png", 11, 11, 1, 40, 40, GrHandle);
break;
case 4:
LoadDivGraph("dat/img/bullet/b7_mid_heart.png", 11, 11, 1, 52, 52, GrHandle); // ←メモリ上に画像を分割してロード。GrHandleには画像がメモリ上のどこにあるかというアドレスが格納される。
break;
case 5:
LoadDivGraph("dat/img/bullet/b7_mid_star.png", 11, 11, 1, 52, 52, GrHandle);
break;
case 6:
LoadDivGraph("dat/img/bullet/b0.png", 5, 5, 1, 76, 76, GrHandle);
break;
default:
break;
};
while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0){
// ScreenFlip() :裏画面と表画面を入れ替える。
// ProcessMessage() :Windowsからの生存確認に対するあれこれを勝手にやってくれる。
// ClearDrawScreen() :次の描画にそなえて裏画面を初期化する。
for (size_t i = 0; i < 11; i++){
DrawRotaGraphF(x, 32 * (i + 1), 1, 0.01f * DX_PI * x, GrHandle[i], TRUE); // ←メモリ上の画像を画面に描画。引数はX座標、Y座標、回転角度(ラジアン指定)、反転フラグ。
}
x += dx * 2; // xを2増やす
if (x >= 620){
dx *= -1; // 画像が画面右端まで届いたら反対の向きに動かす
}else if(x <= 20 && dx <= 0){
dx *= -1; // 画像が画面左端まで届いたら反対の向きに動かす
}
}
DxLib_End();
return 0;
}
重要な関数を一つずつ解説します。
まず描画先画面の指定。
##SetDrawScreen(DX_SCREEN_BACK);
Draw系の関数はこの関数で指定した画面に描画を行います。
裏画面に描画された内容はそれだけでは我々が見ているスクリーンには反映されず、後述のScreenFlip()関数を使用することで裏と表の画面が入れ替わり見えるようになります。
DX_SCREEN_BACKをDX_SCREEN_FRONTに書き換えるといきなり表画面に描画することもできます。
が、それは絶対にしません。ScreenFlip()関数のところで詳しく説明します。
次に画像のメモリ読み込み。
##LoadDivGraph("dat/img/bullet/b7_mid_heart.png", 11, 11, 1, 52, 52, GrHandle);
メモリ上のどこかに画像を分割して読み込みます。この時点ではメモリ上に読み込むだけなので画面に画像は表示されません。
今回の例を引数の順番通り日本語で表すと
「"dat/img/bullet/b7_mid_heart.png"という画像は"全部で11に分割"されていて"X方向には11分割"、"Y方向には1分割"して読み込み、1画像あたりの大きさは"幅52ピクセル"、"高さ52ピクセル"とする。この画像群にアクセスするためのアドレス情報は"GrHandle"に保持する」
という感じ。
わかりにくいので画像を使いながらもう少し解説。
今回使用する画像は上のように分割してそれぞれを1画像として読み込みます。
それぞれの画像はメモリ上のどこかに読み込まれ、GrHandle配列を使用することであたかも画像そのものの配列を扱っているような振る舞いが可能です。Javaで言う参照型みたいなもの。
ゲームプログラミングでは画像や音楽といったストレージに保存されているリソースは予めメモリ上に全て読み込んで使用します。
これは使用する度にストレージから読み込みをするとものすごく処理時間がかかってしまうのが理由です。業務系のアプリでもDBアクセスはできるだけ少ないことがベターとされるのでイメージしやすいと思います。
ちなみに、たいていのPCゲームが起動直後に数秒間『NowLoading......』になるのは、ほとんどの場合あのタイミングでゲーム内で使用する画像や音楽をメモリ上に読み込んでいるからです。
そして、画面の表裏入れ替え処理。
##ScreenFlip()、ProcessMessage()、ClearDrawScreen()
これらは3つ一組と考えて差し支えありません。
ScreenFlip()は一瞬で表画面と裏画面を入れ替えます。これによって裏画面に描画されていた内容がスクリーンに表示されます。
ProcessMessage()はWindowsが各ウィンドウに対して行う生存確認に対する対応を勝手にやってくれます。詳しいことはよくわかりません。
ClearDrawScreen()は裏画面を初期化します。これをやらないと画面にどんどん過去の描画内容が溜まっていきます。
これら3つが全て正常に終了している場合のみ画像の描画処理を行います。
ゲームの処理がScreenFlip()で表画面・裏画面を素早く入れ替えることで動きを表現している理由について少し説明を。
これは単純で、「スムーズな動きにならないから」です。
ゲーム画面の描写の流れは
画面初期化→画像の位置計算→計算結果をもとに画像描画
というようになります。
これを人間の目に触れる表画面でやろうと思うとどんなに高性能なマシンを使っても確実にチラついた動きになります。SetDrawScreenの引数をDX_SCREEN_FRONTにしてやるとよくわかります。
なので描画処理は人間の目に触れない裏画面で済ませておき、ScreenFlip()は描画が完了した一枚の画面を表画面に出すだけ。これを約1/60秒間隔の速度で行うと画面がヌルヌルと動いて見えます。
これがこの項の冒頭で説明した『紙芝居またはパラパラ漫画を超高速で繰り返している』の真意です。
最後に描画自体の処理の解説。
##一連の描画処理
for (size_t i = 0; i < 11; i++){ DrawRotaGraphF(x, 32 * (i + 1), 1, 0.01f * DX_PI * x, GrHandle[i], TRUE); // ←メモリ上の画像を画面に描画。引数はX座標、Y座標、回転角度(ラジアン指定)、反転フラグ。 } x += dx * 2; // xを2増やす if (x >= 620){ dx *= -1; // 画像が画面右端まで届いたら反対の向きに動かす }else if(x <= 20 && dx <= 0){ dx *= -1; // 画像が画面左端まで届いたら反対の向きに動かす }
whileループの中身です。
DrawRotaGraphFをforループで回してやることで分割画像全てを裏画面に描画してやります。
描画する座標や角度はxやdxを元に計算して出します。
whileループの中身は1/60秒に1回呼び出されるので画面がほんの少しずつ変化した状態で描画され、それを素早く連続して表示することで画面が動いて見えます。
ゲームプログラムがどのように動きを表しているかの説明は以上になります。
次はやっとゲームの構成要素を考えていきます。
#ゲームを構成する要素をオブジェクト指向的に考える
オブジェクト指向でゲームを作る以前に必要な考え方の紹介に随分とスペースを使ってしまいました……。
本当は順を追って少しずつオブジェクトを作って組み立てたかったのですが、記事が長くなりすぎるのでいきなりゲームそのものをオブジェクト指向で考えます。
さっきまでと比べて一気に発展する上にソースコードを載せると収拾がつかなくなるため考え方のみの紹介になります。
今後余裕があるときにもう少し各要素を噛み砕いて解説したいと思います。
##ゲーム画面を構成する要素
まずこの画面を見てみましょう。(すみません、準備が間に合わなかったので外枠の画像以外の画像とソースコードは借り物です……)
この画面を構成している要素にはどんなものが挙げられるでしょう?
・自機(Player)
・オプション(Option)
・自機弾(PlayerBullet)
・オプション弾(OptionBullet)
・敵(Enemy)
・敵の弾(EnemyBullet)
・敵が登場するタイミング(EnemyAction)
・スコアボード(ScoreBoard)
・背景(Background)
などが挙げられると思います。
これらはゲーム中常に更新され続けるべきものです。
だからと言って
// ※ソースコードではありません。
#include "DxLib.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
~中略~
while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0){
Playerオブジェクト.action();
for (PlayerBullet bullet : PlayerBulletの配列){
bullet.action();
}
for (Option option : Optionの配列){
option.action();
}
for (OptionBullet bullet : OptionBulletの配列){
bullet.action();
}
for (Enemy enemy : Enemyの配列){
enemy.action();
}
for (EnemyBullet bullet : EnemyBulletの配列){
bullet.action();
}
EnemyActionオブジェクト.action();
ScoreBoardオブジェクト.action();
Backgroundオブジェクト.action();
}
DxLib_End();
return 0;
}
と書くのはあまりにも不格好で可読性が低く、処理が漏れそうな上に保守しにくいのでやめましょう。
ではどうするか?
##ゲームに登場するオブジェクトは全て一括管理! 管理専門のクラスも作る
まず、ゲーム内で生成される全てのオブジェクトの親となるクラス(GameObject)を作りましょう。
次に、GameObject配列をフィールドとして持ち、配列内のオブジェクト全てを管理できるクラスも作りましょう。
この管理クラスは自身が生成された時プレイヤー、敵の登場タイミング、スコアボード、背景を生成します。
仕上げにGameObjectのサブクラスのオブジェクト達は生成されると管理クラスのGameObject配列に格納されるようにします。
クラス構成は以下のようになります。
・ゲームオブジェクト管理クラス(GameObjectAdmin)
・全てのゲームオブジェクトの親クラス(GameObject)
├・自機(Player)
├・オプション(Option)
├・自機弾(PlayerBullet)
├・オプション弾(OptionBullet)
├・敵(Enemy)
├・敵の弾(EnemyBullet)
├・敵が登場するタイミング(EnemyAction)
├・スコアボード(ScoreBoard)
└・背景(Background)
これによってさっきのソースコードまがいは以下のようになります。
// ※ソースコードではありません。
#include "DxLib.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
~中略~
GameObjectAdminオブジェクト(gameAdmin)生成; // ここでプレイヤー、敵の登場タイミング、スコアボード、背景も生成され自身のGameObject配列に格納される
while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0){
for (GameObject object : gameAdminのGameObject配列){
// GameObjectクラスは仮想関数としてaction()を持たせておきます。
// サブクラスではそれぞれの振る舞いに合ったaction()を実装します。
// 例)Playerクラスのaction()は、キーボードから入力を受け取りそれに応じて動く。
// Enemyクラスのaction()は、EnemyActionで予め決められた動きをする。 など
object.action();
// 自機や敵が弾を発射(生成)すると自動で管理クラスのGameObject配列に格納される。
}
}
DxLib_End();
return 0;
}
かなりスッキリした上にGameObjectを継承したクラスは生成されると同時に管理クラスのGameObject配列に格納されるため処理が漏れることがありません。
この改修で
・ゲームを構成する要素を全てGameObjectを継承しているお陰で一つの配列に入れて各要素にaction()関数を実行するだけで一括管理が可能
・しかし、サブクラスにそれぞれ自分用のaction()を実装しているため振る舞いは異なる
という2点の変化が起こりました。同じ名前の関数を呼んだとしても実体クラスによって異なる処理が行われるこの性質は『ポリモーフィズム』と呼ばれ、うまく使えばとても効率よくプログラムを書くことが可能となります。
継承やポリモーフィズムは概念的な話で使ってみないとイマイチ理解できないですが、この記事で少しでもピンと来ていただけるとそれはとっても嬉しいなって……。
ここら辺は別の機会にもう少し細かく切り出して解説したいです……。できるかな……。
余談ですが、今回作ったGameObjectはさらに分類すると画面内を動くもの(自機、弾等)と動かないもの(スコアボード等)に分けられるので、クラス構成は
・ゲームオブジェクト管理クラス(GameObjectAdmin)
・全てのゲームオブジェクトの親クラス(GameObject)
├・移動物(Mover)
│├・自機(Player)
│├・オプション(Option)
│├・自機弾(PlayerBullet)
│├・オプション弾(OptionBullet)
│├・敵(Enemy)
│└・敵の弾(EnemyBullet)
├・敵が登場するタイミング(EnemyAction)
├・スコアボード(ScoreBoard)
└・背景(Background)
とかにして、Moverクラスに画面内座標、点と点の距離を出す関数等を持たせるとさらに幸せになれるかもしれないです。
#広がる自作ゲームの夢
さて、プログラミングから少し離れたゲーム制作の小話をします。
皆さま"Play,Doujin!"という言葉はご存じでしょうか?
ググっていただくとわかるのですが、これは同人サークルが作成したゲームをPS4、PSVITAで遊べるというなかなか革新的なもの。→http://playdoujin.mediascape.co.jp/
PCで同人ゲームを遊ぶ際、ネックになる要素としてプレイヤーそれぞれの環境の違いがありました。(OS、CPU、メモリ、グラボその他色々)
手の込んだ同人ゲーはそれなりのマシンパワーが無いと100%を発揮できないのです……。
しかし、"Play,Doujin!"ではハードがPS4かPSVITAなのでゲームを買う際に『俺のPCで動くかな……』と心配しなくて済みます。
また、作る側にも『今まで同人ゲームを遊んだことが無い層へ切り込む機会が生まれる』というメリットがあり個人的に今後が楽しみなプロジェクトです。
ちなみに今回使用したDXライブラリもこのプロジェクトに一枚噛んでいて、なんとDXライブラリをPS4、PSVITAで使うことができてしまいます。
つまり、DXライブラリで過去に作品を作った実績があると比較的少ない労力でPS4、PSVITA向けゲームをリリース可能ということです。素晴らしい。
ソニーさんの審査はあるけれどそれをクリアすればゲーム制作会社に属さずともコンシューマ機向けゲームが作れてしまう。という時代になってきています。
ゲーム業界はイマイチ盛り上がっていないようですが、同人ゲームはこれを一つのきっかけとして盛り上がってほしいなぁと思いました。
#まとめ
①ゲームプログラミングを通して学べることは
・プログラミング言語の文法
・オブジェクト指向の考え方(継承、ポリモーフィズム等)
・ある現象をプログラミング的考え方に変換する手法
・デザインパターンちょっぴり
などが挙げられる。
②プログラミングの学習としてゲームを作るならツールに頼らずコーディングあるのみ。今回は「C++とDXライブラリ(DirectX)」を使う。
VisualStudio Community 2015ダウンロード:https://www.visualstudio.com/ja/vs/community/
DXライブラリダウンロード:http://dxlib.o.oo7.jp/dxdload.html
プロジェクトテンプレートのダウンロード:こちら
使用する画像のダウンロード:こちら
③ゲームプログラミングはとにかく速度が大事。
使うものは最初に全部メモリに読み込む。
画面の中の動きはパラパラ漫画で表現する。描画は裏画面に行って表画面は常に描画完了したものしか見せない。
④ゲームに必要なものは全てオブジェクトとして考える。
自機、敵、弾はもちろんそれら画面の中で動くものを管理する装置もオブジェクト。
継承、ポリモーフィズムはゲームプログラミングにおいても非常に重要。
⑤"Play,Doujin!"等で自分のゲームがPS4、PSVITAデビュー!?
多少の審査等はあるがコンシューマー機で遊べるゲームもDXライブラリで開発できる、そんな時代になった。
http://playdoujin.mediascape.co.jp/
はい! 後半かな~り走りましたが私の記事は以上です!
ゲーム制作に興味ある方・湧いた方私と一緒に一花咲かせましょう!
普段あまり文章を書かないのでまとめるのがすごく難しかった……。
明日は@HomMarkHuntさんです! よろしくお願いします!
#参考文献・サイト
ロベールのC++入門講座:Amazon商品ページへ
ゲームプログラマになる前に覚えておきたい技術:Amazon商品ページへ
シューティングゲーム アルゴリズムマニアックス 新装版:Amazon商品ページへ
弾幕 最強のシューティングゲームを作る!:Amazon商品ページへ
シューティングゲーム プログラミング:Amazon商品ページへ
DXライブラリ置き場:http://dxlib.o.oo7.jp/
※公式リファレンス:http://dxlib.o.oo7.jp/dxfunc.html
※非公開関数(大量にあります):https://densanken.com/wiki/?dx%A5%E9%A5%A4%A5%D6%A5%E9%A5%EA%B1%A3%A4%B7%B4%D8%BF%F4%A4%CE%A5%DA%A1%BC%A5%B8
新・ゲームプログラミングの館:http://dixq.net/g/
プログラミング入門サイト:http://bituse.info/game/