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


HSPTV!掲示板


未解決 解決 停止 削除要請

2012
0921
pp7-rp7負担解消17解決


pp7-rp7

リンク

2012/9/21(Fri) 18:05:26|NO.49462

負担解消について質問です。

たとえば下のコードを実行するとゲーム内のループでかなりの負担がかかってしまいます。
※ゲームの全体的なことではなく、1部の問題についてです。1部なのでこのままでは実行しません。

;テストで作ったため、このまま実行しても作動しません。 ;変数(1対のキャラ変数)=マップの位置 dim herox,100+1;主人公x dim heroy,100+1;主人公y dim enemx,100+1;敵x dim enemy,100+1;敵y herox(0)=10:heroy(0)=10 enemx(0)=20:enemy(0)=20 herox(1)=50:heroy(1)=50 enemx(1)=50:enemy(1)=50 ;などなど・・・ repeat;ゲーム内のループ ar=0:br=0 repeat 100;主人公当たり判定 a=0 repeat 100;敵の当たり判定 if herox(ar)=enemx(cnt) and heroy(ar)=enemy(cnt):a=1 loop ar++ loop if a=1:mes "当たりました。" redraw 1 await 10 redraw 0 loop

そこで、動作的にはこのままでいいので、もうちょっと負担をなくす方法はありませんか。
説明が分かりづらかったでしょうか。



この記事に返信する


Makoto

リンク

2012/9/21(Fri) 19:38:41|NO.49467

このプログラムの場合、どれか1つでも当たったのがわかればいいようですので、
当たり判定が確定した時点 (a=1 の所) で、当たり判定のループから抜けてしまえば
それ以降の判定は行う必要がなくなり、少し処理が減らせます。

また、
主人公および敵の、移動処理のループがあると思われますが、
この当たり判定のループを、そのどちらかに組み込んでしまえば
当たり判定のために改めて、ループする必要がなくなるので少しは効果があると思います。



暇人

リンク

2012/9/21(Fri) 20:18:24|NO.49468

複数対複数の判定?

a=0 repeat 100;主人公当たり判定 x=herox(cnt) y=heroy(cnt) repeat 100;敵の当たり判定 if x=enemx(cnt) and y=enemy(cnt):a++ loop loop if a>0:mes "当たりました。 "+a
これで半分ぐらいの処理時間になるけど
色々な前提条件を決めないと試行回数を減らすことは出来ない
(減らすのに時間がかかって意味が無かったりする)

後はこう言う単純な判定だけをするDLLを作る(既にあるものから利用するとか)とか
マシン語コード作ってとか・・・



pp7-rp7

リンク

2012/9/21(Fri) 20:38:39|NO.49469

返信ありがとうございます!

>>Makoto
確かにaでループから抜けるとxとyの値が小さいほど処理時間が短縮されると思いますが、
大きくなってしまうと処理時間がより大きくなってしまいます。
何か思いつきそうな感じがする・・・

>>暇人
一応複数のキャラクターを表示させるのですが、当たり数の測定ではないですっ。



暇人

リンク

2012/9/21(Fri) 21:30:12|NO.49470

>一応複数のキャラクターを表示させるのですが、当たり数の測定ではないですっ。
だから
前提条件が分からなければ試行回数を減らすことは出来ない


;変数(1対のキャラ変数)=マップの位置 dim herox,100+1;主人公x dim heroy,100+1;主人公y dim enemx,100+1;敵x dim enemy,100+1;敵y herox(0)=10:heroy(0)=10 enemx(0)=20:enemy(0)=20 herox(1)=50:heroy(1)=50 enemx(1)=50:enemy(1)=50 ;などなど・・・ dim col,640*480 repeat;ゲーム内のループ memset col,0,640*480*4 repeat 100;主人公当たり判定 x=herox(cnt) y=heroy(cnt) if x>=0 and y>=0 and x<641 and y<481 { col(x+y*640)=1 } loop a=0 repeat 100;敵の当たり判定 if col(enemx(cnt)+enemy(cnt)*640) :a=1:break loop if a=1:mes "当たりました。 " redraw 1 await 10 redraw 0 loop
当たったかどうかだけならこれで良いが
目的がはっきり分からないから使えるかどうかは分からない



Makoto

リンク

2012/9/22(Sat) 11:05:46|NO.49484

プログラムの他の部分に部分に手を加えてよければもう少し効率的な方法があります。
当たり判定用の仮想画面を使う方法です。以下のサンプルを実行してみてください。
なおこの回答は、pp7-rp7さんが御自身のサイトで公開されているような、
平面マップ上をキャラクターが動き回るようなゲーム(ですよね?)をイメージして回答しています。


screen , 800 , 600 ; 変数 dim herox , 10 ; 主人公X dim heroy , 10 ; 主人公Y dim enemx , 10 ; 敵X dim enemy , 10 ; 敵Y *main cls 4 dim hitscr , 20 , 20 ; 当たり判定用仮想画面の定義 兼 内容のクリア hit = 0 ; 当たり判定フラグ ; 敵処理 foreach enemX enemx(cnt) = rnd(20) ; 実際には移動処理が入る enemy(cnt) = rnd(20) hitscr(enemx(cnt),enemy(cnt)) = 1 ; 仮想画面に位置を記録 color 0 , 255 , 0 ; 敵表示 pos enemx(cnt) * 16 , enemy(cnt) * 16 mes "E" loop ; 主人公処理 foreach herox herox(cnt)=rnd(20) ; 実際には移動処理が入る heroy(cnt)=rnd(20) color 0,0,255 if hitscr(herox(cnt) , heroy(cnt)) = 1 { ; 主人公の位置の仮想画面をチェック hit = 1 ; 敵がいれば当たり color 255 , 0 , 0 } pos herox(cnt) * 16 , heroy(cnt) * 16 ; 主人公の表示 mes "H" loop if hit = 1 { ; 当たりの表示 color 255 , 0 , 0 pos 0, 320 mes "当たりました。" } ; 仮想画面表示 for y , 0 , 20 for x , 0 , 20 color 255 , 255 , 255 ; 変数内容の表示 (実際には表示する必要はない) pos 400 + x * 16 , Y * 16 mes str(hitscr(x , y)) next next ; ループ pos 0 , 336 mes "スペースキーを押してください" *space wait 1 stick spckey if spckey & 16 : goto *main goto *space

主人公および敵の移動範囲と同じサイズの 2次元の配列を、
仮想画面として用意しそこに敵の位置を記録していきます。
当たり判定を調べるときは、仮想画面上の主人公の座標に敵があるか調べるだけです。
これなら、総当りでループする必要がないので、負荷は小さくなると思われます。

余談ですが、暇人さんが一つ上のレスでやっているように
X+Y*(横サイズ) で計算すれば、1次元の配列でも可能です。



pp7-rp7

リンク

2012/9/22(Sat) 21:13:03|NO.49491

>>Makoto
なるほど・・・
プレイしてみてなんとなく分かりました。
理解が難しい・・・



pp7-rp7

リンク

2012/9/22(Sat) 21:23:09|NO.49492

>>暇人
1時間くらいで簡単なゲームを作ってみました。たとえば目的がこのゲームだとする。
http://be-sp.com/7909pp7/home/kousyoukai/joyful/img/77.exe
↓ソース
http://be-sp.com/7909pp7/home/kousyoukai/joyful/img/78.hsp

やっぱりなかなか理解できずにソースが長くなってしまいます。



pp7-rp7

リンク

2012/9/22(Sat) 23:09:28|NO.49493

うまく返信できなくてごめんなさい



暇人

リンク

2012/9/24(Mon) 01:54:37|NO.49519

前提条件を・・・
固定画面
ブロックは等間隔じゃ無くドット単位で自由に置く
固定ブックと移動ブロックがある

これを、とりあえずの条件に
外周の壁と固定ブロックは最初に完成させる
外壁の当たり判定はしない
固定ブロックと移動ブロックは分けて判定処理
グリッド別にブロックNOを保存(移動ブロックは毎フレーム再保存)して一回の判定回数を減らす
これは、ブロックに対して当たり判定を行うキャラが少ないと意味が無い・・・


*gemstart //ここより上はNO.49492のソースをそのまま使用 #define DEBUG_ON_OFF 1 //デバック用表示有り無し 0=無し 1=有り border_L=20 //左端 border_R=640-70 //右端 border_U=20 //天井 border_D=400-20 //地上 //判定分割処理用 mysizx=46 //自分の一時判定サイズ(実際の判定ではない) gsiz=mysizx //グリッドサイズ gx=640/gsiz //横軸グリッド最大 gy=480/gsiz //縦軸グリッド最大 bkx=0,20,20,0//ブロック4隅のX座標(左上、右上、右下、左下の順) bky=0,0,20,20//ブロック4隅のY座標 hdx=0,mysizx,mysizx,0//自キャラ4隅のX座標(左上、右上、右下、左下の順) hdy=0,0,25,25//自キャラ4隅のY座標 dim bkno,10,gx*gy //ブロックNO保存用、10は複数同じマスに保存できるように(gx*gy個のグリッドに分割して保存する) dim mbkno,10,gx*gy dim bkidx,gx*gy//一つのマスに複数のNOを保存する可能性があるからカウント用 dim mbkidx,gx*gy buffer 1000,640,480 //背景用バッファ gmode 4,,,256 color 255,255,255 brokmax=0 mbrokmax=0 repeat 500 if broks(cnt)>0{ if broks(cnt)<=3{ pos brokx(cnt),broky(cnt) gcopy 17+broks(cnt),0,0,20,20 //外壁と固定ブロックを予め仮想ウィンドウに完成させとく if broks(cnt)=3{ //当たり判定用グリッド分割処理 _bkno=cnt _brokx=brokx(_bkno) _broky=broky(_bkno) bak_cnt=-1 repeat 4//ブロックの4隅(大きさは20にしてる)の座標をグリッド座標にしてブロックNOを保存 _cnt=((_brokx+bkx(cnt))/gsiz) + (((_broky+bky(cnt)))/gsiz)*gx//座標をグリッド座標に(縦軸にgxを掛けて要素数に) if _cnt ! bak_cnt {//連続で同じグリッド座標に保存しないように bkno(bkidx(_cnt),_cnt)=_bkno bkidx(_cnt)++ bak_cnt=_cnt } loop brok(brokmax)=cnt //固定ブロックNO保存 brokmax++ } }else{ mbrok(mbrokmax)=cnt //移動ブロックNO保存 mbrokmax++ } } loop gsel 0 *sistart ;heroaz repeat pos 0,0 gmode 0 gcopy 1000,0,0,640,480 ;boxf if heroz(0)!=0:heroy(0)-heroz(0)/2:heroz(0)-1 key=0 getkey key,90 if key=1 and assd=1{heroz(0)=herozp(0)} key=0 stick key,15 if key=1{ if herox(0)!=0{ heroh(0)=0 if assdk=0{ herox(0)-2 } if heroat(0)!=0{ heroat(0)-1 }else{ heroat(0)=6 if heroaz(0)=1{ heroaz(0)=2 }else{ heroaz(0)=1 } } } }else{ if key=4{ if herox(0)!=0{ heroh(0)=1 if assdt=0{ herox(0)+2 } if heroat(0)!=0{ heroat(0)-1 }else{ heroat(0)=6 if heroaz(0)=1{ heroaz(0)=2 }else{ heroaz(0)=1 } } } }else{ if heroaz!=0:heroaz(0)=0 } } *herokeynot if assd!=1:heroaz(0)=3 //----移動ブロック処理 gmode 4,20,20,256:color 255,255,255 memset mbkidx,0,gx*gy*4 repeat mbrokmax //当たり判定用グリッド分割処理 _bkno=mbrok(cnt) //ブロック配列要素数(ブロックNO) brokx(_bkno)=((brokx(_bkno)-1+640)\640) //左に移動 pos brokx(_bkno),broky(_bkno) gcopy 17+broks(_bkno),0,0,20,20 _brokx=brokx(_bkno) _broky=broky(_bkno) bak_cnt=-1 repeat 4 _cnt=((_brokx+bkx(cnt))/gsiz) + ((_broky+bky(cnt))/gsiz)*gx //座標をgsizで割り配列要素に変換 if _cnt ! bak_cnt { mbkno(mbkidx(_cnt),_cnt)=_bkno //ロックNOを座標に合わせた配列に代入(複数同じマス目になる可能性があるからmbkidx(_cnt)でカウント) mbkidx(_cnt)++ bak_cnt=_cnt } loop loop //----主人公設定 assdk=0:assdt=0 gmode 4,640,480,256:color 255,255,255 colcnt=0 colmes="" repeat 100 if herox(cnt)!=0 and heroy(cnt)!=0 and cnt=0{ herox(cnt)=limit(herox(cnt),border_L,border_R)//壁際処理 heroy(cnt)=limit(heroy(cnt),border_U,border_D) if heroy(cnt)=border_D {assd=1}else{assd=0}//地面なら着地 hx=herox(cnt) hy=heroy(cnt) pos hx,hy gcopy 2+heroaz(cnt)+heroh(cnt)*4,0,0,50,25 repeat 4 //自キャラの4隅を判定 hxy=(hx+hdx(cnt))/gsiz+(((hy+hdy(cnt)))/gsiz)*gx repeat mbkidx(hxy)//移動ブロック _cnt=mbkno(cnt,hxy)//ブロックNO取り出し #if DEBUG_ON_OFF colcnt++ if cnt=0{colmes+"\n"+str(hxy)+" = "} colmes+str(_cnt)+" " color 255 boxf brokx(_cnt),broky(_cnt),brokx(_cnt)+8,broky(_cnt)+8 color 255,255,255 #endif if (hx>=brokx(_cnt)-45 and hx<=brokx(_cnt)+8) and (hy>=broky(_cnt)-18 and hy<=broky(_cnt)+4):assd=1 if (hx>=brokx(_cnt)-12 and hx<=brokx(_cnt)+16) and (hy>=broky(_cnt)-12 and hy<=broky(_cnt)+4):assdk=1 if (hx>=brokx(_cnt)-50 and hx<=brokx(_cnt)-45) and (hy>=broky(_cnt)-12 and hy<=broky(_cnt)+4):assdt=1 if (hx>=brokx(_cnt)-40 and hx+5<=brokx(_cnt)+8) and (hy>=broky(_cnt)+5 and hy<=broky(_cnt)+16):heroz(0)=0:hy+8 loop repeat bkidx(hxy)//固定ブロック _cnt=bkno(cnt,hxy) #if DEBUG_ON_OFF colcnt++ if cnt=0{colmes+"\n"+str(hxy)+" = "} colmes+str(_cnt)+" " color 255 boxf brokx(_cnt),broky(_cnt),brokx(_cnt)+8,broky(_cnt)+8 color 255,255,255 #endif if (hx>=brokx(_cnt)-45 and hx<=brokx(_cnt)+8) and (hy>=broky(_cnt)-18 and hy<=broky(_cnt)+4):assd=1 if (hx>=brokx(_cnt)-12 and hx<=brokx(_cnt)+16) and (hy>=broky(_cnt)-12 and hy<=broky(_cnt)+4):assdk=1 if (hx>=brokx(_cnt)-50 and hx<=brokx(_cnt)-45) and (hy>=broky(_cnt)-12 and hy<=broky(_cnt)+4):assdt=1 if (hx>=brokx(_cnt)-40 and hx+5<=brokx(_cnt)+8) and (hy>=broky(_cnt)+5 and hy<=broky(_cnt)+16):heroz(0)=0:hy+8 loop loop heroy(cnt)=hy } loop if assd!=1{heroy(b)+3} #if DEBUG_ON_OFF gosub *Debug #endif redraw 1 await 10 redraw 0 loop #if DEBUG_ON_OFF *Debug color 255,,255 repeat gx*gy if mbkidx(cnt) or bkidx(cnt){ _x=(cnt\gx)*gsiz _y=(cnt/gx)*gsiz pos _x+4,_y+4 mes cnt line _x,_y,_x+gsiz,_y line _x,_y+gsiz line _x+gsiz,_y+gsiz line _x+gsiz,_y } loop color 255 pos herox(0)+hdx(3),heroy(0)+hdy(3) repeat 4 line herox(0)+hdx(cnt),heroy(0)+hdy(cnt) loop color pos 20,100 mes "assd = "+assd mes "assdk = "+assdk mes "assdt = "+assdk mes mes "colcnt = "+colcnt //当たり判定を何回処理したか mes colmes //マス目数(左上が0) = あたり判定したブロックNO return #endif
当たり判定部分は面倒なんで殆どそのまま利用してる

やってるのは↓と同じ感じ

シューティングゲームにおける弾の空間分割 - 当たり判定
http://d.hatena.ne.jp/tomoemon/20080429/p3



暇人

リンク

2012/9/24(Mon) 02:15:31|NO.49520

>これは、ブロックに対して当たり判定を行うキャラが少ないと意味が無い・・・
ちょっと違うな
移動ブロックが多いのにキャラが少ないと効果が薄い



pp7-rp7

リンク

2012/9/26(Wed) 15:42:08|NO.49583

>>暇人
返信遅くなりました。

なるほど。
http://d.hatena.ne.jp/tomoemon/20080429/p3
こちらのページを見てよく分かった気がします。

主人公の位置の周りのみループで実行して、それ以外の当たり判定の位置はパスするということでしょうか?

たとえば
http://f.hatena.ne.jp/tomoemon/20080429233414
このように14番のマス内に主人公が存在したらそのマスだけの当たり判定を検索するとか?


あと、暇人さんの書いてくれたスプリクトなんですが、36行目あたりでエラー吹くようです。



pp7-rp7

リンク

2012/9/26(Wed) 15:52:38|NO.49584

>>暇人(スプリクトについて)
つい最近、こちらでアップローダーを設置いたしました。
長いスプリクトなどでの投稿などにお使いください。
※拡張子などについてはアップローダーでご確認ください。
http://be-sp.com/7909pp7/home/kousyoukai/upload/upload.cgi

コメ付でのアップは通常の掲示板をご利用ください。
http://be-sp.com/7909pp7/home/kousyoukai/joyful/joyful.cgi



暇人

リンク

2012/9/26(Wed) 18:11:59|NO.49586

>主人公の位置の周りのみループで実行して、それ以外の当たり判定の位置はパスするということでしょうか?
そんな感じ
当たり判定が1ドットじゃない限り複数空間にまたがるから色々工夫が必要になる
後、分割振り分けにも有る程度時間がかかるし普通に総当りに判定した方が軽い可能性もある
処理数が増えるほど空間分割の方が有利になる傾向(判定方法や後処理によっては言い切れないが・・・)

>あと、暇人さんの書いてくれたスプリクトなんですが、36行目あたりでエラー吹くようです。
これはNO.49519のソースだけでは動かない
>*gemstart //ここより上はNO.49492のソースをそのまま使用
コメント読んで



pp7-rp7

リンク

2012/9/27(Thu) 06:37:56|NO.49598

>>これはNO.49519のソースだけでは動かない
申し訳ございませんでした! コメントをしっかり読んでいませんでした。
ちゃんと正常に作動しました。
それにしてもすごすぎます!
ありがとうございました。

ソースの理解が難しい・・・



pp7-rp7

リンク

2012/9/27(Thu) 06:46:10|NO.49599

一応実行ファイルを試しにアップしておきました。
http://be-sp.com/7909pp7/home/kousyoukai/upload/upload.cgi?get=00021

ソースファイルもアップしています。(暗証パス=95359748)
http://be-sp.com/7909pp7/home/kousyoukai/upload/upload.cgi?get=00020

↓アップローダー元
http://be-sp.com/7909pp7/home/kousyoukai/upload/upload.cgi



暇人

リンク

2012/10/13(Sat) 15:34:03|NO.49968

今更だけど
移動ブロック同士が重ならず更に初期配置は均等に並べられるなら
通常の二次元配列を使ったマップデータが利用できる

#define DEBUG_ON_OFF 1 //デバック用表示有り無し 0=OFF 1=ON winsx = 640 winsy = 480 screen 0,winsx,winsy bksx = 32 bksy = 32 //ブロックサイズ=グリッドサイズしてるので //自分のサイズをブロックより大きくすると固定ブロックに対しては判定の修正が必要 //一応移動ブロック側は対応させてる mysx = 32 mysy = 32 gmaxx = winsx/bksx+((winsx\bksx)>0) gmaxy = winsy/bksy+((winsy\bksy)>0) dim map2,gmaxx,gmaxy dim map,limit(gmaxx,20,gmaxx),limit(gmaxy,15,gmaxy)//下のマップデータが二次元配列で作ってるのでそれ以上を確保してる //0=背景、1=固定ブロック、5=横移動ブロック、6=上昇ブロック、9=自分 map(0, 0)=1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 map(0, 1)=1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1 map(0, 2)=1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,1 map(0, 3)=1,0,0,5,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,1 map(0, 4)=1,0,0,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,1 map(0, 5)=1,0,0,0,5,0,5,0,1,1,0,0,0,0,0,0,0,0,0,1 map(0, 6)=1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 map(0, 7)=1,0,0,0,0,1,1,0,1,1,1,0,0,0,0,0,0,0,0,1 map(0, 8)=1,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,1 map(0, 9)=1,0,0,0,0,0,0,0,1,0,6,6,0,0,0,5,5,0,0,1 map(0,10)=1,0,0,5,0,0,1,0,1,0,0,0,0,9,0,5,5,0,0,1 map(0,11)=1,0,0,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,1 map(0,12)=1,0,0,5,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1 map(0,13)=1,0,0,0,0,1,1,1,1,0,1,0,0,0,0,0,0,0,0,1 map(0,14)=1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 buffer 1 gradf 0,0,640,480,0,0,0 gradf 1,1,bksx-1,bksy-1,0,$333333,$333333//背景 gradf bksx,0,bksx,bksy,0,$883333,$553333//固定ブロック gradf bksx*2,0,bksx,bksy,0,$888888,$111111//固定ブロック gradf bksx*5,0,bksx,bksy,1,$aaaaaa,$555555//横移動ブロック gradf bksx*6,0,bksx,bksy,1,$aaaaaa,$5555ff//上昇ブロック gradf bksx*9,0,bksx,bksy,1,$88ff,$88ff//上昇ブロック celdiv 1,bksx,bksy buffer 100,winsx,winsy //背景と固定ブロック用仮想画面 mbkmax = 0 repeat gmaxy c = cnt pos 0,c*bksy repeat gmaxx t = map(cnt,c) if t>=5 {//固定ブロック以外 map(cnt,c) = 0 //元のブロックタイプをクリア(背景セット) if t<9 {//移動ブロック if t=5 {mbvx(mbkmax)=1:mbvy(mbkmax)=0}else{mbvx(mbkmax)=0:mbvy(mbkmax)=-1} //ブロックの移動量設定 mbkt(mbkmax) = t //ブロックタイプを保存 mbkx(mbkmax) = cnt*bksx //グリッド座標からスクリーン座標に変換 mbky(mbkmax) = c*bksy mbkmax++ }else{//自分 myx = cnt*bksx myy = c*bksy } t=0 } celput 1,t loop loop #const L 1 #const U 2 #const R 4 #const D 8 #const LU L | U #const RU R | U #const RD R | D #const LD L | D #const LR L | R #const UD U | D #const LRUD LR | UD gsel 0 my_vx = 2 my_vy = 2 time=0 repeat redraw 0 pos 0,0 gcopy 100,0,0,winsx,winsy //背景と固定ブロック描画(画面クリア) //自分移動処理 myx_old = myx myy_old = myy myvx = 0 myvy = 0 stick st,$ff if st & L {myvx = -my_vx} if st & R {myvx = my_vx} if st & U {myvy = -my_vy} if st & D {myvy = my_vy} myx = limit(myx+myvx,0,winsx-mysx) myy = limit(myy+myvy,0,winsy-mysy) //固定ブロック判定処理 lx = limit(myx/bksx,0,gmaxx-1)//自分左側のグリッドX座標 rx = limit((myx+mysx-1)/bksx,0,gmaxx-1)//自分右側のグリッドX座標 uy = limit(myy/bksy,0,gmaxy-1)//自分上側のグリッドY座標 dy = limit((myy+mysy-1)/bksy,0,gmaxy-1)//自分下側のグリッドY座標 #if DEBUG_ON_OFF //当たった固定ブロックをオレンジで表示 color 200,100 if map(lx,uy)>0 {gradf lx*bksx,uy*bksy,bksx,bksy /*右上に当たった*/} if map(rx,uy)>0 {gradf rx*bksx,uy*bksy,bksx,bksy /*左上に当たった*/} if map(rx,dy)>0 {gradf rx*bksx,dy*bksy,bksx,bksy /*右下に当たった*/} if map(lx,dy)>0 {gradf lx*bksx,dy*bksy,bksx,bksy /*左下に当たった*/} #endif //移動ブロック処理 repeat mbkmax if mbkt(cnt)>=5 { if ((time\(bksx*4))=(bksx*2)) and mbkt(cnt)=5 {mbvx(cnt)*-1} _mbkx=(mbkx(cnt)+mbvx(cnt)+winsx)\winsx _mbky=(mbky(cnt)+mbvy(cnt)+winsy)\winsy mbkx(cnt) = _mbkx mbky(cnt) = _mbky pos _mbkx,_mbky celput 1,mbkt(cnt) } loop //移動ブロック分割空間振り分け処理 memset map2,0,gmaxx*gmaxy*4 //移動ブロック用のマップデータを初期化 repeat mbkmax if mbkt(cnt)>=5 { bx = mbkx(cnt)/bksx by = mbky(cnt)/bksy map2(bx,by) = cnt | $10000 //要素数をブロックナンバーとして使うから0が存在してしまうため $10000をフラグとして使用 } loop //自分の判定区画内外振り分け処理 btcnt = 0 boothx = (bksx*2+mysx)/bksx+((mysx\bksx)>0) //自分の左上を中心に横3縦3の9区画(自分のサイズがブロック以上ならその分増える) boothy = (bksy*2+mysy)/bksy+((mysy\bksy)>0) btx = limit(myx/bksx-1,0,gmaxx-boothx) //一つ左上の区画から検索 bty = limit(myy/bksy-1,0,gmaxy-boothx) repeat boothx*boothy //当たる可能性がある区画だけ検索 no = map2(btx+(cnt\boothx) ,bty+(cnt/boothx)) //$10000のフラグ入り if no>0 { booth(btcnt)=no & $ffff :btcnt++ } //& $ffffでフラグ除去してからbooth(btcnt)に保存 loop //移動ブロック判定処理 //自分の座標にブロックと自分の当たり判定範囲を加減さんして判定座標にする myblx = myx-bksx//左側のx座標(これよりブロックが右にあれば当たってる可能性有り) mybrx = myx+mysx//右側のx座標 mybuy = myy-bksy mybdy = myy+mysy #if DEBUG_ON_OFF //当たり判定範囲(この範囲内に移動ブロックの左上角が入れば当たってる) if (time\2)=0{ color 0,255//緑点滅 line mybrx,mybuy,myblx,mybuy line mybrx,mybdy line myblx,mybdy line myblx,mybuy } #endif //自分の上下を判定処理 repeat btcnt no = booth(cnt) bkx = mbkx(no) bky = mbky(no) if bkx>myblx and bkx<mybrx and bky>mybuy and bky<=mybdy {//移動ブロックに当たった #if DEBUG_ON_OFF hitmbk(hitmcnt) = no //当たったブロックNOを保存 hitmcnt++ #endif } loop #if DEBUG_ON_OFF //自分の判定区画内に入った移動ブロックNo,ブロックを水色で表示 color 50,200,255 repeat btcnt pos bksy+8,bksy+cnt*16+8 mes booth(cnt) gradf mbkx(booth(cnt)),mbky(booth(cnt)),bksx,bksy loop //実際に当たったブロックNo,ロックを赤で表示 color 255 repeat hitmcnt pos bksy*2+8,bksy+cnt*16+8 mes hitmbk(cnt) gradf mbkx(hitmbk(cnt)),mbky(hitmbk(cnt)),bksx,bksy loop hitmcnt = 0 //移動ブロップにNoを表示し左上座標を含む区画を緑で表示 repeat mbkmax pos mbkx(cnt),mbky(cnt) color 255,255,255 mes strf("%2d",cnt) color 55,200 _x = (mbkx(cnt)/bksx)*bksx _y = (mbky(cnt)/bksy)*bksy line _x,_y,_x+bksx,_y line _x,_y+bksy line _x+bksx,_y+bksy line _x+bksx,_y loop repeat boothx*boothy //判定区画を赤点線で表示 _x = (btx+(cnt\boothx))*bksx _y = (bty+(cnt/boothx))*bksy color 255 repeat 4//点線枠描画 c=cnt repeat (bksx/2)*((cnt=0)+(cnt=2))+(bksy/2)*((cnt=1)+(cnt=3)) pset _x+cnt*(((c=0)-(c=2)))*2+bksx*((c=1)+(c=2)),_y+cnt*(((c=1)-(c=3)))*2+bksy*((c=2)+(c=3)) loop loop loop #endif //自キャラ表示 pos myx,myy celput 1,9 redraw 1 getkey Ctrl,17 await 15+Ctrl*200 //Ctrl押してる間遅く time+ loop



pp7-rp7

リンク

2012/10/17(Wed) 17:29:52|NO.50037

>>暇人
返信遅くなって大変申し訳ないですっ

とても正確な当たり判定でした! 理解にかなり時間がかかりそうです。。

気になったところが1つ
ブロックなどをどうやって描いているのが初め不思議に思いました。



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