HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2016
0319
Sado複数の当たり判定をキャラクターに持たせるには21解決


Sado

リンク

2016/3/19(Sat) 03:32:19|NO.74960

hspに直接関係はない質問になります。

http://hsp.tv/play/pforum.php?mode=all&num=74768
の中の
http://hsp.tv/play/pforum.php?mode=all&num=74934
から
>一つのオブジェクトに複数の当たり判定を持たせる場合
>どこに当たり判定(矩形)の相対座標(親との座標差分)を代入すればいいのか悩んでいます。
http://f.st-hatena.com/images/fotolife/s/st1105/20160319/20160319030658_original.png





キャラクターに二個以上の当たり判定(矩形)を持たせようとした場合、
どのようなデータ構造が適しているのでしょうか。

自分が今この場で適当に思いついた管理方法は2つで、どちらも無駄が多すぎるように思います。

1.キャラデータに適当な数の枠を作っておく dim Obj,num→キャラの種類ID(0なら存在なし) ... dim ObjCollision,num,100,3 二次:100個分の矩形を格納可能 三次:(,,0)=矩形の1辺の長さ (,,1)=親からのX座標差分 (,,2)=Y →絶対にメモリ喰い虫になると思う 2.当たり判定だけ別口にする dim Obj,num ... dim ObjCollision,num,2 二次:(,0)=index始まり (,1)=index終わり CollisionData バッファ 0byte目:矩形の1辺の長さ 1byte目:親からのX座標差分 2byte目:Y ...以降繰り返し... →バッファの空きを探索する手間が増える 連続した空きが見つからない場合、 ObjCollision変数ではindexが足りなくなる



この記事に返信する


科学太郎

リンク

2016/3/19(Sat) 12:02:44|NO.74966

・シューティングゲーム アルゴリズムマニアックス 新装版
http://www.amazon.co.jp/dp/4797359978/

この書籍を紹介しておきます。
多関節や、そのあたり判定について書いてありましたよ。



暇人

リンク

2016/3/19(Sat) 20:26:55|NO.74972

今作ってる3D用のモジュールで使ってる方法を利用したのを書いてみる

コリジョンモジュール変数初期化時に
判定データを登録してIDとして使用したインデックスを返す
そのIDをキャラ毎に設定(判定データはキャラタイプ毎に設定すれば済む)

使い方の流れは
addCollisionDataでコリジョンデータを登録してstatにコリジョンIDが返る
CollisionSettingで判定基の座標と判定範囲を設定
getCollisionDataでコリジョンIDと座標を指定して判定して当たってたらstatに当たった数が返る
当たってた場合以下の変数に各種情報が入る(複数なら配列)
COL_INDEX 判定データのインデックス
COL_SIZE 判定データのサイズ
COL_OFFSETX 判定データのオフセットX
COL_OFFSETY 判定データのオフセットY


#module "mod_Collision" Col_id,ListCol_size,ListCol_ofsx,ListCol_ofsy //getCollisionの戻り値が1以上の時に当たった判定のインデックスとオフセット、サイズを取得できるマクロ #define global COL_INDEX _colinsex@mod_Collision #define global COL_SIZE _Colsize@mod_Collision #define global COL_OFFSETX _Colofsx@mod_Collision #define global COL_OFFSETY _Colofsy@mod_Collision #modinit int m_coln,array m_colsize,array m_colofsx,array m_colofsy dim ListCol_size,m_coln //判定サイズ用 dim ListCol_ofsx,m_coln //オフセットX dim ListCol_ofsy,m_coln //オフセットY if coli_empty_cnt=0 { coli_index=coli_next_index coli_next_index=coli_index+1 //次のIDをセット }else{ coli_empty_cnt-- coli_index=coli_empty_list(coli_empty_cnt) //削除されたIDを再利用 } Col_id=coli_index //コリジョンID minx=10000 maxx=-10000 miny=10000 maxy=-10000 repeat m_coln ListCol_size(cnt)=m_colsize(cnt) ListCol_ofsx(cnt)=m_colofsx(cnt) ListCol_ofsy(cnt)=m_colofsy(cnt) chsize=m_colsize(cnt)/2 //最大最小を判定して保持 if (ListCol_ofsx(cnt)-chsize)<minx {minx=ListCol_ofsx(cnt)-chsize} if (ListCol_ofsx(cnt)+chsize)>maxx {maxx=ListCol_ofsx(cnt)+chsize} if (ListCol_ofsy(cnt)-chsize)<miny {miny=ListCol_ofsy(cnt)-chsize} if (ListCol_ofsy(cnt)+chsize)>maxy {maxy=ListCol_ofsy(cnt)+chsize} loop //バウンディングボックスを保持(判定が一つならこの配列のみ判定) minx_list(Col_id)=minx //モジュール変数では無いのでモジュール命令にしなくても判定可能 maxx_list(Col_id)=maxx miny_list(Col_id)=miny maxy_list(Col_id)=maxy minmax_list(Col_id)=maxx-minx Coln_list(Col_id)=m_coln return Col_id //getCollisionで使用するモジュール命令(当たり判定処理) #modcfunc mod_CheckCollision int m_ex,int m_ey,local hit repeat Coln_list(Col_id) csize=(ListCol_size(cnt)+p_cs)/2 if abs((ListCol_ofsx(cnt)+m_ex)-Center_px)>csize {continue } if abs((ListCol_ofsy(cnt)+m_ey)-Center_py)>csize {continue }else{ _colinsex(hit)=cnt _Colsize(hit)=ListCol_size(cnt) _Colofsx(hit)=ListCol_ofsx(cnt) _Colofsy(hit)=ListCol_ofsy(cnt) hit++ } loop return hit //getCollisionで使用するモジュール命令(回転付当たり判定処理) #modcfunc mod_CheckCollisionRot int m_ex,int m_ey,double rot,local hit repeat Coln_list(Col_id) csize=(ListCol_size(cnt)+p_cs)/2 _ListCol_ofsx=cos(rot)*ListCol_ofsx(cnt)-sin(rot)*ListCol_ofsy(cnt) _ListCol_ofsy=sin(rot)*ListCol_ofsx(cnt)+cos(rot)*ListCol_ofsy(cnt) if abs((_ListCol_ofsx+m_ex)-Center_px)>csize {continue } if abs((_ListCol_ofsy+m_ey)-Center_py)>csize {continue }else{ _colinsex(hit)=cnt _Colsize(hit)=ListCol_size(cnt) _Colofsx(hit)=_ListCol_ofsx _Colofsy(hit)=_ListCol_ofsy hit++ } loop return hit //getCollisionDataで使用されるモジュール命令(判定データ取得) #modfunc mod_getCollisionData int m_cn,array m_cs,array m_ox,array m_oy,double rot if rotf_list(Col_id) {//回転有り repeat m_cn _ListCol_ofsx=cos(rot)*ListCol_ofsx(cnt)-sin(rot)*ListCol_ofsy(cnt) _ListCol_ofsy=sin(rot)*ListCol_ofsx(cnt)+cos(rot)*ListCol_ofsy(cnt) m_cs(cnt)=ListCol_size(cnt) m_ox(cnt)=_ListCol_ofsx m_oy(cnt)=_ListCol_ofsy loop }else{ repeat m_cn m_cs(cnt)=ListCol_size(cnt) m_ox(cnt)=ListCol_ofsx(cnt) m_oy(cnt)=ListCol_ofsy(cnt) loop } return //delCollisionで使用されるモジュール命令(判定データ削除) #modterm coli_empty_list(coli_empty_cnt)=Col_id coli_empty_cnt++ return Col_id //「判定サイズとオフセットを登録してID取得」 //addCollisionData 判定の数, 判定サイズ, オフセットX, オフセットY, 回転するか(0=回転無し、1=回転有り) //statにIDが返る #deffunc addCollisionData int coln, var colsize, var colofsx, var colofsy,int rotf dup dup_colsize,colsize //こうするとパラメータ変数を配列として使える dup dup_colofsx,colofsx dup dup_colofsy,colofsy newmod Collision,mod_Collision,coln, dup_colsize, dup_colofsx, dup_colofsy rotf_list(stat)=rotf return stat //「判定基の座標とサイズを設定」(自分と敵複数の判定なら自分のを設定する) //CollisionSetting 判定基点X座標, 判定基点Y座標, 判定サイズ #deffunc CollisionSetting int px,int py,int pcs p_cs=pcs p_chs=pcs/2 Center_px=px Center_py=py return //「CollisionSettingで設定されてる判定情報をコリジョンIDと座標を指定して判定」 //変数 = getCollision( コリジョンID, 基点X座標, 基点Y座標, 回転角度) //当たった判定の数が返る(COL_INDEX、COL_SIZE、COL_OFFSETX、COL_OFFSETYに当たった判定の情報が入る複数なら配列) #defcfunc getCollision int id_col,int ex,int ey,int rot if rotf_list(id_col) {//回転有り //(回転付)複数の判定サイズが設定されてるので更に判定 //バウンテンボックスは左上と右下座標なので回転を考慮してサイズ分補正 bColsize=(minmax_list(id_col)+p_cs) if (ex+minx_list(id_col)-bColsize) > (Center_px) {return 0 }//当たって無いので判定終了 if (ex+maxx_list(id_col)+bColsize) < (Center_px) {return 0 } if (ey+miny_list(id_col)-bColsize) > (Center_py) {return 0 } if (ey+maxy_list(id_col)+bColsize) < (Center_py) {return 0 }else{ return mod_CheckCollisionRot( Collision(id_col),ex, ey,deg2rad(rot) ) } }else{ //バウンテンボックスは左上と右下座標なのでCenter_側にハーフサイズ分補正 if (ex+minx_list(id_col)) > (Center_px+p_chs) {return 0 }//当たって無いので判定終了 if (ex+maxx_list(id_col)) < (Center_px-p_chs) {return 0 } if (ey+miny_list(id_col)) > (Center_py+p_chs) {return 0 } if (ey+maxy_list(id_col)) < (Center_py-p_chs) {return 0 }else{ if Coln_list(id_col)=1 {//判定サイズが一つなら当たったとして抜ける _colinsex=0 _Colsize=minmax_list(id_col) _Colofsx=minx_list(id_col)+_Colsize/2 _Colofsy=miny_list(id_col)+_Colsize/2 return 1 } } return mod_CheckCollision( Collision(id_col),ex, ey ) } return //addCollisionDataで登録されたデータをIDを指定して全て取得」 //getCollisionData コリジョンID, 判定数, 判定サイズ, オフセットX, オフセットY, 回転角度 #deffunc getCollisionData int id_col,var cn,array cs,array ox,array oy,int rot cn=Coln_list(id_col) mod_getCollisionData Collision(id_col),cn, cs, ox, oy,deg2rad(rot) return //「コリジョンデータ削除」 //delCollision コリジョンID #deffunc delCollision int id_col delmod Collision(id_col) return #global rot@=0.0 celload dir_exe+"\\hsptv\\hsptv_img.bmp",1 celdiv 1,64,64,32,32 max=8 ctype_divid=4*8,4*8+2,4*8+4 colsize= 48, 30,30, 32,24,24 colofsx= 0, 0,0, 0,-16,16 colofsy= 0, -15,15, -16,16,16 coln = 1, 2, 3 //各判定の個数 rotf = 0, 1, 1 //回転するかどうか repeat 3 //[ addCollisionData 判定の数, 判定サイズ, オフセットX, オフセットY, 回転するか(0=回転無し、1=回転有り) ] addCollisionData coln(cnt),colsize(total_index), colofsx(total_index), colofsy(total_index),rotf(cnt) //statにコリジョンIDが返るけど今回は0から2まで順番になるので保持しない total_index+coln(cnt) loop repeat max ctype(cnt)=rnd(3) //キャラタイプID(コリジョンIDと同一とする) ex(cnt)=100+100*(cnt\4) ey(cnt)=100+200*(cnt/4) rot(cnt)=rnd(360) cid=cnt+1 CharID(cnt)=cid CharColID( cid ) =ctype(cnt) //キャラIDをインデックスにしてコリジョンIDセット loop repeat gmode 4,,,180 redraw 0 gradf 0,0,640,480,1,$4444,$1111 //判定範囲表示 repeat max if CharID(cnt) { _ex=ex(cnt) _ey=ey(cnt) rot(cnt)++ cid=CharID(cnt) ccid=CharColID( cid ) //[ getCollisionData コリジョンID, 判定数, 判定サイズ, オフセットX, オフセットY, 回転角度 ] getCollisionData ccid, n, cs, ox, oy,rot(cnt) color 255 repeat n gradf _ex+ox(cnt)-cs(cnt)/2,_ey+oy(cnt)-cs(cnt)/2, cs(cnt),cs(cnt) loop color pos _ex,_ey celput 1,ctype_divid(ccid),,,deg2rad( rot( cnt ) ) } loop color gradf mousex-32,mousey-32,64,64 //自分の判定情報セット //[ CollisionSetting 判定中心X座標, 判定中心Y座標, 判定サイズ ] CollisionSetting mousex,mousey,64 //判定処理 repeat max if CharID(cnt) { //[ 変数 = CollisionSetting( コリジョンID, 判定基点X座標, 判定基点Y座標, 回転角度) ] hit=getCollision( CharColID( CharID(cnt) ) ,ex(cnt),ey(cnt),rot(cnt) ) if hit { _ex=ex(cnt) _ey=ey(cnt) color 100,255 pos 50+(cnt\4)*100,(cnt/4)*200 mes "CharID="+CharID(cnt) repeat hit ecs=COL_SIZE(cnt) gradf _ex+COL_OFFSETX(cnt)-ecs/2,_ey+COL_OFFSETY(cnt)-ecs/2,ecs,ecs,1,$ff mes "COL_INDEX="+COL_INDEX(cnt) loop } } loop redraw await 16 loop
一応簡易判定して当たってたら複数判定を行うようにしてる



暇人

リンク

2016/3/19(Sat) 20:41:03|NO.74973

おっと、流れを間違った・・・
>getCollisionDataでコリジョンIDと座標を指定して判定して当たってたらstatに当たった数が返る
じゃ無くて getCollision() の方でした
getCollisionDataは登録した情報を取得する命令



k

リンク

2016/3/19(Sat) 20:42:28|NO.74974

ちょっと思い付きですが、
当たり判定配列は別に用意して

dim ObjCollision,100,4
当たり判定矩形 100個分確保
内容
(,0)=矩形の1辺の長さ
(,1)=親からのX座標差分
(,2)=Y
 (,3)=次のインデックス番号 −1なら終わり

そしてキャラIDに当たり判定配列の
最初のインデックス番号を書いて順番に判定していけば
メモリの無駄が少ないかなと思う

HDDのFATみたいなかんじなので
飛び番号になっても問題ないと思う

空きは(,3)が0の場合とかに数字を埋めていけばいいかと



暇人

リンク

2016/3/20(Sun) 02:07:47|NO.74979

>NO.74972
> rot@=0.0
テストで使ってた変数初期化が残ってた・・・



暇人

リンク

2016/3/20(Sun) 05:10:05|NO.74980

NO.74974のモジュールを使って弾との判定のサンプル

NO.74974のモジュール部分をコピペしてから↓

#global #module "mod_Shot" Shot_px,Shot_py,Shot_addx,Shot_addy #modinit double spx,double spy,double saddx,double saddy Shot_px=spx Shot_py=spy Shot_addx=saddx Shot_addy=saddy return #modcfunc CheckShot array CharID,array ccid,array ex,array ey,array rot,local hit Shot_px+Shot_addx Shot_py+Shot_addy if Shot_px>0 and Shot_px<640 { if Shot_py>0 and Shot_py<480 { CollisionSetting Shot_px,Shot_py,16 foreach CharID if CharID(cnt) { if getCollision( ccid(cnt) ,ex(cnt),ey(cnt),rot(cnt) ) { hit++ break } } loop }else{return -1} }else{return -1} pos Shot_px,Shot_py celput 2,60 return hit #global celload dir_exe+"\\hsptv\\hsptv_img.bmp",1 celdiv 1,64,64,32,32 celload dir_exe+"\\hsptv\\hsptv_img.bmp",2 celdiv 2,32,32,16,16 max=8 ctype_divid=4*8,4*8+2,4*8+4 colsize= 48, 30,30, 32,24,24 colofsx= 0, 0,0, 0,-16,16 colofsy= 0, -15,15, -16,16,16 coln = 1, 2, 3 //各判定の個数 rotf = 0, 1, 1 //回転するかどうか repeat 3 //[ addCollisionData 判定の数, 判定サイズ, オフセットX, オフセットY, 回転するか(0=回転無し、1=回転有り) ] addCollisionData coln(cnt),colsize(total_index), colofsx(total_index), colofsy(total_index),rotf(cnt) //statにコリジョンIDが返るけど今回は0から2まで順番になるので保持しない total_index+coln(cnt) loop repeat max ctype(cnt)=rnd(3) //キャラタイプID(コリジョンIDと同一とする) ex(cnt)=100+100*(cnt\4) ey(cnt)=100+200*(cnt/4) rot(cnt)=rnd(360) cid=cnt+1 CharID(cnt)=cid loop dimtype Shot,5 repeat gmode 4,,,180 redraw 0 gradf 0,0,640,480,1,$4444,$1111 stick stk,$fff if (stk&256)>0 { if (scnt\5)=0 { repeat 16 //弾の中心X座標,弾の中心Y座標,移動速度X,移動速度Y newmod Shot,mod_Shot, mousex, mousey,sin(deg2rad(22.5*cnt))*5,cos(deg2rad(22.5*cnt))*5 loop } scnt++ }else{ scnt=0 } //判定範囲表示 repeat max if CharID(cnt) { _ex=ex(cnt) _ey=ey(cnt) rot(cnt)++ cid=CharID(cnt) ccid=ctype(cnt)//コリジョンIDと同一なので //[ getCollisionData コリジョンID, 判定数, 判定サイズ, オフセットX, オフセットY, 回転角度 ] getCollisionData ccid, n, cs, ox, oy,rot(cnt) color 255 repeat n gradf _ex+ox(cnt)-cs(cnt)/2,_ey+oy(cnt)-cs(cnt)/2, cs(cnt),cs(cnt) loop color pos _ex,_ey celput 1,ctype_divid(ccid),,,deg2rad( rot( cnt ) ) } loop color gradf mousex-32,mousey-32,64,64 //自分の判定情報セット //[ CollisionSetting 判定中心X座標, 判定中心Y座標, 判定サイズ ] CollisionSetting mousex,mousey,64 //判定処理 repeat max if CharID(cnt) { //[ 変数 = CollisionSetting( コリジョンID, 判定基点X座標, 判定基点Y座標, 回転角度) ] hit=getCollision( ctype(cnt) ,ex(cnt),ey(cnt),rot(cnt) ) if hit { _ex=ex(cnt) _ey=ey(cnt) color 100,255 pos 50+(cnt\4)*100,(cnt/4)*200 mes "CharID="+CharID(cnt) repeat hit ecs=COL_SIZE(cnt) gradf _ex+COL_OFFSETX(cnt)-ecs/2,_ey+COL_OFFSETY(cnt)-ecs/2,ecs,ecs,1,$ff mes "COL_INDEX="+COL_INDEX(cnt) loop } } loop gmode 5,,,255 foreach Shot //当たり判定とついでに座標移動と描画も // CheckShot(Shot(cnt),キャラID配列,コリジョンID配列,ex配列,ey配列,rot配列) if CheckShot(Shot(cnt),CharID,ctype,ex,ey,rot) { delmod Shot(cnt) } loop redraw await 16 loop
コリジョンIDとキャラタイプIDが同じにしてるので
CharColIDを無くした



暇人

リンク

2016/3/20(Sun) 10:51:55|NO.74986

NO.74972のモジュールに間違いがあった
削除したIDをソートする必要があった
>//delCollisionで使用されるモジュール命令(判定データ削除)
>#modterm
> coli_empty_list(coli_empty_cnt)=Col_id
> coli_empty_cnt++
>return Col_id


//delCollisionで使用されるモジュール命令(判定データ削除) #modterm coli_empty_list(coli_empty_cnt)=Col_id repeat coli_empty_cnt if coli_empty_list(cnt)<Col_id { memcpy coli_empty_list(cnt+1),coli_empty_list(cnt),(coli_empty_cnt-cnt)*4 coli_empty_list(cnt)=Col_id break } loop return Col_id
に差し替え

newmod実行時に初期化されるインデックスが分かれば
こんな事する必要ないんだが・・・



Sado

リンク

2016/4/17(Sun) 12:51:31|NO.75237

返信がかなり遅れてしまいました! 申し訳ありません!

>暇人さん

複数の判定箱の位置関係をCollisionオブジェクトに保存して、
それらを判定時に呼び出して利用するものなんですね!
オブジェクトの添字(Col_id?)をキャラ情報に含ませるだけでいいと。

モジュール中に見たことがない手法が幾つかありましたので、
それらについて質問させていただきます……



・addCollisionData&newmodの挙動

module変数は使い始めて日が浅いので詳しい仕様が分かっていませんが、
モジュールを見ると、dimでモジュール変数を初期化しているように見えます。
ということはaddCollisionDataを実行する度に判定箱が全て初期化されるのでしょうか?
でも、coli_indexなどのcol_n総合カウンタ?は生きているようにも見えるし、
判定箱は初期化されずに追加されていくのでしょうか?

・dupについて

dupは初めて使いました。(ROM変数みたいな感じ?)
引数は変数(var)なのに、これで配列も参照できるようにするんですね。
でも、addCollisionDataの引数にintを当ててるcol_nやrotfは、
クローン変数を作らずに配列を利用しているようですが、どうなっているんでしょう…あれ??

・各種配列変数どこで初期化して使っているのか

m_col系_list系など、特に初期化している様子もなく配列として利用している変数は
どうやって利用しているのでしょうか。
array_a=a,b,c,...のようにカンマで区切って代入するか、dim等を使わないと
参照できずにエラーが出るものだと記憶していました。
これもよく分からない。



細かい判定時計算やバウンディングボックスの意味などは、
ちょっと見ただけでは理解できませんでした。
何となくのイメージは分かるのですが、ちょっと頭が弱くて暗算だと式をシミュできない……



暇人

リンク

2016/4/17(Sun) 15:48:21|NO.75246

>モジュールを見ると、dimでモジュール変数を初期化しているように見えます。
newmodすると新しく又は空のモジュール変数が割り当てられる
>#module "mod_Collision" Col_id,ListCol_size,ListCol_ofsx,ListCol_ofsy
ここで指定されてる変数がnewmodの度に別物として使える様になる
二回目の newmod Collision は Collision(1) の中にモジュール変数の内容が全てが保存される
> dim ListCol_size,m_coln //判定サイズ用
> dim ListCol_ofsx,m_coln //オフセットX
> dim ListCol_ofsy,m_coln //オフセット
なので↑ので初期化されるのはCollisionやCollision(1)の中身なので
変数名が同じでも使用してるアドレスは別

mod_getCollisionData Collision(id_col)みたいに初期化したモジュール型変数にインデックスを指定すれば
#mod系で定義した命令内で各種モジュール変数に展開されるので
命令内では普通の変数や配列として使用できる

>引数は変数(var)なのに、これで配列も参照できるようにするんですね。
配列の途中からでも使えるようにしたかったので(この方法はちょっと無理やりと言うか手抜き・・・)

>でも、addCollisionDataの引数にintを当ててるcol_nやrotfは、
> クローン変数を作らずに配列を利用しているようですが
ん?
モジュール内で使ってる配列名と引数で使ってる名前を見間違えるんだと思う

>m_col系_list系など、特に初期化している様子もなく配列として利用している変数は
m_col系は#modinitで定義した命令で使用する引数名なので命令を使う側が配列で渡されてる
addCollisionData内でnewmodされて渡されてる

_list系はモジュール変数じゃなく普通の変数で
> minx_list(Col_id)=minx //モジュール変数では無いのでモジュール命令にしなくても判定可能
> maxx_list(Col_id)=maxx
> miny_list(Col_id)=miny
> maxy_list(Col_id)=maxy
> minmax_list(Col_id)=maxx-minx
> Coln_list(Col_id)=m_coln
のようにnewmodされる毎にIDをインデックスとして直接データが代入されてる
なので登録されてるIDを指定すればエラーにはならない

>バウンディングボックスの意味などは、
一つのIDに複数の判定がある場合
毎回複数の判定をするのは効率が悪いので
まず複数の判定を全て含む判定サイズで判定をして
当たってたら複数の判定に移るって方法をやってる



Sado

リンク

2016/4/17(Sun) 16:17:52|NO.75247

お返事ありがとうございます。

なるほど、Collision()オブジェクトは一つの判定箱セットと考えればいいわけですね。
一度目のaddでCollision(0)=汎用判定セット
二度目のaddでCollision(1)=ステージ固有の判定セットなど、
ステージ移動時に(1)を削除して、再度addする…のような。


ああそれと、
配列、配列じゃないで混乱している箇所を挙げます。

#modinit int m_coln,array m_colsize,array m_colofsx,array m_colofsy . . . #deffunc addCollisionData int coln, var colsize, var colofsx, var colofsy,int rotf dup dup_colsize,colsize //こうするとパラメータ変数を配列として使える dup dup_colofsx,colofsx dup dup_colofsy,colofsy newmod Collision,mod_Collision,coln, dup_colsize, dup_colofsx, dup_colofsy rotf_list(stat)=rotf return stat
colnは通常の命令で整数型の引数として出てきたように見えるのですが、
直後に配列として利用しています。
ここがよく分かりません。

極端に言えば、配列で初期化された
dim ListCol_size,m_coln //判定サイズ用
dim ListCol_ofsx,m_coln //オフセットX
dim ListCol_ofsy,m_coln //オフセットY
これら以外が、配列として利用できているだけで、頭がこんがらがっています。

>m_col系は#modinitで定義した命令で使用する引数名なので命令を使う側が配列で渡されてる
これについても、m_colsize,ofsx,ofsyはしっかりarray(配列)と書かれているので分かりますが、
m_colnはintです。
mod系で定義したものは特定の条件下で配列として扱えるとか、
モジュール空間内は何か特別な変数操作ができるのでしょうか。


最後に、
coli_empty_系とdelmodのソート?がどんな働きをしているのかが分かりません。
パット見必要そうに見えません。



暇人

リンク

2016/4/17(Sun) 16:56:52|NO.75248

>直後に配列として利用しています。
配列としては使ってませんよ
多分見間違えてる
> dim ListCol_size,m_coln //判定サイズ用
> dim ListCol_ofsx,m_coln //オフセットX
> dim ListCol_ofsy,m_coln //オフセットY
> repeat m_coln
> Coln_list(Col_id)=m_coln
m_colnが配列になってる所は無いでしょ?


>パット見必要そうに見えません。
モジュール型変数の初期化は空いてる所が使われる(無ければ追加される)
どこが空いてるかは普通なら一つずつ確認するしか方法が無い(どうにかして欲しいが・・・)
なのでnewmod毎にIDを付けて保持して削除されたIDは別リストに保持する
で、もし10までIDを使い
2が削除され次に5が削除された場合
ソートしない場合 2,5 の順に溜まる(使用時は後ろから使う)
ここでnewmodされた場合空いてるのは2なのにIDは5を使ってしまう

NO.74986のソートを使うと 5,2 の順に置き換えられるのでIDも2が使われるようになる



名無し

リンク

2016/4/17(Sun) 17:29:24|NO.75249

>暇人さん

モジュール変数のインスタンスIDは
mref instance_id, 2
で取得できます。



Sado

リンク

2016/4/17(Sun) 17:34:46|NO.75250

>配列としては使ってませんよ
あ……よく見たら。
他にも一部読み間違えている部分がありました。
何かおかしいなと思ったら。

>memcpy coli_empty_list(cnt+1),coli_empty_list(cnt),(coli_empty_cnt-cnt)*4
(coli_empty_cnt-cnt)*4、これは何を意味しているのでしょうか。
cntを重ねるごと4ずつ減少させる意味があるのでしょうか。
byte単位のメモリコピーとありますが、判定箱の保持量によってはデータ量が増減すると
思うのですが、最小4byteでコピーしきれますか?

>_list系はモジュール変数じゃなく普通の変数
>...のようにnewmodされる毎にIDをインデックスとして直接データが代入されてる
>なので登録されてるIDを指定すればエラーにはならない
これについて、もう少し詳しく教えて頂けませんか?

ArrayA(0)=0 ArrayA(1)=1 ArrayA(3)=3 ArrayA(9)=9 foreach ArrayA mes ArrayA(cnt) loop
dimかカンマ代入でしか配列を初期化出来ないとばかり思っていましたが、
このモジュールを見て上記のスクリプトのように代入できると知りました。
が、これはどういう処理が行われているのでしょうか。
ArrayA(9)=9は
dim Array,10:Array(10)=9の処理と同義なのでしょうか。
また、この例は件のモジュールの処理と違うのでしょうか。


質問ばかりで申し訳ありません……



暇人

リンク

2016/4/17(Sun) 17:46:37|NO.75251

おぉ、そんなのあったんだ・・・
> 0〜 7 : ローカルパラメータ#1〜8(数値)
>ローカルパラメータは、ユーザー定義命令(#deffunc)で新規に追加された命令のパラメータ内容を取得するためのものです。
これじゃそんな機能あるとは一切分からない・・・



暇人

リンク

2016/4/17(Sun) 17:59:23|NO.75252

>(coli_empty_cnt-cnt)*4、これは何を意味しているのでしょうか。
削除されたIDのリストをコピーするサイズ
>思うのですが、最小4byteでコピーしきれますか?
IDだけなので4byte

NO.75249でIDを取得出来るのが分かったのでID再利用の処理は必要なくなるけど・・・

>ArrayA(9)=9は
> dim Array,10:Array(10)=9の処理と同義なのでしょうか。
ん?
dim Array,10:Array(9)=9
と同じ

> また、この例は件のモジュールの処理と違うのでしょうか。
newmod Collisionの事なら全然別の話



暇人

リンク

2016/4/17(Sun) 18:18:22|NO.75253

NO.75249のを利用して

#modinit内の
> if coli_empty_cnt=0 {
> coli_index=coli_next_index
> coli_next_index=coli_index+1 //次のIDをセット
> }else{
> coli_empty_cnt--
> coli_index=coli_empty_list(coli_empty_cnt) //削除されたIDを再利用
> }


mref coli_index, 2
に置き換え

#modtermの命令定義内容を削除



Sado

リンク

2016/4/17(Sun) 22:01:49|NO.75255

>> 0〜 7 : ローカルパラメータ#1〜8(数値)
>>ローカルパラメータは、ユーザー定義命令(#deffunc)で新規に追加された命令のパラメータ内容を取得するためのものです。
>これじゃそんな機能あるとは一切分からない・・・
特殊な変数ってこんな使い方もあるんですね。
2は最近実体化したモジュール変数のIDを取得する?もの……なのか?


使わないとは言え、わからないままにするのは気持ちが悪いのでもう一つ……
>>(coli_empty_cnt-cnt)*4、これは何を意味しているのでしょうか。
>削除されたIDのリストをコピーするサイズ
>>思うのですが、最小4byteでコピーしきれますか?
>IDだけなので4byte
これだけ聞くと、定数4byteでいいように思えますが、
memcpy coli_empty_list(cnt+1),coli_empty_list(cnt),4
ではいけないのでしょうか?

ああ、あと、このモジュールを同人ゲームに利用しようと考えていますが、
利用にあたって何か注意点などはありますでしょうか?
座標系を実数型にしたり、その他細かい場所を改変する程度で、ほぼそのまま利用したいと思います。


■ ■ ■ ■ ■ ■ ■ ■ ■ ■


利用するモジュール部分については粗方理解できたので、本スレは解決とします。
暇人さん,名無しさん,科学太郎さん,Kさん、本当に助かりました……
ありがとうございました!



暇人

リンク

2016/4/17(Sun) 23:34:06|NO.75258

>memcpy coli_empty_list(cnt+1),coli_empty_list(cnt),(coli_empty_cnt-cnt)*4
これは追加されるIDより小さいIDが既にリストにあるなら
それ以降を一つ空けてコピーしてる
>coli_empty_list(cnt)=Col_id
で空いた所にIDを追加する

小さいIDが無い場合はそのまま抜けるが
最初に一番後ろに追加してる↓
>coli_empty_list(coli_empty_cnt)=Col_id


例えばcoli_empty_listに 5,3,2 とあってcoli_empty_cntは3
ID4が削除されて追加される場合
>if coli_empty_list(cnt)<Col_id {
ここで3が検索されて、cntは1になるので
memcpy coli_empty_list(1+1),coli_empty_list(1),(3-1)*4
ってなって
coli_empty_list(1)=4
で coli_empty_listの内容が 5,4,3,2 と並ぶ

>利用にあたって何か注意点などはありますでしょうか?
特にありません



Sado

リンク

2016/4/23(Sat) 03:53:04|NO.75295

>暇人さん
ひとつ問題というか、分からない点が出てきました。
モジュールを多少改変してしまったので、僕が原因を作っているかもしれませんが……


暇人さんのサンプルで以下のように、
複数の判定セットを一度に代入してからaddCollisionDataを行っています。

colsize= 48, 30,30, 32,24,24 colofsx= 0, 0,0, 0,-16,16 colofsy= 0, -15,15, -16,16,16 coln = 1, 2, 3 //各判定の個数 rotf = 0, 1, 1 //回転するかどうか repeat 3 //[ addCollisionData 判定の数, 判定サイズ, オフセットX, オフセットY, 回転するか(0=回転無し、1=回転有り) ] addCollisionData coln(cnt),colsize(total_index), colofsx(total_index), colofsy(total_index),rotf(cnt) //statにコリジョンIDが返るけど今回は0から2まで順番になるので保持しない total_index+coln(cnt) loop
僕もソレ(上記のサンプル)に習って、以下のように記述しましたが、
mod_Collisionの#modinitの代入処理
ListCol_size(cnt) =m_colsize(cnt)
ListCol_ofsx(cnt) =m_colofsx(cnt)
ListCol_ofsy(cnt) =m_colofsy(cnt)
ListCol_shapef(cnt) =m_colshapef(cnt)
で配列の要素が無効というエラーをもらってしまいました。
まあ、引数の要素数が突破しているんでしょうけれど、
ならばなぜ、サンプルは同様のエラーにならないのか?理解できません。

index=0 ncnt=0 //debug shape 00 #enum colshape_test1 = 0 coln(index)= 3//判定の個数 colsize(ncnt)= 64, 32, 32 colofsx(ncnt)= 0, -64,64 colofsy(ncnt)= 0, 0, 0 shapef(ncnt)= 0, 1, 1 rotf(index)= 1//回転flg index++ : ncnt+=coln;*/ //debug shape 01 #enum colshape_invader coln(index)= 11//判定の個数 colsize(ncnt)= 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 colofsx(ncnt)= 0, 0, 0, 8, 8, 16, 16, -8, -8,-16,-16 colofsy(ncnt)= -8, 0, 8, -8, 8, 0, 16, -8, 8, 0, 16 shapef(ncnt)= 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 rotf(index)= 1//回転flg index++ : ncnt+=coln;*/ #enum colshape_boxes coln(index)= 4//判定の個数 colsize(ncnt)= 8, 8, 8, 8 colofsx(ncnt)= 8, 8, -8, -8 colofsy(ncnt)= 8, -8, -8, 8 shapef(ncnt)= 0, 0, 0, 0 rotf(index)= 1//回転flg index++ : ncnt+=coln //当たり判定情報・書き込み -------------------------------------- ncnt=0 repeat index addCollisionData coln(cnt), colsize(ncnt), colofsx(ncnt), colofsy(ncnt), shapef(ncnt), rotf(cnt) ncnt+coln(cnt) loop;*/ dim coln:dim colsize:dim colofsx:dim colofsy:dim shapef:dim rotf



KOMARI

リンク

2016/4/23(Sat) 11:16:08|NO.75296

全くの部外者です、こんにちは(・ω・)

colsize,colofsx,colofsy,shapefの各配列のサイズは、lengthもしくはデバッグウィンドウ等でちゃんと確認しましたか?

各当たり判定の代入時の、一番最後にある
index++ : ncnt+=coln;*/

index++ : ncnt+=coln(index-1);*/
ではないですか?

前者の場合、"colshape_boxes"の代入時にncnt==6となるので、colsize〜shapefの6番〜9番が上書きされ、配列のサイズは11のまま。
しかし、最後のループ内では、長さが3+11+4あるものとして扱われたため、配列エラーになったものかと。

何か間違ってたらすいません(・ω・;)



Sado

リンク

2016/4/23(Sat) 11:36:56|NO.75297

>KOMARIさん
ああ、ほんとうだ。
今までにないくらい間抜けな質問をしてしまった……



ONION software Copyright 1997-2021(c) All rights reserved.