Обнаружение края холста и возможность отойти от него - PullRequest
0 голосов
/ 22 сентября 2018

У меня есть небольшая игра, где игрок перемещает круг в пределах холста.У меня возникли проблемы с определением краев холста, запретом игроку проходить мимо этих краев и разрешением пользователю перемещаться от любого заданного края.

В настоящее время игрок может ударить по краям холста и успешно удаляться, большую часть времени.Тем не менее, при комбинации определенных движений и столкновений вдоль края игрок застрянет.

Как создать простое обнаружение столкновения краев холста и позволить пользователю свободно перемещаться после события?

Мой код:

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height - 30;
var dx = 2;
var dy = -2;
var ballRadius = 10;
var rightPressed = false;
var leftPressed = false;
var upPressed = false;
var downPressed = false;

document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);

function keyDownHandler(e) {
  if (e.keyCode == 65) {
    rightPressed = true;
  }

  if (e.keyCode == 68) {
    leftPressed = true;
  }

  if (e.keyCode == 87) {
    upPressed = true;
  }

  if (e.keyCode == 83) {
    downPressed = true;
  }
}

function keyUpHandler(e) {
  if (e.keyCode == 65) {
    rightPressed = false;
  }

  if (e.keyCode == 68) {
    leftPressed = false;
  }

  if (e.keyCode == 87) {
    upPressed = false;
  }

  if (e.keyCode == 83) {
    downPressed = false;
  }
}

function drawBall() {
  ctx.beginPath();
  ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
  ctx.strokeStyle = "black";
  ctx.stroke();
  ctx.closePath();
}

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  drawBall();

  if (x + dx > canvas.width - ballRadius || x + dx < ballRadius - 3) {
    dx = -dx;
  }

  if (y + dy > canvas.height - ballRadius || y + dy < ballRadius - 3) {
    dy = -dy;
  }

  if (rightPressed) {
    x -= dx;
  }

  if (leftPressed) {
    x += dx;
  }

  if (upPressed) {
    y += dy;
  }

  if (downPressed) {
    y -= dy;
  }
}

setInterval(draw, 10);
<canvas id="myCanvas"></canvas>

Ответы [ 3 ]

0 голосов
/ 22 сентября 2018

Ну, я должен признать, что это было давно, так как я не касался старых библиотек, хранящихся в хранилище.К счастью, у меня есть источники под рукой, поэтому после ознакомления я расскажу метод, который работает для меня в отношении , как обнаружить столкновение объекта шара с стеной .

Я думаю, это подойдет вам, не знаю, лучшее или худшее решение, но работает !.Давайте начнем с определения того, как мы представляем данные для каждого шара, вспомним наших друзей из Unix, которые говорят, что часть сложности заключается в структуре данных, поскольку она является частью алгоритма в целом ... но достаточно чата, переходя кимеет значение .. с помощью такой структуры данных для представления Ball

class Ball
{
    radio : number
    x : number
    y : number
}

This is a good way for representing balls in 2d worlds Таким образом, вы можете нарисовать шар следующим образом:

function draw (Graphics g)
{
    int r = ball.getRadio ();
    int diam = rad * 2;
    int px = (int) ball.getPx () - r;
    int py = (int) ball.getPy () - r;
    g.setColor (niceColor);

    g.fillArc (px,py,diameter,diameter,0,360); // Fills a circular or elliptical arc covering the specified rectangle 
}

// Отказ от ответственности, я не очень хорошо знаю примитивы для графических процедур на холсте, но я бы предположил, что у вас будет что-то, чтобы нарисовать круг со всем этим.У вас есть px, py, x, y, радио, диаметр.

В любом случае ответ на вопрос приходит сюда, где вы можете использовать этот код:

function isAHorizontalCollision (ball c,int width)
{
    return (c.x > width - c.radio || c.x < radio);
}

function isAVerticalCollision (ball c,int height)
{
    return (c.y > height - c.radio || c.y < radio);
}

// Предположим, что вмещающий прямоугольникгде мяч может двигаться между (0, ширина) для горизонтальной и (сверху, 0) вертикальной.

Важно сообщить, что это работает, только если значения x идут постепенно слева направо, а y понижается сверху вниз.

Надеюсь, моя машинопись похожаКод хорошо подходит для объяснения.У меня есть много исходных файлов в Java для этого.Если нужно больше.(Например, столкновение между двумя кругами).

Если у вас есть время , я бы порекомендовал проверить это , там очень и очень мощные вещи.

0 голосов
/ 24 сентября 2018

Спасибо за помощь от вас двоих, которые ответили на мой вопрос.Благодаря вам двоим я смог успешно найти решение.

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

if (x + dx > canvas.width - ballRadius || x + dx < ballRadius - 3) {
    dx = -dx;
}

if (y + dy > canvas.height - ballRadius || y + dy < ballRadius - 3) {
    dy = -dy;
}

Однако, как было указано, это меняет направление движения, делая его практически бесполезнымдля моей намеченной цели.Не только это, но и все 4 стороны холста действуют в немного отличающихся друг от друга усадьбах.

Используя обратную связь с другим ответом, вот решение, которое я использую сейчас, которое прекрасно работает:

if (x + dx > canvas.width - ballRadius) {
    var fx = x - dx;
    x = fx;
} 

if (x + dx < ballRadius) {
    var fx = x + dx;
    x = fx;
}

if (y + dy > canvas.height - ballRadius) {
    var fy = y + dy;
    y = fy;
}

if (y + dy < ballRadius) {
    var fy = y - dy;
    y = fy;
}

Таким образом, я успешно обнаруживаю все 4 стороны, останавливая движение пользователя наконтакт, и позволяя игроку отойти от края холста.

0 голосов
/ 22 сентября 2018

Вы немного усложнили все булевы переменные ...
То же самое можно сделать с помощью dx и dy, то есть ваша скорость устанавливает их на 0 для остановки.

Также похоже на то, что вы инвертируете направление клавиш, которое было линиями:

if (x + dx > canvas.width - ballRadius || x + dx < ballRadius - 3) {
  dx = -dx;
}

if (y + dy > canvas.height - ballRadius || y + dy < ballRadius - 3) {
  dy = -dy;
}

Когда эти условия верны, верх теперь понижен, а правое лево, не уверен, что этоЭто было ваше намерение, когда он работал, казалось, что мяч отскакивает от края, но с этого момента ключ был перевернут ... Я убрал это из своего исправления.

Вот мой подход, я добавил немного математического веселья, чтобы оживить вашего игрока:

var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var x = canvas.width / 2;
var y = canvas.height / 2;
var dx = 0;
var dy = 0;
var ballRadius = 10;

document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);

function keyDownHandler(e) {
  if (e.keyCode == 65) dx = -2
  if (e.keyCode == 68) dx = 2
  if (e.keyCode == 87) dy = -2
  if (e.keyCode == 83) dy = 2
}

function keyUpHandler(e) {
  if (e.keyCode == 65) dx = 0
  if (e.keyCode == 68) dx = 0
  if (e.keyCode == 87) dy = 0
  if (e.keyCode == 83) dy = 0
}

function draw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  drawBall();

  var fx = x + dx
  var fy = y + dy
  if (ballRadius < fx && fx < canvas.width - ballRadius) x = fx;
  if (ballRadius < fy && fy < canvas.height - ballRadius) y = fy;
}

setInterval(draw, 10);

var hr = ballRadius / 2 - 1
var pi2 = Math.PI * 2
var i = 0

function drawBall() {
  ctx.beginPath();
  ctx.arc(x, y, ballRadius, 0, pi2);
  ctx.strokeStyle = "black";
  ctx.stroke();

  // draw some small moving circles inside
  ctx.beginPath();
  ctx.fillStyle = "red";
  ctx.arc(x + hr * Math.sin(i), y + hr * Math.cos(i), hr, 0, pi2);
  ctx.fill();
  ctx.beginPath();
  ctx.fillStyle = "blue";
  ctx.arc(x - hr * Math.sin(i), y - hr * Math.cos(i), hr, 0, pi2);
  ctx.fill();
  ctx.closePath();
  i += 0.1 + Math.abs(dx)/15 + Math.abs(dy)/15
}
<canvas id="myCanvas" style="border:1px solid #000000;"></canvas>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...