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


HSPTV!掲示板


未解決 解決 停止 削除要請

2008
1214
ブロック当たり判定について32解決


ブロック

リンク

2008/12/14(Sun) 17:29:41|NO.21556

//ボールのブロックに対する当たり判定//
repeat BROYKAZU
RCNT = cnt
repeat BROXKAZU
if bro_map.cnt.RCNT = 0 : continue ;0ならブロックが存在しないのでスキップする
if((by+bsize)>=broy.cnt.RCNT) & (by<=(broy.cnt.RCNT+broysize)) & ((bx+bsize)>=brox.cnt.RCNT) & (bx<=(brox.cnt.RCNT+broxsize)) { ;ボールがブロックに当たったら
if((bbx+bsize)>=brox.cnt.RCNT) & (bbx<=(brox.cnt.RCNT+broxsize)) { ;ブロックの上か下にボールが当たった場合の処理
bmy=-bmy ;ボールの縦移動の反転
bro_map.cnt.RCNT = 0 ;当たったブロックを消す
gosub *kasan ;得点の加算
brokazu-- ;ブロックの数を一つ減らす
continue ;スキップする
}
if((bby+bsize)>=broy.cnt.RCNT) & (bby<=(broy.cnt.RCNT+broysize)) { ;ブロックの左か右にボールが当たった場合の処理
bmx=-bmx ;ボールの横移動の反転
bro_map.cnt.RCNT = 0 ;当たったブロックを消す
gosub *kasan ;得点の加算
brokazu-- ;ブロックの数を1つ減らす
continue ;スキップする
}
//端にあたったら両方反転//
bmx=-bmx
bmy=-bmy
brokazu--
bro_map.cnt.RCNT = 0 ;当たったブロックを消す
}
loop
loop
return

ブロックとボールの当たり判定がうまくいかないんですけど誰か教えていただけませんか?
横からボールが当たった時になぜかブロックを貫通してしまうんです

よろしくお願いします



この記事に返信する


SYAM

リンク

2008/12/14(Sun) 19:18:16|NO.21558

前後の処理も変数の意味もわからない、スクリプトの一部分からバグを探せというのは、あまりにも無茶ですよう。



ブロック

リンク

2008/12/14(Sun) 20:05:30|NO.21559

では、全て貼り付けさせていただきます

#define BROXSIZE 48 ;ブロックの横サイズ
#define BROYSIZE 20 ;ブロックの縦サイズ
#define RAKETSIZEX 80 ;ラケットの横サイズ
#define RAKETSIZEY 20 ;ラケットの縦サイズ
#define BROXKAZU 10 ;ブロックの横の数
#define BROYKAZU 8 ;ブロックの縦の数
#define BSIZE 15 ;ボールのサイズ
#define WINX 640 ;ウィンドウの横サイズ
#define WINY 480 ;ウィンドウの縦サイズ
#define mm 8 ;間隔
rx=200 ;ラケットのX座標
ry=400 ;ラケットのY座標

*stage1
//ブロックのマップ//
dim bro_map,BROXKAZU,BROYKAZU
bro_map.0.00 = 0,0,0,0,0,0,0,0,0,0
bro_map.0.01 = 0,1,2,1,2,1,2,1,2,0
bro_map.0.02 = 0,2,1,2,1,2,1,2,1,0
bro_map.0.03 = 0,1,2,1,2,1,2,1,2,0
bro_map.0.04 = 0,2,1,2,1,2,1,2,1,0
bro_map.0.05 = 0,1,2,1,2,1,2,1,2,0
bro_map.0.06 = 0,2,1,2,1,2,1,2,1,0
bro_map.0.07 = 0,1,2,1,2,1,2,1,2,0
//ブロックの配置座標の初期化//
dim BROX,BROXKAZU,BROYKAZU
dim BROY,BROXKAZU,BROYKAZU
repeat BROYKAZU
RCNT = cnt
repeat BROXKAZU
BROX.cnt.RCNT = cnt*BROXSIZE ;ブロックの左座標
BROY.cnt.RCNT = RCNT*BROYSIZE ;ブロックの上座標
brokazu++ ;ブロックの数
loop
loop
brokazu=56
screen 0,winx,winy ;ウィンドウのサイズ

*main
stick ky,$1f ;キーの情報を取得 16進数表記 「 $ 」
if ky&128 :goto *owari ;[ESC]中断チェック
redraw 0
color:boxf
gosub *blockdraw
gosub *raket
gosub *tama
gosub *clear
gosub *joho
redraw 1
await 15
goto *main

*blockdraw //ブロックの配置//
repeat BROYKAZU ;ブロックの縦の数
RCNT = cnt
repeat BROXKAZU ;ブロックの横の数
if bro_map.cnt.RCNT = 0 : continue ;0なら何もしない
if bro_map.cnt.RCNT = 1 : color 0,255,0 ;緑色のブロック
if bro_map.cnt.RCNT = 2 : color 0,0,255 ;青色のブロック
if bro_map.cnt.RCNT = 3 : color 100,100,100 : ;ねずみ色のブロック
  boxf BROX.cnt.RCNT,BROY.cnt.RCNT,BROX.cnt.RCNT+BROXSIZE,BROY.cnt.RCNT+BROYSIZE ;ブロックの配置
loop
loop
return

*raket //ラケットの移動//
color 255,0,255:boxf rx,ry,rx+RAKETSIZEX,ry+RAKETSIZEY ;ラケットの描画
stick ky,21
if ky&1 : rx-raketspeed ;ラケットが左移動する
if ky&4 : rx+raketspeed ;ラケットが右移動する
if (rx<0){
rx=0
}
if (rx>(480-raketsizex)){
rx=480-raketsizex
}
if startflg=0 { ;スタートフラグが0なら
if ky&16 { ;スペースキーを押したらスタートする
startflg=1 ;スタートフラグを1にする
bx=rx + 16 ;ボールのX座標
by=380 ;ボールのY座標
bmx=5 ;ボールの横移動量
bmy=5 ;ボールの縦移動量
raketspeed=10 ;ラケットの移動量設定
}
}
return

*tama //玉の移動//
if startflg=0 : return
bbx=bx ;1つ前の玉のX座標
bby=by ;1つ前の玉のY座標
bx+bmx ;玉のX移動
by+bmy ;玉のY移動
if bx<0 : bx=0 : bmx=-bmx ;ウィンドウの一番左端にぶっかったら横移動の反転
if bx+bsize>=480 : bmx=-bmx ;ウィンドウの一番右端にぶったったら横移動の反転
if by+bsize>=480 : startflg=0 ;ウィンドウの一番下に落ちたらフラグを0にする
if by<0 : by=0 : bmy=-bmy ;ウィンドウの一番上にぶっかったら縦移動の反転
if (ry<=(by+bsize)) & ((ry+raketsizey)>by) & (rx<=(bx+bsize)) & ((rx+raketsizex)>bx) { ;ラケットとボールの当たり反転
if (ry<(by+bsize)) & ((ry+raketsizey)>by){
bmx=-bmx
} else {
bmy=-bmy
}
}
color 255,0,0
circle bx,by,bx+bsize,by+bsize,1
//ボールのブロックに対する当たり判定//
 repeat BROYKAZU
  RCNT = cnt
   repeat BROXKAZU
    if bro_map.cnt.RCNT = 0 : continue ;0ならブロックが存在しないのでスキップする
if((by+bsize)>=broy.cnt.RCNT) & (by<=(broy.cnt.RCNT+broysize)) & ((bx+bsize)>=brox.cnt.RCNT) & (bx<=(brox.cnt.RCNT+broxsize)) {
if((bbx+bsize)>=brox.cnt.RCNT) & (bbx<=(brox.cnt.RCNT+broxsize)) {
bmy=-bmy ;ボールの縦移動の反転
bro_map.cnt.RCNT = 0 ;当たったブロックを消す
gosub *kasan ;得点の加算
brokazu-- ;ブロックの数を一つ減らす
continue ;スキップする
}
if((bby+bsize)>=broy.cnt.RCNT) & (bby<=(broy.cnt.RCNT+broysize)) {
bmx=-bmx ;ボールの横移動の反転
bro_map.cnt.RCNT = 0 ;当たったブロックを消す
gosub *kasan ;得点の加算
brokazu-- ;ブロックの数を1つ減らす
continue ;スキップする
}
//端にあたったら両方反転//
bmx=-bmx
     bmy=-bmy
brokazu--
bro_map.cnt.RCNT = 0 ;当たったブロックを消す
}
loop
loop
return

*kasan
hit=0
tokuten + 10 ;得点加算
hit++ ;打ち返しカウント
if tokuten = 1000 : ball = ball + 1 ;ボール加算
gosub *joho ;情報領域表示
return



SYAM

リンク

2008/12/14(Sun) 20:47:52|NO.21560

貫通する(ように見える)理由は分かります。
ボールの移動 1 回で、同じ方向にある 2 個のブロックを同時に破壊したとき、速度の反転を 2 回してしまっているからですね。



GENKI

リンク

2008/12/14(Sun) 20:51:55|NO.21561

・スクリプトの整形に全角スペースを使ってはいけません。tabや半角スペースを使ってください。
・スクリプトを貼り付けるときは、preタグで囲むとタブや半角スペースが使えるのでレイアウトが崩れません。


> では、全て貼り付けさせていただきます

> #ラベルが存在しません [owari]
> #ラベルが存在しません [clear]
> #ラベルが存在しません [joho]

存在しないラベルがいくつかあるようです。
スクリプトを貼り付けるときは
 ・出来るだけそのままで動くもの。(問題が確認できるもの。)
 ・明らかな不要部分(問題とは関係ない部分)を削除したもの。
にするよう心がけていただけると助かります。



ブロック

リンク

2008/12/14(Sun) 22:20:32|NO.21563

SYAMさん
つまり、ボール速度の反転を1回だけにすればいいという事ですか?



SYAM

リンク

2008/12/14(Sun) 22:40:21|NO.21565

私に聞くまでもなく、2 回反転したら元の方向に戻っちゃいますからね…。
反転は 1 回でないといけません。



ブロック

リンク

2008/12/14(Sun) 23:02:30|NO.21567

SYAMさん
何処の反転を修正すればうまくいきますか?



SYAM

リンク

2008/12/14(Sun) 23:34:58|NO.21572

「ボールの移動 1 回で、同じ方向にある 2 個のブロックを同時に破壊したとき、速度の反転を 2 回してしまっている」
の意味はわかったのですか?
伝わっていたらどこが悪いのかはすぐわかると思うのですが……。
ボールがブロックを破壊したときの、ボールの速度を反転している箇所です。


ついでに。
ちなみに、あまりちゃんと読んでないので細かいことは分かりませんが…
もしかして、ブロックの角にななめにぶつかったとき、点数が入らないんじゃないでしょうか?



SYAM

リンク

2008/12/14(Sun) 23:49:03|NO.21574

もうひとつついでに。

角に当たったときに進行方向を180度反転させようとしていますが、
これだとまっすぐ並んだブロックの境界線付近にボールが当たったときに不自然な反射をすることがあります。
角の処理は無いほうがよいかもしれませんね。



リンク

2008/12/15(Mon) 18:26:40|NO.21584

以下のように変更すれば うまくいくようです

//ボールのブロックに対する当たり判定//
repeat BROYKAZU
RCNT = cnt
repeat BROXKAZU
xx=0
if bro_map.cnt.RCNT = 0 : continue ;0ならブロックが存在しないのでスキップする
if((by+bsize)>=broy.cnt.RCNT) & (by<=(broy.cnt.RCNT+broysize)) & ((bx+bsize)>=brox.cnt.RCNT) & (bx<=(brox.cnt.RCNT+broxsize)) {

if((bbx+bsize)>=brox.cnt.RCNT) & (bbx<=(brox.cnt.RCNT+broxsize)) {
bmy=-bmy ;ボールの縦移動の反転
bro_map.cnt.RCNT = 0 ;当たったブロックを消す
gosub *kasan ;得点の加算
brokazu-- ;ブロックの数を一つ減らす
xx=1 ;スキップする
}
}
if bro_map.cnt.RCNT = 0 : continue ;0ならブロックが存在しないのでスキップする
if((by+bsize)>=broy.cnt.RCNT) & (by<=(broy.cnt.RCNT+broysize)) & ((bx+bsize)>=brox.cnt.RCNT) & (bx<=(brox.cnt.RCNT+broxsize)) {

if((bby+bsize)>=broy.cnt.RCNT) & (bby<=(broy.cnt.RCNT+broysize)) {
bmx=-bmx ;ボールの横移動の反転
bro_map.cnt.RCNT = 0 ;当たったブロックを消す
gosub *kasan ;得点の加算
brokazu-- ;ブロックの数を1つ減らす
xx=1 ;スキップする
}
}
if xx=1 : break
loop
if xx=1 : break
loop
return


縦方向の判定と横方向の判定をして
どちらかがあたっていれば
ループを抜けるようにすればいいみたいですね



SYAM

リンク

2008/12/15(Mon) 19:02:47|NO.21585

貫通はしませんが、ブロックの境界線付近で怪しげな反射をしてしまいますね…。
以下に違う方法のサンプルを載せます。


※preタグを使いましょう。。。

x=10.0:y=10.0 vx=0.01:vy=0.007 randomize #module #defcfunc checkhit double x, double y ret=0 pget x,y if (ginfo_r>0):ret=1 return ret #global screen 0,240,240,0:cls 4 color 192,255,255:boxf 0,0,239,239 color 0,0,0:boxf 4,4,235,235 color 255,255,255 repeat 65 font msgothic,rnd(16)+32,rnd(3) pos rnd(211)+4,rnd(188)+4 mes strf("%c",rnd(26)+65) loop *MAIN_ROUTINE redraw 0 if (checkhit(x,y)) { r=ginfo_r if (checkhit(x-vx,y+vy)) { if (checkhit(x+vx,y-vy)){ vx = -vx : vy = -vy } else { vy = -vy } } else { vx = -vx } if (r>250) { color 0,0,0:pset x,y } } else { color 0,0,0 pset x,y } x+=vx y+=vy if (checkhit(x,y)==0) : color 0,255,255 : pset x,y redraw 1,x-2,y-2,4,4 await 0 goto *MAIN_ROUTINE

ボールが点なので見にくいでしょうが、一応白い所を壊しつつ反射を続けます。

キモである反射の部分の仕組みは、

今いる場所が壁なら、
 仮にX方向に反転した先が壁なら
  仮にY方向に反転した先が壁なら
   ・X,Y両方反転(ちょうど窪みの中心に突っ込んだ)
  Y方向に反転した先が壁でないなら
   ・Y方向に反転
 X方向に反転した先が壁でないなら
  ・Y方向に反転
壁でないなら
 ・そのまま直進

…のようになっています。
これだとブロックの境界線付近の反射でも余計な反転はしません。



ブロック

リンク

2008/12/16(Tue) 09:53:07|NO.21622

皆さん教えていただきありがとうございました
ボールとブロックの当たり判定がうまく出来るようになりました

あと、もう一つ聞きたい事があります
ステージを複数組み合わせたいのですけれども
#defineが原因でうまくいかないんですけれども他にやり方があれば
教えていただけませんか?



SYAM

リンク

2008/12/16(Tue) 12:09:26|NO.21624

「うまくいかない」で何が起きているか判るひとは多分いないので、もう少し詳しく…
とりあえず…、
define にしてることが原因だって判っているのなら、そもそもそこを define にしてることが妥当なのかどうかから、考え直してみてはどうでしょう?



ブロック

リンク

2008/12/16(Tue) 14:33:08|NO.21627

ブロックの数を指定している
#define BROXKAZU 10 ;ブロックの横の数
#define BROYKAZU 8 ;ブロックの縦の数
の所なんですけどこれだと全て固定されてしまうのです
だから、ステージごとにブロックの指定をしたいのですが何か良い方法があれば
教えていただけませんか?



SYAM

リンク

2008/12/16(Tue) 15:06:53|NO.21628

>良い方法
「なぜ define なのか考えてみる」



llllllllll

リンク

2008/12/16(Tue) 17:11:28|NO.21631

defineは命令自体よくしらないけど
BROXKAZU=10
とかにすればall okじゃね?って思う
ステージごとにBROXKAZU=12
とかかえていけば



ブロック

リンク

2008/12/17(Wed) 09:28:51|NO.21652

BROXKAZU 10
BROXKAZU 8
て書いてしまうとエラーが起きてしまうんですよ



SYAM

リンク

2008/12/17(Wed) 09:56:48|NO.21653

意図しない動作をする、のではなくて「エラーが起きる」というのは、HSPの書き方に従っていないからです。
何が問題なのか考えてください。
define は、定義した名前の代わりに数字を書くのと完全に同じです。
ですから、実行中にスクリプトに書かれた数字を書き換えることができないのと同じく、変更はききません。
ここまでは実際に defineを使っているのですからお分かりだと思います。お分かりですね?
そうなると、
defineで定義するのではなく、変数を使わないといけないことになります。
変数は実行中にいろんな数値を持つことができますからね。

変数を使うように書き換えるだけなら、エラーには絶対になりませんよね。
元々数字だったところを変数にしただけならエラーになるハズがないです。
defineの定義は数字を直接書くのと完全に等しいのですから、これを変数にするのも同じことです。エラーになるはずがありません。
なったとしたら、書き換えた結果がHSPの文法に従っていないだけです。

というか。
エラーになる
…としか書かないのは情報不足の典型です。解決を望むなら、情報は具体的に出してください。めんどくさがっても解決が遠のくだけです。最初の方からして、情報不足が原因で余計な手間と時間がかかっているでしょう?

“#define”をただ消しただけなのではありませんか?
それだと変数への代入の書き方とは違ってますから当然、エラー2(文法まちがい)になります。



ブロック

リンク

2008/12/17(Wed) 13:28:17|NO.21655

a,b,cに表示させるのを設定して
a="0,0,0,0,0,0,0,0,0,0"
b="0,1,2,1,2,1,2,1,2,0"
c="0,2,1,2,1,2,1,2,1,0"

printで設定した変数を表示させる
print a
print b
print c
:
:

この方法はどうでしょうか?



SYAM

リンク

2008/12/17(Wed) 13:42:33|NO.21656

修正案の是非は 質問者が決めることではありませんか…(汗)なぜ他人に聞くのです。
とりあえず思うさまスクリプトに書けばいいでしょう。
修正案が正しければ、思うように動いてくれます。



k

リンク

2008/12/17(Wed) 15:06:08|NO.21659

BROXKAZU = 10
BROXKAZU = 8
ではだめなのでしょうか?



ブロック

リンク

2008/12/17(Wed) 15:33:55|NO.21660

kさん
それだと複数のステージを組み合わせる事が出来なくなるんですよ



ブロック

リンク

2008/12/17(Wed) 15:41:52|NO.21662

話が変わりますけど
この中で「スカイプ」または「MSNメッセンジャー」を使っている方はいますか?



SYAM

リンク

2008/12/17(Wed) 16:19:58|NO.21663

何がしたいのですか?
複数のステージを組み合わせる…の意味がわからないのですが…(汗)



ブロック

リンク

2008/12/17(Wed) 16:27:00|NO.21664

「スカイプ」または「MSNメッセンジャー」のチャットを使うと会話がやりやすいし
データ交換も出来るので非常に便利かと・・・

現在作っている「ブロック崩し」は30ステージを作ろうと思っているんです
つまり、一つ一つ違ったステージを30種類作りたいのです



SYAM

リンク

2008/12/17(Wed) 19:09:05|NO.21669

複数ステージをもつゲームのサンプルを貼ります。
#define の使いどころの例もついでに示してあります。こうしておくと、ステージの追加がラクですよね。

変数phase は、現在のステージ数です。0からなので表示のときだけ+1してます。
配列 map には、各ステージのデータを格納しています。
ステージ作成時に、そのデータから “*”の並び方を表す二次元配列 m を作っています。

ステージクリアしたあと、phaseに+1して
phase を使ってステージ数に応じた map の中身をよびだしているところが、今回参考にすべきところとなるでしょう。

※mapからmを作っている処理の部分は、ちょっと難しいかもしれませんし、ブロックを色分けしたいならこのままでは使えません。自分のスクリプトに合うように作り直してください。



#define STAGES 3 dim map,10,STAGES map(0,0)=129,0,0,128,0,0,0,129, 4,3 map(0,1)=126,129,2,4,8,16,32,127, 0,7 map(0,2)=42,213,170,85,170,85,170,84, 0,0 screen 0,128,128,0 font msgothic,16 *MAKE_MAP title "PHASE "+(phase+1)+"/"+STAGES cls 4:s=0 color 255,255,255 dim m,8,8 repeat 8 : cnty=cnt : repeat 8 m(cnt,cnty)=(map(cnty,phase)<<cnt)&0x80 if m(cnt,cnty):pos cnt*16,cnty*16:mes "*":s++ loop:loop x=map(8,phase) y=map(9,phase) pos x*16,y*16:mes "■" *WAITING_INPUT stick k if(k=1||k=2||k=4||k=8){ xv=(k=4)-(k=1) yv=(k=8)-(k=2) } else { wait 1:goto *WAITING_INPUT } *MOVING color 0,0,0 boxf x*16,y*16,x*16+16,y*16+16 x+=xv : y+=yv if (x<0||x>7||y<0||y>7) { dialog "OUT":goto *MAKE_MAP } color 255,255,255 pos x*16,y*16:mes "■" if (m(x,y)) { m(x,y)=0 : s-- if(s=0) { phase++ if phase=STAGES:dialog "ALL CLEAR.":end goto *MAKE_MAP } goto *WAITING_INPUT } wait 1:goto *MOVING

※ゲームについて
カーソルキーで■を動かし、すべての*を拾い集めてください。
■は*を拾うまで直進しかできず、止まることもできません。
■が画面外に飛んでっちゃったら、やりなおし。



ブロック

リンク

2008/12/18(Thu) 11:06:07|NO.21682

ブロック崩しで2000ステップいきますか?



SYAM

リンク

2008/12/18(Thu) 11:21:49|NO.21683

問題はどうなったのですか?
回答を無視して話を二転三転させるのであれば、今後回答はしません。



ブロック

リンク

2008/12/18(Thu) 12:51:05|NO.21684

サンプルの方を見させて頂いたのですけれども
ブロックを消えないようにするのですけれども対応できるのですか?



k

リンク

2008/12/18(Thu) 13:11:07|NO.21685

とりあえず「当たり判定について」は
解決したと思いますので
ブロックさんに 解決にチェックをいれていただいても
いいのではないかと思います



SYAM

リンク

2008/12/18(Thu) 13:20:04|NO.21692

スクリプトは穴埋め問題じゃなく、作文です。
できるのですかもなにも
「好きなようにしてください。」
>kさん
そうですね。
話が変わりすぎてますし最初の問題は解決したはずですから もし続けるとしても一度仕切り直すとよいでしょう…



ブロック

リンク

2008/12/18(Thu) 13:21:53|NO.21693

当たり判定については解決しましたのでチェックの方をつけます
ありがとうございました

複数のステージの組み合わせについては、また新規で作らさせていただきます



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