2012年4月8日日曜日

ゲーム開発

去年のある時期を境にiphoneでゲームが作りたくなって、ある程度構想を練って作り始めた訳ですが、

その過程で分かったことがあります。

「ゲームを作る人(作れる人)ってすごい」ということです。

私が今作成しようとしているゲームは、正直ファミコンでも表現可能なゲームです。
そして、cocos2dを使っているので難しいことは考える必要は無いはずなのです。

それでも、作成しようと決意してからすでに半年程度経過しているにもかかわらず、全然実装の終わりが見えない。

一日1時間程度しか時間が取れないという言い訳満開の事実があるにせよ、予定ではすでに完成しているはずなのです。

なのに全然終わらない。なんだコレ。


別に締切りがある訳では無いんですが、ちょっとある企画に乗った形で作っているので
何か申し訳ない気持ちと、焦りの気持ちでいっぱいです。

しかし、中途半端なものを作りたくないので頑張ります。

けど、一度ファミコン時代のプログラムをみてみたいなー
あのスーパ配管工兄弟のゲームでは、メモリ確保の為に今では考えられない色々なことをしていると噂で聞いたことがあります。

どれくらいのコード量なんやろなー。

2012年1月17日火曜日

cocos2dでタワーディフェンス その3


前回の続きです。
前回はCreepクラスを継承して2種類の敵を設定する所まで見ました。

次は、DataModelクラスとWayPointクラスを利用して、敵に動作を与える箇所につて見ていきます。

Creep.mの以下の箇所
- (WayPoint *)getCurrentWaypoint{
 DataModel *m = [DataModel getModel];
 WayPoint *waypoint = (WayPoint *) [m._waypoints objectAtIndex:self.curWaypoint];
 return waypoint;
}

- (WayPoint *)getNextWaypoint{

 DataModel *m = [DataModel getModel];
 int lastWaypoint = m._waypoints.count;
 self.curWaypoint++;
 if (self.curWaypoint > lastWaypoint)
  self.curWaypoint = lastWaypoint - 1;

 WayPoint *waypoint = (WayPoint *) [m._waypoints objectAtIndex:self.curWaypoint];
 return waypoint;
}
「getCurrentWaypoint」は現在のWaypointを取得します。
要は今の敵の位置ですね。

「getNextWaypoint」は次のWaypointを返します。
要は次にどこまで移動するかの情報ですね。

この両メソッドを見てみると、
WayPoint *waypoint = (WayPoint *) [m._waypoints objectAtIndex:self.curWaypoint];
という共通箇所があるのが見れると思います。
ここでは、Creepクラスで保持している「curWaypoint」からwaypointを見つけて返却しています。

次の場所を取得したい場合は、「curWaypoint」の値を増やせばOKです。
ただし、増やした値が配列の最後の値なのかの確認は必要ですが。

配列の末尾の値になったら、「curWaypoint」の値はそれ以上増えません(これ以上移動しないって意味です)。
値を「0」にすると敵はループし続けます。

getNextWaypoint内の
self.curWaypoint = lastWaypoint – 1;

self.curWaypoint = 0;


に変更してみてください。

こうすると、タワーが破壊されない限りWaveが繰り返されます。
「self.curWaypoint = lastWaypoint – 1;」だと、敵が一周すると出てこなくなるのに対して
「self.curWaypoint = 0;」だと一周した後、再び敵が出てくるのがわかりますね。

今回はここまで。
次回はTutorialSceneクラスを見ていきます。

2012年1月11日水曜日

cocos2dでタワーディフェンス その2

今回はDataModelクラスから見ていきましょう。

DataModelクラスはNSCodingを実装したsingletonクラスです。
NSCodingを実装しているのはゲームの現在の状態を保持しておきたいから、
またsingletonにしているのはDataModelクラスはゲーム内に一つしか必要ないからのようです。

どの辺がsingletonかというと、DataModel.mの以下の部分ですね。

+(DataModel*)getModel
{
 if (!_sharedContext) {
  _sharedContext = [[self alloc] init];
 }
 return _sharedContext;
}
この辺の詳細を知りたいならGoogle先生に聞いてくださいまし。
まぁ、Objective-cでsingletonの実装をするなら↑のようになると思ってください。

DataModelクラスを他から呼び出す場合は

DataModel *m = [DataModel getModel];
となりますね。

また、ここでは主要なものは配列で保持しています。コードを見てみましょう。

#import "cocos2d.h"

@interface DataModel : NSObject  {
 CCLayer *_gameLayer;
 NSMutableArray *_targets;
 NSMutableArray *_waypoints;
 NSMutableArray *_waves;
 UIPanGestureRecognizer *_gestureRecognizer;
}

@property (nonatomic, retain) CCLayer *_gameLayer;

@property (nonatomic, retain) NSMutableArray * _targets;
@property (nonatomic, retain) NSMutableArray * _waypoints;
@property (nonatomic, retain) NSMutableArray * _waves;
@property (nonatomic, retain) UIPanGestureRecognizer *_gestureRecognizer;;
+ (DataModel*)getModel;

@end

変数の説明ですが
target は敵ですね(TDのcreepのことです)。
waypoint はそのままです。詳しくは前回の投稿を見てください。
waves は Waveクラス(敵の数とか登場する間隔とかを定義しているクラス)を保持する為の配列です。

そのほかに、DataModelクラスはUIPanGestureRecognizer型とCCLayer型の変数を持っています。
まずCCLayerですが、タッチ入力と加速度センサー入力を受け取るクラスです。
このチュートリアルでは
現在のゲームレイヤーへのポインタで、全てのアクションがここで実行されている
と説明されてます。

UIPanGestureRecognizerはタッチジェスチャーを検出するためのクラスですが、
ここでは
480×320に制限されたゲームのスクリーンをスムーズにスクロールするために使う
みたいな事書いてました(かなり意訳)。

まぁ、そのへんは後々に。


次に「敵」のクラスを見ていきましょう。敵を表すクラスはCreepクラスです。

#import "cocos2d.h"

#import "DataModel.h"
#import "WayPoint.h"

@interface Creep : CCSprite  {
        int _curHp;
 int _moveDuration;
 int _curWaypoint;
}

@property (nonatomic, assign) int hp;
@property (nonatomic, assign) int moveDuration;
@property (nonatomic, assign) int curWaypoint;

- (Creep *) initWithCreep:(Creep *) copyFrom;
- (WayPoint *)getCurrentWaypoint;
- (WayPoint *)getNextWaypoint;

@end

@interface FastRedCreep : Creep {
}
+(id)creep;
@end

@interface StrongGreenCreep : Creep {
}
+(id)creep;
@end


Creepクラスは
・HP(HitPoint)
・敵の速さ
・現在のWayPoint
をそれぞれセットできます。

敵はCreepを継承したものを作成します。
ここでは

・FastRedCreep
  移動スピードは早いが弱い(HPが少ない)敵(赤色)
・StrongGreenCreep
  移動スピードは遅いが強い敵(緑色)

を用意しています。
それではこの敵をどうやって実装していくか実装部分を見ていきましょう。

@implementation FastRedCreep

+ (id)creep {
    FastRedCreep *creep = nil;
    if ((creep = [[[super alloc] initWithFile:@"Enemy1.png"] autorelease])) {
        creep.hp = 10;
        creep.moveDuration = 4;
  creep.curWaypoint = 0;
    }
    return creep;
}

まず、staticメソッドを用意して、ここで敵の設定を行います。
この敵を呼び出すときは

[FastRedCreep creep]

とすることで、すぐに画面に反映されます。
また、このクラスはCCSpriteを継承しているので、その機能を色々使えるようになってます。

ちなみにCCSpriteはcocos2dで画像を表示するためのクラスです。
背景とかキャラクターとかはこのクラスで表示させます。

とりあえず第2回はここまで。
次回は敵が今どこにいるのかを取得する箇所からやってきます。

いやー、意外に時間かかるなー



2012年1月4日水曜日

cocos2dでタワーディフェンス その1


ここは、このページを参考にしてcocos2dを使ってタワーディフェンスゲームを作成していく備忘録です。

このチュートリアルでは、まず以下の事からやっていくようです。

■ waypointの作り方
■ タイルマップを読み込んで、オブジェクトとして扱う方法
■ Creeps/Bad Guys/Enemies (要は侵入者ですか) の作り方
■ 決められた軌道に沿って移動を行う方法
■ iphone上でスムーズに移動を行う方法

これらの事無くしてタワーディフェンスとは言えないらしいですな。
まぁ、第一回目は基本の敵がタイルマップ上の決められたパスに従って移動させる方法の紹介のようですね。

これから解説するソースコードは以下からDLできます。
http://www.iphonegametutorials.com/wp-content/uploads/2011/04/TowerDefensePart1.zip


ここではタイルマップの作成に「Tiles」というツールを使うので以下からインストールします
http://www.mapeditor.org/

あと、cocos2dは必須なんでDLしときましょ。設定の仕方はググッてくだされ。
http://www.cocos2d-iphone.org/


それではDLしたソースの重要なクラスの機能を簡単に紹介

■ TowerDefenseTutorialAppDelegate
このクラスはWindowをつくって、CCDirectorをロードして、最初のシーンを作成するクラスとなります。

■ RootViewController
UIViewControllerを継承してるから、画面の向きを簡単に変えられるますとのこと。
まぁ、ここで画面を横向きにしているんでしょね。多分。

■ GameConfig
この時点では画面の向きに関する基本的な定数しか定義してないですね。
後々いろいろとここで定義するんでしょうな。

■ TutorialScene
一番メインのクラス(色々やってるクラス)みたいですね。
ここではマップを読み込んで「creep」(敵ですね。あとで説明します)をパスにセットするみたいですね。

■ DataModel
簡易検索のためのメインデータの配列を格納しておくシンプルなModelインターフェースらしいです。

■ Creep
敵クラスです。はじめは2種類ですが、後々増えてくるみたいです。

■ Waypoint
タイルマップエディタと組み合わせて使用する単純なクラス。
このクラスで「Tiles」と連携するんでしょうかね。

■ Wave
「creep(敵)」の順番を制御するクラスですね。

とりあえずこんな感じのようです。
説明で、「creep」って出てきたと思いますが、タワーディフェンス(以下 TD)には色々用語があります。

覚えておくとクラス名とかから、何をしているのか想像しやすくなるので解説しておきます。

■ wave
敵の隊列。TD系のゲームではwave=ステージやレベルとなることが多いです。

■ creep、bad guy
敵ですね。

■ range
砲台の射程距離です。

■ upgrade
砲台を強化することです。
3段階まで強化できるのをよく見かけます。

■ waypoint
敵が通る順路です。
たいての場合、敵がどこを通るかが何らかの方法で示されています(道が光ったり)。

あと色々あったと思うんですが、思い出し次第書いていこうかと思います。

とりあえず今回はここまで。
次回から実装の方に入っていきたいと思います。