左下、右下両方当たってるなら上に戻す
右上、右下両方当たってるなら左に戻す
これだと角一つだけ当たってる時に上手く行かないので
移動前の座標も使う
右下が当たってたらブロックの上か左辺が当たったとして処理
移動速度が縦か横どちらか0なら速度のある方を移動
斜めに移動してたら移動前の座標から直線移動では絶対当たらない
方向を除外して移動
ブロックの斜め方向から当たった場合の処理は手抜きなので
作ってるものによっては気になるかも知れない・・・
#define CHIPSIZE 64
#define MAPMAXX 10
#define MAPMAXY 8
mysizex=CHIPSIZE //自分のサイズ
mysizey=CHIPSIZE
mycsx=mysizex-1 //自分の左上を基点にして右下端の判定をする時キャラサイズをそのまま使うと隣のブロックを最小してしまうので-1(キャラがウィンドウ座標0にいてキャラ右端を64としたら64で割ると1になってしまう)
mycsy=mysizey-1
myspx=4 //自分の速度
myspy=4
//4が障害物、100以上が自分
map_txt={"
1,4,4, 1,1,1,1,1,1,1
1,4,1, 1,1,1,1,4,1,1
2,4,2, 2,2,2,2,4,2,2
2,2,2, 2,4,4,4,2,4,4
2,2,2, 2,2,2,4,2,2,4
3,3,3,103,3,3,3,3,3,4
4,3,3, 4,4,4,3,3,3,4
4,4,3, 3,3,3,3,4,4,4"}
dim map,MAPMAXX,MAPMAXY+1
buffer 1
//テキストデータをそのまま判定にも使うと面倒(個人的にだが)なので配列に入れなおす。ついでにbufferに背景を作成
split map_txt,"\n",map_y_txt
repeat MAPMAXY
split map_y_txt(cnt),",",map_x_txt
mapy=cnt
repeat MAPMAXX
map(cnt,mapy)=int(map_x_txt(cnt))
if map(cnt,mapy)=4 {//障害物
gradf cnt*CHIPSIZE,mapy*CHIPSIZE,CHIPSIZE,CHIPSIZE,((cnt+mapy)\2),$444444,$888888
}else{//障害物以外
if map(cnt,mapy)>=100 {//自分
mypx=cnt*CHIPSIZE:mypy=mapy*CHIPSIZE
map(cnt,mapy)=map(cnt,mapy)\100 //座標をセットしたらクリア(100未満を背景マップチップとして指定できる)
}
gradf cnt*CHIPSIZE,mapy*CHIPSIZE,CHIPSIZE-1,CHIPSIZE-1,1,$880077-$220000*map(cnt,mapy),$880055-$220000*map(cnt,mapy)
}
loop
loop
gsel 0
repeat
redraw 0
pos 0,0
celput 1,0
stick stk,$F
//移動量を求めるための準備(判定後の処理に必要になってくる)
mypx_old=mypx
mypy_old=mypy
if stk&1 {mypx-myspx}
if stk&4 {mypx+myspx}
if stk&2 {mypy-myspy}
if stk&8 {mypy+myspy}
//マップデータ外に出さない処理
mypx=limit(mypx,0,CHIPSIZE*MAPMAXX-mysizex)
mypy=limit(mypy,0,CHIPSIZE*MAPMAXY-mysizey)
//自分の左上のグリッド座標(マップ左上が0,0で右下最大がMAPMAXX-1,MAPMAXY-1 、0からなので使用チップ数-1になる)
myg_lx=mypx/CHIPSIZE
myg_uy=mypy/CHIPSIZE
//自分の右下のグリッド座標(myg_lx,myg_dyで左下、myg_rx,myg_uyが右上になる)
myg_rx=(mypx+mycsx)/CHIPSIZE
myg_dy=(mypy+mycsy)/CHIPSIZE
color 255,255,255
pos 0,0
if map(myg_lx,myg_uy)=4 {mes strf("X=%d,Y=%d",myg_lx,myg_uy):gradf myg_lx*CHIPSIZE,myg_uy*CHIPSIZE,CHIPSIZE,CHIPSIZE,1,$aa4444,$aa8888}//左上
if map(myg_rx,myg_uy)=4 {mes strf("X=%d,Y=%d",myg_rx,myg_uy):gradf myg_rx*CHIPSIZE,myg_uy*CHIPSIZE,CHIPSIZE,CHIPSIZE,1,$aa4444,$aa8888}//右上
if map(myg_lx,myg_dy)=4 {mes strf("X=%d,Y=%d",myg_lx,myg_dy):gradf myg_lx*CHIPSIZE,myg_dy*CHIPSIZE,CHIPSIZE,CHIPSIZE,1,$aa4444,$aa8888}//左下
if map(myg_rx,myg_dy)=4 {mes strf("X=%d,Y=%d",myg_rx,myg_dy):gradf myg_rx*CHIPSIZE,myg_dy*CHIPSIZE,CHIPSIZE,CHIPSIZE,1,$aa4444,$aa8888}//右下
//二つ以上の角が当たってるか判定
rlud=0
if map(myg_lx,myg_uy)=4 {rlud | 3}//左上が当たってたら左1上2で3を設定(stickと同じ)
if map(myg_rx,myg_uy)=4 {rlud | 6}
if map(myg_rx,myg_dy)=4 {rlud | 12}
if map(myg_lx,myg_dy)=4 {rlud | 9}
if rlud {//どこかが当たってる
if (rlud&5)=5 {//自分の左右が当たってる
if (mypy-mypy_old)>0 {//下に移動中
mypy=myg_dy*CHIPSIZE-mysizey //ブロックの上に戻す
}else{//上に移動中
mypy=myg_uy*CHIPSIZE+CHIPSIZE //ブロックの下に戻す
}
mypy_old=mypy //縦方向の移動は無かった事にする
myg_uy=mypy/CHIPSIZE //移動したので再度グリッド座標算出
myg_dy=(mypy+mycsy)/CHIPSIZE
}else{
if (rlud&10)=10 {//自分の上下が当たってる
if (mypx-mypx_old)>0 {//右に移動中
mypx=myg_rx*CHIPSIZE-mysizex //ブロックの左に戻す
}else{//左に移動中
mypx=myg_lx*CHIPSIZE+CHIPSIZE //ブロックの右に戻す
}
mypx_old=mypx
myg_lx=mypx/CHIPSIZE
myg_rx=(mypx+mycsx)/CHIPSIZE
}
}
//上の処理してもまだ当たってる場合の処理
//移動速度(上で判定後の移動処理してからの速度となる)
spdx=mypx-mypx_old
spdy=mypy-mypy_old
spd_rlud=(spdx<0) | (spdx>0)*4 | (spdy<0)*2 | (spdy>0)*8 //左に移動なら1、上に移動なら2を設定(stickと同じ)
if spd_rlud {//移動中
if spdx=0 or spdy=0 {//縦か横に移動中
if spd_rlud=1{//左
if map(myg_lx,myg_uy)=4 or map(myg_lx,myg_dy)=4{mypx=myg_lx*CHIPSIZE+CHIPSIZE}
}
if spd_rlud=2 {//上
if map(myg_lx,myg_uy)=4 or map(myg_rx,myg_uy)=4{mypy=myg_uy*CHIPSIZE+CHIPSIZE}
}
if spd_rlud=4 {//右
if map(myg_rx,myg_uy)=4 or map(myg_rx,myg_dy)=4{mypx=myg_rx*CHIPSIZE-mysizex}
}
if spd_rlud=8 {//下
if map(myg_lx,myg_dy)=4 or map(myg_rx,myg_dy)=4{mypy=myg_dy*CHIPSIZE-mysizey}
}
}else{//斜めに移動中
if spd_rlud=3 {//左上に移動中
if map(myg_lx,myg_uy)=4 {//左上が当たった
if myg_uy = (mypy_old/CHIPSIZE) {//前回のグリッド位置が今回当たったブロックと同じY位置だから側面しか当たらないとして処理
mypx=myg_lx*CHIPSIZE+CHIPSIZE //ブロックの右に移動
}else{//上で処理されなかったもの全てブロックの下に当たったとして処理(手抜き)
mypy=myg_uy*CHIPSIZE+CHIPSIZE //ブロックの下に移動
}
}else{//右上と左下の判定
if map(myg_rx,myg_uy)=4 {//右上が当たった
mypy=myg_uy*CHIPSIZE+CHIPSIZE
}else{
if map(myg_lx,myg_dy)=4 {mypx=myg_lx*CHIPSIZE+CHIPSIZE}//左下が当たった
}
}
}
if spd_rlud=6 {//右上に移動中
if map(myg_rx,myg_uy)=4 {
if myg_uy = (mypy_old/CHIPSIZE) {
mypx=myg_rx*CHIPSIZE-mysizex
}else{
mypy=myg_uy*CHIPSIZE+CHIPSIZE
}
}else{
if map(myg_lx,myg_uy)=4 {mypy=myg_uy*CHIPSIZE+CHIPSIZE}else{
if map(myg_rx,myg_dy)=4 {mypx=myg_rx*CHIPSIZE-mysizex}
}
}
}
if spd_rlud=12 {//右下に移動中
if map(myg_rx,myg_dy)=4 {
if myg_dy = ((mypy_old+mycsy)/CHIPSIZE) {
mypx=myg_rx*CHIPSIZE-mysizex
}else{
mypy=myg_dy*CHIPSIZE-mysizey
}
}else{
if map(myg_lx,myg_dy)=4 {mypy=myg_dy*CHIPSIZE-mysizey}else{
if map(myg_rx,myg_uy)=4 {mypx=myg_rx*CHIPSIZE-mysizex}
}
}
}
if spd_rlud=9 {//左下に移動中
if map(myg_lx,myg_dy)=4 {
if myg_dy = ((mypy_old+mycsy)/CHIPSIZE) {
mypx=myg_lx*CHIPSIZE+CHIPSIZE
}else{
mypy=myg_dy*CHIPSIZE-mysizey
}
}else{
if map(myg_rx,myg_dy)=4 {mypy=myg_dy*CHIPSIZE-mysizey}else{
if map(myg_lx,myg_uy)=4 {mypx=myg_lx*CHIPSIZE+CHIPSIZE}
}
}
}
}
}
}
gradf mypx,mypy,mysizex,mysizey,1,$55ddee,$55ddee
//自分の直ぐ下にブロックがあるか判定
if map(mypx/CHIPSIZE,(mypy+mysizey)/CHIPSIZE)=4 or map((mypx+mycsx)/CHIPSIZE,(mypy+mysizey)/CHIPSIZE)=4 {mes "着地"}//mycsyじゃ無くmysizeyを使って足元下の座標にする
redraw 1
await 16
loop
map(,)の判定回数は最大で7回
足元の判定含めて最大9回