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


HSPTV!掲示板


未解決 解決 停止 削除要請

2015
0710
IkTk色判定による地面判定 改良お願いします!!18解決


IkTk

リンク

2015/7/10(Fri) 22:10:59|NO.70030


screen 0,800,500,0 :cls 4 repeat redraw 0 color 255,255,255 boxf // 斜線 color 0,0,0 line 300,250,500,100 // 縦線 line 000,200,400,200 // 横線 line 200,100,200,400 pget charx+16,chary+33 r=ginfo(16) : g=ginfo(17) : b=ginfo(18) pos 0,0:color 0,0,0 mes "R:"+str(r)+"G:"+str(g)+"B:"+str(b) getkey lk,37 getkey rk,39 if rk{ charx+3 } if lk{ charx-3 } //スペースキーでジャンプ getkey key,32//スペースキー if key=1 and jump=0{ jump=1 chary-50 } color 255,0,0 boxf charx,chary,charx+32,chary+32 if r=255 and g=255 and b=255{ chary+1 } if r=0 and g=0 and b=0{ chary-1 jump=0 } redraw wait 1 loop

[操作方法]
  →  :右移動
  ←  :左移動
スペース:ジャンプ(問題あり)

上記のプログラムで一応黒いところが床という設定で動けているのですが、

・重力がおかしい
・地面ではずっとキャラがガタガタしている
・壁を貫通
・斜めを上がれない
・ジャンプがおかしい

などと問題が多すぎるのですが、どうすればいいですか?

漠然としていてすいません。
お願いします!!



この記事に返信する


スペース

リンク

2015/7/11(Sat) 13:05:56|NO.70040

多少修正。斜め上がれないのは判定の問題。

screen 0,800,500,0 :cls 4 repeat redraw 0 color 255,255,255 boxf // 斜線 color 0,0,0 line 300,250,500,100 line 301,250,501,100 // 縦線 line 000,200,400,200 // 横線 line 200,100,200,400 pget charx+16,chary+33 r=ginfo(16) : g=ginfo(17) : b=ginfo(18) pos 0,0:color 0,0,0 mes "R:"+str(r)+"G:"+str(g)+"B:"+str(b) getkey lk,37 getkey rk,39 if rk{ charx+3 } if lk{ charx-3 } //スペースキーでジャンプ getkey key,32//スペースキー if key=1 and keyBac=0{ 上昇フラグ=1 上昇カウント=0 } if 上昇フラグ=1:{ 上昇カウント+1 chary-10//上昇速度 if 上昇カウント=5:上昇フラグ=0 } color 255,0,0 boxf charx,chary,charx+32,chary+32 if r=255 and g=255 and b=255 and 上昇フラグ=0{ chary+1 } keyBac=key redraw wait 1 loop



スペース

リンク

2015/7/11(Sat) 15:06:24|NO.70045

床と判定される範囲が狭すぎるのが原因です。
横線の部分をこの様にすることで、解決できます。

// 縦線 boxf 0,200,800,500



IkTk

リンク

2015/7/11(Sat) 16:06:04|NO.70046

おお!
できました!

でも、そうすると、ジャンプの着地点の座標が毎回変わってしまいます。
回避はできないのですかね?



Humi/BassClef

リンク

2015/7/11(Sat) 17:17:55|NO.70051

あまりこういうことをすると、他の人に怒られそうですけど、今後の勉強になればと思い、
少々、リファクタリングをば。

まず、repeat-loop の最初から最後までを redraw でくくるのは余りおすすめできません。
難しい考え方ですけど、できるだけ処理は分けたほうが、
バグの早期発見などにも役に立ちますし、
何よりも処理を書き足すときにラクです。


screen 0,800,500,0 :cls 4 repeat // 移動判定 getkey lk, 37 getkey rk, 39 if rk :charx += 3 if lk :charx -= 3 // 上昇判定 getkey key, 32 // スペースキー if 1 == key and 0 == keyBac { // スペースキーでジャンプ 上昇フラグ = 1 上昇カウント = 0 } if 1 == 上昇フラグ { 上昇カウント++ chary -= 10 // 上昇速度 if 5 == 上昇カウント :上昇フラグ = 0 } keyBac = key // 下降判定 if 0 == 上昇フラグ { // 下降 repeat 10 // ここの数字が下降速度 pget charx+16, chary+33 r=ginfo_r :g=ginfo_g :b=ginfo_b if 255 != r or 255 != g or 255 != b { break } chary++ loop } // 描画 redraw 0 // 背景 color 255,255,255 boxf pos :color mes "R:"+str(r)+"G:"+str(g)+"B:"+str(b) // 斜線 color line 300,250,500,100 line 301,250,501,100 // 縦線 line 000,200,400,200 // 横線 line 200,100,200,400 // 移動対象 color 255 boxf charx, chary, charx+32, chary+32 redraw wait 1 loop

参考になるといいのですけど……



Humi/BassClef

リンク

2015/7/11(Sat) 17:23:44|NO.70052

補足ですけど、
斜め上がりたいのなら

if rk :charx += 3 if lk :charx -= 3
ここらへんの処理を変更するとできると思います。



IkTk

リンク

2015/7/11(Sat) 20:45:24|NO.70054

具体的にどのように変えればよいのでしょうか?
もう1つif文を作るのでしょうか?
教えてください!!



スペース

リンク

2015/7/12(Sun) 01:39:28|NO.70061

自分が作ったプログラムの動きは完全に把握できていますか?



Humi/BassClef

リンク

2015/7/12(Sun) 14:31:21|NO.70064

そうですね、スペースさんの言うとおり、
なぜ、左右に進むと上がれないかを調べるとその対処法もわかると思います。



IkTk

リンク

2015/7/12(Sun) 15:20:57|NO.70066


pget charx+18, chary+33 r=ginfo_r :g=ginfo_g :b=ginfo_b if r=0{ chary-1 }
これを追加して、斜面を太くすれば、ある程度の傾きまでは上るのですが、
45°とかになると上がらないで貫通します。

どうすればいいのでしょうか?



スペース

リンク

2015/7/12(Sun) 18:01:27|NO.70072

その当たり判定でゲームを作ることは出来なくはないですが、
初心者にはこっちの処理方法の方がやりやすいと思う。
30分ほどで作った物なのでバグあるかもしれません。

winX=200 winY=200 ブロック数x=10 ブロック数y=10 ブロックサイズx=double(winx)/double(ブロック数y) ブロックサイズy=double(winy)/double(ブロック数y) Screen 0,winX,winY dim マップ,ブロック数x,ブロック数y //0が空宙、1が地面、2が壁 マップ.0.0=2,2,2,2,2,2,2,2,2,2 マップ.0.1=2,0,0,0,0,0,0,0,2,2 マップ.0.2=2,0,0,0,0,0,0,1,1,2 マップ.0.3=2,0,0,0,0,0,1,1,1,2 マップ.0.4=2,0,0,0,1,1,1,1,1,2 マップ.0.5=2,0,0,0,0,0,0,0,0,2 マップ.0.6=2,0,0,0,0,0,0,0,0,2 マップ.0.7=2,0,0,0,2,1,1,1,1,2 マップ.0.8=2,0,0,0,2,0,0,0,0,2 マップ.0.9=2,1,1,1,1,1,1,1,1,2 CpX=1:CpY=1//キャラの位置。キャラクターポジションの略 repeat//メインループ getkey 左key,37//キー入力チェック。上キーでジャンプもいいけど今回はスペースでジャンプ getkey 右key,39 getkey 上key,38 getkey 下key,40 getkey スペースkey,32 //現在地のマップの状況を判定 移動済みフラグ=0 if マップ.CpX.Cpy=0:{//次キャラが空宙に居る時 if マップ.CpX.(Cpy+1)=0{//かつ下も空宙の時 if ジャンプフラグ=0:Cpy+1//下に移動(重力) } if 右key=1:{//右に移動しようとした時 if マップ.(CpX+1).Cpy=0 and 移動済みフラグ=0:CpX+1:移動済みフラグ=1//右が空宙=何もなかった時 if マップ.(CpX+1).Cpy=1 and 移動済みフラグ=0:CpX+1:CpY-1:移動済みフラグ=1//右に地面があった時。 if マップ.(CpX+1).Cpy=2 and 移動済みフラグ=0:移動済みフラグ=1//右が壁だった時。今回は特に処理無し } if 左key=1:{//左に移動しようとした時 if マップ.(CpX-1).Cpy=0 and 移動済みフラグ=0:CpX-1:移動済みフラグ=1//右が空宙=何もなかった時 if マップ.(CpX-1).Cpy=1 and 移動済みフラグ=0:CpX-1:CpY-1:移動済みフラグ=1//右に地面があった時。 if マップ.(CpX-1).Cpy=2 and 移動済みフラグ=0:移動済みフラグ=1//右が壁だった時。今回は特に処理無し } if スペースkey=1 and スペースkeyBac=0:ジャンプフラグ=1 if ジャンプフラグ=1:{ if マップ.CpX.(Cpy-1)=0:Cpy-1//上が空宙である事を判定 ジャンプカウント+1 if ジャンプカウント=4:ジャンプフラグ=0:ジャンプカウント=0//ジャンプの高さ } } redraw 0 Color 255,255,255:boxf//画面初期化 repeat ブロック数x//空宙・地面・壁をわかりやすく描画 ct=cnt repeat ブロック数y if マップ.ct.cnt=0:Color 255,200,200 if マップ.ct.cnt=1:Color 200,255,200 if マップ.ct.cnt=2:Color 200,200,50 pos ct*ブロックサイズx,cnt*ブロックサイズy:mes "■" loop loop pos Cpx*ブロックサイズx,Cpy*ブロックサイズy:Color 0,0,255:mes "●"//次キャラを●で描画 redraw 1 await 100//await 17-(cnt\3=0)//60fpsを維持 左keyBac=左key 右keyBac=右key 上keyBac=上key 下keyBac=下key スペースkeyBac=スペースkey loop



kanamaru

リンク

2015/7/12(Sun) 19:49:33|NO.70074

ふと思ったんですけど、
hspで日本語の変数名って使えるんですか?
使えたとしても推奨されるものではないと思いますが



Humi/BassClef

リンク

2015/7/12(Sun) 20:05:59|NO.70077

一応日本語の変数名も使えますけど、なるべくローマ字を使ったほうがよいと思います。
ですが、変に分かりづらくなるくらいなら日本語でもかまわないと私は思います。

burokkusuux = 0
と書くくらいなら

ブロック数x = 0
のほうがいいです



IkTk

リンク

2015/7/12(Sun) 20:09:34|NO.70078

なるべくこのままの方法にしたいのですが、、、



Humi/BassClef

リンク

2015/7/12(Sun) 20:17:12|NO.70080

わからないなら徐々に覚えていくでいいと思います。
たいていexeにする際に変数名なんてどっかに消えてしまいますw



暇人

リンク

2015/7/13(Mon) 23:44:22|NO.70113

点の色で判定は、移動経路を縦横1ドット毎に、接触するまで繰り返す事が必要(と言うか結局一番楽)。
通過できない部分を、塗りつぶして、移動先の点だけ判定しても結局接触しなくなるところを、探す必要が出るし
壁の厚さを、速度が上回れば通り抜けてしまう


screen 0,800,500,0 :cls 4 csx=32 //キャラサイズ csy=32 ccx=csx-1 //キャラコリジョンサイズ(当り判定は0〜サイズなので32にすると範囲33になる) ccy=csy-1 charx=10 charx=10 repeat redraw 0 color 255,255,255 boxf // 斜線 color 0,0,0 line 300,250,500,100 // 縦線 line 000,200,400,200 // 横線 line 200,100,200,400 line 550,100,500,100 line 550,100,600,200 line 600,200,800,250 line 200,100,300,100 line 200,100,300,200 line 200,200,300,100 getkey lk,37 getkey rk,39 char_vx=0 if rk {char_vx+3} //移動速度 if lk {char_vx-3} if jump { //ジャンプ中なら if char_vy<25 {char_vy+1}//25を限度に速度加算(最初はマイナスなので徐々に減速し頂点で逆転する) } //スペースキーでジャンプ key_bak=key getkey key,32//スペースキー if key=1 and jump=0 {jump=1 : char_vy=-16}//ジャンプフラグとジャンプ速度をセット nx=abs(char_vx) //移動速度を判定ループ総回数にする ny=abs(char_vy) _charx=charx+ccx/2 //判定用座標 _chary=chary+ccy if char_vx > 0 {svx=1}else{svx=-1} //判定ループ一回の移動量 if char_vy >= 0 {svy=1}else{svy=-1} if nx>ny {//横のループ回数のほうが多い if ny { vx=nx/ny //縦に1ドット進んだ時の横の判定ループ回数 repeat ny+((nx\vx)>0) //余りがあるなら1回分加算 repeat limit(nx,0,vx) pget _charx+svx,_chary //仮座標で色取得 if ginfo_r | ginfo_g | ginfo_b { _charx+svx }else{break}//接触無しなので実際に移動 loop if ny=cnt {break} //1回分追加されたのは横移動のためなので縦移動は終了 nx-vx //判定ループ総回数から今回の判定ループ回数を減算して残りを次のループ回数にする pget _charx,_chary+svy //仮座標で色取得 if (ginfo_r | ginfo_g | ginfo_b) {_chary+svy}//接触無しなので実際に移動 loop }else{//縦移動無し(傾斜対応) repeat nx pget _charx+svx,_chary if ginfo_r | ginfo_g | ginfo_b { _charx+svx }else{//横移動で接触した pget _charx,_chary-1 //真上の色取得 if (ginfo_r | ginfo_g | ginfo_b)=0 {break}//真上に天井があるので抜ける _chary_bak=_chary //上れなかったら戻せるように repeat 2 //縦2ドットまで上る _chary-- //とりあえず上に移動 pget _charx+svx,_chary //上に移動した場合の色を取得 if ginfo_r | ginfo_g | ginfo_b {//接触無しなので ystop=0 //上りストップフラグクリアして抜ける break }else{ystop++} //上がっても接触してるので上りストップフラグセット loop if ystop {_chary=_chary_bak:ystop=0:break}//上っても接触してるのでY座標を戻して横移動を抜ける _charx+svx } //下り坂を地面として対応させる(45度以上の傾斜は落下になる) if jump=0 {//地上にいる pget _charx,_chary+1 if ginfo_r | ginfo_g | ginfo_b {_chary+1}//接触して無いなら下に移動 } loop } }else{//縦のループ回数のほうが多い if ny { if nx { vy=ny/nx repeat nx+((ny\vy)>0) repeat limit(ny,0,vy) pget _charx,_chary+svy if ginfo_r | ginfo_g | ginfo_b {_chary+svy}else{break} loop if nx=cnt {break} ny-vy pget _charx+svx,_chary if ginfo_r | ginfo_g | ginfo_b {_charx+svx}//else{if svy<0 {char_vy=0:break}} loop }else{//横移動無し repeat ny pget _charx,_chary+svy if ginfo_r | ginfo_g | ginfo_b {_chary+svy}else{break} loop } } } if svy>0 {//落下か縦移動無し pget _charx,_chary+1 //足元の座標の色取得 if ginfo_r | ginfo_g | ginfo_b {//無いのでジャンプ中フラグセット jump=1 }else{//接触したのでジャンプ中フラグとジャンプ速度クリア jump=0 char_vy=0 } }else{//上昇中 pget _charx,_chary-1 //真上の色を取得 if (ginfo_r | ginfo_g | ginfo_b)=0 {char_vy=0}//天井が有るのでジャンプ速度クリア } charx=_charx-ccx/2 chary=_chary-ccy color 255,0,0 gradf charx,chary,csx,csy //boxfはサイズと思って座標を指定すると1ドット大きくなってドット単位の判定してる場合見た目がややこしいのでgradfを使用 redraw await 16 loop
足元1ドットしか判定してないので頭上とかキャラの幅に合う壁の判定するなら
更に判定回数は増える



IkTk

リンク

2015/7/14(Tue) 01:36:40|NO.70115

暇人さん、あなたは天才なんですか!?!?
僕の持っていた疑問が完全にすべて解決されました!!
ほかの方たちも本当にありがとうございました!!

またよろしくお願いします!!



IkTk

リンク

2015/7/14(Tue) 01:42:37|NO.70117

メカニズムのわかりやすい説明もありがとうございます!!
きちんと理解していきたいと思います!
これからもプログラミングがんばります!!



暇人

リンク

2015/7/23(Thu) 00:44:01|NO.70201

モジュール内の命令として作れば
複数キャラにも間単に対応できる

#module #deffunc bgcol var charx,var chary,var char_vx,var char_vy,var jump,int ccx,int ccy nx=abs((charx+char_vx)-charx) //移動速度を判定ループ総回数にする ny=abs((chary+char_vy)-chary) _charx=(charx+ccx/2) //判定用座標 _chary=(chary+ccy) if char_vx >= 0 {svx=1}else{svx=-1} //判定ループ一回の移動量 if char_vy >= 0 {svy=1}else{svy=-1} if nx>ny {//横のループ回数のほうが多い if ny { vx=nx/ny //縦に1ドット進んだ時の横の判定ループ回数 repeat ny+((nx\vx)>0) //余りがあるなら1回分加算 repeat limit(nx,0,vx) pget _charx+svx,_chary //仮座標で色取得 if ginfo_r | ginfo_g | ginfo_b { _charx+svx }else{break}//接触無しなので実際に移動 loop if ny=cnt {break} //1回分追加されたのは横移動のためなので縦移動は終了 nx-vx //判定ループ総回数から今回の判定ループ回数を減算して残りを次のループ回数にする pget _charx,_chary+svy //仮座標で色取得 if (ginfo_r | ginfo_g | ginfo_b) {_chary+svy}//接触無しなので実際に移動 loop }else{//縦移動無し(傾斜対応) repeat nx pget _charx+svx,_chary if ginfo_r | ginfo_g | ginfo_b { _charx+svx }else{//横移動で接触した pget _charx,_chary-1 //真上の色取得 if (ginfo_r | ginfo_g | ginfo_b)=0 {break}//真上に天井があるので抜ける _chary_bak=_chary //上れなかったら戻せるように repeat 2 //縦2ドットまで上る _chary-- //とりあえず上に移動 pget _charx+svx,_chary //上に移動した場合の色を取得 if ginfo_r | ginfo_g | ginfo_b {//接触無しなので ystop=0 //上りストップフラグクリアして抜ける break }else{ystop++} //上がっても接触してるので上りストップフラグセット loop if ystop {_chary=_chary_bak:ystop=0:break}//上っても接触してるのでY座標を戻して横移動を抜ける _charx+svx } //下り坂を地面として対応させる(45度以上の傾斜は落下になる) if jump=0 {//地上にいる pget _charx,_chary+1 if ginfo_r | ginfo_g | ginfo_b {_chary+1}//接触して無いなら下に移動 } loop } }else{//縦のループ回数のほうが多い if ny { if nx { vy=ny/nx repeat nx+((ny\vy)>0) repeat limit(ny,0,vy) pget _charx,_chary+svy if ginfo_r | ginfo_g | ginfo_b {_chary+svy}else{break} loop if nx=cnt {break} ny-vy pget _charx+svx,_chary if ginfo_r | ginfo_g | ginfo_b {_charx+svx}//else{if svy<0 {char_vy=0:break}} loop }else{//横移動無し repeat ny pget _charx,_chary+svy if ginfo_r | ginfo_g | ginfo_b {_chary+svy}else{break} loop } } } if svy>0 {//落下か縦移動無し pget _charx,_chary+1 //足元の座標の色取得 if ginfo_r | ginfo_g | ginfo_b {//無いのでジャンプ中フラグセット jump=1 }else{//接触したのでジャンプ中フラグとジャンプ速度クリア jump=0 char_vy=0 } }else{//上昇中 pget _charx,_chary-1 //真上の色を取得 if (ginfo_r | ginfo_g | ginfo_b)=0 {char_vy=0}//天井が有るのでジャンプ速度クリア } charx=_charx-ccx/2 chary=_chary-ccy return #global screen 0,800,500,0 :cls 4 csx=32 //キャラサイズ csy=32 ccx=csx-1 //キャラコリジョンサイズ(当り判定は0〜サイズなので32にすると範囲33になる) ccy=csy-1 charx=10.0 chary=10.0 esx=32 esy=32 ecx=esx-1 ecy=esy-1 enemy_max=10 //敵の数 dim enemyx,enemy_max dim enemyy,enemy_max dim enemy_vx,enemy_max dim enemy_vy,enemy_max dim enemy_jump,enemy_max repeat redraw 0 color 255,255,255 boxf // 斜線 color 0,0,0 line 300,250,500,100 // 縦線 line 000,200,400,200 // 横線 //color 200 line 200,100,200,400 line 550,100,500,100 line 550,100,600,200 line 600,200,800,250 line 200,100,300,100 line 200,100,300,200 line 200,200,300,100 getkey lk,37 getkey rk,39 char_vx=0 if rk {char_vx=3} //移動速度 if lk {char_vx=-3} if jump { //ジャンプ中なら if char_vy<25 {char_vy+1}//25を限度に速度加算(最初はマイナスなので徐々に減速し頂点で逆転する) } //スペースキーでジャンプ key_bak=key getkey key,32//スペースキー if key=1 and jump=0 {jump=1 : char_vy=-16}//ジャンプフラグとジャンプ速度をセット repeat enemy_max if rnd(150)=0 {enemy_vx(cnt)*-1} if enemyx(cnt)<100 {enemy_vx(cnt)=2} if enemyx(cnt)>ginfo_sx-100 {enemy_vx(cnt)=-2} if enemy_jump(cnt) { //ジャンプ中なら if enemy_vy(cnt)<25 {enemy_vy(cnt)+1}//25を限度に速度加算(最初はマイナスなので徐々に減速し頂点で逆転する) } if rnd(100)=0 and enemy_jump(cnt)=0 {enemy_jump(cnt)=1 : enemy_vy(cnt)=-16}//ジャンプフラグとジャンプ速度をセット bgcol enemyx(cnt), enemyy(cnt), enemy_vx(cnt), enemy_vy(cnt), enemy_jump(cnt), ecx, ecy loop bgcol charx, chary, char_vx, char_vy, jump, ccx, ccy color 128,0,128 repeat enemy_max color 128,0,128 gradf enemyx(cnt),enemyy(cnt),esx,esy color 0,128,0 gradf enemyx(cnt)+4,enemyy(cnt)+4,esx-8,esy-8 loop color 255,0,0 gradf charx,chary,csx,csy //boxfはサイズと思って座標を指定すると1ドット大きくなってドット単位の判定してる場合見た目がややこしいのでgradfを使用 redraw await 16 loop



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