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


HSPTV!掲示板


未解決 解決 停止 削除要請

2007
0608
うひょジャンプアクションゲームの当たり判定がうまくいかない13解決


うひょ

リンク

2007/6/8(Fri) 22:02:59|NO.8841


#define global ctype iflet(%1,%2,%3) (((0!(%1))*(%2))|((0=(%1))*(%3))) #define global ctype ptmap(%1,%2) ((%1<<16) | %2) #define global ctype _ptX(%1) (((%1>>16)&$FFFF)) #define global ctype _ptY(%1) ((%1&$FFFF)) #define global ctype ptX(%1) (((%1>>16)&$FFFF)*32) #define global ctype ptY(%1) ((%1&$FFFF)*32) #module #defcfunc outSpace str strA mystr = "" myss = 0 sdim strB,100 strC = strA repeat getstr strB,strC,myss,' ' if strsize=0:break mystr += strB myss += strsize loop return mystr #defcfunc eq array p1,int p2,local ret ret=0 foreach p1 if p2=p1(cnt):ret=1:break loop return ret #global #const global blockMax 600 #const scrx 512 #const scry 320 #define softName "(ソフト名)" buffer 5,32*6,32*3 // picload "pattern.bmp" color 0,0,255 boxf 0,0,ginfo_winx,64 color 255,255 boxf 0,65,ginfo_winx,ginfo_winy color 0,128,0 line 31,ginfo_winy,31,65 *start screen 0,scrx,scry title softName gmode 4,,,256 boxf rightBlock = 'a','b','c','d' rightTeki = 'B','C' dim pattern,255 pattern('a') = ptmap(0,2) pattern('b') = ptmap(1,2) pattern('c') = ptmap(2,2) pattern('d') = ptmap(3,2) font msgothic,50 color 255,255,255 pos 10,20 mes softName sysfont pos 210,150 mes "Press Enter" repeat stick k,32 if k&32:break await 17 loop //**********************************ステージ読み込み開始 color:boxf dim blockon,blockMax dim blockx,blockMax dim blocky,blockMax dim blockNum,blockMax sdim mine,1000 mine ={"%backR%:0 %backG%:128 %backB%:255 %stageX%:30 %stageY%:20 $map$ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aa..........................aa aa...........B.....C...D.....a aa...aaaaaaaaaaaaaaaaaaaaa...a aa..Ca...................a...a a...aa.......aaaaa.......aa..a a...a......aaaaaaaaa......a..a a..aaaa.....aaaaaaa.....aaaa.a a.....aa...............aa....a a......aa.............aa.....a a......aa.............aa.....a a.....aa...............aa....a a..aaaa.....aaaaaaa.....aaaa.a a...a......aaaaaaaaa......a..a a...aa.......aaaaa.......aa..a aa...a...................a...a aa...aaaaaaaaaaaaaaaaaaaaa...a aa...........................a aa..A.......................aa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa "} notesel mine repeat notemax rerm="" noteget rerm,cnt rerm = outSpace(rerm) if yomu_mode=0{ switch peek(rerm,0) case '%' option_name = strmid(rerm,1,instr(rerm,1,"%")) option_value= strmid(rerm,instr(rerm,0,":")+1,iflet(instr(rerm,0,";")!-1,instr(rerm,0,";"),strlen(rerm))) switch option_name case "backR" backR=int(option_value) swbreak case "backG" backG=int(option_value) swbreak case "backB" backB=int(option_value) swbreak case "stageX" stageX=int(option_value) swbreak case "stageY" stageY=int(option_value) swbreak swend case '$' command_name = strmid(rerm,1,instr(rerm,1,"$")) if command_name="map"{ gyou=0 repeat stageY,cnt+1 rerm="" noteget rerm,cnt repeat stageX if eq(rightBlock,peek(rerm,cnt)){ mnt=cnt repeat blockMax if blockon(cnt)=1:continue blockon(cnt)=1 blockx(cnt)=mnt*32 blocky(cnt)=gyou*32 blockNum(cnt)=peek(rerm,mnt) break loop } if peek(rerm,cnt)='A'{ x=cnt*32 y=gyou*32 } loop gyou++ loop yomu_mode=1 } swbreak swend }else{ break } loop //**********************************ステージ読み込み終わり**********************************初期設定 cur = 0 ;コマ数 mode= 0 ;主人公モード 0=停止 1=歩行 2=ジャンプ muki= 0 ;0=左 1=右 jump_vy = 0 ;ジャンプY移動量 jumpflg=0 ;ジャンプフラグ speedmax=5 ;横移動スピードMax jumpmax=15 ;ジャンプY移動Max fallmax=8 ;ジャンプ降下量Max //**********************************初期設定終わり *main redraw 0 color backR,backG,backB:boxf scrollX = limit(x-scrx/2+16,0,stageX*32-scrx) ;スクロール量 scrollY = limit(y-scry/2+16,0,stageY*32-scry) ;↓ color 128,0,128 //**********************************ブロック描画 repeat blockMax if blockon(cnt)=0:continue // dialog "x:"+blockx(cnt)+"\ny:"+blocky(cnt)+"\nscrollX:"+scrollX+"\nscrollY:"+scrollY+"\n\n"+((blockx(cnt)>scrollX)or(blockx(cnt)<(scrollX-32))or(blocky(cnt)>scrollY)or(blocky(cnt)<(scrollY-32))),2 // if stat=7:end if blockx(cnt)>(scrollX+scrx):continue if blockx(cnt)<(scrollX-32):continue if blocky(cnt)>(scrollY+scry):continue if blocky(cnt)<(scrollY-32):continue pos blockx(cnt)-scrollX,blocky(cnt)-scrollY gcopy 5,ptX(pattern(blockNum(cnt))),ptY(pattern(blockNum(cnt))),32,32 loop //**********************************ブロック描画終わり stick key,31 ;キー判定 //**********************************歩・止ってるとき処理 if mode<=1{ xx=x if key&5{ //**********************************移動処理 if key&1:x-=speedmax:mode=1:muki=0 if key&4:x+=speedmax:mode=1:muki=1 }else:mode=0 ;キー左右どっちも押されてなければmode=0(止) //**********************************ジャンプ処理 if key&16{ mode=2 jump_vy=-jumpmax jump_vx=x-xx } }else{ //**********************************ジャンプ中処理 if key&1:jump_vx-=1 if key&4:jump_vx+=1 if jump_vx<0:muki=0 if jump_vx>0:muki=1 jump_vx = limit(jump_vx,-speedmax,speedmax) x+=jump_vx } //**********************************ジャンプ処理 if mode=2{ if jumpflg:jump_vy++ jump_vy = limit(jump_vy,-jumpmax,fallmax) y+=jump_vy jumpflg^=1 ky=0 /* repeat blockMax if blockon(cnt)=0:continue if x<(blockx(cnt)+32):if blockx(cnt)<(x+32):if blocky(cnt)<(y+32):if y<(blocky(cnt)+32){ } loop */ } //**********************************ジャ中処理終わり //**********************************当たり判定全般処理 repeat blockMax if blockon(cnt)=0:continue if x<(blockx(cnt)+32):if blockx(cnt)<(x+32):if blocky(cnt)<(y+32):if y<(blocky(cnt)+32){ if mode=2{ //**********************************天井処理 if jump_vy<0{ if (blocky(cnt)<y)|(y<(blocky(cnt)+32)){ // myx = x+16-iflet(muki=1,1,0) // if (myx>=blockx(cnt))and(myx<=(blockx(cnt)+31))and(y>=blocky(cnt))and(y<=(blocky(cnt)+31)){ if iflet(muki=0,(x<(blockx(cnt)+32))and(blockx(cnt)<(x+16))and(blocky(cnt)<(y+32))and(y<(blocky(cnt)+16)),((x+16)<(blockx(cnt)+32))and(blockx(cnt)<(x+32))and(blocky(cnt)<(y+32))and(y<(blocky(cnt)+16))){ y = blocky(cnt)+32:jump_vy=1 break } } } //**********************************床処理 if jump_vy>0{ if (blocky(cnt)>y)|((y+32)<blocky(cnt)){ myx = x+16-iflet(muki=1,1,0) myy = y+31 // if (myx>=blockx(cnt))and(myx<=(blockx(cnt)+31))and(y>=blocky(cnt))and(y<=(blocky(cnt)+31)){ if iflet(muki=0,(x<(blockx(cnt)+32))and(blockx(cnt)<(x+16))and(blocky(cnt)<(y+32))and(y<(blocky(cnt)+16)),((x+16)<(blockx(cnt)+32))and(blockx(cnt)<(x+32))and(blocky(cnt)<(y+32))and(y<(blocky(cnt)+16))){ y = blocky(cnt)-32:mode=0 break } } } } //**********************************左右壁処理 if x<blockx(cnt){ if (blockx(cnt)-x)<=16:x = blockx(cnt)-17 if mode=2:break }else{ if (x-blockx(cnt))<=16:x = blockx(cnt)+17 if mode=2:break } //**********************************左右壁処理終了 // break } loop //**********************************画面外に出ない処理 x=limit(x,scrollX-16,scrollX+scrx-16) cur++ if cur&8:cur=0 //**********************************描画処理 pos x-scrollX,y-scrollY switch mode case 0 if muki{ buffer 7,32,32 pos 31,0 gzoom -32,32,5,0,0,32,32 gsel 0 gcopy 7,0,0,32,32 }else{ gcopy 5,0,0,32,32 } swbreak case 1 if muki{ buffer 7,32,32 pos 31,0 gzoom -32,32,5,64+(cur<4)*32,0,32,32 gsel 0 gcopy 7,0,0,32,32 }else{ gcopy 5,64+(cur<4)*32,0,32,32 } swbreak case 2 if muki{ buffer 7,32,32 pos 31,0 gzoom -32,32,5,32+(jump_vy>0)*128,0,32,32 gsel 0 gcopy 7,0,0,32,32 }else{ gcopy 5,32+(jump_vy>0)*128,0,32,32 } swbreak swend //**********************************描画処理終わり //デバッグ用 pos 0,0 mes "scrollX:"+scrollX mes "scrollY:"+scrollY mes "x:"+x+" y:"+y mes "mode:"+mode mes "myflag:"+myflag redraw 1 await 17 // await 300 goto *main
これは多少長いですがジャンプアクションゲームのスクリプトです。
このスクリプトでは、ジャンプ(スペースキー)したときにたまに障害物を突き抜けたり、
ジャンプしているときに壁に横から壁にぶつかるとそのまま下にさがっていったりするのですが、
これらの症状はどのようにすれば改善できるでしょうか?
理想としては、ジャンプしたときに上にぶつかるとそのまま下に落ち始め、
床にぶつかるとそのままそこで止まる、
ジャンプしているときに壁に横から壁にぶつかった場合はY方向の進行量に影響を与えることなく
壁の方向に進めないようになる、ということです。
よろしくお願いします。



この記事に返信する


GENKI

リンク

2007/6/8(Fri) 23:09:59|NO.8842

 いらないところは極力削りましょう。 …長い。_| ̄|○とりあえずプレイはしてみたけどスクリプトは未見です。
とは言えジャンプアクションになると、削ってもこのくらいの量になってしまうのは仕方ないですね。
でもとりあえずオープニングは必要ないと思います。その他、見直して不要なところは削ったほうが
バグの原因特定に役立ちますよ。

 最近ジャンプアクションの質問多いような気が…とりあえず、いつもの参考資料どうぞ。

HSP開発Wiki
http://hspwiki.tm.land.to/?%BE%AE%A5%EF%A5%B6%2F%A5%A2%A5%AF%A5%B7%A5%E7%A5%F3%2F%B4%F0%CB%DC%C6%B0%BA%EE
http://hspwiki.tm.land.to/?cmd=read&page=%B2%A3%A5%B9%A5%AF%A5%ED%A1%BC%A5%EB%B7%BF%A5%B2%A1%BC%A5%E0%2F%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8

一部スクリプトが消失またはHSP2ですが、参考にはなると思います。
(そろそろHSP3用のを書かなきゃいけないかなぁ…。)



a

リンク

2007/6/9(Sat) 04:19:16|NO.8845

GENKIさん、正直そんな丁寧に答えなくていいと思うよ。
ダメなものはダメってはっきり言ってやらないと周りが
「あぁ別に掲示板の注意書きに書かれてることは無視しても怒られることはないんだ」
って思うだけ。

うひょ、お前のそのスクリプトは何行あるんだ?え?
327行あるぞ。それがお前の言うところの多少長いスクリプトか?え?
っざけんじゃねぇよ!!!!長いどころかキリマンジャロ級になげぇスクリプトなんだよ!!!
冗談っぽく書いてるけどコレ本当の話。
お前が分からないもの、俺たちがひょいひょい分かると思ってんのかよ。カス。
お前が分からないものは俺たちはもっとわからねぇんだよ。
お前が苦労すべきところを俺たちに押し付けんなっつうんだよ。
俺たちに答えて欲しかったら俺たちにわかりやすいように書きやがれ。

いいか?一般的に短いスクリプトっていうのは、
エディタの画面に納まりきるコードのことを指すんだ。
フォントによって影響するがな、大体50行前後だと覚えておけ。
がこれはエディタでソースコードを見た場合の話だ。
ブラウザでソースコードを読む場合は40行前後だと覚えておけ。
50行過ぎたらそれはもう長いコードに入るんだよ。
さらに一行の文字数は半角80文字ってことも覚えておけ。
HSPがマルチステートメントを使えるからって行数減らすKIMUみたいに横に広げりゃいいってもんじゃねぇんだよ。
目で追いきれないスクリプトの状態を『コードが散漫』って呼ぶんだ。
逆に余計なコードが詰まりすぎてるのもダメだ。
意味のあるコードがまとまってることが良いソースコードっつうんだよ。
といってもホビー言語のHSPにそこまでソースコードの品質を論じても無駄か?お遊びだもんな。

ったくアレだな。コード読む気しなかったから全然読んでないが、
GENKIの内容を見るが切り、ほんとうに自分の質問にはどの部分のコードが必要なのかわかってねぇんだよな。
オープニングとかまじふざけんじゃねぇよっつう感じ。

お前の理想を俺たちに実現させようとすんじゃねぇよ。



b

リンク

2007/6/9(Sat) 07:04:56|NO.8846

つーか、TUTとうひょは同一人物だって!
TUTで教えてもらえなかったからうひょで聞いてんだって!
IP見りゃすぐ分かるって!



c

リンク

2007/6/9(Sat) 07:40:07|NO.8847

この前のIWGPの挑戦試合、良かったですよ。越中さん。



うひょ

リンク

2007/6/9(Sat) 08:23:18|NO.8848

皆様、申し訳ありませんでした。
確かにコードが無駄に長く、
TUTは僕と同一人物です。
さすがにもうここには居られないので一応解決にしておきます。



eller

リンク

2007/6/9(Sat) 10:14:45|NO.8849

みなさん、おはようございます。

> さすがにもうここには居られない
 そんなことはないはずです。aさんもbさんも「ハンドルネームを複数使うやつはもう書きこむな」といった意図の書き込みはしていないですよね。「分かりやすいように書いてくれ」とは仰ってますが。
 確かにあまり誉められたことではないですが、この反省を次回に活かせば良いのではないでしょうか。

 それに、質問をしたのですから中途半端に終わらせてほしくないと思います。礼節の面は言うまでもないのですが、このスレッドが近い将来うひょさん以外の誰かの役に立つかもしれませんし、意見をいただければWikiに反映させることもできます。
 少なくともGENKIさんのリンクで解決できたのか、それでも足りなかったのか(そしてどこが足りなかったのか)を教えてほしいです。

 もちろん無理にとは言いませんので、時間をおいて考え直してみてくださいね。



a

リンク

2007/6/9(Sat) 13:26:35|NO.8852

>b
同一人物だったってぇ?!!?!?まっじかようううううう!気づかなかったわ!!!
もうこいつはダメだな!!!二度とこれないなこれわ。
どうせ他にも名前つかってたんじゃねぇの?www



GENKI

リンク

2007/6/9(Sat) 13:35:07|NO.8853

 …まんまとダマサレてしまってました。(^_^;
同じ掲示板内で名前変えてもメリットないですよ。
…それはさておき。

 前回もHSP開発Wikiのアドレスは提示してたから、やっぱり読んでもわからなかったってことでしょうか。
どの辺が上手くいかなかったとか、わかりにくかったとか、言ってもらえると解決にもつながるし、Wikiの修正もできて今後の人たちの役にも立つのですが…。
Wikiのどの辺の記事がだめだったんでしょうか?


> さすがにもうここには居られないので一応解決にしておきます。

 aさんもbさんももみなさんうひょさんを追い出したいわけじゃないんですから、言い方がキツイのはそう気にされないほうが…。

後は…というかすでにと言うか、ellerさんの書き込みと内容かぶるので以下省略〜。



p

リンク

2007/6/9(Sat) 16:46:36|NO.8857

馬鹿の分際でHN変えるから来れなくなるんだろ。馬鹿は黙ってルールに従ってろ。
プログラミング初心者はコードを短くしろ云々言われても困るだろうが
鬱陶しくてもネチケットを守っとかないと回答が得にくいぞ。
特にここは他に比べてもネチケットにうるさい部類に入るから。



Drip

リンク

2007/6/9(Sat) 20:23:46|NO.8860

Dripです。

 うひょさん、こんにちは。
ソースを見させていただきました。当たり判定がうまく行かない原因は、
ジャンプ中の時と接地時の時、上昇中の時、下降中の時、
天井判定、左右壁判定、地面判定と、とにかく処理がばらばらになっているため混乱し、
当たり判定を間違えて処理している事が原因のようです。

 この状態で決定的な原因を洗い出すのは非常に困難と思われますし、
このソースを用いてゲーム開発を続行しても拡張性、安定性共に乏しすぎると思います。
自分でも混乱してしまったソースは一旦破棄し、失敗を教訓にゼロから作り直すことで、
より洗練された、短くわかりやすいコーディングができるようになっているはずです。

 以下に厳密な当たり判定のアクションゲームのサンプルを示します。
うひょさんのソースコードも、ここまでブラッシュアップすることができるので、
確実に、落ち着いてコーディングするよう心がけ、完成を目指してみてください。

#define maxx 32 //マップサイズ #define maxy 32 #define size 32 //マップチップサイズ //●当たり判定を一本化する。プレイヤーが壁にめり込むとp1に1を返すマクロを作成。 #define chk(%1,%2,%3) if map((%2)/size,(%3)/size)!0:%1=0:else:\ if map((%2+size-1)/size,(%3)/size)!0:%1=0:else:\ if map((%2)/size,(%3+size-1)/size)!0:%1=0:else:\ if map((%2+size-1)/size,(%3+size-1)/size)!0:%1=0:else:\ %1=1 //ランダムマップ作成 dim map,maxx,maxy:repeat 300:map(rnd(maxx),rnd(maxy))=1:loop repeat maxy:map(maxx-1,cnt)=1:map(0,cnt)=1:loop repeat maxx:map(cnt,maxy-1)=1:map(cnt,0)=1:loop jumpct=0.0:px=size:py=size //プレイヤーの位置と座標初期化 repeat //●メイン stick ky,15 redraw 0 color 255,255,255:boxf //背景クリア jumpct+=0.2 //ジャンプカウンタ増加 if jumpct>=size:jumpct=-0.001+size //ジャンプカウンタがチップサイズを上回ることはない。 py+=jumpct //ジャンプカウンタ反映 chk ans,px,py //プレイヤーがめり込まなかったかチェック if ans=0:{ //めり込んだ場合 //プレイヤーの座標をめり込まない位置に逃がし、ジャンプカウンタをリセットする if jumpct>0:py=py/size*size:else:py=py/size*size+size jumpct=0.0 } if ky&1:chk ans,px-2,py:px-2 //キー操作によってプレイヤが壁にめり込まなければ移動させる if ky&4:chk ans,px+2,py:px+2 //キー操作によってプレイヤが壁にめり込まなければ移動させる chk ans,px,py+1 //プレイヤーが接地しているかチェック if ans=0:if ky&16:jumpct=-8.0 //接地しており、スペースキーが押されていればジャンプする camx=px-ginfo_winx/2:camy=py-ginfo_winy/2 //カメラの位置を設定 color 255:boxf px-camx,py-camy,px-camx+size-1,py-camy+size-1:color ,255 //プレイヤー描画 //マップ描画 repeat ginfo_winx/16:tx=cnt:lx=tx+camx/size repeat ginfo_winy/16:ty=cnt:ly=ty+camy/size if lx<0 | ly<0 | lx>=maxx | ly>=maxy:continue x=tx*size-camx\size:y=ty*size-camy\size if map(lx,ly)!0:boxf x,y,x+size-1,y+size-1 loop loop redraw 1:await 15 //画面を再描画 loop



eller

リンク

2007/6/9(Sat) 20:49:03|NO.8863

> Dripさん
横槍失礼します。ご本人でなくて申し訳ない。
私信に近いのですが、Dripさんのメールアドレスが分からなかったのでここで失礼します。

勝手ながらGENKIさんの挙げていらっしゃるHSP開発Wikiのページ(小ワザ/アクション/基本動作)から「Dripさんによるスクリプト(HSP3)が掲載されています」として、このスレッドにリンクさせていただきました。
もし問題があるようでしたら仰ってください。



うひょ

リンク

2007/6/9(Sat) 21:11:45|NO.8866

皆様、ありがとうございました。
Dripさんの言うとおり、ゼロから作り直すことにします。

しかし、僕がまた掲示板に来てもaさんやbさんのような方が騒いで
この掲示板が荒れてしまうと思うので、
ここに顔を出すのは控えておきます。



.

リンク

2007/6/10(Sun) 15:16:56|NO.8883

既に解決しているようですが一応。
pgetを使って判定する方法もあります。

buffer 1,50,50 : color 128,128,128 : boxf 0,0,50,50 buffer 2,25,25 : color 255,255,255 : boxf 0,0,50,50 screen 0,200,800,,,,200,300 : gmode 2 dim map,4,16 //マップ作成 map(0,1)=1,1,1,0:map(0,3)=0,1,0,1:map(0,5)=0,0,1,0:map(0,7)=0,1,0,0:map(0,9)=1,0,1,0 map(0,11)=0,1,0,0:map(0,12)=0,0,0,1:map(0,13)=1,1,0,1:map(0,14)=1,0,0,1:map(0,15)=1,1,1,1 cx=0 : cy=0 : x=50.0 : y=710.0 : s=3.0 : j=0.0 : gs=0.0 : cy=y+150 *main redraw 0 : color 0,0,0 : boxf cy=y-150 : cy=limit(cy,0,500) //カメラ調整 groll cx,cy //スクロール color 128,128,128 repeat 4 : c=cnt : repeat 16 //マップ描画 if map(c,cnt)=1 : pos c*50,cnt*50 : gcopy 1,0,0,50,50 loop:loop color 255,255,255 //情報を表示 gs:落下速度 j:ジャンプ pos 5+cx,5+cy:mes ""+strf("%.1f",x)+","+strf("%.1f",y)+" GS:"+strf("%.1f",gs)+" J:"+strf("%.1f",j) gs+=0.2 : gs=limitf(gs,0.0,8.0) //落下速度を加算 pget x,y+12 //左のブロックに当たっているか if ginfo(16)=128 && ginfo(17)=128 && ginfo(18)=128 : x+=s pget x+25,y+12 //右のブロックに当たっているか if ginfo(16)=128 && ginfo(17)=128 && ginfo(18)=128 : x-=s pget x+12,y+20 //下のブロックに当たっているか if ginfo(16)=128 && ginfo(17)=128 && ginfo(18)=128 : gs=0.0 y+=gs //落下 if j>0.1 {//ジャンプ j-=0.5 : y-=j-15.0 pget x+12,y+20 //下のブロックに当たっているか if ginfo(16)=128 && ginfo(17)=128 && ginfo(18)=128 : y-=15.0:j=0.0 pget x+12,y //上のブロックに当たっているか if ginfo(16)=128 && ginfo(17)=128 && ginfo(18)=128 : y+=13.0:j=0.0 } pos x,y : gcopy 2,0,0,25,25 //自機表示 redraw 1 : stick key,15 if key&1 : x-=s if key&4 : x+=s if key&16 : if j<=0 && gs<=0 : j=30.0 //スペースキーが押されていて、落下速度が0ならジャンプする x=limitf(x,0.0,175.0) : y=limitf(y,0.0,775.0) //自機が画面外に出ないようにする await 15 : goto *main



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