пытаясь воссоздать элемент красной зоны Battle-Royale, используя триг и холст JavaScript - PullRequest
0 голосов
/ 17 ноября 2018

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>

- каждая оболочка имеет радиус всплеска, если вы находитесь внутри окружности с радиусом, равным этому радиусу всплеска , окружающему точку, в которую она попала, вы умрете

Уточнение:

Когда я говорил, что иногда алгоритм не работает для первой точки, я имею в виду, что иногда первая точка создается слишком близко к границе "красной зоны".

...