|
|
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
そこで、動作的にはこのままでいいので、もうちょっと負担をなくす方法はありませんか。
説明が分かりづらかったでしょうか。
|
|
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を作る(既にあるものから利用するとか)とか
マシン語コード作ってとか・・・
|
|
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
当たったかどうかだけならこれで良いが
目的がはっきり分からないから使えるかどうかは分からない
|
|
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次元の配列でも可能です。
| |
|
2012/9/22(Sat) 21:13:03|NO.49491
>>Makoto
なるほど・・・
プレイしてみてなんとなく分かりました。
理解が難しい・・・
|
|
2012/9/22(Sat) 21:23:09|NO.49492
|
|
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
>これは、ブロックに対して当たり判定を行うキャラが少ないと意味が無い・・・
ちょっと違うな
移動ブロックが多いのにキャラが少ないと効果が薄い
|
|
2012/9/26(Wed) 18:11:59|NO.49586
>主人公の位置の周りのみループで実行して、それ以外の当たり判定の位置はパスするということでしょうか?
そんな感じ
当たり判定が1ドットじゃない限り複数空間にまたがるから色々工夫が必要になる
後、分割振り分けにも有る程度時間がかかるし普通に総当りに判定した方が軽い可能性もある
処理数が増えるほど空間分割の方が有利になる傾向(判定方法や後処理によっては言い切れないが・・・)
>あと、暇人さんの書いてくれたスプリクトなんですが、36行目あたりでエラー吹くようです。
これはNO.49519のソースだけでは動かない
>*gemstart //ここより上はNO.49492のソースをそのまま使用
コメント読んで
|
|
2012/9/27(Thu) 06:37:56|NO.49598
>>これはNO.49519のソースだけでは動かない
申し訳ございませんでした! コメントをしっかり読んでいませんでした。
ちゃんと正常に作動しました。
それにしてもすごすぎます!
ありがとうございました。
ソースの理解が難しい・・・
|
|
2012/9/27(Thu) 06:46:10|NO.49599
|
|
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
| |
|
2012/10/17(Wed) 17:29:52|NO.50037
>>暇人
返信遅くなって大変申し訳ないですっ
とても正確な当たり判定でした! 理解にかなり時間がかかりそうです。。
気になったところが1つ
ブロックなどをどうやって描いているのが初め不思議に思いました。
|
|