弾の打ち合い



さあここまで来るともっとややこしくなります。ってゆうかおそくなります。
難易度は前回のとさほど変わりませんが、長くなるとすごくごちゃごちゃしてギブアップしてしまうなんて事もあるので、長いスクリプトを書くときにはわかりやすいようにコメントを入れておくといいと思います。
さて、敵に弾を撃たせるのですが、自弾の場合とは違い、自動的に弾を撃たせるというようになります。
毎回毎回弾を発射していたのではとんでもない数の弾が出現してしまうので、一定時間あけて一つずつ発射するというようにします。
これにさらに敵弾の当たり判定もつけて、一通り出来上がります。まだHPとかがないのでどちらも死にませんが、それはまた今度。

	;自機と自弾と敵と敵弾の当たり判定
	randomize	;乱数の初期化

	screen 0,300,400,1	;パレットモードの方がとりあえず早い

	jx=130		;自機の初期位置x
	jy=270		;自機の初期位置y
	jsizex=40	;自機の大きさx
	jsizey=40	;自機の大きさy

	jtm=100		;自弾の最大数
	jtmsizex=10	;自弾の大きさx
	jtmsizey=10	;自弾の大きさy
	dim jtmc,jtm	;自弾の表示フラグ
	dim jtmx,jtm	;自弾の位置x
	dim jtmy,jtm	;自弾の位置y
	jtmno=0		;次の弾のナンバー

	enemy=3		;敵の数
	dim ex,enemy	;敵機の初期位置x
	dim ey,enemy	;敵機の初期位置y
	dim em,enemy	;敵機の横移動量
	esizex=40	;敵機の大きさx
	esizey=40	;敵機の大きさy
	ex=100,20,250	;敵機の初期位置x(適当)
	ey=40,100,160	;敵機の初期位置y(とりあえず重ならないように)
	em=2,1,-1	;敵機の横移動量(自由かな)
;-------------------------------------------------------------------------------
;	a=b,c,dという記述方法はa.0=b:a.1=c:a.2=dという記述と同じ意味になります。
;-------------------------------------------------------------------------------
	dim etmtim,enemy;敵の発射間隔

	etm=100		;敵弾の最大数
	etmsizex=10	;敵弾の大きさx
	etmsizey=10	;敵弾の大きさy
	dim etmc,etm	;敵弾の表示フラグ
	dim etmx,etm	;敵弾の位置x
	dim etmy,etm	;敵弾の位置y
	dim etmmx,etm	;敵弾の移動量x
	dim etmmy,etm	;敵弾の移動量y
	etmno=0		;次の弾のナンバー
	waittime=60	;敵弾のおおよその発射時間の間隔

*mainloop
	redraw 0	;描画ストップ
	color : boxf	;背景塗りつぶし
	stick ky,15,1
	if ky!=0 {
		if ky&1 {
			jx-- : if jx<0 : jx=0		;画面外へ行かないように
		}
		if ky&2 {
			jy-- : if jy<0 : jy=0
		}
		if ky&4 {
			jx++ : if jx>(winx-jsizex) : jx=winx-jsizex
		}
		if ky&8 {
			jy++ : if jy>(winy-jsizey) : jy=winy-jsizey
		}
		if ky&16 {
			jtmc.jtmno=1				;自弾表示ON
			jtmx.jtmno=jsizex-jtmsizex/2+jx		;自機の真ん中
			jtmy.jtmno=jy				;自機の先端
			jtmno++ : if jtmno=jtm : jtmno=0	;次の弾へ
		}
	}
	gosub *jdraw
	gosub *jtmdraw
	gosub *enemydraw
	gosub *etmdraw
	redraw 1	;再描画
	await 1		;ウェイトを入れておかないとキー取得が出来ない。入れないと止まる
	goto *mainloop

*jdraw
	color ,255 : boxf jx,jy,jx+jsizex,jy+jsizey	;■の描画
return

*jtmdraw
	repeat jtm
		if jtmc.cnt=1 {
			jtmy.cnt-2	;上方向へ移動
			if jtmy.cnt<(-jtmsizey) : jtmc.cnt=0	;上端までいったらフラグをオフにする
			color 255 : boxf jtmx.cnt,jtmy.cnt,jtmx.cnt+jtmsizex,jtmy.cnt+jtmsizey	;自弾の描画
		}
	loop
return

*enemydraw
	repeat enemy
		ecnt=cnt		;2重ループのため
		ex.cnt+em.cnt		;横移動のみ
		if ex.cnt+esizex<0 : ex.cnt=winx	;左端でのチェック
		if ex.cnt>winx : ex.cnt=-esizex		;右端でのチェック
		if etmtim.cnt=0 {
			etmc.etmno=1				;敵弾発射フラグON
			etmx.etmno=esizex-etmsizex/2+ex.cnt	;敵機の真ん中
			etmy.etmno=ey.cnt+esizey-etmsizey	;敵機の先端
			rnd etmmx.etmno,5 : etmmx.etmno-2	;横移動-2〜2
			rnd etmmy.etmno,3 : etmmy.etmno++	;縦移動1〜3
			rnd etmtim.cnt,waittime : etmtim.cnt+=waittime/2	;次の弾発射までの間隔
			etmno++ : if etmno=etm : etmno=0
		}
		etmtim.cnt--
		color ,,255
		repeat jtm		;弾に当たっているかのチェック
			if jtmc.cnt=1 {
				if (jtmx.cnt<(ex.ecnt+esizex))&(jtmx.cnt+jtmsizex>ex.ecnt)&(jtmy.cnt<(ey.ecnt+esizey))&(jtmy.cnt+jtmsizey>ey.ecnt) {
					color 255,255,255
					jtmc.cnt=0	;ここにコメントをつけると弾が貫通する
				}
			}
		loop
;---------------------------------------------------------
;	弾に当たっていれば白、あたっていなければ青になる。
;---------------------------------------------------------
		boxf ex.cnt,ey.cnt,ex.cnt+esizex,ey.cnt+esizey
	loop
return

*etmdraw
	repeat etm
		if etmc.cnt=1 {
			etmx.cnt+etmmx.cnt	;横移動
			etmy.cnt+etmmy.cnt	;縦移動
			if (etmx.cnt<(jx+jsizex))&(etmx.cnt+etmsizex>jx)&(etmy.cnt<(jy+jsizey))&(etmy.cnt+etmsizey>jy) {
				color 255,255,255 : boxf	;自機にあたったらフラッシュさせる
				etmc.cnt=0	;ここコメントにするとあたってる間ずっと真っ白になる
			}
			if etmx.cnt<(-etmsizex) : etmc.cnt=0	;左端でチェック
			if etmx.cnt>winx : etmc.cnt=0		;右端でチェック
			if etmy.cnt>winy : etmc.cnt=0		;下の端でチェック
			color 255,255 : boxf etmx.cnt,etmy.cnt,etmx.cnt+etmsizex,etmy.cnt+etmsizey	;敵弾の表示
		}
	loop
return

敵の弾の発射はenemydrawルーチンで行っています。これまでのを全て理解しているなら、今回のはそれほど難しく感じないはずです。
追加されたetmdrawルーチンは敵の弾の描画と自機に当たったときの当たり判定を行っています。
この自機スピードじゃ全然敵の弾避けられませんよね。
これで一通りのシューティングに必要な部分は出来ました。しかしこのやり方ではまだ高速化できると思います。
弾の当たり判定なんか無理矢理だし、スクリプト見づらいし、直すところもまだまだあります。とりあえずこれは練習用ということで、各自で応用させてください。
次回でHPもつけます。これは簡単です。


前へ 戻る 次へ