質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Processing

Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

Q&A

解決済

1回答

1035閲覧

ブロック崩しについて

sirasus0623

総合スコア1

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Processing

Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

1グッド

0クリップ

投稿2022/06/16 09:08

processingでブロック崩しを作っています。

前提

processingでブロック崩しを作りたい。

画面をクリックするとスタートするようにしているのですが、クリックしてもボールが動きません。この原因が分かりません。
また、上から降ってくる玉が自機に当たるとダメージを受けてしまい、3回当たると失敗
という風ににしたいのですが、実行すると当たってないのに体力が減ってしまいます(当たり判定がおかしい)
どのようにすれば解決できるか教えていただけたらありがたいです。
よろしくお願いします。

実現したいこと

始めに画面をクリックしたらボールが動き、ゲームが始まる。

発生している問題・エラーメッセージ

・始めに画面をクリックしてもボールが動かない
・降ってくる玉と自機との当たり判定がよくわからない

該当のソースコード

processing

1int block[][] = new int[10][10]; 2float x, y =60; 3float b_w = 10, b_h = 10, dx, dy; 4float r_w = 50.0, r_h = 3.0; 5int hp = 3; 6int enemy_x[]=new int[10]; 7int enemy_y[]=new int[10]; 8int enemy_speed[]=new int[10]; 9int r_x = mouseX; 10int r_y = height-50; 11int gseq; 12int mcnt; 13void setup() { 14 size(600,700); 15 initBall(); 16 initBlocks(); 17 showEnemy(); 18} 19 20void draw() { 21 22 background(192, 192, 255); 23 rect(x, y, b_w, b_h); // ball 24if(gseq == 0){ 25 gameTitle(); 26}else if(gseq == 1){ 27 x += dx; // dx は1フレームごとにx方向に動く距離(速度) 28 y += dy; // dy は1フレームごとにy方向に動く距離(速度) 29 gameplay(); 30}else{ 31 gameover(); 32} 33 checkBlocks(); 34 showBlocks(); 35 36 checkAndShowRacket(height-50); 37 38 // 壁との衝突 39 if (y + b_h >= height) { 40 //initBall(); 41 initBlocks(); 42 gseq = 2; 43 } 44 if (x < 0 || x+b_w >=width) {dx = -dx;} 45 if (y < 0) {dy = -dy;} 46} 47void initBall() { 48 x = 40; 49 y = 400; 50 dx = 1; 51 dy = 2; 52} 53float bw, bh = 40.0; 54 55/* 56 10個のブロックを初期化する 57*/ 58void initBlocks() { 59 for(int j=0; j<3; j++){ 60 for (int i = 0; i < block.length ; i++) { 61 block[i][j] = 1; 62 } 63 bw = width / block.length; // ブロックの幅を決める 64 } 65} 66 67/* 68 10個のブロックのどれかにぶつかっていたら跳ね返る 69*/ 70void checkBlocks() { 71 for (int j = 0; j < 3; j++) { 72 for (int i = 0; i < block.length ; i++) { 73 if (block[i][j] > 0) { 74 int ret = blockHitCheck(i*bw,j*bh+200,bw,bh,x,y,b_w,b_h,dx,dy); 75 if (ret > 0) { 76 if (ret == 1) { 77 dx = -dx; 78 block[i][j]--; 79 } else if (ret == 2) { 80 dy = -dy; 81 block[i][j]--; 82 } else if (ret == 3) { 83 dx = -dx; 84 dy = -dy; 85 block[i][j]--; 86 } 87 return; 88 } 89 } 90 } 91 } 92} 93 94/* 95 10個のブロックを表示する 96*/ 97void showBlocks() { 98 for (int j = 0; j < 3; j++) { 99 for (int i = 0; i < block.length ; i++) { 100 if (block[i][j] > 0) { 101 fill(255); 102 rect(i * bw, j*bh+200, bw, bh); // ブロックの形の表示 103 } 104 } 105 } 106} 107void enemymove(){ 108 for(int i=0;i<10;i++){ 109 fill(255,0,0); 110 rect(enemy_x[i],enemy_y[i],10,10); 111 enemy_y[i]+=enemy_speed[i]; 112 if(enemy_y[i]>height){ 113 enemy_x[i]=int(random(width)); 114 enemy_y[i]=-50; 115 enemy_speed[i]=int(random(2,6)); 116 } 117 } 118} 119 120void hitEnemy(){ 121 for(int i=0;i<10;i++){ 122 if((enemy_x[i]<r_x+50 || r_x<enemy_x[i]) && enemy_y[i]==r_y){ 123 hp=hp-1; 124 } 125 } 126} 127void showMyhp(){ 128 fill(255); 129 text("hp:"+hp,10,30); 130} 131 132 133void showEnemy(){ 134 for(int i=0;i<10;i++){ 135 enemy_x[i]=int(random(width)); 136 enemy_y[i]=-50; 137 enemy_speed[i]=int(random(2,6)); 138 } 139} 140/* 141 ふたつの長方形が重なるかどうかをしらべて、 142 重なったとき:true, 重ならないとき:false を返す 143*/ 144boolean isOverlap(float x1, float y1, float w1, float h1, 145 float x2, float y2, float w2, float h2) { 146 return x1 < x2+w2 && x2 < x1+w1 && y1 < y2+h2 && y2 < y1+h1; 147} 148 149/* 150 ブロックの位置と大きさ、 151 ボールの位置と大きさ、ボールの移動速度の情報を与えて 152 跳ね返る方向(x軸、y軸の別)を返す 153 跳ね返らない時: 0 154 x軸のみの時: 1 155 y軸のみの時: 2 156 x軸, y軸両方の時: 3 157*/ 158int blockHitCheck(float x, float y, float w, float h, 159 float bx, float by, float bw, float bh, float dx, float dy) { 160 int xflag = 0, yflag = 0; 161 162 if (!isOverlap(x,y,w,h,bx+dx,by+dy,bw,bh)) { 163 return 0; // ぶつからなかったら 0を返す 164 } 165 166 if (isOverlap(x,y,w,h,bx+dx,by,bw,bh)) xflag = 1; 167 if (isOverlap(x,y,w,h,bx,by+dy,bw,bh)) yflag = 2; 168 if (xflag + yflag > 0) { return xflag + yflag;} 169 return 3; 170} 171/* 172 checkAndShowRacket() 173 float r_y; // r_hはラケットのy座標 174*/ 175void checkAndShowRacket(float r_y) { 176 float r_x = mouseX; // r_x はラケットの左側のx座標 177 178 if (r_x + r_w > width) { // 右に寄りすぎていたら補正する 179 r_x = width - r_w; 180 } 181 182 /* ブロックがぶつかっていたら上に跳ね返る */ 183 if (blockHitCheck(r_x,r_y,r_w,r_h,x,y,b_w,b_h,dx,dy) > 0) { 184 dy = -2; 185 } 186 187 rect(r_x, r_y, r_w, r_h); // racketを表示する 188} 189 void gameTitle(){ 190 checkAndShowRacket(height-50); 191 showBlocks(); 192 mcnt++; 193 if((mcnt%60)<40){ 194 textSize(20); 195 fill(255,0,0); 196 text("Click to start!!", 220,400); 197 } 198} 199 200void gameInit(){ 201 x += dx; // dx は1フレームごとにx方向に動く距離(速度) 202 y += dy; // dy は1フレームごとにy方向に動く距離(速度) 203 gseq = 0; 204 //initBall(); 205 showBlocks(); 206 mcnt = 0; 207} 208 209void gameplay(){ 210 x += dx; // dx は1フレームごとにx方向に動く距離(速度) 211 y += dy; // dy は1フレームごとにy方向に動く距離(速度) 212 checkAndShowRacket(height-50); 213 showBlocks(); 214 initBall(); 215 enemymove(); 216 hitEnemy(); 217 showMyhp(); 218} 219void gameover(){ 220 checkAndShowRacket(height-50); 221 showBlocks(); 222 textSize(50); 223 fill(0); 224 text("GAME OVER", 200, 500); 225 mcnt++; 226 if((mcnt%60) < 40){ 227 textSize(20); 228 fill(0); 229 text("Click to retry!!", 170,400); 230 } 231} 232void mousePressed(){ 233 if(gseq == 2){ 234 gameInit(); 235 return; 236 } 237 if(gseq == 0){ 238 gseq = 1; 239 } 240}

試したこと

ボールが動かないことに関しては、gameplay()やgameInit()の中を色々変えてみた。
当たり判定に関しては、ボールと同じようにやろうとしたが、分からなくなった。

TN8001👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

画面をクリックするとスタートするようにしているのですが、クリックしてもボールが動きません。この原因が分かりません。

gameInit中のinitBallをコメント化してgameplay中のinitBallを生かしていますが、逆のつもりだったんじゃないですか?

また、上から降ってくる玉が自機に当たるとダメージを受けてしまい、3回当たると失敗
という風ににしたいのですが、実行すると当たってないのに体力が減ってしまいます(当たり判定がおかしい)

かなりの複合原因のため、うまく言葉で伝わるか心配です^^;

まず(enemy_x[i]<r_x+50 || r_x<enemy_x[i])はおかしいです。
「自機の左右範囲内に降ってくる玉があったら」のはずですから、&&でしょう。

次にグローバルに定義したr_xr_yです。

int r_x = mouseX; int r_y = height-50;

r_xは0のまま一切変わりません。なぜかというとcheckAndShowRacketで変更しているr_xは、ローカル変数だからです。
r_yはこの時点では50になります。sizeに初期化しないと正しい値になりません。

さらに&& enemy_y[i]==r_yの部分ですが降ってくる玉のスピードはランダムなため、必ずしも自機のy(r_y)と一致するとは限りません。
結局ブロックと同じようにisOverlapを使って、自機に当たったら降ってくる玉を消して(リセットして)しまうほうが楽そうな気がします。


これらと共通点がやけに多いですが、「改造してみよう」みたいな課題なんですかね?
ブロック崩しのなかでブロックが壊れるとともにボールを増やす方法
ブロック崩しゲームにおいて自分の考えた内容をどうゆう風にプログラムで書き換えばいいのか教えてください。

別にそれがどうということはないのですが、(予想される元々の)コードがちょっと癖があるのが気になったもので^^;


Processing

1int block[][] = new int[10][10]; 2float x, y = 60; 3float b_w = 10, b_h = 10, dx, dy; 4float r_w = 50.0, r_h = 3.0; 5int hp = 3; 6int enemy_x[] = new int[10]; 7int enemy_y[] = new int[10]; 8int enemy_speed[] = new int[10]; 9//int r_x = mouseX; 10//int r_y = height - 50; 11float r_x; 12float r_y; 13int gseq; 14int mcnt; 15float bw, bh = 40.0; 16 17 18void setup() { 19 size(600, 700); 20 initBall(); 21 initBlocks(); 22 showEnemy(); 23 // 初期化 24 r_y = height - 50; 25} 26 27void draw() { 28 background(192, 192, 255); 29 30 rect(x, y, b_w, b_h); 31 if (gseq == 0) { 32 gameTitle(); 33 } else if (gseq == 1) { 34 x += dx; 35 y += dy; 36 gameplay(); 37 } else { 38 gameover(); 39 } 40 41 checkBlocks(); 42 showBlocks(); 43 44 checkAndShowRacket(height - 50); 45 46 if (y + b_h >= height) { 47 initBlocks(); 48 gseq = 2; 49 } 50 if (x < 0 || x + b_w >= width) { 51 dx = -dx; 52 } 53 if (y < 0) { 54 dy = -dy; 55 } 56} 57 58void initBall() { 59 x = 40; 60 y = 400; 61 dx = 1; 62 dy = 2; 63} 64 65void initBlocks() { 66 for (int j = 0; j < 3; j++) { 67 for (int i = 0; i < block.length; i++) { 68 block[i][j] = 1; 69 } 70 bw = width / block.length; 71 } 72} 73 74void checkBlocks() { 75 for (int j = 0; j < 3; j++) { 76 for (int i = 0; i < block.length; i++) { 77 if (block[i][j] > 0) { 78 int ret = blockHitCheck(i * bw, j * bh + 200, bw, bh, x, y, b_w, b_h, dx, dy); 79 if (ret > 0) { 80 if (ret == 1) { 81 dx = -dx; 82 block[i][j]--; 83 } else if (ret == 2) { 84 dy = -dy; 85 block[i][j]--; 86 } else if (ret == 3) { 87 dx = -dx; 88 dy = -dy; 89 block[i][j]--; 90 } 91 return; 92 } 93 } 94 } 95 } 96} 97 98void showBlocks() { 99 for (int j = 0; j < 3; j++) { 100 for (int i = 0; i < block.length; i++) { 101 if (block[i][j] > 0) { 102 fill(255); 103 rect(i * bw, j * bh + 200, bw, bh); 104 } 105 } 106 } 107} 108 109void enemymove() { 110 for (int i = 0; i < 10; i++) { 111 fill(255, 0, 0); 112 rect(enemy_x[i], enemy_y[i], 10, 10); 113 enemy_y[i] += enemy_speed[i]; 114 if (enemy_y[i] > height) { 115 enemy_x[i] =int(random(width)); 116 enemy_y[i] = -50; 117 enemy_speed[i] =int(random(2, 6)); 118 } 119 } 120} 121 122void hitEnemy() { 123 for (int i = 0; i < 10; i++) { 124 //if ((enemy_x[i] < r_x + 50 && r_x < enemy_x[i]) && enemy_y[i] == r_y) { 125 // hp = hp - 1; 126 //} 127 if (isOverlap(r_x, r_y, r_w, r_h, enemy_x[i], enemy_y[i], 10, 10)) { 128 hp = hp - 1; 129 enemy_x[i] = int(random(width)); 130 enemy_y[i] = -50; 131 enemy_speed[i] = int(random(2, 6)); 132 } 133 } 134} 135 136void showMyhp() { 137 fill(255); 138 text("hp:" + hp, 10, 30); 139} 140 141 142void showEnemy() { 143 for (int i = 0; i < 10; i++) { 144 enemy_x[i] = int(random(width)); 145 enemy_y[i] = -50; 146 enemy_speed[i] = int(random(2, 6)); 147 } 148} 149 150boolean isOverlap(float x1, float y1, float w1, float h1, 151 float x2, float y2, float w2, float h2) { 152 return x1 < x2 + w2 && x2 < x1 + w1 && y1 < y2 + h2 && y2 < y1 + h1; 153} 154 155int blockHitCheck(float x, float y, float w, float h, 156 float bx, float by, float bw, float bh, float dx, float dy) { 157 int xflag = 0, yflag = 0; 158 159 if (!isOverlap(x, y, w, h, bx + dx, by + dy, bw, bh)) { 160 return 0; 161 } 162 163 if (isOverlap(x, y, w, h, bx + dx, by, bw, bh)) xflag = 1; 164 if (isOverlap(x, y, w, h, bx, by + dy, bw, bh)) yflag = 2; 165 if (xflag + yflag > 0) { 166 return xflag + yflag; 167 } 168 return 3; 169} 170 171void checkAndShowRacket(float r_y) { 172 //float r_x = mouseX; 173 r_x = mouseX; 174 175 if (r_x + r_w > width) { 176 r_x = width - r_w; 177 } 178 179 if (blockHitCheck(r_x, r_y, r_w, r_h, x, y, b_w, b_h, dx, dy) > 0) { 180 dy = -2; 181 } 182 183 rect(r_x, r_y, r_w, r_h); 184} 185 186void gameTitle() { 187 checkAndShowRacket(height - 50); 188 showBlocks(); 189 mcnt++; 190 if ((mcnt % 60) < 40) { 191 textSize(20); 192 fill(255, 0, 0); 193 text("Click to start!!", 220, 400); 194 } 195} 196 197void gameInit() { 198 x += dx; 199 y += dy; 200 gseq = 0; 201 initBall(); 202 showBlocks(); 203 mcnt = 0; 204} 205 206void gameplay() { 207 x += dx; 208 y += dy; 209 checkAndShowRacket(height - 50); 210 showBlocks(); 211 enemymove(); 212 hitEnemy(); 213 showMyhp(); 214} 215 216void gameover() { 217 checkAndShowRacket(height - 50); 218 showBlocks(); 219 textSize(50); 220 fill(0); 221 text("GAME OVER", 200, 500); 222 mcnt++; 223 if ((mcnt % 60) < 40) { 224 textSize(20); 225 fill(0); 226 text("Click to retry!!", 170, 400); 227 } 228} 229 230void mousePressed() { 231 if (gseq == 2) { 232 gameInit(); 233 return; 234 } 235 if (gseq == 0) { 236 gseq = 1; 237 } 238}

投稿2022/06/16 12:00

編集2022/06/16 16:04
TN8001

総合スコア9317

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sirasus0623

2022/06/16 12:35

丁寧な回答ありがとうございます。急いでるもので、コードが少し雑ですみません。一つ目のボールについては無事動きました! 二つ目の方ですが、具体的にisOverlapをどのように使えばいいんでしょうか? このブロック崩しは課題として出されたものを改造してるので他の人のものはよく分からないですね...(同じ学校とかそんな感じかも..?)
TN8001

2022/06/16 13:58 編集

> 二つ目の方ですが、具体的にisOverlapをどのように使えばいいんでしょうか? isOverlapにコメントがついていますよね? その通りに使うだけですが、難しいですか? void hitEnemy() { for (int i = 0; i < 10; i++) { if (isOverlap(r_x, r_y, r_w, r_h, enemy_x[i], enemy_y[i], 10, 10)) { hp = hp - 1; enemy_x[i] = int(random(width)); enemy_y[i] = -50; enemy_speed[i] = int(random(2, 6)); } } } もちろん↓の処置も必要です。 >> r_xは0のまま一切変わりません。なぜかというとcheckAndShowRacketで変更しているr_xは、ローカル変数だからです。 >> r_yはこの時点では50になります。sizeの後に初期化しないと正しい値になりません。 あとr_xはfloatにしないと、その後の計算の部分でエラーになりますね。
sirasus0623

2022/06/16 15:11

飲み込み悪くてすみません、どうすればいいか分からないので教えていただけたらありがたいです。
TN8001

2022/06/16 15:52

> 飲み込み悪くてすみません、どうすればいいか分からないので教えていただけたらありがたいです。 え!?私の説明が悪いんでしょうね。。。 もうこれ以上言葉で説明できそうにないのでコードを追記しますorz
sirasus0623

2022/06/16 15:54

いえ、おそらく他の人なら余裕で理解できるんでしょうが、自分の知識不足がでてしまっています...お手数おかけします。
TN8001

2022/06/16 16:04

通知が行っていないかもしれないので念のため。 もう追記済みです。コメントのあるところが変更点です。
sirasus0623

2022/06/16 16:16

最初から最後まで丁寧な回答、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問