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

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

新規登録して質問してみよう
ただいま回答率
85.47%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Processing

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

Q&A

解決済

2回答

878閲覧

円同士が衝突したときにモンストのような反射の挙動をしてほしい

HERO

総合スコア1

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Processing

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

1グッド

0クリップ

投稿2023/11/28 04:35

編集2023/12/01 03:00

実現したいこと

円同士が衝突したときにモンストのような反射の挙動をしてほしい

前提

Processingでモンストのようなゲームを作っています。

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

衝突したときにめり込んだ影響で、振動してしまってうまく反射してくれない。

該当のソースコード

Processing(java)

1//dx,dyをvelocityに変更した影響でdx,dyがコメントアウトがしてあります 2class Chara { 3 float[][] position = new float[4][2]; 4 float[] dx = new float[4]; 5 float[] dy = new float[4]; 6 float[][] velocity=new float[4][2]; 7 float[] start_x = new float[4]; 8 float[] start_y = new float[4]; 9 float[] speed = new float[4]; 10 int[] attack = new int[4]; 11 int[] HP = new int[4]; 12 int allHP; 13 int currentHP; 14 int damage; 15 float r = 80; 16 boolean[] isDrag = new boolean[4]; 17 boolean[] isStopped = new boolean[4]; 18 19 int currentPhase; 20 int nowCP; 21 22 Chara() { 23 nowCP=0; 24 currentPhase = 0; 25 for (int i = 0; i < 4; i++) { 26 position[i][0] = (i + 1) * 128; 27 position[i][1] = 600; 28 // dx[i] = 0; 29 velocity[i][0]=0; 30 // dy[i] = 0; 31 velocity[i][1]=0; 32 start_x[i] = 0; 33 start_y[i] = 0; 34 speed[i] = 30; 35 attack[i]=30000; 36 HP[i]=25000; 37 allHP+=HP[i]; 38 isDrag[i] = false; 39 isStopped[i] = false; 40 } 41 currentHP=allHP; 42 } 43 44 void update() { 45 switch (nowCP) { 46 case 0: 47 updateBall(0); 48 break; 49 case 1: 50 updateBall(1); 51 break; 52 case 2: 53 updateBall(2); 54 break; 55 case 3: 56 updateBall(3); 57 break; 58 } 59 } 60 61 62 void updateBall(int index) { 63// dx[index] *= 0.99; 64// dy[index] *= 0.99; 65 velocity[index][0]*=0.99; 66 velocity[index][1]*=0.99; 67 68 if (abs(velocity[index][0]) < 0.5 && abs(velocity[index][1]) < 0.5) { 69 velocity[index][0] = 0; 70 velocity[index][1] = 0; 71 stop(index); 72 } 73 move(index, position[index][0], position[index][1], velocity[index][0], velocity[index][1]); 74 bound(index, position[index][0], position[index][1]); 75 76} 77 78 void display() { 79 showChara(); 80 showArrow(); 81 showHP(); 82 } 83 84 85 86 void mousePressed() { 87 88 if (scene_number == SCENE_GAME&&isStopped[nowCP]&&!m.phase) { 89 nowCP=currentPhase; 90 currentPhase++; 91 if (currentPhase >= 4) { 92 currentPhase = 0; 93 } 94 } 95 if(!m.phase){ 96 start_x[nowCP] = mouseX; 97 start_y[nowCP] = mouseY; 98 isDrag[nowCP] = true; 99 } 100} 101 102 103 void mouseReleased() { 104 if (scene_number == SCENE_GAME && isStopped[nowCP]&&!m.phase) { 105 resume(nowCP); 106 m.phase=true; 107 arrow(position[nowCP][0], position[nowCP][1], start_x[nowCP], start_y[nowCP]); 108 float l = mag(start_x[nowCP] - mouseX,start_y[nowCP] - mouseY); 109 110 //dx[nowCP] = (start_x[nowCP] - mouseX) * speed[nowCP]/l; 111 // dy[nowCP] = (start_y[nowCP] - mouseY) * speed[nowCP]/l; 112 velocity[nowCP][0] = (start_x[nowCP] - mouseX) * speed[nowCP]/l; 113 velocity[nowCP][1] = (start_y[nowCP] - mouseY) * speed[nowCP]/l; 114 isDrag[nowCP] = false; 115 116 if (l < r/2) { 117 // dx[nowCP] = 0; 118 // dy[nowCP] = 0; 119 velocity[nowCP][0]=0; 120 velocity[nowCP][1]=0; 121 currentPhase--; 122 m.phase=false; 123 } 124 } 125} 126void showChara(){ 127 fill(0); 128 for (int i = 0; i < 4; i++) { 129 strokeWeight(1); 130 stroke(0); 131 circle(position[i][0], position[i][1], r); 132 fill(63*i); 133 } 134 // text(nowCP,width/2,height/2,0); 135} 136 137void showArrow(){ 138 for (int i = 0; i < 4; i++) { 139 if (isDrag[i]) { 140 arrow(position[i][0], position[i][1], start_x[i], start_y[i]); 141 } 142 } 143} 144void arrow(float x, float y, float start_x, float start_y) { 145 PVector arrow = new PVector(x + start_x - mouseX, y + start_y - mouseY); 146 if (isStopped[nowCP]) { 147 stroke(0); 148 strokeWeight(10); 149 line(arrow.x, arrow.y, x, y); 150 151 } 152} 153 154void showHP(){ 155 float HPbar; 156 HPbar=map(currentHP,0,allHP,0,width); 157 textSize(50); 158 strokeWeight(10); 159 stroke(255,255,0); 160 line(0,height,HPbar,height); 161 textAlign(RIGHT); 162 text(allHP,width,height); 163 textAlign(LEFT); 164 text("/",width-155,height); 165 textAlign(RIGHT); 166 text(currentHP,width-150,height); 167} 168 169 170 171 void bound(int index, float x, float y) { 172 boolean collision[]=new boolean[6]; 173 for(int i=0;i<m.M;i++){ 174 if(m.HP[i]>=0){ 175 collision[i]=false; 176 } 177 } 178 179 if (x > width && velocity[index][0] > 0) { 180 //dx[index] *= -1; 181 velocity[index][0]*=-1; 182 } 183 if (x < 0 && velocity[index][0] < 0) { 184 // dx[index] *= -1; 185 velocity[index][0]*=-1; 186 } 187 if (y > height && velocity[index][1] > 0) { 188 // dy[index] *= -1; 189 velocity[index][1]*=-1; 190 } 191 if (y < 0 && velocity[index][1] < 0) { 192 //dy[index] *= -1; 193 velocity[index][1]*=-1; 194 } 195 196 for(int i=0;i<m.M;i++){ 197 if(m.HP[i]>=0){ 198 199 float d=distance(m.position[i][0],m.position[i][1],x,y); 200 if(d<r/2+m.r/2){ 201 collision[i]=true; 202 text("collision",width/2,100); 203 if(abs(velocity[index][0])>=abs(velocity[index][1])&&collision[i]){ 204 velocity[index][0] *= -1; 205 m.HP[i]-=attack[nowCP]; 206 } 207 if(abs(velocity[index][0])<abs(velocity[index][1])&&collision[i]){ 208 velocity[index][1]*=-1; 209 m.HP[i]-=attack[nowCP]; 210 } 211 } 212 } 213 } 214 } 215 216 217float distance(float x1, float y1, float x2, float y2) { 218 float dx = x2 - x1; 219 float dy = y2 - y1; 220 return sqrt(dx * dx + dy * dy); 221} 222 223 void move(int index, float x, float y, float dx, float dy) { 224 position[index][0] = x + dx; 225 position[index][1] = y + dy; 226 } 227 228 229 230 void stop(int index) { 231 isStopped[index] = true; 232 233 } 234 235 void resume(int index) { 236 isStopped[index] = false; 237 } 238}

試したこと

bound関数の中身をずっといじっているのですが見当違いなのでしょうか?

補足情報(FW/ツールのバージョンなど)

Processing 4.2

TN8001👍を押しています

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

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

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

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

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

jimbe

2023/11/28 04:57

>衝突したときにめり込んだ影響で、振動してしまってうまく反射してくれない それで、そのコードで何が問題なのでしょうか。 結果として「反射したように表示がされない」こととコードと何の関係がありますか。 例え何かを求める式が正常だったとしても、どう表示するか・どう表示に用いるかで結果は異なるのでは無いでしょうか。 "めり込み"が原因なら"めり込まないようにする"というのが対処としてまずあると思いますが、如何でしょうか。
jimbe

2023/11/28 09:30

まだ全体像が見えませんので想像ですが、 updateBall で個々の動きを更新する際に、それぞれが個別に衝突判定・計算をするためではないでしょうか。本来(?)衝突は同時に起き同時に双方に変化を起こすはずです。 お互いが動き、結果衝突が発生してお互いが向きを逆にし、かつ次の move で確実にお互いが衝突状態にならないように position もしくは dx/dy の値を決めるとか衝突フラグ等を持たせるとかが考えられると思います。
HERO

2023/12/01 03:07

解答ありがとうございます。 なんとなくおっしゃっていることはわかりますが、理解力が低く、具体的な解決策が思いつきませんでした、、、 「衝突フラグを持たせる」が解決できそうだと思いやってみたんですが変わらずでした…
guest

回答2

0

ベストアンサー

衝突したときにめり込んだ影響で、振動してしまってうまく反射してくれない。

コードが不完全で実行できませんが、こういうことですよね?(質問者のほうで再現可能な最小サンプルを提供してください)
めり込み動画

bound関数の中身をずっといじっているのですが見当違いなのでしょうか?

というかdxdyを反転しているだけなので、めり込み以前に円同士の反射になっていませんよね?(矩形相手の反射)
法線がどうのこうの計算が必要なのではないですか?(わたしはさっぱりわかりませんが^^;
反射・壁ずり・鏡像ベクトルの考え方

Processing

1PVector position = new PVector(50, 350); 2PVector m_position = new PVector(200, 200); 3PVector velocity = new PVector(); 4float r = 30; 5float m_r = 50; 6 7PVector sp, ep; 8boolean mode = true; 9 10void setup() { 11 size(400, 400); 12 ellipseMode(RADIUS); 13} 14 15void draw() { 16 background(255); 17 18 fill(mode ? #ff0000 : #0000ff); 19 circle(m_position.x, m_position.y, m_r); 20 21 if (sp != null) { 22 var p = PVector.add(position, PVector.sub(sp, ep)); 23 line(position.x, position.y, p.x, p.y); 24 } 25 26 updateBall(); 27 showChara(); 28} 29 30void updateBall() { 31 velocity.mult(0.99); 32 if (velocity.mag() < 0.5) { 33 velocity.set(0, 0); 34 } 35 36 move(); 37 bound(); 38} 39 40void showChara() { 41 fill(0); 42 circle(position.x, position.y, r); 43} 44 45void bound() { 46 var x = position.x; 47 var y = position.y; 48 49 if (x > width && velocity.x > 0) velocity.x *= -1; 50 if (x < 0 && velocity.x < 0) velocity.x *= -1; 51 if (y > height && velocity.y > 0) velocity.y *= -1; 52 if (y < 0 && velocity.y < 0) velocity.y *= -1; 53 54 var d = position.dist(m_position); 55 if (d < r + m_r) { 56 if (mode) { 57 58 // オリジナル 59 if (abs(velocity.x) >= abs(velocity.y)) { 60 velocity.x *= -1; 61 } else { 62 velocity.y *= -1; 63 } 64 } else { 65 66 // 円の反射 67 var n = PVector.sub(position, m_position); 68 n.normalize(); 69 var length = PVector.mult(velocity, -1).dot(n); 70 var de = n.mult(length); 71 var dh = PVector.add(velocity, de.mult(2)); 72 velocity = dh; 73 } 74 } 75} 76 77void move() { 78 position.add(velocity); 79} 80 81void mousePressed() { 82 sp = new PVector(mouseX, mouseY); 83 ep = sp.copy(); 84} 85void mouseDragged() { 86 ep.set(mouseX, mouseY); 87} 88void mouseReleased() { 89 velocity.set(sp.sub(ep).div(10)); 90 sp = ep = null; 91} 92void mouseClicked() { 93 if (mouseButton == RIGHT) mode = !mode; 94}

PVector / Reference / Processing.org
アプリ動画


これでもめり込み問題は残ります(円周にくっつくような挙動)
そもそもめり込まないようにするのがいいんじゃないですかね?(めり込み量はわかってるんで雑に離すだけでも効果ある?)
円同士を重ならない位置まで補正する

どちらの円も動くような場合はこちら。
動く円と円の衝突と反発ベクトルの求め方


わたしだったら難しいことを考えたくないので、fisicaかなんかで作ると思います(別の難しさはありますが^^;

追記

円の反射についてですがモンストでは基本的には単純に向きを反転する反射をします。
なのでその点については気にしなくて大丈夫です!

なるほど反射はdxdyの大きいほう(=角度)で決まるのですね。

重ならない位置まで補正すればうまく解決しそうなのはわかるのですが、うまくできないのが現状です…

押し出すような手法もあると思いますが、面倒なので向きと位置で反射するかどうかを判断するのはどうでしょう?

現状↓のような状態でめり込みが発生しています。
めり込み発生図
青い線のところで反射しないようにすれば、そのまま抜けて連続反射にはならなくなりますね?

Processing

1PVector position = new PVector(50, 350); 2PVector m_position = new PVector(200, 200); 3PVector velocity = new PVector(); 4float r = 30; 5float m_r = 50; 6 7PVector sp, ep; 8 9 10void setup() { 11 size(400, 400); 12 ellipseMode(RADIUS); 13} 14 15void draw() { 16 background(255); 17 18 fill(#ff0000); 19 circle(m_position.x, m_position.y, m_r); 20 21 if (sp != null) { 22 var p = PVector.add(position, PVector.sub(sp, ep)); 23 line(position.x, position.y, p.x, p.y); 24 } 25 26 updateBall(); 27 showChara(); 28} 29 30void updateBall() { 31 velocity.mult(0.99); 32 if (velocity.mag() < 0.5) { 33 velocity.set(0, 0); 34 } 35 36 move(); 37 bound(); 38} 39 40void showChara() { 41 fill(0); 42 circle(position.x, position.y, r); 43} 44 45void bound() { 46 var x = position.x; 47 var y = position.y; 48 49 if (x > width && velocity.x > 0) velocity.x *= -1; 50 if (x < 0 && velocity.x < 0) velocity.x *= -1; 51 if (y > height && velocity.y > 0) velocity.y *= -1; 52 if (y < 0 && velocity.y < 0) velocity.y *= -1; 53 54 var d = position.dist(m_position); 55 if (d < r + m_r) { 56 if (abs(velocity.x) >= abs(velocity.y)) { 57 58 // 右向きに進んでいて、自分が相手より左にいるなら反射 59 if (0 < velocity.x && x < m_position.x) { 60 velocity.x *= -1; 61 } 62 // 左向きに進んでいて、自分が相手より右にいるなら反射 63 if (velocity.x < 0 && m_position.x < x) { 64 velocity.x *= -1; 65 } 66 } else { 67 if ((0 < velocity.y && y < m_position.y) || 68 (velocity.y < 0 && m_position.y < y)) { 69 velocity.y *= -1; 70 } 71 } 72 } 73} 74 75void move() { 76 position.add(velocity); 77} 78 79void mousePressed() { 80 sp = new PVector(mouseX, mouseY); 81 ep = sp.copy(); 82} 83void mouseDragged() { 84 ep.set(mouseX, mouseY); 85} 86void mouseReleased() { 87 velocity.set(sp.sub(ep).div(10)); 88 sp = ep = null; 89}

かすったような時に、すり抜けは発生するかな?(当たり判定がやや小さくなる)

投稿2023/11/29 09:30

編集2023/12/01 13:55
TN8001

総合スコア9326

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

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

HERO

2023/12/01 02:55

解答ありがとうございます。 憶測通り再現動画のようになっています。 円の反射についてですがモンストでは基本的には単純に向きを反転する反射をします。 なのでその点については気にしなくて大丈夫です! 重ならない位置まで補正すればうまく解決しそうなのはわかるのですが、うまくできないのが現状です…
TN8001

2023/12/01 04:27

回答に追記しました^^
HERO

2023/12/05 07:36

ありがとうございます! 概ね希望の挙動をしてくれるようになりました! ベストアンサーにさせていただきます
guest

0

[香車]東上☆あらし☆海美「刻み幅を 1/2 にして、2 回計算してから、表示するようにする」

投稿2023/11/28 05:44

umimi

総合スコア231

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問