敵の出現と移動(2/2)

 5.敵を移動する

 敵のうち存在するものだけを移動します。カウンターenemycntは1回移動するたびに1増やします。カウンターに対応する移動データ(enemvdx,enemvdy)を敵の座標に足します。しかし、どんどん増えていくカウンターに対して、移動データの要素は0〜15しかありません。これは、0から1つずつ増えて、15の後は0に戻らなければなりません。ここでもまた、モジュロ演算子"\"を使います。
    i=enemycnt.cnt\16
 iはenemycnt.cntを16で割った余りですから、enemycnt.cntが0から始まって1ずつ増えていくのに対して、iは0,1,2,……,14,15,0,1,2,……,14,15,0,1,2,……というふうに変化していきます。
 y座標が448よりも大きくなったら、存在フラグを0にします。
    repeat 10
        if enemyf.cnt=1 {
            i=enemycnt.cnt\16
            enemyx.cnt=enemyx.cnt+enemvdx.i
            enemyy.cnt=enemyy.cnt+enemvdy.i
            if enemyy.cnt>448 { enemyf.cnt=0 }
            enemycnt.cnt=enemycnt.cnt+1
        }
    loop

16進数

 16進数は、それぞれの位が16のべき乗で表される数です。
  ……+n2*16^2+n1*16^1+n0*16^0
 10進数は、各々の位に0から9までの数字が書けます。2進数は、0か1です。16進数は0から15までです。ただし、10をA、11をB、……、15をFで表します。例えば、4E6Cという数は、
  4*16^3+14*16^2+6*16^1+12*16^0
 つまり10進数の20076です。
 10進数は、10で桁が繰り上がります。
  0,1,2,……,9,10,11,……
 2進数は、2で桁が繰り上がります。
  0,1,10,11,100,101,……
 16進数は、16で桁が繰り上がります。
  0,1,2,……,F,10,11,12,……,1F,20,21,22,……,FF,100,……
 HSPでは、16進数には頭に"$"をつけます。

 6.敵を描画する

 絵のファイルに敵のアニメーションパターンを追加しました。
  敵のパターン
 ファイル中の座標は図の通りです。敵のサイズは32×32ドットです。  青い数字の順番で変えながら表示します。
 描画するたびに絵を変えると、アニメーションのスピードが速すぎるので、4回に1回にします。     i=enemycnt.cnt/4
 こうすると、iは、0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,……というふうに変化します。どうしてかというと、HSP(の標準機能)では、整数しか扱えないので、割り算した結果も整数になるからです。この場合、小数点以下は切り捨てとなります。よって、カウンターの値が0〜3の時結果は0、4〜7の時は1、8〜11の時は2、……となるのです。
 今、3の後は0に戻るようにしたいので、先ほどと同じようにモジュロ演算を使います。
    i=(enemycnt.cnt/4)\4
 iの値と、表示する絵の対応は上図の通りです。
    repeat 10
        if enemyf.cnt=1 {
            ddpos enemyx.cnt,enemyy.cnt
            i=(enemycnt.cnt/4)\4
            if i=0 { x=$80 }
            if (i=1)|(i=3) { x=$A0 }
            if i=2 { x=$C0 }
            ddsetrect x,0,32,32
            ddgcopy 1
        }
    loop

 7.現在位置を少し進める

 スクロールは1度に2ドット動かそうと思います。ですから、mappntも2増やします。     mappnt=mappnt+2
 この命令は、描画処理の直前に置くことにします。


 以上をふまえて、今回の処理をまとめます。
	; プログラム起動時の初期設定

	; 敵の変数宣言
	dim enemyf,10
	dim enemyx,10
	dim enemyy,10
	dim enemycnt,10

	; 敵の動きのパターン
	dim enemvdx,16
	dim enemvdy,16
	enemvdx.0=-8:enemvdy.0=4
	enemvdx.1=-6:enemvdy.1=4
	enemvdx.2=-4:enemvdy.2=4
	enemvdx.3=-2:enemvdy.3=4
	enemvdx.4=0:enemvdy.4=4
	enemvdx.5=2:enemvdy.5=4
	enemvdx.6=4:enemvdy.6=4
	enemvdx.7=6:enemvdy.7=4
	enemvdx.8=8:enemvdy.8=4
	enemvdx.9=6:enemvdy.9=4
	enemvdx.10=4:enemvdy.10=4
	enemvdx.11=2:enemvdy.11=4
	enemvdx.12=0:enemvdy.12=4
	enemvdx.13=-2:enemvdy.13=4
	enemvdx.14=-4:enemvdy.14=4
	enemvdx.15=-6:enemvdy.15=4


	; ステージスタート時の初期設定
	repeat 10
		enemyf.cnt=0
	loop

	mappnt=0

	randomize


	; メインループ

	; 敵の移動
	repeat 10
		if enemyf.cnt=1 {
			i=enemycnt.cnt\16
			enemyx.cnt=enemyx.cnt+enemvdx.i
			enemyy.cnt=enemyy.cnt+enemvdy.i
			if enemyy.cnt>448 { enemyf.cnt=0 }
			enemycnt.cnt=enemycnt.cnt+1
		}
	loop

	; 敵の出現
	if mappnt\64=0 {
		n=0
		w=-1
		repeat 10
			if enemyf.cnt=0 {
				repeat
					rnd r,18
					if r!w { break }
				loop
				w=r
				enemyx.cnt=(r+1)*32
				enemyy.cnt=0
				enemyf.cnt=1
				enemycnt.cnt=0
				n=n+1
				if n=2 { break }
			}
		loop
	}

	; マップ上の位置を2つ進める
	mappnt=mappnt+2

	; 敵を描画
	repeat 10
		if enemyf.cnt=1 {
			ddpos enemyx.cnt,enemyy.cnt
			i=(enemycnt.cnt/4)\4
			if i=0 { x=$80 }
			if (i=1)|(i=3) { x=$A0 }
			if i=2 { x=$C0 }
			ddsetrect x,0,32,32
			ddgcopy 1
		}
	loop

実行画面
実行画面


[プログラム全体と絵をダウンロード]

ひとくちメモ:
・変数名の命名規則
 前に、変数には一時的な用途で使うものと、プログラム全体を通して使う用途のものがあると説明しました。私の場合、明確な用途を持った変数にはそれが分かりやすい名前を、一時的、雑用的な用途のものにはアルファベット1文字、あるいはそれに数字を何文字かくっつけた名前をつけるようにしています。名前をつけるルールを命名規則といいます。このように、自分なりの命名規則を決めておけば、名前をつける時に悩む量が多少は減るかと思います。あまり細かく決めると、かえってわずらわしくなりますが。
 
・なぜ座標を16進数で書いたのか?
 今回、ファイル中の敵のx座標を16進数で書いています。なぜなら、この方が計算しやすいからです。例えば、32×32ドットの矩形を1ブロックとすると、左端を0ブロック目として何ブロック目かを数え、2倍して後ろに0をつけるだけでx座標が算出できます。例えば4ブロック目なら$80です。(32が16進数で$20だからです。)もちろん、y座標についても同様です。10進数で書こうとすると、絵が増えるに従って計算は鬱陶しくなります。暗算が得意な人ならいいですが、アクセサリーから電卓を起動して(あるいは本物の電卓を用意して)いちいち計算するのはちょっと面倒くさいですね。特に、書いてある座標値からどの絵を指しているのか分かろうとすると、10進数より16進数の方が探しやすいです。
  x座標の計算

 

[目次へ][前へ][次へ] inserted by FC2 system