標準スプライト(es_命令)その3 敵弾を作る

2026年 11月 5日
 
 
 引き続き HSP Dishの標準スプライト(es_命令)で敵弾を作ります。


 ソース

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

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

randomize ; 乱数初期

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 ; 斜めスピード

; ショット
sb=30 ; 最大数
ssp=10 ; スピード
sc=0 ; カウンター
scn=3 ; 発射間隔

; 敵
eb=50 ; 最大数
esp=1 ; スピード
ec=0 ; 出現カウンター
ecn=20 ; 出現間隔

; 敵弾
tb=100 ; 最大数
tsp=2 ; スピード
tcn=200 ; 発生率

; スプライトNo.始め
tna=1 ; 敵弾
sna=tna+tb ; ショット
ena=sna+sb ; 敵

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 ; 移動方向
	}
   }

; 敵弾
   repeat eb-1
    epn=ena+cnt ; 敵のスプNo.
    es_get f,epn,0 ; 生存フラグ
     if f=0 : continue ; 無い
    r=rnd(tcn)
     if r>0 : continue ; 0なら弾発生

    es_new tpn,tna,tb-1 ; スプNo.
     if spn=-1 : break ; 空きが無い
    es_getpos epn,x,y

    es_set tpn,x,y,4 ; スプセット
    es_ang x,y,jx,jy ; 確度取得
     rag=stat ; 発射確度
    r=rnd(11)-5 ; 確度乱数
    es_adir tpn,rag+r,tsp*100
   loop


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

   es_check spn,0,,,tna,tna+tb-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

 
 敵弾の発生は、まず敵の生存フラグを調べて敵ごとに、弾の発生率でランダムに弾を発生させます。

 ランダムだとダマになるので、実際はカウンターで弾の発生間隔を空けた方が良いです。

 弾の初期座標は es_getpos epn,x,yで敵の座標を参照します。

 es_getposは、そのスプNo.の座標を調べる命令です。

 es_ang x,y,jx,jy : rag=statで自機と敵との確度(アングル) ragを求めます。

 これ x,y,jx,jyの並びで、自機(jx,jy)を後ろにしないと変になります、逆方向になるのかな、元が左で向かう先が右かな。

es_ang p1,p2,p3,p4
p1(0)=基準点のX座標
p2(0)=基準点のY座標
p3(0)=目的点のX座標
p4(0)=目的点のY座標

 だから基準点が先ですね、目的点が後です。

 発射確度には乱数で幅を持たせます、この場合は r=rnd(11)-5で -5~5までの確度の揺れです、もう少し大きい揺れ幅でも良いと思います。

 ちなみに 3way弾のようなものは、中心確度(この場合は rag)に -5と +5とかの弾を作るだけです。

 es_adir tpn,rag+r,tsp*100で移動方向とスピードをセットします。
 
 
 当たり判定は、

es_check spn,0,,,tna,tna+tb-1 ; 敵弾
 if spn!-1 : gamef=1 ; ゲームオーバー

 で、敵との当たり判定と同じです。
 
 
 これだと当たり判定が大きいと思うので、

 こんな感じで、当たり判定の大きさを変えると良いと思うんだけど、

es_size 16,16,100 ; 大きさx、y、当たり判定大きさ%
 es_pat 1,0,0 ; 自機
 es_pat 2,16,0 ; 敵
 es_pat 3,0,16 ; ショット

es_size 16,16,30 ; 大きさx、y、当たり判定大きさ%
 es_pat 4,16,16 ; 弾

 そもそも、この当たり判定の座標って左上?それとも中心?

 衝突したら止まるようにしました。

   

 きちんと中心座標なんですね。

50%

表示座標は左上ですね(jx=0,jy=0で表示)

 当たり判定は左上の表示座標から es_sizeで指定した x,yの大きさの矩形(四角)ですね、画像は関係ないようです。

 %による大きさの補正は、ちゃんと中心座標で処理してくれるようです。
 
 
 次回はホーミングミサイルをやってみたいと思います。
 
 

コメントを残す

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