i phone勉強会 2010_03_06_gameloop
TRANSCRIPT
ゲームループのつくりかた
沖田@tmokita
12年11月17日土曜日
おわび
• いまさらな内容かもしれませんしiPhone固有というところはあまりないです。ごめんなさい。
• ゲーム作りのきっかけになればと思って発表することにしました。その程度です、ごめんなさい。
12年11月17日土曜日
おねがい• 発表の途中でも・よくわからねぇぞ!《゚Д゚》ゴラァア!! とか・細かく説明しろ!《゚Д゚》ゴラァア!! とかあったら随時お気軽にお願いします。
• つっこんでもらったほうが安心します。12年11月17日土曜日
自己紹介
12年11月17日土曜日
沖田知彦@
tmokita12年11月17日土曜日
本業12年11月17日土曜日
零細ゲームデベロッパ所属
iPhone案件はじめました12年11月17日土曜日
しかし12年11月17日土曜日
不況12年11月17日土曜日
なので12年11月17日土曜日
副業12年11月17日土曜日
iPhoneプログラマ12年11月17日土曜日
関わったアプリ
12年11月17日土曜日
その他はひみつ
12年11月17日土曜日
あらためて12年11月17日土曜日
ゲームループのつくりかた(初級編)
12年11月17日土曜日
目次• はじめに
• 業界用語
• 基本ループの考えかた
• Sceneとかなんとか
• おまけ
12年11月17日土曜日
はじめに
• ゲームの作り方を難しく考えすぎている人が多い
12年11月17日土曜日
が!12年11月17日土曜日
• 実はたいしたことはやっていませんごめんなさい
12年11月17日土曜日
とりあえず知っとけ的な物
12年11月17日土曜日
業界用語• リソース(音とか絵とかバイナリとか、データそのもの)• レイヤー(大きい単位での描画優先順位)• プライオリティ(小さい単位での描画優先順位)• BG(背景)
• スプライト、オブジェ(細かく動くやつ)• フレーム(FPS:フレーム/Sec 60FPS=秒間60回画面更新)
•シーン、モード(各画面)12年11月17日土曜日
リソース(Resource)
• リソースマネージャがあると便利
• 無駄な重複読み込みを防ぐ
• 最適なリソース配置
• 非同期ロードなどの処理
12年11月17日土曜日
レイヤー(Layer)• 描画順番を大きく区切るための構造
• フォトショップのレイヤーとか
奥
手前12年11月17日土曜日
プライオリティ• 同じレイヤー内での描画順番
Layer Layer
> <12年11月17日土曜日
BG,スプライト
BG スプライト(オブジェ)
都合により発表時とは画像を変えてあります
12年11月17日土曜日
以上をふまえて
12年11月17日土曜日
ループの話
12年11月17日土曜日
ゲームの基本は無限ループ
12年11月17日土曜日
基本ループ 1
• int main(){ GameInitialize(); whlie( isGameFinish() ) { GameMainLoop(); } GameFinalize();}
12年11月17日土曜日
iPhoneの場合はタイマーで
12年11月17日土曜日
基本ループ 2• applicationDidFinishLaunching
{ GameInitialize(); SetTimer(1.f/60.f);}
• OnTimer{ GameMainLoop();}
• applicationWillTerminate{ GameFinalize();}
12年11月17日土曜日
ソースコードは壊滅的
12年11月17日土曜日
でも書きます
12年11月17日土曜日
そしてシーン
12年11月17日土曜日
これが今日のメイン
12年11月17日土曜日
Scene
• Webでいうところの各ページ
• 各画面をSceneとして作り最後に接続する
• ex.)タイトル画面ゲームメインエンディング
12年11月17日土曜日
エンディングゲームプレイ画面タイトル画面
シーンのイメージ(あくまでもイメージ)
Title GameMain Ending
都合により発表時とは画像を変えてあります
12年11月17日土曜日
各シーンのつくり方
12年11月17日土曜日
Pattern 1• Switch−Caseでの分岐
while(1) { switch(nScene) { case kSceneTitle: funcTitleScene(); break; case kSceneGameMain: funcGameMainScene(); break; case kSceneEnding: funcEndingScene(); break; }}
12年11月17日土曜日
Pattern 2
• 関数ポインタにする• typedef void (*SceneFunc)(void*);
SceneFunc funcScenes[] = { funcTitleScene, funcGameMainScene, funcEndingScene};
• while(1) { funcScenes[nScene](&arg);}
12年11月17日土曜日
Pattern 3
• 仮想関数にする• CSceneBase sceneArray[] = {
TitleClass, GameMainClass, EndingClass,};
• while(1) { CSceneBase* currentScene = getCurrentScene(); currentScene->exec();}
12年11月17日土曜日
• 基本的なループはこんなかんじ
12年11月17日土曜日
ためしに
12年11月17日土曜日
•スプライトを一つ保持して描画するシーンを考える
• Class SceneOne{ CSprite* sprite;}
12年11月17日土曜日
必要な処理を考える
• Initialize - 初期化
•Main - 毎フレーム呼ばれる
•Finalize - 終了処理
12年11月17日土曜日
書いてみる• Scene::Initialize
{ sprite = [[CSprite alloc] initWithData:@”texture.png”];}
• Scene::Main(){ [sprite updateParameter]; [sprite draw];}
• Scene::Finalize(){ [sprite release];}
12年11月17日土曜日
できた12年11月17日土曜日
しかし12年11月17日土曜日
あれれのれ?
•非同期ロードは?→「NowLoading」とかは?
•ん?描画ってこれでいいの?
12年11月17日土曜日
• リソースのロードは非同期に行うそのため「ロード要求」と「ロードしたデータのセット」は段階をわけて行う必要がある
• レイヤーやプライオリティを考慮したり高速化のためには描画はまとめて一気に行うほうが都合がよい
12年11月17日土曜日
もういちど考える• Initialize - 初期化
•Loading - リソースのロード中
•PreMain - ロード後メインループ前に一回
• Main - 毎フレーム呼ばれる処理
•Draw - 描画処理
• Finalize - 終了処理
12年11月17日土曜日
も一回書いてみる(1)• Scene::Initialize
{ sprite = [[CSprite alloc] init]; [ResourceManage requestLoad_SpriteData];}
• Scene::Loading(){ [GameSystem requestDraw_NowLoading];}
• Scene::PreMain(){ data = [ResourceManage getLoadedSpriteData()]; [sprite setData:data]; [sprite setLayer:LAYER_0]; [sprite setPriority:100];}
12年11月17日土曜日
も一回書いてみる(2)• Scene::Main
{ [sprite updateParameter];}
• Scene::Draw{ [GameSystem requestDraw:sprite];}
• Scene::Finalize(){ [sprite release];}
12年11月17日土曜日
できた!12年11月17日土曜日
シーン完成!
• 一つのSceneは基本的にこんなかんじ
12年11月17日土曜日
そして12年11月17日土曜日
接続12年11月17日土曜日
Sceneの接続
•Sceneをつなぐ1 現在実行中のシーンの終了2 次のシーンの初期化
12年11月17日土曜日
while(1){CSceneBase* curentScene = getCurrentScene();
// 初期化if( [curentScene isNotInitialize] )
[curentScene Initialize];
//ロード中if( [ResourceManager isLoading] )
[curentScene Loading];
// ロード完了後に一回だけif( [ResourceManager isLoadFinish] )
[currentScene PreMain];
// Loading中にMain、Drawを呼ぶかはご自由に[currentScene Main]; [currentScene Draw];
// シーンのDrawでRequestされたものをレイヤーとプライオリティを考慮して描画[GameSystem DrawRequestedObject];
if( [SceneManager isRequestChange] ){
[currentScene Finalize];[SceneManager setNextScene: getRequestedScene()];
}}
12年11月17日土曜日
ソースコードは壊滅的
12年11月17日土曜日
Tips
• Scene選択できるSceneを作っておく
•できるだけScene単体で動くようにしておく
•→分業&デバッグが楽
12年11月17日土曜日
まとめ12年11月17日土曜日
まとめ• つまりはゲーム用の「便利なタスク」
• ゲーム用としてLoading、Draw、を考慮
• 仕組みを理解すれば各描画パーツに応用可能
12年11月17日土曜日
おまけ12年11月17日土曜日
お!12年11月17日土曜日
こいつ12年11月17日土曜日
できるな!12年11月17日土曜日
と思わせる小ワザ• メモリプールをつくる(実は大技)
• 構造体は無駄なく並べる
• 2の累乗の剰余は&でマスク
• 2の累乗を掛ける(割る)ときはシフト
• キー入力のバリエーションをつくる
12年11月17日土曜日
キー入力
• Normal - 押している間だけOn
• Repeat - 押した瞬間と一定時間後にOn
• Trig - 押した瞬間だけOn
• EndTrig - 離した瞬間だけOn
12年11月17日土曜日
これで12年11月17日土曜日
できるね!12年11月17日土曜日
やったね!12年11月17日土曜日
おめでとう!
12年11月17日土曜日
ありがとうございました
12年11月17日土曜日
• いずれどこかで中級編を・・・
• Twitter : tmokita
12年11月17日土曜日