|
|
|
2019/10/20(Sun) 19:20:27|NO.88657
どうもこんにちは。
いつもどおりhspdxfix.asプラグインで作った、STGゲームの質問になります。
二次元配列で敵を出しているので、弾の管理を1匹1匹するのではなく、
二次元配列で後ろの配列をグループとして管理しております。
基準命令だとこの方法でうまくいったのですがスプライトで扱う場合、
グループと敵弾が紐付いていない処理になってしまいます。
原因は「NOMARU_TAMA:フラグ立っているな、よし通れ」っていうのを行っているせいで、
3グループで配置したい弾が、2グループで弾が出されているのはわかるのですが、
どうやって処理していいのかアイディアが出てこないのでアドバイスがあればお願いします。
また、そもそもこのグループ管理がいけないという場合もあるので、そっちの指摘でもいいです。
【仕様】
・5匹の敵を1グループとして管理
・1グループ目に敵弾フラグが立ってたら、1グループのみから敵弾を発射(右側の敵)
・3グループ目に敵弾フラグが立ってたら、3グループのみから敵弾を発射(真ん中の敵)
・敵たまは敵の座標から発射
・敵弾が画面外に行ったら、その敵から再発射
・敵弾にある「TEK_G = 0〜3」はデバック用として用意しています。この出し分けは本ソースではしません
#include "hspdxfix.as" ;DXライブラリ使用
width ,,130,200 ;ウィンドウの位置
es_ini 600,512,1024 ;スプライトの最大数、キャラクタ定義の最大数,周の精度(256*4)
es_screen 640,480 ,0,0,1,1 ;スクリーン
es_window 30,10, 412,460 ;スプライト表示エリア設定
es_area -10,-10, 432,480 ;スプライト有効エリア設定
;---敵---
es_size 18,19, 50
es_pat 60, 0,0
;---敵弾---
es_size 17,17, 50
es_pat 65, 70,0
;敵
TEKI_MAX = 5 ;敵の最大数
TEKI_Gmax = 3 ;グループ数
TEKI_GOKEI = TEKI_MAX * TEKI_Gmax ;敵合計数
dim TEKI_f,TEKI_MAX,TEKI_Gmax
dim TEKI_x,TEKI_MAX,TEKI_Gmax
dim TEKI_y,TEKI_MAX,TEKI_Gmax
;敵弾
dim TEKI_TM_f,TEKI_MAX,TEKI_Gmax;フラグ
dim TEKI_TM_x,TEKI_GOKEI ;敵弾配置X
dim TEKI_TM_y,TEKI_GOKEI ;敵弾配置Y
dim TEKI_TM_soto_x,TEKI_GOKEI ;画面外X
dim TEKI_TM_soto_y,TEKI_GOKEI ;画面外X
dim TEKI_TM_c,TEKI_MAX,TEKI_Gmax;カウント
;▼▼▼▼▼▼▼敵配列▼▼▼▼▼▼▼
;グループ1 右上
TEKI_x(0,0) = 390,390,390,390,390
TEKI_y(0,0) = 200,160,120,80,40
;グループ2 左上
TEKI_x(0,1) = 50,50,50,50,50
TEKI_y(0,1) = 200,160,120,80,40
;グループ3 真ん中
TEKI_x(0,2) = 230,230,230,230,230
TEKI_y(0,2) = 200,160,120,80,40
;■■■■■■敵配置■■■■■■
repeat TEKI_Gmax ;グループ数(3)
TEK_G = cnt
repeat TEKI_MAX ;敵の最大数(5)
es_exnew TEKI ,60,74 ;新規スプライトNo
es_set TEKI, TEKI_x(cnt,TEK_G),TEKI_y(cnt,TEK_G), 60 ;スプライトNo, X,Y座標 ,キャラNo
loop
loop
;************メインループ***************
*メイン
es_cls ;画面クリア
es_draw ;スプライト描画
;************カウンター******************
pos 420,20 : es_mes "TEKI_TM_f(0,0) " + TEKI_TM_f(0,0)
pos 420,40 : es_mes "TEKI_TM_f(1,0) " + TEKI_TM_f(1,0)
pos 420,60 : es_mes "TEKI_TM_f(2,0) " + TEKI_TM_f(2,0)
pos 420,80 : es_mes "TEKI_TM_f(3,0) " + TEKI_TM_f(3,0)
pos 420,100 : es_mes "TEKI_TM_f(4,0) " + TEKI_TM_f(4,0)
pos 420,130 : es_mes "TEKI_TM_f(0,1) " + TEKI_TM_f(0,1)
pos 420,150 : es_mes "TEKI_TM_f(1,1) " + TEKI_TM_f(1,1)
pos 420,170 : es_mes "TEKI_TM_f(2,1) " + TEKI_TM_f(2,1)
pos 420,190 : es_mes "TEKI_TM_f(3,1) " + TEKI_TM_f(3,1)
pos 420,210 : es_mes "TEKI_TM_f(4,1) " + TEKI_TM_f(4,1)
pos 420,240 : es_mes "TEKI_TM_f(0,2) " + TEKI_TM_f(0,2)
pos 420,260 : es_mes "TEKI_TM_f(1,2) " + TEKI_TM_f(1,2)
pos 420,280 : es_mes "TEKI_TM_f(2,2) " + TEKI_TM_f(2,2)
pos 420,300 : es_mes "TEKI_TM_f(3,2) " + TEKI_TM_f(3,2)
pos 420,320 : es_mes "TEKI_TM_f(4,2) " + TEKI_TM_f(4,2)
;**************************************
gosub *敵弾移動
es_sync ;画面更新
await 16
goto *メイン
;*************敵弾移動****************
*敵弾移動
NOMARU_TAMA = 1,0, 1;敵弾グループフラグ
TEKI_TM = 60 ;敵スプライト
TEKI_TM_hs = 200 ;敵弾配置
TEKI_TM_no = 200 ;敵弾画面外
repeat TEKI_Gmax ;グループ数(3)
TEK_G = cnt
if NOMARU_TAMA(cnt) = 1 { ;敵弾グループフラグ
repeat TEKI_MAX ;敵の最大数(5)
es_get TEKI_TM_x(cnt,TEK_G),TEKI_TM,3 ;敵X座標に敵弾を置く
es_get TEKI_TM_y(cnt,TEK_G),TEKI_TM,5 ;敵Y座標に敵弾を置く
if TEKI_TM_f(cnt,TEK_G) = 0 {
TEKI_TM_f(cnt,TEK_G) = 1
es_set TEKI_TM_hs, TEKI_TM_x(cnt,TEK_G),TEKI_TM_y(cnt,TEK_G),65 ;スプライト設定
;↓どこから出しているのか見やすくするため出し分け (デバック用)
if TEK_G = 0 : es_apos TEKI_TM_hs, -1,1, 200 ;左下に移動する
if TEK_G = 1 : es_apos TEKI_TM_hs, 1,1, 200 ;右下に移動する
if TEK_G = 2 : es_apos TEKI_TM_hs, 0,1, 200 ;下に移動する
}
;---画面外判定---
es_get TEKI_TM_soto_x(cnt,TEK_G),TEKI_TM_no,3 ;敵弾X
es_get TEKI_TM_soto_y(cnt,TEK_G),TEKI_TM_no,5 ;敵弾Y
if (TEKI_TM_soto_x(cnt,TEK_G) < 30) or (TEKI_TM_soto_y(cnt,TEK_G) < 10) or (TEKI_TM_soto_x(cnt,TEK_G) > 412) or (TEKI_TM_soto_y(cnt,TEK_G) > 460) {
TEKI_TM_f(cnt,TEK_G) = 0 ;敵弾フラグ
}
TEKI_TM++ ;敵スプライト
TEKI_TM_hs++ ;敵弾配置
TEKI_TM_no++ ;敵弾画面外
loop
}
loop
return
| |
|
2019/10/20(Sun) 20:47:44|NO.88658
;■■■■■■敵配置■■■■■■
dim TEKI_spno,TEKI_MAX,TEKI_Gmax
repeat TEKI_Gmax ;グループ数(3)
TEK_G = cnt
repeat TEKI_MAX ;敵の最大数(5)
es_exnew TEKI_spno(cnt,TEK_G) ,60,74 ;新規スプライトNo
es_set TEKI_spno(cnt,TEK_G), TEKI_x(cnt,TEK_G),TEKI_y(cnt,TEK_G), 60 ;スプライトNo, X,Y座標 ,キャラNo
loop
loop
敵弾移動のループ内の
repeat TEKI_MAX ;敵の最大数(5)
es_get TEKI_TM_x(cnt,TEK_G),TEKI_spno(cnt,TEK_G),3 ;敵X座標に敵弾を置く
es_get TEKI_TM_y(cnt,TEK_G),TEKI_spno(cnt,TEK_G),5 ;敵Y座標に敵弾を置く
これを置き換えれば、とりあえずは設定通りに弾は出される
でも、今はうまく行ってるみたいに見えるけど後々問題が出そう・・・
|
|
2019/10/20(Sun) 23:14:05|NO.88659
暇人さん。
答えてくれてありがとうございます。
なるほど、敵配置でも二次元でやらないとダメだったんですね。
その二次元でおいた変数をゲットして、それも二次元で取らないとダメだったんですね
(私はなんで二次元で処理しているくせに、二次元で取らなかったんだろう・・・)
あと「dim TEKI_f,TEKI_MAX,TEKI_Gmax」これはいらない処理です・・・
>>でも、今はうまく行ってるみたいに見えるけど後々問題が出そう・・・
後々問題がおきそうっというのは、どのような懸念がありそうですか。
他の敵弾を用意したときに発生しうる仕様バグか、敵を倒したときか。
|
|
2019/10/23(Wed) 22:52:17|NO.88676
>他の敵弾を用意したときに発生しうる仕様バグか、敵を倒したときか。
そんな感じですね
死んだ敵の分もループ回さないと都合が悪い処理になってるし・・・
自分ならこんな感じにするかな
#include "hspdx.as" ;DXライブラリ使用
width ,,130,200 ;ウィンドウの位置
es_ini 600,512,1024 ;スプライトの最大数、キャラクタ定義の最大数,周の精度(256*4)
es_screen 640,480 ,0,0,1,1 ;スクリーン
es_window 30,10, 412,460 ;スプライト表示エリア設定
es_area -10,-10, 432,480 ;スプライト有効エリア設定
;---敵---
es_size 18,19, 50
es_pat 60, 0,0
;---敵弾---
es_size 17,17, 50
es_pat 65, 70,0
;敵
TEKI_MAX = 5 ;敵の最大数
TEKI_Gmax = 3 ;グループ数
TEKI_GOKEI = TEKI_MAX * TEKI_Gmax ;敵合計数
dim TEKI_x,TEKI_MAX,TEKI_Gmax
dim TEKI_y,TEKI_MAX,TEKI_Gmax
dim TEKI_NO_GID,512 //敵スプライトNOを使って敵グループインデックス用
dim TEKI_NO_DID,512 //敵スプライトNOを使って敵データインデックス格納用
;敵弾
dim TEKI_TM_f,TEKI_MAX,TEKI_Gmax;フラグ
dim TAMA_NO_DID,512 //敵弾スプライトNOを使ってデータインデックス格納用
;▼▼▼▼▼▼▼敵配列▼▼▼▼▼▼▼
;グループ1 右上
TEKI_x(0,0) = 390,390,390,390,390
TEKI_y(0,0) = 200,160,120,80,40
;グループ2 左上
TEKI_x(0,1) = 50,50,50,50,50
TEKI_y(0,1) = 200,160,120,80,40
;グループ3 真ん中
TEKI_x(0,2) = 230,230,230,230,230
TEKI_y(0,2) = 200,160,120,80,40
;■■■■■■敵配置■■■■■■
repeat TEKI_Gmax ;グループ数(3)
TEK_G = cnt
repeat TEKI_MAX ;敵の最大数(5)
es_exnew TEKI ,60,74 ;新規スプライトNo
es_set TEKI, TEKI_x(cnt,TEK_G),TEKI_y(cnt,TEK_G), 60 ;スプライトNo, X,Y座標 ,キャラNo
es_type TEKI,128
TEKI_NO_GID(TEKI) = TEK_G //スプライトNOをキーにグループインデックス格納
TEKI_DID = TEK_G*TEKI_MAX+cnt //データインデックス(一次元配列とした場合のインデックス)
TEKI_NO_DID(TEKI) = TEKI_DID //スプライトNOをキーにデータインデックス格納
loop
loop
;************メインループ***************
*メイン
es_cls ;画面クリア
es_draw ;スプライト描画
;************カウンター******************
pos 420,20 : es_mes "TEKI_TM_f(0,0) " + TEKI_TM_f(0,0)
pos 420,40 : es_mes "TEKI_TM_f(1,0) " + TEKI_TM_f(1,0)
pos 420,60 : es_mes "TEKI_TM_f(2,0) " + TEKI_TM_f(2,0)
pos 420,80 : es_mes "TEKI_TM_f(3,0) " + TEKI_TM_f(3,0)
pos 420,100 : es_mes "TEKI_TM_f(4,0) " + TEKI_TM_f(4,0)
pos 420,130 : es_mes "TEKI_TM_f(0,1) " + TEKI_TM_f(0,1)
pos 420,150 : es_mes "TEKI_TM_f(1,1) " + TEKI_TM_f(1,1)
pos 420,170 : es_mes "TEKI_TM_f(2,1) " + TEKI_TM_f(2,1)
pos 420,190 : es_mes "TEKI_TM_f(3,1) " + TEKI_TM_f(3,1)
pos 420,210 : es_mes "TEKI_TM_f(4,1) " + TEKI_TM_f(4,1)
pos 420,240 : es_mes "TEKI_TM_f(0,2) " + TEKI_TM_f(0,2)
pos 420,260 : es_mes "TEKI_TM_f(1,2) " + TEKI_TM_f(1,2)
pos 420,280 : es_mes "TEKI_TM_f(2,2) " + TEKI_TM_f(2,2)
pos 420,300 : es_mes "TEKI_TM_f(3,2) " + TEKI_TM_f(3,2)
pos 420,320 : es_mes "TEKI_TM_f(4,2) " + TEKI_TM_f(4,2)
;**************************************
gosub *敵弾移動
es_sync ;画面更新
await 16
goto *メイン
;*************敵弾移動****************
*敵弾移動
t++
NOMARU_TAMA = ((t+300)/300)\2,(t/300)\2, ((t+300)/300)\2;敵弾グループフラグ(300フレーム毎に切り替え)
TEKI_find_no = 60 ;敵スプライト検索開始NO
TEKI_find_end_no = TEKI_find_no+14 ;敵スプライト検索終了NO
TEKI_TM_hs = 200 ;敵弾配置
dup dup_TEKI_TM_f,TEKI_TM_f //多次元配列を一次元配列として使用
repeat
es_find TEKI,128,TEKI_find_no,TEKI_find_end_no,1
if TEKI<0 {break}
TEK_G = TEKI_NO_GID(TEKI) //敵スプライトNOをキーにグループインデックス取り出し
if NOMARU_TAMA( TEK_G )=1 {
TEKI_DID = TEKI_NO_DID(TEKI) //敵スプライトNOをキーに敵データインデックス取り出し
if dup_TEKI_TM_f(TEKI_DID) = 0 {
es_exnew TAMA ,TEKI_TM_hs ;新規スプライトNo
if TAMA>0 {
dup_TEKI_TM_f( TEKI_DID ) = 1 //一次元配列にしてるので敵データインデックスをキーにフラグ設定
TAMA_NO_DID( TAMA ) = TEKI_DID //弾のスプライトNOをキーに敵データインデックス格納(これで弾と敵データとの紐付)
es_get tmpx,TEKI,3 ;敵X座標に敵弾を置く
es_get tmpy,TEKI,5 ;敵Y座標に敵弾を置く
es_set TAMA, tmpx,tmpy,65 ;スプライト設定
es_type TAMA,1024
;↓どこから出しているのか見やすくするため出し分け (デバック用)
if TEK_G = 0 : es_apos TAMA, -1,1, 200 ;左下に移動する
if TEK_G = 1 : es_apos TAMA, 1,1, 200 ;右下に移動する
if TEK_G = 2 : es_apos TAMA, 0,1, 200 ;下に移動する
}
}
}
TEKI_find_no=TEKI+1
loop
;---画面外判定---
TAMA_find_no = 200 ;敵弾スプライト検索開始NO
TAMA_find_end_no = TAMA_find_no+14 ;敵弾スプライト検索終了NO
repeat
es_find TAMA,1024,TAMA_find_no,TAMA_find_end_no,1
if TAMA<0 {break}
es_get tmpx,TAMA,3 ;敵弾X
es_get tmpy,TAMA,5 ;敵弾Y
if (tmpx < 30) or (tmpy < 10) or (tmpx> 412) or (tmpy > 460) {
TEKI_DID = TAMA_NO_DID(TAMA) //弾のスプライトNOをキーに敵データインデックス取り出し
dup_TEKI_TM_f( TEKI_DID ) = 0 ;敵弾フラグ
es_kill TAMA
}
TAMA_find_no=TAMA+1
loop
return
| |
|
2019/10/24(Thu) 20:36:23|NO.88682
暇人さんソースありがとうございます!
>>そんな感じですね
>>死んだ敵の分もループ回さないと都合が悪い処理になってるし・・・
やっぱそんな感じだったんですかー
今本ソースに適応していたら色々不備があって手こずっておりました。
dim TEKI_NO_GID,512
なんで512なんだ!?上限か!保険?
っていうぐらいのスタートなのと、リアルがちょっと立て込むので、解読するまでに時間かかりそうです。
多分今月いっぱいかかるので確認したお返事だけ〜
|
|
2019/10/24(Thu) 21:02:11|NO.88684
>なんで512なんだ!?上限か!保険?
本当は確保するなら600でした・・・
>es_ini 600,512,1024 ;スプライトの最大数、キャラクタ定義の最大数,周の精度(256*4)
スプライトの最大数を512と見間違えてた
スプライトを作ってから代入されるから足りなくても自動拡張されるけど・・・
|
|
2019/11/9(Sat) 12:00:53|NO.88821
ようやく解読する時間が取れたので解読しました。
>>本当は確保するなら600でした・・・
なるほどスプライトの上限だったのか。
そしていくつか疑問点が出てきました。
dup dup_TEKI_TM_f,TEKI_TM_f
今までdupというのは使ったことはないのですが、
「dup_TEKI_TM_f」として処理するけど、「TEKI_TM_f」としても扱いますよってことなのかな
ミニソースで処理してみたけどわからなった(´・ω・`)理解が足りないせいで使用するメリットもわからず。
そしてどのタイミングで二次元として発生させているのかもわからず・・・
使われてい変数で代入して、それをメッセージとして出したけどわからず・・・
es_find TEKI,128,TEKI_find_no,TEKI_find_end_no,1
差分は宣言したほうがいいのでしょうか。
TEKI_find_no=TEKI+1
「TEKI_no++」でも良さそうな気がしますが、上記で処理するメリットを知りたいです
逆に「TEKI_no++」だとダメな理由はあったりしますか
es_find TAMA,1024,TAMA_find_no,TAMA_find_end_no,1
多分2つ↑と同じだと思うけど、こっちは「,1」を消すとシステムエラーになる・・・
差分は2以上扱わない場合、宣言しなくってもいいという解釈だったんだけど違うのかな
また、1宣言するとエラーにならない理由がわからないです。
後の処理はどういうものかわかったのですが、いまいち上のやつがわからなかったです。
ゆっくりでも大丈夫なので、お答えいただければ幸いです
|
|
2019/11/9(Sat) 14:29:27|NO.88822
>「dup_TEKI_TM_f」として処理するけど、「TEKI_TM_f」としても扱いますよってことなのかな
簡単に言うと、違う名前でも同じ変数を使える様にする命令
今回は二次元配列にある敵データの場所を示すインデックスを
通し番号にしたので、そのまま使える様に一次元配列として使用
>そしてどのタイミングで二次元として発生させているのかもわからず・・・
最初の確保時に二次元にしてて(dim TEKI_TM_f,TEKI_MAX,TEKI_Gmax)
一次元配列用の名前でdup_TEKI_TM_fを指定(dup dup_TEKI_TM_f,TEKI_TM_f)
TEKI_TM_fの方は二次元配列として、そのまま使用可能
多次元配列は一次元配列より処理が重いので、大量に処理する場合は
dupを使ったりするけど、ヘルプにあるように
>初心者向けに、dup命令を推奨することはありません。
通常は、あまり使わないかも知れない
>es_find TEKI,128,TEKI_find_no,TEKI_find_end_no,1
> 差分は宣言したほうがいいのでしょうか。
確か増分は-1も指定できて、省略時の処理が
p3よりp4の方が大きければ1が設定されて
p3よりp4の方が小さい場合は-1が設定される
で、今回の場合p3よりp4の方が小さくなる事があるので
指定しないと無限ループに・・・
これは、type別けしてるならp4の検索終了Noに+1すれば防げるので、お好みで・・・
>逆に「TEKI_no++」だとダメな理由はあったりしますか
ぱっと見TEKI_find_no=TEKI+1の方が何を意味してるのか分かり易いだけなので
「TEKI_no++」の方法でも問題ありません
大量に処理する場合は少しでも処理が軽い「TEKI_no++」の方が良いかも
|
|
2019/11/9(Sat) 19:05:15|NO.88823
暇人さん、返答ありがとうございます
>簡単に言うと、違う名前でも同じ変数を使える様にする命令
おぉ、やっぱそんな感じなのか〜
>最初の確保時に二次元にしてて(dim TEKI_TM_f,TEKI_MAX,TEKI_Gmax)
>TEKI_TM_fの方は二次元配列として、そのまま使用可能
そんな裏技があるとは・・・
今まで確保→変数名(0.0)...ってな感じでやってたので、dup処理が不思議に感じたか。
>多次元配列は一次元配列より処理が重いので、大量に処理する場合は
>dupを使ったりするけど、ヘルプにあるように
>>初心者向けに、dup命令を推奨することはありません。
>通常は、あまり使わないかも知れない
やっぱあんま使わない感じですかね。
理解はなんとなくで使いこなせる自信がまだないので、二次元配列のフラグ部分のみ使うことにします。
>で、今回の場合p3よりp4の方が小さくなる事があるので
>指定しないと無限ループに・・・
repeatに回数が宣言されていないから「TEKI_find_no」が75になり
「es_find TEKI,128,TEKI_find_no,TEKI_find_end_no」を処理すると無限ループが起きる感じか。
今まで「repeat」の回数を宣言してたので、「p5=増分」を宣言しなくっても処理できてたんですね・・・
差分を省略するメリットは特にないので、repeatに回数が宣言されていない処理は1宣言しておきます。
リファレンスを改めて見ると「自動的に設定されますので通常は指定しなくても構いません。」
「通常は」→「通常以外は?」っていうのを疑問に思えば辿り着く答えだったかも。
>>ぱっと見TEKI_find_no=TEKI+1の方が何を意味してるのか分かり易いだけなので
>>「TEKI_no++」の方法でも問題ありません
>>大量に処理する場合は少しでも処理が軽い「TEKI_no++」の方が良いかも
なるほど、何かしら意味があると思ってたのですが、そういう意図があったんですね。
たくさんお世話になると思うので「++」でやろうと思います。
長いお時間を取ってもらったにも関わらずお答えいただきありがとうございます!
>>今本ソースに適応していたら色々不備があって手こずっておりました。
これはのちにオバケとして出てくると思います・・・使いこなせるかなー・・・
| |
|