The Problem:
Если вы когда-либо играли или смотрели какой-то игровой процесс в битве королевской игры (например, PUBG, например), вы всегда найдете событие в любом сражении под названием theкрасная зона .
Как правило, в определенный момент времени в игре случайная зона на карте (возможно, квадрат, возможно круг) будет обстреляна артиллерийским огнем в течение примерно 30 секунд.или так.Игра выпустит, скажем, 20 снарядов в случайных местах в пределах этой красной зоны.Если вы находитесь в красной зоне, и случается так, что вы находитесь в пределах радиуса всплеска (см. Ниже) оболочки, вы мгновенно умрете.
Моя попытка воссоздать красныйФункция Zone с использованием холста JS:
с использованием eventListener
, когда пользователь нажимает на холст, генерируется случайная точка и вокруг этой точки строится окружность с радиусом 50
, ноесть ловушка:
Если сгенерированная точка находится на расстоянии менее 50
единиц от границы зоны или , сгенерированная точка находится на расстоянии менее чем 100
единиц отдругая уже сгенерированная точка , алгоритм будет продолжать генерировать новые точки и проверять их на соответствие 2 ранее указанным условиям, пока не встретит их, затем он добавит эту точку в массив, содержащий все точки.
Алгоритм работает, как и предполагалось, для всех тестовых случаев, , но иногда первая точка и ТОЛЬКО первая сгенерированная точка нарушает эти 2 условия. Понятия не имеюхй.Я попытался использовать цикл do-while
вместо цикла while
(который продолжает генерировать новые точки, пока не будет выполнено 2 условия), но не повезло.
Пожалуйста, помогите мне с этой проблемой как можно быстреенасколько это возможно.Заранее спасибо.Вот код (CodePen): https://codepen.io/Undefined_Variable/full/oQeoqE/
let canvas = document.body.querySelector("canvas");
let ctx = canvas.getContext("2d");
canvas.width = 0.75 * screen.width;
canvas.height = 0.8 * screen.height;
let CW = canvas.width;
let CH = canvas.height;
canvas.style.top = (screen.height / 2) - (canvas.height / 2) + "px";
canvas.style.left = (screen.width / 2) - (canvas.width / 2) + "px";
let dotArr = [];
let dotSize = 50
let dotDistance = 100;
let borderDistance = 50;
let dotCounter = 0;
class dot {
constructor(posX, posY) {
this.posX = posX;
this.posY = posY;
this.radius = dotSize;
}
drawDot() {
ctx.save();
ctx.translate(this.posX, this.posY);
ctx.fillStyle = "black";
ctx.beginPath();
ctx.arc(0, 0, this.radius, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
ctx.restore();
}
}
function mainLoop() {
function drawCircle() {
ctx.save();
ctx.translate(CW / 2, CH / 2);
ctx.strokeStyle = "black";
ctx.beginPath();
ctx.arc(0, 0, 0.25 * CW, 0, Math.PI * 2);
ctx.closePath();
ctx.stroke();
ctx.restore();
}
function drawDots() {
for (let dot of dotArr) {
dot.drawDot();
}
}
ctx.clearRect(0, 0, CW, CH);
drawCircle();
drawDots();
requestAnimationFrame(mainLoop);
}
function addDot() {
function generateDot() {
let center_x = CW / 2;
let center_y = CH / 2;
let angle = Math.random() * 360;
let distance = Math.random() * (0.25 * CW);
let radius = 0.25 * CW;
return [center_x + Math.cos(angle) * distance, center_y + Math.sin(angle) * distance, center_x + Math.cos(angle) * radius, center_y + Math.sin(angle) * radius]
}
function verifyDotPosition(xPar, yPar, xBorder, yBorder) {
for (let dot of dotArr) {
if (Math.sqrt(Math.pow(xPar - dot.posX, 2) + Math.pow(yPar - dot.posY, 2)) < dotDistance) {
return false;
}
if (Math.sqrt(Math.pow(xPar - xBorder, 2) + Math.pow(yPar - yBorder, 2)) < borderDistance) {
return false;
}
}
dotCounter++;
return true;
}
let newDots = generateDot();
let x1 = newDots[0];
let y1 = newDots[1];
let x2 = newDots[2];
let y2 = newDots[3];
while (!verifyDotPosition(x1, y1, x2, y2)) {
newDots = generateDot();
x1 = newDots[0];
y1 = newDots[1];
x2 = newDots[2];
y2 = newDots[3];
}
if (dotCounter < 10) {
dotArr.push(new dot(x1, y1));
} else {
canvas.removeEventListener("click", addDot);
}
}
mainLoop();
canvas.addEventListener("click", addDot);
canvas {
border: 1px solid black;
position: absolute;
}
body {
margin: 0;
}
<!DOCTYPE html>
<html>
<head>
<title>redZone-demo</title>
</head>
<body>
<canvas></canvas>
</body>
</html>
- каждая оболочка имеет радиус всплеска, если вы находитесь внутри окружности с радиусом, равным этому радиусу всплеска , окружающему точку, в которую она попала, вы умрете
Уточнение:
Когда я говорил, что иногда алгоритм не работает для первой точки, я имею в виду, что иногда первая точка создается слишком близко к границе "красной зоны".