diff --git a/index.html b/index.html
index 2e31784..7fe3de3 100644
--- a/index.html
+++ b/index.html
@@ -227,6 +227,47 @@
return false;
}
+
+ function forceValidPos(ball) {
+ // 壁でない六角形ののうち、近い方から3つ選び、それらの中心の平均に向ける
+ let fst = null;
+ let snd = null;
+ let trd = null;
+ let minDist = Infinity;
+ let sndDist = Infinity;
+ let trdDist = Infinity;
+ for (let i = 0; i < numHexagons - (HEXAGON_MAP_LEVEL + 1) * 6; i++) {
+ const hex = hexagons[i];
+ const dist = Math.sqrt((ball.x - hex.x) ** 2 + (ball.y - hex.y) ** 2);
+ if (dist < minDist) {
+ trd = snd;
+ trdDist = sndDist;
+ snd = fst;
+ sndDist = minDist;
+ fst = hex;
+ minDist = dist;
+ } else if (dist < sndDist) {
+ trd = snd;
+ trdDist = sndDist;
+ snd = hex;
+ sndDist = dist;
+ } else if (dist < trdDist) {
+ trd = hex;
+ trdDist = dist;
+ }
+ }
+
+
+ // 大きさを維持したまま、中心に向ける
+ const dx = (fst.x + snd.x + trd.x) / 3 - ball.x;
+ const dy = (fst.y + snd.y + trd.y) / 3 - ball.y;
+ const length = Math.sqrt(dx ** 2 + dy ** 2);
+ ball.dx = dx / length * MID_SPEED;
+ ball.dy = dy / length * MID_SPEED;
+ ball.x += dx;
+ ball.y += dy;
+ }
+
function checkCollision(ball) {
const collisionHexagons = [];
for (let i = 0; i < numHexagons; i++) {
@@ -240,35 +281,21 @@
return Math.sqrt((ball.x - a.x) ** 2 + (ball.y - a.y) ** 2) - Math.sqrt((ball.x - b.x) ** 2 + (ball.y - b.y) ** 2);
});
- if (collisionHexagons.length === 0 || collisionHexagons.length >= 4) {
- console.log("error", collisionHexagons);
+ if (collisionHexagons.length === 0) {
+ console.log("error: ball not in any hexagons", ball);
+ forceValidPos(ball);
return;
}
+ if (collisionHexagons.length === 4) {
+ // ボールが小さければこうなることはない
+ console.log("error: ball in 4 hexagons", collisionHexagons);
+ }
if (collisionHexagons.length === 1) {
if (collisionHexagons[0].color === WALL_COLOR) {
console.log("error: ball in wall", collisionHexagons[0]);
+ forceValidPos(ball);
- // 一番近い壁でない六角形の中心に向ける
- let minhex = null;
- let minDist = Infinity;
- for (let i = 0; i < numHexagons - (HEXAGON_MAP_LEVEL + 1) * 6; i++) {
- const hex = hexagons[i];
- const dist = Math.sqrt((ball.x - hex.x) ** 2 + (ball.y - hex.y) ** 2);
- if (dist < minDist) {
- minDist = dist;
- minhex = hex;
- }
- }
-
- // 大きさを維持したまま、中心に向ける
- const dx = minhex.x - ball.x;
- const dy = minhex.y - ball.y;
- const length = Math.sqrt(dx ** 2 + dy ** 2);
- ball.dx = dx / length * MID_SPEED;
- ball.dy = dy / length * MID_SPEED;
- ball.x += dx;
- ball.y += dy;
} else if (collisionHexagons[0].color === NEITHER_COLOR) {
collisionHexagons[0].color = ball.reverseColor;
} else if (collisionHexagons[0].color !== ball.reverseColor) {
@@ -414,11 +441,12 @@
scoreElement.textContent = `day ${dayScore} | night ${nightScore}`;
balls.forEach((ball) => {
- drawBall(ball);
checkCollision(ball);
+ drawBall(ball);
ball.x += ball.dx;
ball.y += ball.dy;
+
addRandomness(ball);
});