解剖記のスクリプトを改造しよう

実はここまでの所さえ理解できていれば、DirectX対応に改造することは可能です。ただし、もちろんスプライトの機能は使えません^^;

というわけで「解剖記」のサンプルスクリプトを改造しちゃいましょう。当然スプライトの機能は使いません。否、まだ使えないでしょって^^;

サンプルスクリプトv2.1のダウンロード

; シューティングゲームサンプルv2.1
; by たかのん
; HSP v2.5 で作成されています
; 敵と自機の距離によって画面に倍数が表示されます。
; この倍数は、距離が近いほど大きくなります。

; v1.1との違い
; 画面描写をDirectXに対応
; ただし、スプライトの機能は使ってません
; ジョイスティックに対応


;■ DirectX 初期化&チェック
	#include "hspdxfix.as"
	#include "hspjsis.as"

	es_ini : es_screen 640,480,8,0
	if stat=1 : goto *dxerr1
	if stat=2 : goto *dxerr2
goto *gamesetting

*dxerr1
	dialog "DirectXの初期化に失敗しました。",1    : end
*dxerr2
	dialog "スクリーンの初期化に失敗しました。",1 : end
*dxerr3
	es_bye : wait 100
	dialog "VRAMの容量が不足しています。",1       : end

*gamesetting
	cls 4
	highscore=5000
	randomize
	move=5			;自機の移動速度を指定
	smax=50 		;星の最大数
	emax=50			;敵の最大数
	tmax=200		;敵弾最大数
	wmax=3			;自機弾最大数
	imax=10			;倍数表示最大数
	vmax=10			;情報表示最大数
	bmax=10			;爆風最大数
	cmax=50			;カスリ効果最大数
	level=1			;難易度


;■ バッファへ画像の読みこみ
	buffer 2,640,480,1
	pos 0,0
	picload "sample2.bmp",1
	es_buffer 0,0
	if stat=1 : goto *dxerr3		;オフスクリーンバッファへの転送と成否判定


;■ 効果音とBGMの読みこみ
	sndload "Int01.mid",0,1
	sndload "dmg.wav",1,0
	sndload "exp.wav",2,0
	sndload "shot.wav",3,0
	sndload "kin.wav",4,0
	snd 0


;■ 配列定義
*gamestart
	dim sx,smax		;星のx軸座標
	dim sy,smax		;星のy軸座標
	dim sc,smax		;星の色
	dim ss,smax		;星の移動速度

	dim ex,emax		;敵x軸座標
	dim ey,emax		;敵y軸座標
	dim ef,emax		;敵固さ・生死
	dim en,emax		;敵種類
	dim exv,emax		;敵x方向運動量
	dim eyv,emax		;敵y方向運動量
	dim et,emax		;敵出現からの時間

	dim tx,tmax		;敵弾x軸座標
	dim ty,tmax		;敵弾y軸座標
	dim tf,tmax		;敵弾on/off
	dim txv,tmax		;敵弾x方向運動量
	dim tyv,tmax		;敵弾y方向運動量

	dim wx,wmax		;自機弾のx軸座標
	dim wy,wmax		;自機弾のy軸座標
	dim wf,wmax		;自機弾のOn/Off
	dim wyv,wmax		;自機弾のy軸移動距離

	dim ix,imax		;倍数x軸座標
	dim iy,imax		;倍数y軸座標
	dim iff,imax		;倍数表示時間
	dim iv,imax		;倍数フォントサイズ
	dim in,imax		;元得点

	dim bx,bmax		;爆風x軸座標
	dim by,bmax		;爆風y軸座標
	dim bf,bmax		;爆風表示時間

	dim cx,cmax		;カスリ効果x軸座標
	dim cy,cmax		;カスリ効果y軸座標
	dim cxv,cmax		;カスリ効果x方向移動距離
	dim cyv,cmax		;カスリ効果y方向移動距離
	dim cf,cmax		;カスリ効果表示時間

;■ 星の準備
	repeat smax
		rnd sx.cnt,640
		rnd sy.cnt,480
		rnd sc.cnt,10
		ss.cnt=10-sc.cnt
		sc.cnt=sc.cnt*5
	loop

;■ 平方根の準備
	dim calc,900
	repeat 900
		temp=cnt : calc.cnt=temp*temp
	loop

;■ スタート前準備
	mx=295 : my=400		;自機の初期位置を指定
	mf=8			;自機の初期シールドを指定
	gameovertime=0
	score=0
	frame=0
	highdst=0
	gsel 0
	es_cls
	es_sync
	wait 100

;■ メインルーチン
*main
	es_cls bgcolor,0,0 : bgcolor=0
	gosub *message					;ゲーム情報
	gosub *haikei					;星の描写
	gosub *jikimove					;自機移動
	gosub *weapon					;自機弾
	if frame\(25-level)=0 : gosub *enemyborn	;敵生成
	gosub *enemymove				;敵移動
	gosub *tekitamamove				;敵弾移動
	if pat&128>0 : gosub *pausegame			;ポーズ
	getkey returntop,123 : if returntop=1 : end 	;強制終了(F12)
	if mf<1 : mxv=0 : myv=0 : gameovertime++ : gosub *bomb
	if gameovertime>100 : goto *gameover
	await 0
	es_sync 30
	frame++
	level=frame/500+1
	if level>20 : level=20
goto *main


;■ 自機移動
*jikimove
	if mf>0 : stick pat,79 : jstick 79
	if stat!0 : pat=stat		;ジョイスティック入力判定
	shottime--
	if mf>0 : if (pat&64>0)&(shottime<0) : shot=1
	xv=(pat>>2&1)-(pat&1)
	yv=(pat>>3&1)-(pat>>1&1)
	if mf>0 : mx=xv*move+mx : my=yv*move+my
	if mx<0		: mx=0
	if mx>590	: mx=590
	if my<0		: my=0
	if my>430	: my=430
	pos mx,my : gmode 1,50,50 : es_copy 0,xv*50+50,0
return


;■ 背景描写
*haikei
	repeat smax
		sy.cnt=sy.cnt+ss.cnt
		if sy.cnt>480 : sy.cnt=0 : rnd sx.cnt,640
		pos sx.cnt,sy.cnt : gmode 1,5,5 : es_copy 0,400,sc.cnt
	loop
return


;■ 自機弾発射
*weapon
	repeat wmax
		if (shot=1)&(wf.cnt<1) {
			wf.cnt=1
			wx.cnt=mx+12
			wy.cnt=my
			shot=0
			shottime=1
	;		snd 3	;効果音がうるさいので切ってあります^^;
			}
		if wf.cnt<1 : continue
		wy.cnt=wy.cnt-40
		if wy.cnt<-50 : wf.cnt=0
		pos wx.cnt,wy.cnt : gmode 1,25,50 : es_copy 0,150,0
	loop
return


;■ 敵生成
*enemyborn
	rnd temp,7
	if temp=0 : return
	repeat emax
		if ef.cnt>0 : continue
		if temp=1 : en.cnt=1
		if temp=2 : en.cnt=1
		if temp=3 : en.cnt=1
		if temp=4 : en.cnt=2
		if temp=5 : en.cnt=2
		if temp=6 : en.cnt=3
		ef.cnt=en.cnt		; 固さ
		rnd ex.cnt,640		; 初期出現位置x軸
		ey.cnt=-50		; 初期出現位置y軸
		exv.cnt=0		; 初期移動量x軸
		eyv.cnt=10		; 初期移動量y軸
		et.cnt=0
		break
	loop
return


;■ 敵移動
*enemymove
	repeat emax
		et.cnt++
		if ef.cnt<1 : continue
		if en.cnt=1 : gosub *enemy1
		if en.cnt=2 : gosub *enemy2
		if en.cnt=3 : gosub *enemy3
		if ef.cnt<1 : continue
		ent=cnt
		repeat wmax
			if wf.cnt<1 : continue
			ddx=(ex.ent+25)-(wx.cnt+12) : if ddx<0 : ddx=-ddx
			ddy=(ey.ent+25)-(wy.cnt+25) : if ddy<0 : ddy=-ddy
			if (ddx<20)&(ddy<40) {
				ef.ent-- : wf.cnt=0
				if ef.ent>0 {
					pos wx.cnt,wy.cnt
					gmode 1,25,25 : es_copy 0,175,25
					snd 4
					score++
				}
				else {
					pos ex.ent,ey.ent
					gmode 1,50,50 : es_copy 0,200,0
					snd 2
					gosub *messageborn
				}
			}
		loop
	loop
return

;■ 敵1
*enemy1
	dx=mx-ex.cnt
	dy=my-ey.cnt
	if dy<350 {
		if dx<0 {
			exv.cnt=exv.cnt-1
			if exv.cnt<-25 : exv.cnt=-25
		}
		else {
			exv.cnt=exv.cnt+1
			if exv.cnt>25 : exv.cnt=25
		}
	}
	if dx<0 : dx=-dx
	if dx<50 : gosub *tamaborn
	eyv.cnt=4
	ex.cnt=ex.cnt+exv.cnt
	ey.cnt=ey.cnt+eyv.cnt
	if ex.cnt<-50 : ef.cnt=0
	if ex.cnt>640 : ef.cnt=0
	if ey.cnt<-50 : ef.cnt=0
	if ey.cnt>480 : ef.cnt=0
	pos ex.cnt,ey.cnt : gmode 1,50,50 : es_copy 0,250,0
return


;■ 敵2
*enemy2
	dx=mx-ex.cnt
	if et.cnt<2 {
		if dx<0 {
			exv.cnt=-6
		}
		else {
			exv.cnt=6
		}
	}
	if et.cnt>25 : eyv.cnt-- : if eyv.cnt<-10 : eyv.cnt=-10
	if ey.cnt>200 : gosub *tamaborn
	ex.cnt=ex.cnt+exv.cnt
	ey.cnt=ey.cnt+eyv.cnt
	if ex.cnt<-50 : ef.cnt=0
	if ex.cnt>640 : ef.cnt=0
	if ey.cnt<-50 : ef.cnt=0
	if ey.cnt>480 : ef.cnt=0
	pos ex.cnt,ey.cnt : gmode 1,50,50 : es_copy 0,300,0
return


■ 敵3
*enemy3
	dx=mx-ex.cnt
	if et.cnt<2 {
		if dx<0 {
			exv.cnt=-3
		}
		else {
			exv.cnt=3
		}
	}
	if ey.cnt>200 : eyv.cnt--
	if et.cnt>20 : if ey.cnt<50 : eyv.cnt++
	if ey.cnt>200 : gosub *tamaborn
	if et.cnt>20 : if ey.cnt<50 : gosub *tamaborn
	ex.cnt=ex.cnt+exv.cnt
	ey.cnt=ey.cnt+eyv.cnt
	if ex.cnt<-50 : ef.cnt=0
	if ex.cnt>640 : ef.cnt=0
	if ey.cnt<-50 : ef.cnt=0
	if ey.cnt>480 : ef.cnt=0
	pos ex.cnt,ey.cnt : gmode 1,50,50 : es_copy 0,350,0
return


;■ 弾生成
*tamaborn
	if frame\(8-(level/4))>0 : return
	dx=mx-ex.cnt : px=dx : if dx<0 : dx=0-dx
	dy=my-ey.cnt : py=dy : if dy<0 : dy=0-dy
	dst=(dx*dx)+(dy*dy)
	edx=ex.cnt+12 : edy=ey.cnt+12
	repeat 900
		if dst<calc.cnt : dst=cnt : break
	loop
	repeat tmax
		if tf.cnt>0 : continue
		tf.cnt=1
		tx.cnt=edx : ty.cnt=edy
		rnd ds,8 : ds=level/5+3+ds
		txv.cnt=px*ds/dst
		tyv.cnt=py*ds/dst
		break
	loop
return


;■ 敵弾移動 & 当り判定
*tekitamamove
	repeat tmax
		if tf.cnt<1 : continue
		tx.cnt=tx.cnt+txv.cnt
		ty.cnt=ty.cnt+tyv.cnt
		if tx.cnt>640 : tf.cnt=0 : continue
		if tx.cnt<-25 : tf.cnt=0 : continue
		if ty.cnt>480 : tf.cnt=0 : continue
		if ty.cnt<-25 : tf.cnt=0 : continue
		dx=(mx+25)-(tx.cnt+12) : if dx<0 : dx=-dx
		dy=(my+25)-(ty.cnt+12) : if dy<0 : dy=-dy
		if (dx<5)&(dy<5) {
			repeat tmax : tf.cnt-- : loop
			pos tx.cnt,ty.cnt
			gmode 1,25,25 : es_copy 0,175,25
			bgcolor=128
			snd 1
			mf--
		}
		if (dx<30)&(dy<30) {
			score++
			ent=cnt
			repeat cmax
				if cf.cnt>0 : continue
				cx.cnt=tx.ent+10
				cy.cnt=ty.ent+10
				rnd cxv.cnt,3 : cxv.cnt-1
				rnd cyv.cnt,3 : cyv.cnt-1
				cf.cnt=10
				break
			loop
		}
		pos tx.cnt,ty.cnt : gmode 1,25,25 : es_copy 0,175,0
	loop
return


;■ 倍率表示
*messageborn
	dmy=my-ey.ent : if dmy<0 : dmy=-dmy
	dstv=480-dmy/50
	if highdst<dstv : highdst=dstv
	dstlevel=level
	dstcore=dstv*dstlevel
	score=en.ent*100*dstcore+score
	repeat imax
		if iff.cnt>0 : continue
		ix.cnt=ex.ent
		iy.cnt=ey.ent
		iv.cnt=dstv
		iff.cnt=40
		in.cnt=en.ent*100
		il.cnt=dstlevel
		break
	loop
return

;■ ゲーム情報
*message
	repeat cmax
		if cf.cnt<1 : continue
		cx.cnt=cx.cnt+cxv.cnt
		cy.cnt=cy.cnt+cyv.cnt
		gmode 1,5,5
		cw=10-cf.cnt*5
		pos cx.cnt,cy.cnt
		es_copy 0,405,cw
		cf.cnt--
	loop
	repeat imax
		if iff.cnt<1 : continue
		rnd icr,8 : icr=icr*32+31
		rnd icg,8 : icg=icg*32+31
		rnd icb,8 : icb=icb*32+31
		color icr,icg,icb
		font "Impact",iv.cnt*5+12
		pos ix.cnt,iy.cnt
		es_fmes ""+in.cnt+" x "+iv.cnt
		iy.cnt++
		iff.cnt--
	loop

	font "MSゴシック",12,3
	if highscore<score : highscore=score
	color 0,255,255
	pos 10,10 : es_fmes "HIGHSCORE "+highscore

	color 255,255,255
	pos 10,30 : es_fmes "SCORE "+score

	color 0,255,0
	pos 10,50
	es_fmes "HIGH DISTANCE "+highdst

	color 255,255,0
	pos 10,70
	es_fmes "LEVEL "+level

	color 255,255,255
	pos 10,460
	es_fmes "SHIELD "
	if mf<1 : return
	repeat mf
		color 255,cnt*32,0
		pos cnt*10+60,460
		es_fmes "■"
	loop
return


;■ 自機爆風
*bomb
	repeat bmax
		bf.cnt--
		if bf.cnt<1 {
			rnd bf.cnt,10 : bf.cnt=bf.cnt+10
			rnd bx.cnt,50 : bx.cnt=25-bx.cnt+mx
			rnd by.cnt,50 : by.cnt=25-by.cnt+my
		}
		pos bx.cnt,by.cnt
		gmode 1,50,50 : es_copy 0,200,0
		rnd dbx,10 : dbx=dbx-5
		bx.cnt=bx.cnt+dbx
		by.cnt=by.cnt+10
	loop
	rnd effect,10
	if effect=0 : snd 1 : bgcolor=128
	if effect=1 : snd 2 : bgcolor=255
return


;■ ポーズ処理
*pausegame
	es_cls
	gosub *message					;ゲーム情報
	font "MSゴシック",40,3
	rnd icr,8 : icr=icr*32+31
	rnd icg,8 : icg=icg*32+31
	rnd icb,8 : icb=icb*32+31
	color icr,icg,icb
	pos 250,200 : es_fmes "PAUSE"
	stick pat : stick pat,79 : jstick 79 : if stat!0 : pat=stat
	if pat&128>0 : return
	getkey returntop,123 : if returntop=1 : end ; 強制終了(F12)
	es_sync 30
	await 0
goto *pausegame


;■ ゲームオーバー
*gameover
	es_cls
	gosub *message					;ゲーム情報
	font "MSゴシック",40,3
	rnd icr,8 : icr=icr*32+31
	rnd icg,8 : icg=icg*32+31
	rnd icb,8 : icb=icb*32+31
	color icr,icg,icb
	pos 200,200 : es_fmes "GAME OVER"
	pos 30,250 : es_fmes "PUSH RETURN TO RESTART"
	stick pat : stick pat,79 : jstick 79 : if stat!0 : pat=stat
	if pat&32>0 : goto *gamestart
	getkey returntop,123 : if returntop=1 : end ; 強制終了(F12)
	es_sync 30
	await 0
goto *gameover

hspdxfix.dll対応にする際に変更を加えた箇所はこの色になってます。大きく異なるのは基本設定の部分と、ポーズ&ゲームオーバーの処理です。その瞬間の画面のまま静止させるのが面倒だったので、ポーズ&ゲームオーバーのルーチンはその部分だけでループさせてます。画面上には文字しか表示されないです。もしやるとしたら、敵や自機などの表示だけをさせるルーチンを用意しましょう。試しに作ってみましたがやっぱり面倒でしたes_getbufを使って画面全部をbufferに保存して表示する・・・というやり方も試してみたんですが、こちらはうまくいかなかったです^^;

後はmes命令が全部es_fmesに変わってます。この命令は単純に置き換えできるので、エディタの置換機能で一気に変更しちゃいましょう。gcopyの部分も単純置換できるかな?

後は、カスリ効果を視認できるようにしたのと倍率表示を派手にしたのが変更点。もちろん改造元のスクリプトでやらかしてた部分(無駄な計算や、動かす前に表示しちゃってた事)も直してます^^;

前へ戻る 改造記メニューへ戻る 次へ進む