前回は、Enemyクラスを紹介しました。
今回は、StarlingCameraクラスの紹介です。
プラットフォームゲームに必須といえる機能の一つに、「視点の移動」があります。
ステージの横幅が、画面サイズ内で収まるのであれば必要はありませんが、そんなことはほぼないと思います。
視点が固定であった場合、キャラクターを操作できたとしても、ユーザーが操作した結果、キャラクターが画面外へ出てしまっては、ゲームを続けてプレイする事は出来ません。
上記のような理由から、プラットフォームゲームではユーザーの操作に対して、自動的に視点が移動することが望ましいですが、自前で実装すると、オブジェクトの管理や、座標の計算等の処理が必要になってくる為とても大変です。
このような手間を全て吸収した上で、視点の移動・拡大縮小を簡単に実装する事ができるのが、CitrusEngineのStarlingCameraクラスになります。
StarlingCameraクラスにターゲットのオブジェクトを指定すると、そのオブジェクトの動きに追従するように視点が移動します。
そのため、ターゲットをHeroオブジェクトにすると、ユーザーが操作した場合でも、ステージが続く限りキャラクターを移動させる事が可能となります。
一点だけ注意しなければいけないのが、StarlingCameraというクラス名ですが、カメラの対象となるオブジェクトは、add関数で追加する事が出来るCitrusで用意されているオブジェクト(CitrusObjectやHero/Enemy等)のみとなります。
StarlingCameraのセットアップは、以下のように行います。
//作業用にStarlingCameraインスタンスを用意 private var _camera:StarlingCamera; //StarlingStateのviewが持つcameraを有効にする view.camera.enabled = true; //viewのcameraを用意したStarlingCameraインスタンスの参照先に設定 _camera = view.camera as StarlingCamera; _camera.setUp( hero ); //ステージを基準としたカメラの範囲を定める _camera.bounds = new Rectangle(-10000,-10000,20000,20000); //回転を有効にする _camera.allowRotation = true; //拡大・縮小を有効にする _camera.allowZoom = true; _camera.reset();
boundsプロパティはカメラの移動範囲を設定することができ、ステージのゼロポイントを基準として指定します。
上記の例では、開始地点に-10000、widthとheightには20000を指定しているので、ステージを中心として左上-10000から20000の範囲がカメラが移動する範囲となります。
そのため、Rectの指定を(0,0,20000,20000)とした場合は、ステージより左側にはカメラは移動しません。
allowRotation/allowZoomを有効にした場合は、回転と拡大縮小を行う事が出来ます。
//回転 _camera.setRotation( 90 ); //拡大 _camera.setZoom( 2 ); //縮小 _camera.setZoom( 0.5 );
簡単なご紹介となりましたが、以上で本記事は終了となります。
最後まで御覧いただきありがとうございました。
package {
//Starling及び、Box2Dのインポート
import citrus.core.starling.StarlingState;
import citrus.physics.box2d.Box2D;
import citrus.objects.platformer.box2d.Enemy;
import citrus.objects.platformer.box2d.Hero;
import citrus.objects.platformer.box2d.MovingPlatform;
import citrus.objects.platformer.box2d.Platform;
import citrus.objects.platformer.box2d.Coin;
import citrus.view.starlingview.AnimationSequence;
import citrus.objects.Box2DPhysicsObject;
import org.osflash.signals.Signal;
import starling.display.Quad;
import starling.textures.Texture;
import starling.textures.TextureAtlas;
import starling.events.Event;
import flash.geom.Point;
import flash.geom.Rectangle;
import feathers.controls.*;
import citrus.view.starlingview.StarlingCamera;
import starling.display.Image;
//StarlingStateを継承する
public class CitrusTest extends StarlingState {
[Embed(source=”../../../assets/Hero.png”)]
private var heroBitmap:Class;
[Embed(source=”../../../assets/Hero.xml”, mimeType=”application/octet-stream”)]
private var heroXml:Class;
[Embed(source=”../../../assets/coin.png”)]
private var CoinBitmap:Class;
private var camTarget:Point = new Point();
private var _camera:StarlingCamera;
private var hero:Hero;
private var fieldData:Array = [
{ x: 0 , y:600 , width:3000, height:10, color:0xC0C0C0 },
{ x: -150 , y:420 , width: 350, height:10, color:0xC0C0C0 },
{ x: -860 , y:-150 , width: 200, height:10, color:0xC0C0C0 },
{ x: -800 , y:200 , width: 100, height:10, color:0xC0C0C0 },
{ x: -40 , y:200 , width: 80, height:10, color:0xC0C0C0 },
{ x: -560 , y:280 , width: 140, height:10, color:0xC0C0C0 },
{ x: 0 , y: 0 , width: 800, height:10, color:0xC0C0C0 },
{ x:-1300 , y:150 , width: 400, height:10, color:0xC0C0C0 },
{ x: 1200 , y: 40 , width: 250, height:10, color:0xC0C0C0 },
{ x: 400 , y:240 , width: 150, height:10, color:0xC0C0C0 },
{ x: -900 , y:460 , width: 150, height:10, color:0xC0C0C0 },
{ x: 540 , y:360 , width: 300, height:10, color:0xC0C0C0 },
{ x: 950 , y:120 , width: 300, height:10, color:0xC0C0C0 },
{ x: 1300 , y:280 , width: 400, height:10, color:0xC0C0C0 },
{ x:-1260 , y:0 , width: 100, height:10, color:0xC0C0C0 },
//左の壁
{ x:-1500 , y: 300, width: 10, height:600, color:0xC0C0C0 },
//右の壁
{ x: 1500 , y: 300 , width: 10, height:600, color:0xC0C0C0 },
];
//コンストラクタ
public function CitrusTest()
{
super();
}
//初期化処理のところで色々と配置する
override public function initialize():void
{
super.initialize();
//Box2d空間の作成
var box2D:Box2D = new Box2D(“box2d”);
add(box2D);
createField();
createHero();
view.camera.enabled = true;
_camera = view.camera as StarlingCamera; // a reference for future use
_camera.setUp( hero );
_camera.bounds = new Rectangle(-10000,-10000,20000,20000);
_camera.allowRotation = true;
_camera.allowZoom = true;
_camera.reset();
var texture:Texture = Texture.fromBitmap( new CoinBitmap() );
var rotateButton:Button = new Button();
rotateButton.defaultSkin = new Image( texture );
rotateButton.label = “rotateButton”;
rotateButton.x = 650;
rotateButton.y = 100;
rotateButton.addEventListener( Event.TRIGGERED, onClickEvent );
addChild( rotateButton );
var zoomButton:Button = new Button();
zoomButton.defaultSkin = new Image( texture );
zoomButton.label = “zoomButton”;
zoomButton.x = 750;
zoomButton.y = 100;
zoomButton.addEventListener( Event.TRIGGERED, onClickEvent );
addChild( zoomButton );
}
/**
* フィールド生成
*/
private function createField():void
{
for( var i:uint = 0; i < fieldData.length; i++ ){
//地面作成
var fieldView:Quad = new Quad( fieldData[ i ].width, fieldData[ i ].height, fieldData[ i ].color );
var field:Platform = new Platform("ground",
{ width : fieldData[ i ].width,
height : fieldData[ i ].height,
x : fieldData[ i ].x,
y : fieldData[ i ].y,
view : fieldView
});
add( field );
}
}
/**
* ヒーロー生成
*/
private function createHero():void
{
//テクスチャアトラス生成
var texture:Texture = Texture.fromBitmap( new heroBitmap() );
var xml:XML = XML( new heroXml() );
var textureAtlas:TextureAtlas = new TextureAtlas( texture, xml );
//xmlで定義されているアニメーション名を格納した配列を生成
var animNames:Array = ["idle", "walk", "die", "jump", "hurt", "duck"];
//テクスチャアトラスからAnimationSequence生成
var animationSequence:AnimationSequence = new AnimationSequence( textureAtlas, animNames, animNames[ 0 ], 12, true );
//AnimationSequenceをviewに設定したHeroオブジェクトの生成
hero = new Hero("hero",
{ width : animationSequence.width,
height : animationSequence.height,
x : 100,
y : stage.stageHeight - 200,
view : animationSequence
});
add( hero );
}
/**
* ボタンタッチイベント
*/
private function onClickEvent( evt:Event ):void
{
var button:Button = Button( evt.target );
var value:Number;
switch( button.label ){
//回転ボタン
case "rotateButton":
value = Math.floor( Math.random() * 5 );
trace( "value :: " + value );
_camera.setRotation( value );
break;
//拡大・縮小ボタン
case "zoomButton":
value = Math.random() * 2;
trace( "value :: " + value );
_camera.setZoom( value );
break;
}
}
}
}
[/as3]
<次回の更新について>
次回は、ボーンアニメーションをご紹介致します。
弊社では全国各地の請負い(ご自宅)で作業協力頂ける、フリーランスエンジニアの方を常時探しております。
ご興味ある方は、お気軽にお問い合わせ下さい。