初めは、プログラミングガイドを読んでいたが、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
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
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
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
if nocurve=0 and cubex>300 {
es_aim n,px,py,1000
es_setp n,ESI_OPTION,1
}
}
}
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