敵と自機弾の当たり判定(2/2)

 3.敵がダメージを受けている時の処理

 存在フラグが2(ダメージを受けている)であれば、dmgcntを1増やします。dmgcntが3になったら、存在フラグを1(通常)に変更します。
    repeat 10
        if enemyf.cnt=2 {
            dmgcnt.cnt=dmgcnt.cnt+1
            if dmgcnt.cnt=3 { enemyf.cnt=1 }
        }
    loop

 4.敵が爆発中の処理

 存在フラグが3(爆発中)であれば、eplcntを1増やします。eplcntが15になったら、存在フラグを0(消滅)に変更します。
    repeat 10
        if enemyf.cnt=3 {
            eplcnt.cnt=eplcnt.cnt+1
            if eplcnt.cnt=15 { enemyf.cnt=0 }
        }
    loop

 5.敵がダメージを受けている絵を表示する

  ダメージ、爆発
 絵のファイルに、残機数表示用の自機(小さい自機)、爆発、ダメージを受けて真っ白になっている敵を追加しました。
 小さい自機の座標は($60,$10)、サイズは16×16です。
 爆発パターンの座標は($0,$20)、($20,$20)、($40,$20)、サイズは32×32です。
 ダメージを受けているパターンの座標は($60,$20)、($80,$20)、($A0,$20)、サイズは32×32です。

「敵を描画」処理を、ダメージを受けているパターンも表示できるように改造します。存在フラグの値によって、表示する絵を変えます。
    ; 敵を描画
    repeat 10
        if (enemyf.cnt=1)|(enemyf.cnt=2) {
            gdx=enemyx.cnt:gdy=enemyy.cnt
            i=(enemycnt.cnt/4)\4
            if enemyf.cnt=1 {
                if i=0 { gdox=$80 }
                if (i=1)|(i=3) { gdox=$A0 }
                if i=2 { gdox=$C0 }
                gdoy=0
            }
            if enemyf.cnt=2 {
                if i=0 { gdox=$60 }
                if (i=1)|(i=3) { gdox=$80 }
                if i=2 { gdox=$A0 }
                gdoy=$20
            }
            gdw=32:gdh=32
            gosub *Graphic_Draw
        }
    loop

 6.敵の爆発を表示する

 存在フラグが3である敵につき、爆発の絵を表示します。eplcntが0〜4の時は1番目のパターンを、5〜9の時は2番目のパターンを、10〜14の時は3番目のパターンを表示します。
    repeat 10
        if enemyf.cnt=3 {
            gdx=enemyx.cnt:gdy=enemyy.cnt
            if eplcnt.cnt<5 { gdox=0 }
            if (eplcnt.cnt>=5)&(eplcnt.cnt<10) { gdox=$20 }
            if eplcnt.cnt>=10 { gdox=$40 }
            gdoy=$20
            gdw=32:gdh=32
            gosub *Graphic_Draw
        }
    loop

 7.スコア、残機数を表示する

 文字列を出力する処理をサブルーチン化します。出力する座標をmsx,msyに、文字列をmescontに代入してこのサブルーチンを呼ぶものとします。(ms,mesはmessage、contはcontentsの略です。)
*wrtmes
    ; msx,msy : 出力する座標
    ; mescont : メッセージの内容

    ddcolor 255,255,255
    ddpos (640-xsize)/2+msx,(480-ysize)/2+msy
    font "MS 明朝",16
    ddprint mescont
    return
 本サンプルプログラムでは、文字色は白、フォントは大きさ16のMS 明朝で統一することにします。

 点数を表示します。スコアを左上に、ハイスコアを右上の方に表示します。
    msx=0:msy=0
    mescont="SCORE:"+score
    gosub *wrtmes
    msx=160:msy=0
    mescont="HI-SCORE:"+hiscore
    gosub *wrtmes
 "+"演算子を文字列に対して使った場合は、「連結」の意味になります。"+"の左の文字列と右の文字列をつなげて一つにします。上のように、文字列に数値をつなげることもできます。

 自機の残り数を表示します。小さい自機を、残機数の分だけ横に並べて表示します。が、実際の残機数より1つ少なく描くのが一般的です。
 すると、nplayerが1以下の時は、この処理をやる必要はないということになります。
    if nplayer>1 {
        repeat nplayer-1
            gdx=cnt*18 :gdy=36
            gdox=$60 :gdoy=$10
            gdw=16 :gdh=16
            gosub *Graphic_Draw
        loop
    }

 8.その他

 敵が移動するのは、通常状態の時かダメージを受けている時です。そこで、「敵の移動」処理にも修正が必要になります。
    ; 敵の移動
    repeat 10
        if (enemyf.cnt=1)|(enemyf.cnt=2) {
            ・
            ・
            ・
        }
    loop


 以上をまとめますと、敵と自機弾の当たり判定に関する処理は以下のようになります。

	; プログラム起動時の初期設定

	hiscore=50000

	; 敵の変数宣言
	dim enelife,10
	dim dmgcnt,10
	dim eplcnt,10


	; ゲームスタート時の初期設定
	score=0	
	oneup=50000
	nplayer=3


	; メインループ

	; 敵の移動
	repeat 10
		if (enemyf.cnt=1)|(enemyf.cnt=2) {	; 変更した行
			i=enemycnt.cnt\16
			enemyx.cnt=enemyx.cnt+enemvdx.i
			enemyy.cnt=enemyy.cnt+enemvdy.i
			if enemyy.cnt>=ysize { 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,xsize/32-2
					if r!w { break }
				loop
				w=r
				enemyx.cnt=(r+1)*32
				enemyy.cnt=-32
				enemyf.cnt=1
				enemycnt.cnt=0
				enelife.cnt=3	; 追加した行
				n=n+1
				if n=2 { break }
			}
		loop
	}

	; 敵がダメージを受けている時の処理
	repeat 10
		if enemyf.cnt=2 {
			dmgcnt.cnt=dmgcnt.cnt+1
			if dmgcnt.cnt=3 { enemyf.cnt=1 }
		}
	loop

	; 敵が爆発中の処理
	repeat 10
		if enemyf.cnt=3 {
			eplcnt.cnt=eplcnt.cnt+1
			if eplcnt.cnt=15 { enemyf.cnt=0 }
		}
	loop

	; 敵と自機弾の当たり判定
	repeat 4
		if shotf.cnt=1 {		
			x=shotx.cnt:y=shoty.cnt
			f=0
			repeat 10
				if ((enemyf.cnt=1)|(enemyf.cnt=2))&(x<(enemyx.cnt+32))&
					((x+4)>enemyx.cnt)&(y<(enemyy.cnt+32))&
					((y+16)>enemyy.cnt) {
					f=1
					enemyf.cnt=2
					dmgcnt.cnt=0
					enelife.cnt=enelife.cnt-1
					if enelife.cnt=0 {
						enemyf.cnt=3
						eplcnt.cnt=0
						score=score+200
						if score>hiscore { hiscore=score }
						if score>=oneup {
							nplayer=nplayer+1
							oneup=oneup+100000
						}
					}
				}
			loop
			if f=1 { shotf.cnt=0 }
		}
	loop	 

	; 敵を描画
	repeat 10
		if (enemyf.cnt=1)|(enemyf.cnt=2) {
			gdx=enemyx.cnt:gdy=enemyy.cnt
			i=(enemycnt.cnt/4)\4
			if enemyf.cnt=1 {
				if i=0 { gdox=$80 }
				if (i=1)|(i=3) { gdox=$A0 }
				if i=2 { gdox=$C0 }
				gdoy=0
			}
			if enemyf.cnt=2 {
				if i=0 { gdox=$60 }
				if (i=1)|(i=3) { gdox=$80 }
				if i=2 { gdox=$A0 }
				gdoy=$20
			}
			gdw=32:gdh=32
			gosub *Graphic_Draw
		}
	loop

	; 敵の爆発を描画
	repeat 10
		if enemyf.cnt=3 {
			gdx=enemyx.cnt:gdy=enemyy.cnt
			if eplcnt.cnt<5 { gdox=0 }
			if (eplcnt.cnt>=5)&(eplcnt.cnt<10) { gdox=$20 }
			if eplcnt.cnt>=10 { gdox=$40 }
			gdoy=$20
			gdw=32:gdh=32
			gosub *Graphic_Draw
		}
	loop

	; 点数表示
	msx=0:msy=0
	mescont="SCORE:"+score
	gosub *wrtmes
	msx=160:msy=0
	mescont="HI-SCORE:"+hiscore
	gosub *wrtmes

	; 自機残り数表示
	if nplayer>1 {
		repeat nplayer-1
			gdx=cnt*18 :gdy=36
			gdox=$60 :gdoy=$10
			gdw=16 :gdh=16
			gosub *Graphic_Draw
		loop
	}


	; メッセージ出力
*wrtmes
	; msx,msy	: 出力する座標
	; mescont	: メッセージの内容

	ddcolor 255,255,255
	ddpos (640-xsize)/2+msx,(480-ysize)/2+msy
	font "MS 明朝",16
	ddprint mescont
	return
「敵と自機弾の当たり判定」処理より「敵がダメージを受けている時の処理」、「敵が爆発中の処理」を前にしています。逆にすると、dmgcntやeplcntに0を設定しても、すぐさま1になってしまうからです。「敵の出現」より「敵の移動」を前にしたのと同じような理由です。

実行画面
実行画面


[プログラム全体と絵をダウンロード]
※「Push Ctrl Key」と書く処理も、今回作ったサブルーチンを呼ぶように書き換えています。また、ゲームタイトルを文字から画像に変えています。

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