現在地:オレ様のWP > HSP > 実例講座 > シューティングゲームを作る
オレ様のWP

3.シューティングゲームを作る

HSPでシューティングゲームを作ってみましょう

◆どう作るか

今回も例によって、どう作るかを考えてから作成しましょう。

今回は、
  1. stick命令でキー入力を取得し、自機を移動
  2. 配列変数を使いまくり、弾を発射
  3. 敵も配列変数を使いまくる
  4. 敵の弾も配列変数w スピード・方向は乱数で決定
  5. 当たり判定をつける
  6. あとは、適当にアレンジ
のようにします。

◆作成

どう作るかを考えたので、早速作成に取り掛かりましょう。
今回は相当根気が要ります。今までとくらべものにならない程度にw

ちなみに今回使用する画像は
使用画像
です。
※画像の素材はこちらのものを使わせていただきました。

◇stick命令でキー入力を取得し、自機を移動

まずは1の「stick命令でキー入力を取得し、自機を移動」です。まぁ比較的簡単です。
buffer 1
picload "pic.bmp"
screen 0,300,500
title "ShotGame"

*start
mx=133 : my=452
repeat 8
sx(cnt)=1000 : sy(cnt)=1000
loop

repeat
redraw 0

color 0,0,0 : boxf

stick key,31
gosub *me

redraw 1
await 10
loop

*me
if key&1 : mx=mx-6 : if mx<=0 : mx=0
if key&2 : my=my-6 : if my<=0 : my=0
if key&4 : mx=mx+6 : if mx>=265 : mx=265
if key&8 : my=my+6 : if my>=452 : my=452
pos mx,my
gmode 2
gcopy 1,0,0,35,48
return
メインルーチンでstick命令を使ってキー入力情報を読み込んでいます。そしてキー入力情報によって、自機の座標を変え、ウィンドウID1のバッファから画像を読み出しています。
また、「if mx<=0 : mx=0」のような部分で、画面からはみでないようにする処理をしています。

◇配列変数を使いまくり、弾を発射

次に2の「配列変数を使いまくり、弾を発射 」です。
buffer 1
picload "pic.bmp"
screen 0,300,500
title "ShotGame"

*start
dim sx,8 : dim sy,8 : dim st,8

mx=133 : my=452 : tk=1
repeat 8
sx(cnt)=1000 : sy(cnt)=1000
loop
tks(6)=1 : tks(7)=1

repeat
redraw 0

color 0,0,0 : boxf

stick key,31
gosub *me

repeat 8
c=cnt
gosub *shot
loop

redraw 1
await 10
loop

*me
if key&1 : mx=mx-6 : if mx<=0 : mx=0
if key&2 : my=my-6 : if my<=0 : my=0
if key&4 : mx=mx+6 : if mx>=265 : mx=265
if key&8 : my=my+6 : if my>=452 : my=452
pos mx,my
gmode 2
gcopy 1,0,0,35,48
return

*shot
if st(c)=0 and ss=0 {
	if key&16 {
		sx(c)=mx+11 : sy(c)=my
		st(c)=1 : key=0
		ss=40
	}
}
else {
	sy(c)=sy(c)-10
	if sy(c)<0 : st(c)=0
}

if st(c)=1 {
	color 0,0,0
	pos sx(c),sy(c)
	gmode 2
	gcopy 1,35,0,12,12
}
ss=ss-1
if ss<0 : ss=0
return
shotルーチンが加わりました。このルーチンでは、配列変数stに弾が表示されているかいないかの状態を代入し、それによってスペースキーが押されている時に弾を発射するかしないかを決めています。
ss=40というのは、弾発射までの装填時間と思っていいでしょう。この時間がないと、弾が一気に発射されてしまいます。

◇敵も配列変数を使いまくる

敵の表示にも、配列変数を使いまくります。
buffer 1
picload "pic.bmp"
screen 0,300,500
title "ShotGame"

*start
dim sx,8 : dim sy,8 : dim st,8
dim tx,8 : dim ty,8 : dim tks,8

mx=133 : my=452 : tk=1
repeat 8
sx(cnt)=1000 : sy(cnt)=1000
loop
tks(6)=1 : tks(7)=1

repeat
redraw 0

color 0,0,0 : boxf

stick key,31
gosub *me

repeat 8
c=cnt
gosub *shot
gosub *teki
loop

redraw 1
await 10
loop

*me
if key&1 : mx=mx-6 : if mx<=0 : mx=0
if key&2 : my=my-6 : if my<=0 : my=0
if key&4 : mx=mx+6 : if mx>=265 : mx=265
if key&8 : my=my+6 : if my>=452 : my=452
pos mx,my
gmode 2
gcopy 1,0,0,35,48
return

*shot
if st(c)=0 and ss=0 {
	if key&16 {
		sx(c)=mx+11 : sy(c)=my
		st(c)=1 : key=0
		ss=40
	}
}
else {
	sy(c)=sy(c)-10
	if sy(c)<0 : st(c)=0
}

if st(c)=1 {
	color 0,0,0
	pos sx(c),sy(c)
	gmode 2
	gcopy 1,35,0,12,12
}
ss=ss-1
if ss<0 : ss=0
return

*teki
if tk=1 {

	if tkt=0 {
		repeat 6
			tx(cnt)=cnt*50
		loop
		repeat 6
			ty(cnt)=cnt*40-240
		loop
		tkt=1
	}

	if tks(c)=0 {
		ty(c)=ty(c)+3
		if ty(c)>500 : tks(c)=1
		pos tx(c),ty(c)
		gmode 2
		gcopy 1,47,0,51,48
	}
	if tks(c)=1 {
		ty(c)=500
	}

	repeat 8
		tkm=tkm+tks(cnt)
	loop
	if tkm=8 {
		tkm=0
		tkt=0
		tk=2
		repeat 8
			tks(cnt)=0
		loop
	} else { 
		tkm=0
	}

}


if tk=2 {

	if tkt=0 {
		repeat 6
			tx(cnt)=cnt*50
		loop
		repeat 3
			ty(cnt)=cnt*40
		loop
		repeat 3,3
			ty(cnt)=200-(cnt*40)
		loop
		tkt=1
	}

	if tks(c)=0 {
		ty(c)=ty(c)+3
		if ty(c)>500 : tks(c)=1
		pos tx(c),ty(c)
		gmode 2
		gcopy 1,98,0,37,48
	}
	if tks(c)=1 {
		ty(c)=500
	}

	repeat 8
		tkm=tkm+tks(cnt)
	loop
	if tkm=8 {
		tkm=0
		tkt=0
		tk=3
	} else { 
		tkm=0
	}

}

if tk=3 {
color 180,180,180 : boxf 50,180,250,320
color 120,120,120 : boxf 65,240,235,275
color 0,0,0 : pos 60,180 : font "",50,2 : mes "CLEAR"
pos 65,240 : font "",30,2 : mes "SCORE:"+scr
pos 65,290 : font "",16 : mes "※エンターキーでもう一度"
redraw 1
repeat
stick key
if key&32 : break
wait 1
loop
goto *start
}

return
このスクリプトを実行すると、零戦がななめの編隊・F15戦闘機がV字形の編隊で出てくるはずです。
新しく加わったのはtekiルーチン。変数tkの状態で敵の種類を決めています。そして、変数tksの状態で個々の敵の表示・非表示を決めています。

◇敵の弾も配列変数w スピード・方向は乱数で決定

敵の弾を表示してみましょう。今回もまた配列変数です。
buffer 1
picload "pic.bmp"
screen 0,300,500
title "ShotGame"

*start
dim sx,8 : dim sy,8 : dim st,8
dim tx,8 : dim ty,8 : dim tks,8
dim tsx,8 : dim tsy,8 : dim tss,8 : dim tdx,8 : dim tdy,8
mx=133 : my=452 : tk=1
repeat 8
sx(cnt)=1000 : sy(cnt)=1000
loop
tks(6)=1 : tks(7)=1

repeat
redraw 0

color 0,0,0 : boxf

stick key,31
gosub *me

gosub *tkshot

repeat 8
c=cnt
gosub *shot
gosub *teki
loop

redraw 1
await 10
loop

*me
if key&1 : mx=mx-6 : if mx<=0 : mx=0
if key&2 : my=my-6 : if my<=0 : my=0
if key&4 : mx=mx+6 : if mx>=265 : mx=265
if key&8 : my=my+6 : if my>=452 : my=452
pos mx,my
gmode 2
gcopy 1,0,0,35,48
return

*shot
if st(c)=0 and ss=0 {
	if key&16 {
		sx(c)=mx+11 : sy(c)=my
		st(c)=1 : key=0
		ss=40
	}
}
else {
	sy(c)=sy(c)-10
	if sy(c)<0 : st(c)=0
}

if st(c)=1 {
	color 0,0,0
	pos sx(c),sy(c)
	gmode 2
	gcopy 1,35,0,12,12
}
ss=ss-1
if ss<0 : ss=0
return

*teki
if tk=1 {

	if tkt=0 {
		repeat 6
			tx(cnt)=cnt*50
		loop
		repeat 6
			ty(cnt)=cnt*40-240
		loop
		tkt=1
	}

	if tks(c)=0 {
		ty(c)=ty(c)+3
		if ty(c)>500 : tks(c)=1
		pos tx(c),ty(c)
		gmode 2
		gcopy 1,47,0,51,48
	}
	if tks(c)=1 {
		ty(c)=500
	}

	repeat 8
		tkm=tkm+tks(cnt)
	loop
	if tkm=8 {
		tkm=0
		tkt=0
		tk=2
		repeat 8
			tks(cnt)=0
		loop
	} else { 
		tkm=0
	}

}


if tk=2 {

	if tkt=0 {
		repeat 6
			tx(cnt)=cnt*50
		loop
		repeat 3
			ty(cnt)=cnt*40
		loop
		repeat 3,3
			ty(cnt)=200-(cnt*40)
		loop
		tkt=1
	}

	if tks(c)=0 {
		ty(c)=ty(c)+3
		if ty(c)>500 : tks(c)=1
		pos tx(c),ty(c)
		gmode 2
		gcopy 1,98,0,37,48
	}
	if tks(c)=1 {
		ty(c)=500
	}

	repeat 8
		tkm=tkm+tks(cnt)
	loop
	if tkm=8 {
		tkm=0
		tkt=0
		tk=3
	} else { 
		tkm=0
	}

}

if tk=3 {
color 180,180,180 : boxf 50,180,250,320
color 120,120,120 : boxf 65,240,235,275
color 0,0,0 : pos 60,180 : font "",50,2 : mes "CLEAR"
pos 65,240 : font "",30,2 : mes "SCORE:"+scr
pos 65,290 : font "",16 : mes "※エンターキーでもう一度"
redraw 1
repeat
stick key
if key&32 : break
wait 1
loop
goto *start
}

return

*tkshot
r=rnd(8) : e=rnd(8)
if tss(r)=0 {
	tsx(r)=tx(r)+8 : tsy(r)=ty(r)+16
	tdx(r)=((rnd(4)+7)-2*4) : tdy(r)=(rnd(2)+1)*8
	tss(r)=1
}
repeat 8
c=cnt
if tss(c)=1 {
pos tsx(c),tsy(c) : gcopy 1,35,12,12,12
tsx(c)+=tdx(c) : tsy(c)+=tdy(c)
if (tsx(c)<0)|(tsx(c)>312)|(tsy(c)>512) : tss(c)=0
}
loop
return
tkshotルーチンが加わりました。説明はめんどいのでしません。がんばって解釈してくださいなw

◇当たり判定をつける

弾に当たったら爆発などをして消えないと、ゲームになりません。if文を使った当たり判定を組み込みましょう。
buffer 1
picload "pic.bmp"
screen 0,300,500
title "ShotGame"

*start
dim sx,8 : dim sy,8 : dim st,8
dim tx,8 : dim ty,8 : dim tks,8
dim tsx,8 : dim tsy,8 : dim tss,8 : dim tdx,8 : dim tdy,8
mx=133 : my=452 : tk=1
repeat 8
sx(cnt)=1000 : sy(cnt)=1000
loop
tks(6)=1 : tks(7)=1

repeat
redraw 0

color 0,0,0 : boxf

stick key,31
gosub *me

gosub *tkshot

repeat 8
c=cnt
gosub *shot
gosub *teki
gosub *check
loop

redraw 1
await 10
loop

*me
if key&1 : mx=mx-6 : if mx<=0 : mx=0
if key&2 : my=my-6 : if my<=0 : my=0
if key&4 : mx=mx+6 : if mx>=265 : mx=265
if key&8 : my=my+6 : if my>=452 : my=452
pos mx,my
gmode 2
gcopy 1,0,0,35,48
return

*shot
if st(c)=0 and ss=0 {
	if key&16 {
		sx(c)=mx+11 : sy(c)=my
		st(c)=1 : key=0
		ss=40
	}
}
else {
	sy(c)=sy(c)-10
	if sy(c)<0 : st(c)=0
}

if st(c)=1 {
	color 0,0,0
	pos sx(c),sy(c)
	gmode 2
	gcopy 1,35,0,12,12
}
ss=ss-1
if ss<0 : ss=0
return

*teki
if tk=1 {

	if tkt=0 {
		repeat 6
			tx(cnt)=cnt*50
		loop
		repeat 6
			ty(cnt)=cnt*40-240
		loop
		tkt=1
	}

	if tks(c)=0 {
		ty(c)=ty(c)+3
		if ty(c)>500 : tks(c)=1
		pos tx(c),ty(c)
		gmode 2
		gcopy 1,47,0,51,48
	}
	if tks(c)=1 {
		ty(c)=500
	}

	repeat 8
		tkm=tkm+tks(cnt)
	loop
	if tkm=8 {
		tkm=0
		tkt=0
		tk=2
		repeat 8
			tks(cnt)=0
		loop
	} else { 
		tkm=0
	}

}


if tk=2 {

	if tkt=0 {
		repeat 6
			tx(cnt)=cnt*50
		loop
		repeat 3
			ty(cnt)=cnt*40
		loop
		repeat 3,3
			ty(cnt)=200-(cnt*40)
		loop
		tkt=1
	}

	if tks(c)=0 {
		ty(c)=ty(c)+3
		if ty(c)>500 : tks(c)=1
		pos tx(c),ty(c)
		gmode 2
		gcopy 1,98,0,37,48
	}
	if tks(c)=1 {
		ty(c)=500
	}

	repeat 8
		tkm=tkm+tks(cnt)
	loop
	if tkm=8 {
		tkm=0
		tkt=0
		tk=3
	} else { 
		tkm=0
	}

}

if tk=3 {
color 180,180,180 : boxf 50,180,250,320
color 120,120,120 : boxf 65,240,235,275
color 0,0,0 : pos 60,180 : font "",50,2 : mes "CLEAR"
pos 65,240 : font "",30,2 : mes "SCORE:"+scr
pos 65,290 : font "",16 : mes "※エンターキーでもう一度"
redraw 1
repeat
stick key
if key&32 : break
wait 1
loop
goto *start
}

return

*tkshot
r=rnd(8) : e=rnd(8)
if tss(r)=0 {
	tsx(r)=tx(r)+8 : tsy(r)=ty(r)+16
	tdx(r)=((rnd(4)+7)-2*4) : tdy(r)=(rnd(2)+1)*8
	tss(r)=1
}
repeat 8
c=cnt
if tss(c)=1 {
pos tsx(c),tsy(c) : gcopy 1,35,12,12,12
tsx(c)+=tdx(c) : tsy(c)+=tdy(c)
if (tsx(c)<0)|(tsx(c)>312)|(tsy(c)>512) : tss(c)=0
}
loop
return

*check
if tk=1 {
repeat 8
if (sx(cnt)+12>=tx(c))&(sx(cnt)<=tx(c)+51)&(sy(cnt)+12>=ty(c))&(sy(cnt)<=ty(c)+48) {
	gcopy 1,135,0,36,48
	tks(c)=1
	scr=scr+10
	ty(c)=500
}
loop
}
if tk=2 {
repeat 8
if (sx(cnt)+12>=tx(c))&(sx(cnt)<=tx(c)+37)&(sy(cnt)+12>=ty(c))&(sy(cnt)<=ty(c)+48) {
	gcopy 1,135,0,36,48
	tks(c)=1
	scr=scr+10
	ty(c)=500
}
loop
}


if (mx+35>=tsx(c))&(mx<=tsx(c)+12)&(my+48>=tsy(c))&(my<=tsy(c)+12) {
color 180,180,180 : boxf 50,180,250,320
color 120,120,120 : boxf 65,240,235,275
color 0,0,0 : pos 60,190 : font "",30,2 : mes "GAMEOVER"
pos 65,240 : font "",30,2 : mes "SCORE:"+scr
pos 65,290 : font "",16 : mes "※エンターキーでもう一度"
redraw 1
repeat
stick key
if key&32 : break
wait 1
loop
goto *start
}

return

◆完成スクリプト

buffer 1
picload "pic.bmp"
screen 0,300,500
title "ShotGame"

*start
dim sx,8 : dim sy,8 : dim st,8
dim tx,8 : dim ty,8 : dim tks,8
dim tsx,8 : dim tsy,8 : dim tss,8 : dim tdx,8 : dim tdy,8
mx=133 : my=452 : tk=1
repeat 8
sx(cnt)=1000 : sy(cnt)=1000
loop
tks(6)=1 : tks(7)=1

repeat
redraw 0

color 0,0,0 : boxf

gosub *icon

stick key,31
gosub *me

gosub *tkshot

repeat 8
c=cnt
gosub *shot
gosub *teki
gosub *check
loop

redraw 1
await 10
loop

*icon
color 200,200,200 : boxf 0,0,120,30
color 0,0,0:pos 0,5:font "",20,1
mes "SCORE:"+scr
return

*me
if key&1 : mx=mx-6 : if mx<=0 : mx=0
if key&2 : my=my-6 : if my<=0 : my=0
if key&4 : mx=mx+6 : if mx>=265 : mx=265
if key&8 : my=my+6 : if my>=452 : my=452
pos mx,my
gmode 2
gcopy 1,0,0,35,48
return

*shot
if st(c)=0 and ss=0 {
	if key&16 {
		sx(c)=mx+11 : sy(c)=my
		st(c)=1 : key=0
		ss=40
	}
}
else {
	sy(c)=sy(c)-10
	if sy(c)<0 : st(c)=0
}

if st(c)=1 {
	color 0,0,0
	pos sx(c),sy(c)
	gmode 2
	gcopy 1,35,0,12,12
}
ss=ss-1
if ss<0 : ss=0
return

*teki
if tk=1 {

	if tkt=0 {
		repeat 6
			tx(cnt)=cnt*50
		loop
		repeat 6
			ty(cnt)=cnt*40-240
		loop
		tkt=1
	}

	if tks(c)=0 {
		ty(c)=ty(c)+3
		if ty(c)>500 : tks(c)=1
		pos tx(c),ty(c)
		gmode 2
		gcopy 1,47,0,51,48
	}
	if tks(c)=1 {
		ty(c)=500
	}

	repeat 8
		tkm=tkm+tks(cnt)
	loop
	if tkm=8 {
		tkm=0
		tkt=0
		tk=2
		repeat 8
			tks(cnt)=0
		loop
	} else { 
		tkm=0
	}

}


if tk=2 {

	if tkt=0 {
		repeat 6
			tx(cnt)=cnt*50
		loop
		repeat 3
			ty(cnt)=cnt*40
		loop
		repeat 3,3
			ty(cnt)=200-(cnt*40)
		loop
		tkt=1
	}

	if tks(c)=0 {
		ty(c)=ty(c)+3
		if ty(c)>500 : tks(c)=1
		pos tx(c),ty(c)
		gmode 2
		gcopy 1,98,0,37,48
	}
	if tks(c)=1 {
		ty(c)=500
	}

	repeat 8
		tkm=tkm+tks(cnt)
	loop
	if tkm=8 {
		tkm=0
		tkt=0
		tk=3
	} else { 
		tkm=0
	}

}

if tk=3 {
color 180,180,180 : boxf 50,180,250,320
color 120,120,120 : boxf 65,240,235,275
color 0,0,0 : pos 60,180 : font "",50,2 : mes "CLEAR"
pos 65,240 : font "",30,2 : mes "SCORE:"+scr
pos 65,290 : font "",16 : mes "※エンターキーでもう一度"
redraw 1
repeat
stick key
if key&32 : break
wait 1
loop
goto *start
}

return

*tkshot
r=rnd(8) : e=rnd(8)
if tss(r)=0 {
	tsx(r)=tx(r)+8 : tsy(r)=ty(r)+16
	tdx(r)=((rnd(4)+7)-2*4) : tdy(r)=(rnd(2)+1)*8
	tss(r)=1
}
repeat 8
c=cnt
if tss(c)=1 {
pos tsx(c),tsy(c) : gcopy 1,35,12,12,12
tsx(c)+=tdx(c) : tsy(c)+=tdy(c)
if (tsx(c)<0)|(tsx(c)>312)|(tsy(c)>512) : tss(c)=0
}
loop
return

*check
if tk=1 {
repeat 8
if (sx(cnt)+12>=tx(c))&(sx(cnt)<=tx(c)+51)&(sy(cnt)+12>=ty(c))&(sy(cnt)<=ty(c)+48) {
	gcopy 1,135,0,36,48
	tks(c)=1
	scr=scr+10
	ty(c)=500
}
loop
}
if tk=2 {
repeat 8
if (sx(cnt)+12>=tx(c))&(sx(cnt)<=tx(c)+37)&(sy(cnt)+12>=ty(c))&(sy(cnt)<=ty(c)+48) {
	gcopy 1,135,0,36,48
	tks(c)=1
	scr=scr+10
	ty(c)=500
}
loop
}


if (mx+35>=tsx(c))&(mx<=tsx(c)+12)&(my+48>=tsy(c))&(my<=tsy(c)+12) {
color 180,180,180 : boxf 50,180,250,320
color 120,120,120 : boxf 65,240,235,275
color 0,0,0 : pos 60,190 : font "",30,2 : mes "GAMEOVER"
pos 65,240 : font "",30,2 : mes "SCORE:"+scr
pos 65,290 : font "",16 : mes "※エンターキーでもう一度"
redraw 1
repeat
stick key
if key&32 : break
wait 1
loop
goto *start
}
	
return

Java Plugin 1.4.2 or later is not installed.

Powered by HSPLet 3.0
スクリーンショット


iconサブルーチンでスコアを表示するようにしただけですw

◆カウンター

161413

◆愚痴等

※オレ様キーロガーの後継ソフト「ControlCatcher Ver1.0β」を公開しました。