忍者ブログ
まったくのプログラミング素人の筆者がC++/HSPを使用してSTG(シューティングゲーム)を作っていく過程を書くブログでしたが最近は脱線気味。プログラミング以外にも、ゲーム関連の記事、日々の戯言など。
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

昨日追加した多関節キャラなのですが、上手く動いていませんでした。
で、上手く動くように考えていたのですが、どうにもこうにも上手くいかないので
とりあえずの妥協案で当り判定は台座のみとし、倒した時の消去はスプライトNOの数字を直接指定するようにして
なんとか上手く動くようにはなりました。
1216.jpg
でも消去の為に腕のスプライトNOを変数ではなく数字で指定しているので
同時に2つの多関節キャラを出現させる事は出来ないんですよね・・・
まぁ1体づつ出現させれば問題ないので、これは後々の課題としておきます。

で、ちゃんとマップ作製をしながらタイムテーブルを作り初めているのですが、出現位置を確認するのに、いちいち最初から
確認しないと上手く確認出来ないので、非常に面倒くさいです(汗)
マップチップに出現位置も埋め込めれば楽なのですが、イマイチやり方が判らないんですよね^^;
PR
多関節キャラを追加してみたものの、どうも上手く動きません・・・
1215.jpg
とりあえず、表示させて動かす事までは出来たのですが、問題は当り判定と倒した後の敵の消去方法でした。
当り判定に関しては、キャラの台座と先端の砲台の2つに当り判定を持たせて、台座が破壊されたら全てのキャラを削除、
砲台が破壊されたら、砲台のみ削除と言うようにしたいのですが、どうも上手くいかないんですよね・・・
砲台だけ残ってみたり、全部消えてしまったり、腕だけ残ってみたりと動きが安定しません。
何か簡単な事で間違っているような気がするのですが、その簡単な事に気づくのが難しいんですよね^^;
前々から作ってみたかった多関節キャラを作ってみました。
考え方としては
1,まず基準の座標を決めます。
2,その基準の座標から表示するキャラの半分の半径の位置に円を描くようにしてキャラを表示させます。
3,基準の座標にキャラの中心側の先端が来るように画像を回転させて表示します。
4,表示したキャラの外側の先端の座標を計算します。
5,外側の先端の座標を、次のキャラの基準の座標とします。
6,2に戻ります。

って文章で書いても全然わかりにくいですね・・・
とりあえず簡単なスクリプトを作って考えてみました↓
*************************************
*start
#include "hspdxfix.as"
;■ DirectX 初期化&チェック
dialog "fullscreenで起動しますか?「はい」を選択した場合、画面解像度を640×480に変更します。",2,"Config"
if stat=6:screenmode=0
if stat=7:screenmode=1
es_ini 1024,1024,360;スプライト最大数2048,キャラクタ最大数1024,角度360度
es_screen 640,480,16,0,screenmode,1;directX使用時の解像度640*480
if stat=1 : goto *dxerr1
if stat=2 : goto *dxerr2
goto *setup
*dxerr1
dialog "DirectXの初期化に失敗しました。",1 : end
*dxerr2
dialog "スクリーンの初期化に失敗しました。",1 : end
*dxerr3
es_bye : wait 100
dialog "VRAMの容量が不足しています。",1 : end

*setup
;■ バッファへ画像の読みこみ
buffer 5,96,208,0 ;バッファ作成
pos 0,0 : picload "bou1.gif",1 ;バッファへ読み込み
es_buffer 3,0 ;オフスクリーンバッファへの転送
if stat=1 : goto *dxerr3

;敵1,20腕,38砲台,39台座
es_size 48,48,0,0
es_pat 4,0,160,0
es_size 96,96,0,0
es_pat 20,0,0,0
es_size 32,32,80,0
es_pat 38,0,96,0
es_size 64,64,0,0
es_pat 39,32,96

;■スプライト登録
es_window 0,0,640,480 ;スプライト描写範囲設定
es_area -64,-64,640,480 ;スプライト有効範囲設定

es_set 939,px,py,4 ;自機スプライト登録(1)
es_type 939,1 ;自機Type値設定(1)

gsel 0
es_cls
es_sync
wait 100

*gamesetup
enemyk=48.;円の半径
r=0.;角度
r=6.283/360;角度(3.1415の2倍÷360)
enemyr1=0;開始角度
px=192:py=432 ;自機の初期位置
move=4 ;自機速度
gtime=0 ;フレーム数
enex=150;敵の基準x座標
eney=100;敵の基準y座標

;■ メインルーチン
*main
es_cls;画面クリア
gosub *jikimove
gosub *enemy1
es_draw;スプライト描画
gosub *kabehyouji
gosub *fpshyouji
await 0
es_sync 16
getkey syuryo,27:if syuryo=1:end;ESCを押すと強制終了
gtime=gtime+1 ;タイムテーブルの為の変数
if gtime=300 : gtime=0
goto *main

*jikimove;自機移動処理
stick ky,15;キーボードのチェック,非トリガータイプ設定
xv=(ky>>2&1)-(ky&1);x軸移動処理
yv=(ky>>3&1)-(ky>>1&1);y軸移動処理
px=xv*move+px : py=yv*move+py;自機移動処理
;画面からはみ出さない為の処理
if px<0 :px=0
if px>368 :px=368
if py<0 :py=0
if py>432 :py=432
es_pos 939,px,py;自機表示
return

*enemy1
es_set 200,enex+16,eney+16,39;台座の表示
if ab=0 : speed=2;abが0の時腕1の回転方向をプラス
if ab=1 : speed=-2;abが1の時腕1の回転方向をマイナス
if enemyr1>180 : ab=1;腕1の角度180度で反転
if enemyr1<0 : ab=0;腕1の角度0度で反転
;腕1
enemyr1=enemyr1+speed;腕1の回転方向と回転速度(プラスで時計回り,マイナスで反時計回り)
a=r*enemyr1;
enemyx=enemyk*cos(a)+enex;腕1の円の計算x座標
enemyy=enemyk*sin(a)+eney;腕1の円の計算y座標
es_set 140,enemyx,enemyy,20;腕1表示
es_ang enex,eney,enemyx,enemyy;表示角度の計算
es_effect 140,96,100,0,0,stat;腕1の動きに合わせて画像を回転させて表示

;腕2
enemyx1=(enemyx+(enemyx-enex));腕1の先端のx座標の計算
enemyy1=(enemyy+(enemyy-eney));腕1の先端のy座標の計算
if gtime<200 : speed2=1
if gtime>200 : speed2=4
enemyr2=enemyr2+speed2;腕2の回転方向と回転速度(gtimeによって回転速度が変わる)
a1=r*enemyr2
enemyx2=enemyk*cos(a1)+enemyx1;腕2の円の計算x座標
enemyy2=enemyk*sin(a1)+enemyy1;腕2の円の計算y座標
es_set 100,enemyx2,enemyy2,20;腕2表示
es_ang enemyx1,enemyy1,enemyx2,enemyy2;表示角度の計算
es_effect 100,96,100,0,0,stat;腕2の動きに合わせて画像を回転させて表示
if enemyr2>=360 : enemyr2=0;腕2の角度を戻す

;腕3
enemyx3=(enemyx2+(enemyx2-enemyx1));腕3の先端のx座標の計算
enemyy3=(enemyy2+(enemyy2-enemyy1));腕3の先端のy座標の計算
es_ang enemyy3,enemyx3,py,px;腕3の向きの計算
enemyr3=stat;腕3の回転方向を自機に向ける
a2=r*enemyr3
enemyx4=enemyk*cos(a2)+enemyx3;腕3の円の計算x座標
enemyy4=enemyk*sin(a2)+enemyy3;腕3の円の計算y座標
es_set 99,enemyx4,enemyy4,20;腕3表示
es_ang enemyx3,enemyy3,enemyx4,enemyy4;表示角度の計算
es_effect 99,96,100,0,0,stat;腕3の動きに合わせて画像を回転させて表示

;砲台
enemyx5=(enemyx4+(enemyx4-enemyx3));腕3の先端のx座標の計算
enemyy5=(enemyy4+(enemyy4-enemyy3));腕3の先端のy座標の計算
es_set 98,enemyx5+32,enemyy5+32,38;砲台表示
es_ang enemyx5,enemyy5,px,py;砲台の表示角度の計算
es_effect 98,32,32,0,0,stat;砲台を回転させて表示
return

*kabehyouji
color 0,0,50
es_boxf 416,0,640,480;画面右をを塗り潰す
return

*fpshyouji
;fps表示
font "msgothic",18,0
es_getfps fps
color 255,255,255
pos 416,460
es_fmes "Fps="+fps
pos 416,10
es_fmes "ab="+ab
pos 416,30
es_fmes "enemyr1="+enemyr1
pos 416,50
es_fmes "enemyr2="+enemyr2
pos 416,70
es_fmes "enemyr3="+enemyr3
pos 416,90
es_fmes "gtime="+gtime
return
*************************************
HSP3.0使用 hspdxfix使用 画像は↓を使用
bou1.gif
この画像はHamCorossamさんの所で配布されている素材をお借りしています。

スクリプトを実行するとこんな感じです↓
1207.jpg

3本の腕が別々に動いて、いかにも多関節キャラって感じです^^

多関節キャラを考える上で計算しないといけないのは、キャラの両先端と中心の座標の3つです。
腕1の動きで考えてみます。
12071.gif
まず、元の基準のとなるenex,eneyを決めます。
その元の基準enex,eneyを中心として腕1が回転すれば良いのですから、その計算をします。
ただし、キャラを回転させるので半径はキャラの半分(この場合96ドットのキャラなので48)
enemyr1=enemyr1+speed
a=r*enemyr1
enemyx=enemyk*cos(a)+enex
enemyy=enemyk*sin(a)+eney
この部分で円の計算しています。
で、enex,eneyから見たenemyx,enemyyの角度をes_angで計算してes_effectで画像を回転させてやれば
enex,eneyを中心として腕1がグルグル回転します。
es_ang enex,eney,enemyx,enemyy
es_effect 140,96,100,0,0,stat
この部分で画像回転の計算をしています。

次は腕2です。腕2は腕1の先端(enemyx1,enemyy1)に繋がらないとおかしいです。
なのでenemyx1,enemyy1の計算をします。
これは簡単です。
enex,eneyとenemyx,enemyyの座標は判っているので、enemyx,enemyyそれぞれにenemyx,enemyyからenex,eneyを引いた数字を
足してやればenemyx1,enemyy1の座標が判ります。
enemyx1=(enemyx+(enemyx-enex))
enemyy1=(enemyy+(enemyy-eney))
この部分で腕1の先端の座標を計算しています。

enemyx1,enemyy1の座標が判ってしまえば、あとはこの座標を元の座標として考えれば良いので、スクリプトを繰り返していけば
多関節キャラの出来上がり!

と簡単そうに書いていますが、相当悩みまくってやっと出来た〜って感じです(汗)
でも、スクリプトが上手く動いた時は嬉しくてちょっと感動してしまいました^^
スタート時の発進画面を作ってみました。
12051.jpg
これも、HamCorossamさんの所で配布されているマップチップ画像を元に作りました^^
開始時は発射台は停止していて、発射と共に発射台は下がっていき自機は上に上がってから下がってきます(ジャンプするような感じ)

本当は自機が回転しながら上に発射されて、左右の翼から飛行機雲?のような線を回転しながら出して行きたかったんですが
回転する自機の画像を作るのが大変なので、とりあえずそのまま上に上がってから下がってきて元の位置に戻るようにしています。
こんな、なにげない演出でもスクリプトを作るのは結構大変です。
演出の凝っているゲームってのは、作るのホント大変なんだろうな〜と感じました^^;
先日公開した縦スクロールスクリプトのコメント欄で、ありさんに5万回以上リピートしているので遅いのでは?とアドバイスを頂きました。

そんなにリピートしてたかなぁ?と思ってちゃんと数えて見ると・・・
2重リピートの中に、更に2重リピートを使っていたので合計1ループで57460回リピートしてました(汗)
具体的には↓こんな感じで書いていたのですが
repeat 16
repeat 13
gosub *lite;描画ルーチンへ
〜色々な処理
loop
loop
*lite
repeat 13
repeat 20
〜描画処理
loop
loop
return
リピート回数が小さいのでそれ程気にしてませんでしたが、ちゃんと考えると恐ろしい回数になるんですね・・・

で、なるべくリピート回数を減らす事が出来ないかと思って、ちょっと描画方法について考えてみました。
元々はこんなスクリプトで描画していたのですが、この場合260回必ずリピートしてしまいます。(マップチップが260個あるので)
*************************************
*lite
repeat 416/chp_sy;マップチップ画像のxサイズが416ドットなので
ent=cnt
repeat 640/chp_sx;マップチップ画像のyサイズが640ドットなので
if cd=cnt+ent*640/chp_sx:pos cb,cc+idy:es_copy 8,chp_sx*cnt,chp_sy*ent,chp_sx,chp_sy
loop
loop
return
*************************************
で、↑コレを↓このように変更してみました。
*************************************
*lite
if cd=13:return
if (cd>=0)&(cd<20):pos cb,cc+idy:es_copy 8,chp_sx*cd,0,chp_sx,chp_sy:return
if (cd>=20)&(cd<40):pos cb,cc+idy:es_copy 8,chp_sx*(cd-20),32,chp_sx,chp_sy:return
if (cd>=40)&(cd<60):pos cb,cc+idy:es_copy 8,chp_sx*(cd-40),64,chp_sx,chp_sy:return
if (cd>=60)&(cd<80):pos cb,cc+idy:es_copy 8,chp_sx*(cd-60),96,chp_sx,chp_sy:return
if (cd>=80)&(cd<100):pos cb,cc+idy:es_copy 8,chp_sx*(cd-80),128,chp_sx,chp_sy:return
if (cd>=100)&(cd<120):pos cb,cc+idy:es_copy 8,chp_sx*(cd-100),160,chp_sx,chp_sy:return
if (cd>=120)&(cd<140):pos cb,cc+idy:es_copy 8,chp_sx*(cd-120),192,chp_sx,chp_sy:return
if (cd>=140)&(cd<160):pos cb,cc+idy:es_copy 8,chp_sx*(cd-140),224,chp_sx,chp_sy:return
if (cd>=160)&(cd<180):pos cb,cc+idy:es_copy 8,chp_sx*(cd-160),256,chp_sx,chp_sy:return
if (cd>=180)&(cd<200):pos cb,cc+idy:es_copy 8,chp_sx*(cd-180),288,chp_sx,chp_sy:return
*************************************
変数cdにマップチップのデータが入っているのですが、それを利用してマップチップ画像のコピー位置を指定するようにすれば
if文が10回なので(つまりrepeat 10と同じ)、repeatが260回から10回に減らす事が出来、
全体で57460回のrepeatが最高でも2210回のrepeatを行うように変更出来ました^^
そして、描画が終わったら即returnするようにして、背景チップ(全く画像がない所)は描画せずにreturnするようにしてみたら
かなり描画速度が上昇しました!

・・・・・・と言ってもFPS50位なのですが(汗)

でも、ちょっとの工夫でスクリプトの実行速度を上げる事が出来るって事がわかっただけでも大きな収穫です。
また暇をみて、もっと効率的に描画できる方法を考えてみようと思っています。
とりあえず、スプライトを使用したスクロールを使用すれば速度的には問題ないので、そちらで製作を進めて行こうと思っています^^
Twitter
カレンダー
04 2025/05 06
S M T W T F S
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
最新コメント
[04/20 kt.]
[04/19 うぇむ]
[11/24 kt.]
[11/21 NONAME]
[11/24 kt.]
プロフィール
HN:
kt.
性別:
男性
自己紹介:
プログラミング経験は昔ファミリーベーシックでちょっとさわったくらい。
好きなSTGは、怒首領蜂大往生、エスプガルーダ(2)等の弾幕STGやら雷電シリーズなんかの非弾幕、バトルガレッガ、グラディウスシリーズ、R-TYPE等、STGなら何でも好きです。
音楽がカッコイイSTGが特に好きで、並木学氏は最高!
ブログ内検索
忍者ブログ [PR]