標準スプライト(es_命令)その2 ショットと敵を作り当たり判定をする


2026年 11月 2日
 
 
 今回は HSP Dishの標準スプライト(es_命令)で、前回に引き続きショットと敵を追加し当たり判定をやります。


 ではソースを

#include "hsp3dish.as" ; HSP3Dishランタイムを使用する
#include "hspmath.as" ; round(四捨五入)用

;--- initialize(初期) ----------

rag45=0.7853982	; ラジアンで45度
wx=320 : wy=240 ; 画面大きさ

; 自機
jox=16 : joy=16 ; 自機大きさ
jxa=0.0 : jxb=double(wx-jox) ; 座標範囲x
jya=0.0 : jyb=double(wy-joy) ; 座標範囲y
jx=wx/2-8 : jy=wy/2-8 ; 自機座標
jxf=double(jx) : jyf=double(jy) ; 小数点座標
jsp=2.0 ; 自機スピード
jsp2=jsp*rag45 ; 斜めスピード

; ショット
sna=1 ; スプライトNo.の始め
sb=30 ; 最大数
ssp=10 ; スピード

screen 0,wx,wy

es_ini ,,360; スプライトの初期化
es_area -16,-16,wx+16,wy+16 ; スプライト生存エリア

buffer 2 : picload "test5.png" ; 画像

es_size 16,16,100 ; 大きさx、y、当たり判定大きさ%

; キャラ登録
 es_pat 1,0,0   ; 自機
 es_pat 2,16,0  ; 敵
 es_pat 3,0,16  ; ショット
 es_pat 4,16,16 ; 弾

;スプライト登録(スプNo.、座標x、座標y、キャラNo.)
es_set 0,jx,jy,1 ; 自機


;--- メイン ----------

gsel 0 ; 操作画面をメインスクリーンに戻す

repeat

  stick key,31 ; キー入力
   if key&128 : break ; [ESC]で終了
   repeat 1
    if key&1 and key&2 : jxf-=jsp2 : jyf-=jsp2 : break ; 左上
    if key&2 and key&4 : jxf+=jsp2 : jyf-=jsp2 : break ; 右上
    if key&1 and key&8 : jxf+=jsp2 : jyf+=jsp2 : break ; 左下
    if key&4 and key&8 : jxf+=jsp2 : jyf+=jsp2 : break ; 右下
    if key&2 : jyf-=jsp ; 上
    if key&8 : jyf+=jsp ; 下
    if key&1 : jxf-=jsp ; 左
    if key&4 : jxf+=jsp ; 右
   loop

   jxf=limitf(jxf,jxa,jxb) ; 座標範囲x
   jyf=limitf(jyf,jya,jyb) ; 座標範囲y

   jx=int(round(jxf)) ; 最終座標x
   jy=int(round(jyf)) ; 最終座標y
   
   es_pos 0,jx,jy ; 座標セット

   if key&16 { ; ショット
    es_new spn,sna,sb-1 ; 空いてるスプライトNo.
    if spn!-1 { ; -1は無かった場合
	 es_set spn,jx,jy,3 ; スプラト登録
	 es_adir spn,180,ssp*100 ; 移動方向
	}
   }

;--- 表示 ----------
 redraw 0
  color 1,1,1 : boxf
  es_draw ; スプライト描画

  color 255,255,255 : pos 10,10 : mes "FPS "+fpsn ; FPS表示
  pos 10,50 : mes "key "+key
 redraw 1
 await 1000/60 ; 60FPS

; FPS表示
 tn2=gettime(6) ; 秒取得
 if tn1 not tn2 : tn1=tn2 : fpsn=fps : fps=0 ; リセット
 fps+ ; FPS計測値
loop

end

 

 es_areaはスプライトが生存するエリアで、es_area -16,-16,wx+16,wy+16と書いてるので、この場合スプライトの座標が -16,-16,336,256の外になった場合、そのスプライトを自動で消去してくれます、これは便利。

 if key&16 この場合 SPACEキーを押した時にショットを発生します。

 まず es_new命令でスプライトの空きを探します。

es_new スプライトNo.,検索 No.始め,検索個数
es_new spn,sna,sb-1

 スプライトNo.は空いていた No.が格納されます、この場合は変数 spnです、無かった場合は -1が格納されます。

 検索始めはソースの初期設定で sna=1になってます、検索個数は sbがショットの最大数で、この場合 30に設定してますけど、なぜか検索個数が一個多くなるので sb-1の様に -1します。

 つまり 3と指定すると実際には 4個になります。

 es_adirで移動させます。

es_adir スプライトNo.,移動方向,移動スピード
es_adir spn,180,ssp*100

 移動方向は 0が増下で半時計回り、一周は es_iniで設定した 360なので真上が 180になります、右は 90で左は 270ですね。

 その方向に移動スピード分だけ移動します、スピードは 0~100%の指定なので *100を書きます。
 
 
 
 次は敵を出現させます。

 基本的にはショットと同じです。

; 敵
ena=sna+sb ; スプライトNo.の始め
eb=100 ; 最大数
esp=1 ; スピード
ec=0 ; 出現カウンター
ecn=10 ; 出現間隔

   ec+
  if ec=ecn { ; 敵出現
    ec=0
    es_new spn,ena,eb-1 ; スプNo.
    if spn!-1 {
	 ex=rnd(wx-16) : ey=-16 ; 初期座標
	 es_set spn,ex,ey,2 ; スプ登録
	 es_adir spn,0,esp*100 ; 移動方向
	}
   }

 
 ec出現カウンターにより 10フレームに 1機出現します。

 x座標はランダム、y座標は -16、移動方向は真下なので 0です。


 
 
 
 最後に当たり判定をします。

;--- 当たり判定 ---------
   es_check spn,0,,,ena,ena+eb-1
   if spn!-1 : gamef=1 ; ゲームオーバー

 
 なんとこれだけで当たり判定ができてしまいます。

 es_cheakで判定します。

es_cheak 結果を入れる変数 , チェックするスプNo , type値 , 判定フラグ , 開始No. , 終了No.
es_check spn,0,,,ena,ena+eb-1

 spnに結果(重なってるスプNo.)が代入されます、無かった場合は -1です。

 チェックするスプNo.はこの場合、自機はスプ No.0なので 0です。

 type値は、例えば敵に type値を設定して置くと、その type値だけチェックします、例えば空中物=0で地上物=1に設定するとかです。

 判定フラグはスプライトが回転表示してる時に斜めに正確に判定するそうです、少し重くなるとの事です。

 開始No.は enaで敵スプライトの開始 No.、終了 No.は ena+eb(最大数)-1です。

 終了No.は指定した No.も含むとの事で、出現の時と同じく -1です。


 
 
 
 ショットと敵の当たり判定。

   repeat sb-1 ; ショット
    spn=sna+cnt ; ショットのスプNo.
    es_get f,spn,0 ; 生存フラグ
     if f=0 : continue ; 無い
    es_check epn,spn,,,ena,ena+eb-1
     if epn=-1 : continue ; 無かった
    es_kill spn ; ショット削除
    es_kill epn ; 敵削除
    scr+=10 ; スコア
   loop

 
 ショット一つ々に敵全部の衝突判定を行います。

 まず es_getでショットのスプNo.が生存してるか確認します。

es_get 値格納変数 , 参照スプNo. , 参照項目
es_get f,spn,0

 参照項目 0はフラグで、生存してない場合は 0になります。

 生存確認をしないと、一部のゾンビに衝突します、フラグ以外の数値はそのまま残ってるようです。

 es_check epn,spn,,,ena,ena+eb-1で敵との衝突判定をします。

 epnに衝突した敵のスプ No.が、無かった場合は epnに -1が代入されます。

 es_kill nでスプライトを消去します、nはスプNo.です。
 
 
 ここまでのソース。

#include "hsp3dish.as" ; HSP3Dishランタイムを使用する
#include "hspmath.as" ; round(四捨五入)用

;--- initialize(初期) ----------

rag45=0.7853982	; ラジアンで45度
wx=320 : wy=240 ; 画面大きさ

; 自機
jox=16 : joy=16 ; 自機大きさ
jxa=0.0 : jxb=double(wx-jox) ; 座標範囲x
jya=0.0 : jyb=double(wy-joy) ; 座標範囲y
jx=wx/2-8 : jy=wy/2-8 ; 自機座標
jxf=double(jx) : jyf=double(jy) ; 小数点座標
jsp=2.0 ; 自機スピード
jsp2=jsp*rag45 ; 斜めスピード

; ショット
sna=1 ; スプライトNo.の始め
sb=30 ; 最大数
ssp=10 ; スピード
sc=0 ; カウンター
scn=3 ; 発射間隔

; 敵
ena=sna+sb ; スプライトNo.の始め
eb=100 ; 最大数
esp=1 ; スピード
ec=0 ; 出現カウンター
ecn=10 ; 出現間隔

scr=0 ; スコア

screen 0,wx,wy

es_ini ,,360; スプライトの初期化
es_area -16,-16,wx+16,wy+16 ; スプライト生存エリア

buffer 2 : picload "test5.png" ; 画像

es_size 16,16,100 ; 大きさx、y、当たり判定大きさ%

; キャラ登録
 es_pat 1,0,0   ; 自機
 es_pat 2,16,0  ; 敵
 es_pat 3,0,16  ; ショット
 es_pat 4,16,16 ; 弾

;スプライト登録(スプNo.、座標x、座標y、キャラNo.)
es_set 0,jx,jy,1 ; 自機


;--- メイン ----------

gsel 0 ; 操作画面をメインスクリーンに戻す

repeat

  stick key,31 ; キー入力
   if key&128 : break ; [ESC]で終了
   repeat 1
    if key&1 and key&2 : jxf-=jsp2 : jyf-=jsp2 : break ; 左上
    if key&2 and key&4 : jxf+=jsp2 : jyf-=jsp2 : break ; 右上
    if key&1 and key&8 : jxf+=jsp2 : jyf+=jsp2 : break ; 左下
    if key&4 and key&8 : jxf+=jsp2 : jyf+=jsp2 : break ; 右下
    if key&2 : jyf-=jsp ; 上
    if key&8 : jyf+=jsp ; 下
    if key&1 : jxf-=jsp ; 左
    if key&4 : jxf+=jsp ; 右
   loop

   jxf=limitf(jxf,jxa,jxb) ; 座標範囲x
   jyf=limitf(jyf,jya,jyb) ; 座標範囲y

   jx=int(round(jxf)) ; 最終座標x
   jy=int(round(jyf)) ; 最終座標y
   
   es_pos 0,jx,jy ; 座標セット

   repeat 1 ; ショット
    sc+ : if sc<scn : break ; 発射間隔
    sc=0 ; カウンター
    if key&16 {
     es_new spn,sna,sb-1 ; 空いてるスプライトNo.
      if spn=-1 : break ; -1は無かった場合
	 es_set spn,jx,jy,3 ; スプラト登録
	 es_adir spn,180,ssp*100 ; 移動方向
	}
   loop

; 敵
   ec+
  if ec=ecn { ; 敵出現
    ec=0
    es_new spn,ena,eb-1 ; スプNo.
    if spn!-1 {
	 ex=rnd(wx-16) : ey=0 ; 初期座標
	 es_set spn,ex,ey,2 ; スプ登録
	 es_adir spn,0,esp*100 ; 移動方向
	}
   }

;--- 当たり判定 ---------
   es_check spn,0,,,ena,ena+eb-1
   if spn!-1 : gamef=1 ; ゲームオーバー

   repeat sb-1 ; ショット
    spn=sna+cnt ; ショットのスプNo.
    es_get f,spn,0 ; 生存フラグ
     if f=0 : continue ; 無い
    es_check epn,spn,,,ena,ena+eb-1
     if epn=-1 : continue ; 無かった
    es_kill spn ; ショット削除
    es_kill epn ; 敵削除
    scr+=10 ; スコア
   loop

;--- 表示 ----------
 redraw 0
  color 1,1,1 : boxf
  es_draw ; スプライト描画

  color 255,255,255
  pos 255,220 : mes "FPS "+fpsn ; FPS表示
  pos 10,220 : mes "key "+key
  pos 10,5 : mes "score "+scr ; スコア
  if gamef=1 : pos 140,100 : mes "GAME OVER"
 redraw 1
 await 1000/60 ; 60FPS
 
if gamef=1 : break ; ゲームオーバー

; FPS表示
 tn2=gettime(6) ; 秒取得
 if tn1 not tn2 : tn1=tn2 : fpsn=fps : fps=0 ; リセット
 fps+ ; FPS計測値
loop

stop

 

 この程度では FPS60ですね。


 
 
 ここまでは Linuxでも動きますね。

 細かい事ですけど Linuxでは全角スペースはエラーになりました。
 
 
 今回は以上です、次回は敵弾をやります。
 
 

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です