HSP Dishでのグラフィック表示について考えてみる その1 標準スプライト機能(es_命令)について


2026年 10月 22日
 
 
 シューティングを作るので、次は HSP Dishでのグラフィック表示の方法について考えてみる。

 シューティングゲームだと高速に表示するのが命題になる、60FPS(1秒間に60回表示)がスタンダートらしいけど、そんな技術は無いので、できれば 30FPS、最低限 20FPSは欲しい。

 合わせて、シューティングはキャラや弾を大量に表示する必要があるので、高速に表示する方法が必要になってくる。

 トランスミッター(STG)を作った時は HSPDX(hspdxfix.as)と言うのを使っていて、これはダイレクトXで表示するものだと思ったけど es_setとか es_drawとかで表示していた。

 特に当たり判定(衝突判定)が楽で es_check命令とかで簡単に処理できた。

 今回説明書を読みなおしたら、なんと HSP Dishでは標準スプライトと言うものがあって、これは「HSPDXプラグインの 命令をもとに、手軽で扱いやすい 2D専用のスプライトとして用意された標準スプライト」との事で一連の es_命令が標準で使えるようです。


 標準スプライトは HSP Dishを使うための #include "hsp3dish.as"を書けば使えるとの事です(または HGIMG4)、つまり何もしなくても HSPDXと同じ es_命令が使えるようになってるようです。

 ああ、説明書によると、この機能は Linuxでも使えるとの事です、これは期待できますね。

 説明書には「スプライト」の説明も書かれてますね。

 なつかしい、MSXにもスプライトの機能があって、スプライトと言うのは妖精の一種でフェアリーとかアールブとかピクシーと一緒の意味です、画面内を妖精が飛ぶように表示できるので、そのような名前だったと記憶してます。
 
 
 
 それでは使ってみます。

画像を用意して

プログラムを書いて

#include "hsp3dish.as"	; HSP3Dishランタイムを使用する

wx=320 : wy=240 ; 画面大きさ
jx=wx/2-8 : jy=wy/2-8 ; 自機座標

screen 0,wx,wy

es_ini ; スプライトの初期化

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 ; 操作画面をメインスクリーンに戻す
redraw 0
 color 1,1,1 : boxf
 es_draw ; スプライト描画
redraw 1
stop

 
実行画面

 
 
 まず #include "hsp3dish.as"を書いて HSP Dishを使います。

 これ(es_命令)は HSPDishでは無くて HGIMG4定義でも使えるとの事です。

 screenでウインドウ定義をします(es_screenでは無い)、この後に es_ini命令を置かないと機能しませんでした、つまり es_iniの後に screen命令を置くと es_命令を使えません。

es_ini p1,p2,p3,p4 ; システムの初期化
 p1=スプライトの最大数
 p2=キャラクタ定義の最大数
 p3=周の精度
 p4=マップ定義の最大数

 p1スプライトの最大数は省略で 512個、p2キャラクタ定義の最大数は省略で 1024個、弾幕系とか余程の STGを作るのでも無ければ初期値(省略)で OKです。

 画像を元にキャラクターを定義して、そのキャラクターを元にスプライトをいくつも登録して動かす形になります。

 例えば「弾」と言うキャラクターを定義して、それを元に複数の弾をスプライトに登録して動かします。


 
 
 p3周の精度は円 360°を何分割かですけど、初期値(省略)で 60分割です、つまり 1値 6°になりますけど、STGで実用的だと 1週 360分割くらいにした方が良いです。

 例えば敵の弾を 360の方向に移動させる事ができるとかです、60だと方向的(角度的)に少ない、と言うような事になります。

 es_ini ,,360のような感じです。

 redrawの間に es_draw命令を書く事で es_命令の表示を全て行います。
 
 
 
 次は自機の移動をやってみます。

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

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

screen 0,wx,wy

es_ini ; スプライトの初期化

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
 redraw 0

  stick key,15 ; キー入力
   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 ; 座標セット

  color 1,1,1 : boxf
  es_draw ; スプライト描画

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

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

end

 
 rag45=0.7853982と言うのは、ラジアンが円一周で 3.14なのでその 4分の 1です、要するに 45°ですね。

 自機が上下左右に 1移動すると、斜めはこの 0.7853982移動すると言う事です。

 なぜラジアン(3.14)の 4分の 1が斜め移動の座標値の比率と同じなのかは忘れました。

 要するに 1,1移動で斜め移動すると上下左右より早く動いてしまいます。

 と言う訳で、自機の座標は小数点で持ちます。

 limitfで自機の座標が画面外になるのを止めます。

 jxf=limitf(jxf,jxa,jxb)、jxaが 0で、jxbは wx(画面大きさ)-jox(自機大きさ)で、この場合は 304です、その範囲外の値の場合には、その値(0、304)にリセットされます。

 es_pos命令で自機の座標をセットします、この時 round命令で四捨五入して整数にします。

 FPS(1秒間に表示した回数)を計測してみました、流石にこの段階では 60FPSですね。


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


 
 
 記事が長くなると思うので、今回はここまで。

 次回からは、ショット、敵、敵弾の順でやってみます。
 
 

コメントを残す

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