初めは、プログラミングガイドを読んでいたが、PCの画面で読んでもイマイチ頭に入ってこない。なので、サンプルシューティングゲーム「マジカル タマホーキ」のソースをプリントアウトして、何の処理をしているかメモを取りながら勉強した。
年齢的なものもあるが、この方法が一番しっくりくる。今の子供は紙の教科書だけでなく、タブレットや、オンラインで授業を受けなくてはならないが、理解できるのだろうか。
と、余計な話は置いておいて。
HSPの標準スプライト機能は、単純に座標を指定して表示するだけではなく、便利な機能が満載だった。
まずはアニメーション。パターンを登録するときに、es_patanim命令を使うと、連続するパターンを一括で登録できて、さらに、指定したフレーム数で画像を切り替えてくれる。
スプライトの移動を自動でやってくれる命令がある。
es_apos命令は、X座標の移動量、Y座標の移動量、移動スピードを指定すると、勝手に動いてくれる。
シューティングゲームなどで、直線的に動くモノに使えば、移動処理をいちいち書かなくていい。
例えば、自機の弾なんかもこれが使える。
も一つ移動系で便利なのは、es_aim命令。
これは、X座標、Y座標、移動スピードを指定すると、その座標に向かって勝手に動いてくれる。
これもシューティングゲームでよくある、自機を狙ってくる敵弾や、ホーミングする敵に使える。
sin、cosを使って、移動方向を決めなくてもいいのが便利。
あとは、弾幕で使えそうな、移動方向を指定して移動し続けてくれるes_adir命令がある。
es_aim、es_apos、es_adirの3つだけで、シューティングゲームの基本の動きを作れるのがすばらしい。
そして、スプライト同士の衝突判定も簡単。es_check命令が用意されている。
指定したスプライトと衝突しているスプライトNoを知ることができる。
es_checkと合わせて使うと便利なのが、es_type命令と、es_find命令。
es_typeは、任意のタイプ番号をスプライトに設定できる命令。
ビットで処理するため、数字は1,2,4,8…と、2のn乗の値を設定する。
これだけだと何のことやらとなるんだけど、es_findやes_checkでは、このタイプ番号を持つスプライトだけを検索、チェック対象にできる。
使い方の一つに、自機のショットと敵の当たり判定がある。
例えば、ショットはタイプ番号2、敵はタイプ番号4と設定したとする。
es_findで、タイプ番号2のスプライトを探して、es_checkで、そのスプライト番号と、タイプ番号が4のスプライトが衝突しているかを判定できる。
普通に考えると、ショット1発、敵1体ごとの座標を配列などに格納しておいて、判定するとかを考えるのだけど、配列を使わなくて単純なループだけで衝突判定ができる。
これをもとに、それっぽい何かwを作ったのがこちら。
youtu.be
BASIC!で、初めて作ったキューブ避けゲームの画像を使って、キューブが張り付く処理も加えてみた。これも上で説明した命令群で簡単に作れた。
これから作ろうとしているアイデアの大半を、実現できそうということが分かったことが、大きな収穫だった。
#include "hsp3dish.as" screen 0,800,600,0 es_ini ;スプライト初期化 buffer 2 picload "bg.png" buffer 3 ;バッファを作成 picload "meta.png" ;画像を読み込み es_size 42,23 ;パターンサイズ es_pat 0,0,0 ;パターンを読み込み buffer 4 picload "cube.png" es_size 53,58,60 es_patanim 1,3,0,0,10 es_patanim 11,3,0,0,0 gsel 0 ;操作バッファを0に戻す px=300:py=200 es_set 0,px,py,0,0,1 gamecnt=0 cubenum=99 showcube=0 randomize *main redraw 0 stick key,1+2+4+8 if key&1 : px=px-5 ;カーソル左 if key&4 : px=px+5 ;カーソル右 if key&2 : py=py-5 ;カーソル上 if key&8 : py=py+5 ;カーソル下 px=limit(px,0,800-42) py=limit(py,0,600-23) if key&128 : end ;ESCでゲーム終了(暫定) pos 0,0 gcopy 2,0,0,800,600 color 255,0,0:gmode 2 pos 0,0:mes "残りCUBE="+str(cubenum) gamecnt++ es_pos 0,px,py gosub *addenemy es_draw ,,0,1,100 ;自機の当たり判定はいったんコメントアウト ;es_check hitf,0 ;if hitf>0 : assert redraw 1 await 1000/60 goto *main *addenemy ;キューブの追加処理 if showcube<3 and cubenum>0 { es_exnew snum,100,200,1 es_set snum,800,rnd(600),1,,100 es_type snum,2 es_apos snum,-(rnd(10)+1),0 showcube++ cubenum-- } ;キューブを自機に向かって飛ばすか? if gamecnt\50=0 { es_find n,2,100 if n>0 { ;向きを変えるキューブの属性を取得 es_get nocurve,n,ESI_OPTION es_getpos n,cubex,cubey ;もし、一度も向きを変えていなくて、X座標が300未満なら向きを変える if nocurve=0 and cubex>300 { es_aim n,px,py,1000 es_setp n,ESI_OPTION,1 ;向きを変えたことをOPTIONに持たせる } } } ;キューブの当たり判定処理 n=100 repeat es_find n,2,n if n=-1 : break es_check cubeco,n,4 es_getpos n,cx,cy,0 if cx<=0 or cy<=0 or cy>=600-58 or cubeco>0 { es_get pt,n,ESI_CHRNO es_type n,4 es_apos n,0,0 es_chr n,pt+10 showcube-- } n+ loop return