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でも動きます。

記事が長くなると思うので、今回はここまで。
次回からは、ショット、敵、敵弾の順でやってみます。