読者です 読者をやめる 読者になる 読者になる

【enchant.js】ドロイドくんもぐらたたきのコードを読み解いてみる

ということで引きこもってましたがちゃまにあですどーもこんばんは。

今日は1日enchant.jsいじり。
集中力がなくてほとんど進んでないけど。

サンプルになっている「ドロイドくんもぐらたたき」について考えてみました。

大体意味はわかるけど

例によって手書きノートを晒します。

f:id:gachamania:20140719232220j:plain


f:id:gachamania:20140719232229j:plain


f:id:gachamania:20140719232236j:plain


f:id:gachamania:20140719232243j:plain


これがコード全文。
http://code.9leap.net/内のサンプルより引用しました。

enchant();
//ドロイド君の出現数
maxDroid = 30;

//穴クラスの定義
Pit = Class.create(Sprite,{ //Spriteクラスを継承する
	initialize:function(x,y){
		enchant.Sprite.call(this,48,48); //Spriteクラスのコンストラクタ呼び出し
		this.image = game.assets['mogura.png'];
		this.x = x;
		this.y = y;
		this.addEventListener('enterframe',this.tick); //イベントリスナーを定義
		this.addEventListener('touchstart',this.hit); //叩いた場合のイベントリスナーを定義
		this.mode = 2; //ドロイド君の出現モードを待つ、からに設定
		this.nextMode = 0; 
		this.waitFor =  game.frame+Math.floor(Math.random()*100); 
	},
	tick:function(){ //ドロイド君が出るアニメーションを繰り返す
		if(game.frame%2!=0)return; //4フレームごとに実行する
		switch(this.mode){
			case 0: //穴からドロイド君がでてくる
				this.frame++;
				if(this.frame>=4){
					this.mode=2; 	//出切ったら、待つモードへ
					this.nextMode=1;//待った後に遷移するモードは1(隠れる)
					this.waitFor = game.frame+Math.floor(Math.random()*30);
				}
				break;
			case 1://ドロイド君が穴に隠れる
				this.frame--;
				if(this.frame<=0){
					this.mode=2; 	//出切ったら、待つモードへ
					this.nextMode=0;//待った後に遷移するモードは0(出現)
					this.waitFor = game.frame+Math.floor(Math.random()*200);

					//ドロイド君の最大数を減らす
					maxDroid--;
					//もしこれ以上ドロイド君は出現しないなら、穴を塞ぐ
					if(maxDroid<=0)this.mode=3; 
				}
				break;
			case 2://待つ
				if(game.frame>this.waitFor){
					this.mode = this.nextMode;
				}
				break;
			case 3://なにもしない(この穴からもうドロイド君は出ない)
				break;
		}
	},
	hit:function(){ //ドロイド君を殴る
		if(this.frame==5)return;//既に殴れた状態だったらなにもしない
		if(this.frame>=2){ // ドロイド君が半分以上出ていた場合
			this.frame=5; //殴れたドロイド君
			this.mode=2;  //待ちモードに入る
			this.nextMode=1;
			this.waitFor = game.frame+10; //待つフレーム数は10で一定
			scoreLabel.add(1); //スコアに追加
		}
	}
});
//ScoreLabelクラスの定義
ScoreLabel = Class.create(Label,{ //Labelクラスを継承する
	initialize:function(x,y){
		enchant.Label.call(this,"SCORE:0"); //Labelクラスのコンストラクタ呼び出し
		this.x=x;
		this.y=y;
		this.score = 0;
	},
	add:function(pts){ //スコアを加算
		this.score+=pts;
		this.text="SCORE:"+this.score; //表示を修正
	}
});
window.onload = function(){//初期化
	game = new Game(320, 320);
	game.preload('mogura.png');//ドロイド君画像を読み込み
	game.onload = function(){

		//スコアラベルを表示
		scoreLabel=new ScoreLabel(5,5);
		game.rootScene.addChild(scoreLabel);

		//穴を4x4に並べる
		for(y=0;y<4;y++){
			for(x=0;x<4;x++){
				var pit = new Pit(x*48+20,y*48+20);
				game.rootScene.addChild(pit);
			}
		}
    }
    game.start();
}


コードだけではなくノートとかメモを貼るのは、どういうところに引っかかるか見てもらうため。
どうでもいいような所で躓いたりしてると思うので(笑)

で、今回の疑問。
変数って宣言しなくていいの??
modeもnextModeもwaitForも、varで宣言してないけど。

「Pit = Class.create(Sprite,{・・・」は、
「var Pit=enchant.Class.create(enchant.Sprite{・・・」の書きかえってことでいいのかな。

あと、ifを使う時って{}でくくらなくていいんでしょうか。breakだからOKとかあるの?

うーむ。


まあ大体の仕組みはわかったので(nextModeの役割がわかったときはおおぉ!ってなった)良しとしています。
あとはこれを生かしてコードを書くと。

折角なので画像も作ります。ドット絵。
まずは簡単なゲームを完成させたい!


--追記--
わかったことをまるっと書いてないっていう(笑)
むしろここからが本番。

maxDroid=30;
ドロイド君の出現回数を制御。
tickのcase1(穴にもぐるアクション)で減らしてる。
逃げられたら1機ミスみたいな感じ。

function tick
変数modeで状態ごとに指示を出す。
case0=出現、case1=潜る、case2=待機、case3=出現無効化
フレーム進行での分岐(「if(this.frame>・・・」など)と、変数nextModeを仕込むことで行動を指示。
mode=0のとき
フレームが4以上に進行したらmodeの値を2、nextModeの値を1、waitForの値を「フレーム数+30までの整数」にする。
mode=1のとき
frame--で、出現アクションを逆再生。
maxDroidも減らす。
mode=2のとき
フレームがwaitForの値まで進行するまで待機
nextModeを仕込んであるおかげで、mode=0→mode=2→mode=1をループすることができる。

for(y=0;y<4;y++){・・・A
for(x=0;x<4;x++){・・・B
Bで4つ作ったものを、Aで4つ作る。
つまり4×4=16のスプライトを生成。


こんなもんでしょうかね。