Citrus知っとらす?30分でスーマリっぽいゲームを作れるYO!

注意! 本記事のタイトルは©太田貞一民です。決して私が考えた物ではありません。

大変便利なゲームエンジンを紹介したいと思います。Citrus Engineと言う、ゲーム制作向けのフレームワークで、ゲームの面倒な処理をハンドルしてくれるのが基本的な動作です。例えばレベルデータを読み込んでそれぞれのゲームオブジェクトを物理エンジンに登録する、その後にフレーム毎に物理エンジンの時間を進めてアップデート関数を呼んで、その結果を画面に表示する。Citrusが各パーツの縫い合わせを担当してくれるので、開発時間(特にスタートアップの時間)をかなり節約出来ます。

では具体的な例で見てみよう。Citrusは非常に一般的な物で色んなジャンルで役に立ちますが、例としてプラットフォーマー(つまりマリオ的な)ゲームを作って見よう。

① 準備

まずはCitrusのSWCをダウンロードしよう。全体的なソースは全部Githubにあるが、必要なライブラリーのみのSWCを使う方が便利である。(Citrusが複数の物理エンジンや表示エンジンに対応しているので、全体ソースを自分のプロジェクトに入れると、使っていないエンジンをインポートしないように気をつけないといけない。) 今回の表示はStarling、物理エンジンはBox2Dを使いますのでCitrusのダウンロードページの「Citrus+Starling+Feathers+Box2D」と書いてあるSWCをダウンロードする。

② コード開始

Flash Builderで新AS3プロジェクトを作る。プロジェクト名を「CitrusPlatformer」に設定。「ビルドパス」で「SWCを追加」して先のSWCを指定する。プロジェクト設定これでOK。 次はプロジェクトのメインクラスを「StarlingCitrusEngine」を継承するように設定する。Citrusの基本的な考え方は、用意してある一般的な物を継承・オーバーライドしてカスタマイズする、という流れである。で、StarlingCitrusEngineとはStarlingを使った場合のCitrusプロジェクトの一般的なベースクラスのこと。今のところではこのクラスに2行だけ足す:

package {
import citrus.core.starling.StarlingCitrusEngine;

[SWF(frameRate="60", width="1024", height="768", backgroundColor="#EEEEEE")]
public class CitrusPlatformer extends StarlingCitrusEngine {

public function CitrusPlatformer() {
setUpStarling(true);
state = new PlatformLevel1();
}

}
}

setUpStarling()とは、Stage3Dオブジェクトを作ってContext取得等をハンドルしてくれる。次行のstateはエンジンのプロパティーは基本的にゲームのレベルだと思うこと。そしてPlatformLevel1は今からつくるゲームのレベル1のクラスにしよう。

FBヒント:new PlatformLevel1(); を入力したところでコマンド+1(WinではCTRL+1)を押すと、自動的にクラスを作製できる。

③ レベル1を作る

PlatformLevel1クラスをStarlingStateを継承するように設定する。StarlingStateは色々一般的な仕組みはあるので、後は基本的に変えたいところをオーバーライドして行こう。まずは初期のinitialize関数をオーバーライドして、物理エンジンオブジェクトを作って、add()でステートに追加しよう:

package {
import citrus.core.starling.StarlingState;
import citrus.physics.box2d.Box2D;

public class PlatformLevel1 extends StarlingState {
public function PlatformLevel1() {
super();
}

override public function initialize():void {
super.initialize();

var physics:Box2D = new Box2D("box2d");
physics.visible = true;
add(physics);
}
}
}

これでBox2Dセットアップは完了。(!)物理エンジンのvisibleプロパティーをtrueにすると、Citrusは自動的に各ゲームオブジェクトの代わりに色付きの四角を描いてくれる。画像アセットがまだなくてもゲームの基本的な動作を作れる。

④ プラットフォーマーだからプラットフォームを作る。あと主人公とか。

ここまでの流れはどんなジャンルのゲームでも通用するが、ここからはプラットフォーマー(つまりマリオ的な)オブジェクトを追加してそれらしい物を作ろう。

どうでも良い雑学:プラットフォーマーというゲームジャンルはソフトウェア等のプラットフォームとは関係ない。主人公が上に立つプラットフォーム(台)が由来である。つまりプラットフォーマーゲームは、主人公が台から台にジャンプしたりするわけ。やはりどうでも良かったか。

実はCitrusにプラットフォーマー向けのデモクラスがソースに入っている。要は最低限のプラットフォーマーが既にできているので継承・オーバーライドしながら作れる。それぞれのクラスがcitrus.objects.platformer.box2dのパッケージにある。各オブジェクトにオブジェクト名(String)とパラメータ(Object)を渡すが、両方はそのまま物理エンジンに渡される。オブジェクト名は、あとでゲームオブジェクトを取得するための物なので、後でアクセスしたいオブジェクトの場合にはユニークなStringを使おう。パラメータは、物理エンジンが認識できる設定をオブジェクトに詰めるだけ。コードで言うと:

var hero:Hero = new Hero("myHero", { width:40, height:80, x:200, y:200 } );
add(hero);

var floor:Platform = new Platform("myFloor", { width:1000, height:20, x:500, y:600 } );
add(floor);

上記のコードをinitialize()に足してテストムービーすると、主人公(赤い)と台(緑)が見える。矢印キーで移動、スペースでジャンプの仕組みがデフォルトで出来ちゃっている。ちなみにBox2Dではオブジェクトの(x,y)は必ずそのオブジェクトの中心で設定される。

役に立つプラットフォーマーのクラスはこんな感じ:

  • Hero:主人公。矢印キーとスペースで移動。
  • Enemy:敵。左右に移動する(leftBoundとrightBoundの間に)。HeroがEnemyに横から接触するとHeroが跳ねられるが、上からだとEnemyが消える。
  • Platform:台。「oneWay」をtrueにしすると下からは通れる。
  • MovingPlatform:2つの点の間に移動するプラットフォーム。
  • Coin:主人公が接触すると、イベントを発生して消える。
  • Sensor:他のオブジェクトが接触するとイベントを発生するセンサー。
  • Crate:物理エンジン対象の箱。

などなど。ミサイルや下からぶつかるとコインが出てくる箱など、色々用意してあるので各クラスの説明を参照しよう。適当にコードに付け加えると、それっぽいゲームを数分で作れる:

override public function initialize():void {
super.initialize();

var physics:Box2D = new Box2D("box2d");
physics.visible = true;
add(physics);

var hero:Hero = new Hero("myHero", { width:40, height:80, x:200, y:500 } );
add(hero);
hero.jumpHeight = 12;

var floor:Platform = new Platform("floor", { width:1028, height:20, x:1024/2, y:758 } );
var leftwall:Platform = new Platform("w1", { width:20, height:768, x:10, y:768/2 } );
var rightwall:Platform = new Platform("w2", { width:20, height:768, x:1018, y:768/2 } );
add(floor);
add(leftwall);
add(rightwall);

var platform1:Platform = new Platform("p1", { width:300, height:20, x:300, y:600 } );
platform1.oneWay = true;
add(platform1);

var elevator:MovingPlatform = new MovingPlatform("p2", { width:200, height:20, x:650, y:500,
startX:650, startY:500, endX:650, endY:300 } );
elevator.oneWay = true;
add(elevator);

var enemy:Enemy = new Enemy("enemy", { width:40, height:80, x:650, y:300,
leftBound:300, rightBound:600 } );
add(enemy);

var c1:Crate = new Crate( "c1", { width:40, height:40, x:400, y:300 } );
var c2:Crate = new Crate( "c2", { width:40, height:40, x:390, y:200 } );
var c3:Crate = new Crate( "c3", { width:40, height:40, x:380, y:100 } );
add(c1);
add(c2);
add(c3);
}

これでCitrusの一般的な紹介は終わります。次の課題は:

  • ゲームオブジェクトに画像やアニメーションを付け加える
  • レベル全体をコードで書くのではなくFlash等のツールで作って、Citrusに読み込む

この課題を次の記事でカバーしようと思います。

ソースファイル:

CitrusPlatformer.zip (ASソース、3 kb)