2014-12-28 2 views
0

Я написал html5 игровой фрейм и попытался создать платформу 2d. Но я застрял в части обнаружения столкновения в игре, моя инфраструктура содержит прямой объект с методом «пересекает». Таким образом, вы можете проверить, пересекается ли прямой с другим прямоугольником, он отлично работает, но я не знаю, как реагировать на этот метод. Я попытался установить позицию игрока в последнюю «не сталкивающуюся» позицию, но проблема в том, что это было смещение скорости игрока, каждый раз, когда имелся пробел со скоростью игрока ...Как реагировать на обнаружение столкновений в платформах 2d

Я могу Я больше не думаю.

+0

Я думаю, что это вопрос дизайна игры в целом и специально не связан с HTML5 или JS. Вы должны обновить теги вашего вопроса. – Rapti

+0

Спасибо. Я дам вам подробный ответ в ближайшее время. – Rapti

+0

Нет подсказки, но не обновляйте позицию игроков, когда они сталкиваются? – ManyQuestions

ответ

1

Я думаю, что это вопрос механики игры в целом, а не только для игр HTML5/JS. Я не знаком с синтаксисом HTML5, поэтому вам, возможно, придется переписать некоторые детали моих примеров кода. Кроме того, я не знаю, как именно вы структурировали свой код; Я предполагаю, что и у игрока, и у блока есть некоторые функции, такие как getX(), getXSpeed(), setX() и так далее.

Когда вы обнаруживаете столкновение между игроком (или любым другим объектом, который может двигаться) и блок среды, вам нужно обновить позицию игрока, чтобы он просто касался блока, не перехватывая его. Прежде чем вы сможете это сделать, вам нужно найти , как он сталкивается с блоком: игрок попал в блок сверху, слева, справа или снизу?

Во-первых, нам нужна позиция игрока.

playerX = player.getX(); 
playerY = player.getY(); 

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

if(player.getXSpeed() > 0) { 
    playerX += player.getWidth(); 
} 
if(player.getYSpeed() > 0) { 
    playerY += player.getHeight(); 
} 

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

blockX = player.getXSpeed() > 0? block.getX() : block.getX() + block.getWidth(); 
blockY = player.getYSpeed() > 0? block.getY() : block.getY() + block.getHeight(); 

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

Я создал небольшую схему в случае, если вы не понимаете, почему мы делаем это:

Collision Diagram

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

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

(currentPlayerY - previousPlayerY)/(currentPlayerX - previousPlayerX) 

меньше

(currentPlayerY - blockY)/(currentPlayerX - blockX) 

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

bool verticalSide = abs(player.getYSpeed()/player.getXSpeed()) < abs((playerY/blockY)/(playerX - blockX)); 

Поскольку мы можем игнорировать гравитацию, мы можем делать вид, что движение игрока является линейной. Нам нужна только одна точка на этой линии, чтобы указать, в каком направлении идет игрок. Это значит, что (currentPlayerY - previousPlayerY)/(currentPlayerX - previousPlayerX) всегда будет равен player.getYSpeed()/player.getXSpeed(), независимо от того, насколько далеко игрок находился в предыдущем игровом цикле. Обратите внимание, что игрок не обязательно приходит из левого верхнего положения, поэтому наклон, который мы рассчитали, может быть отрицательным. Мы используем математический класс «abs()», который обычно предоставляют языки программирования, чтобы получить абсолютное значение, т. Е. Положите все отрицательные значения.

Теперь, когда мы знаем, имеем ли мы дело с горизонтальным или вертикальным столкновением, мы можем изменить положение игрока соответственно:

if(verticalSide) { 
    player.setX(player.getXSpeed() > 0? blockX - player.getWidth(): blockX); 
    player.setXSpeed(0); 
} else { 
    player.setY(player.getYSpeed() > 0? blockY - player.getHeight(): blockY); 
    player.setYSpeed(0); 
} 

Если verticalSide правда, игрок задевая сторону блока. Теперь мы проверяем, положительна ли скорость игрока, чтобы узнать, идет ли он слева или справа и обновляет свою позицию, поэтому он просто касается блока. Мы также устанавливаем его горизонтальную скорость на 0. Однако, если verticalSide не соответствует действительности, игрок натыкается на верхнюю или нижнюю часть блока, поэтому мы делаем то же самое для оси y. Это должно быть все, что вам нужно.

Но у меня есть дополнительный совет для вас: вам, скорее всего, нужна информация о том, касается ли игрок в данный момент касания земли, чтобы определить, может ли он прыгать, когда пробел или какая-либо клавиша нажата. Для этого вам необходимо создать логическое поле grounded в вашем классе игрока, которое при каждом перемещении игрока будет установлено на false. Во время проверки на столкновение снова установите значение true, если игрок попадает в верхнюю часть блока, то есть verticalSide равен false, а player.getYSpeed() > 0 - true. Если нажать клавишу перехода, проверьте, grounded - true перед тем, как запустить скачок.

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

+0

О, мой бог, THX sooooo много человек :)). Поскольку я начал создавать игры с javascript/java и т. Д., У меня была эта проблема и она никогда не решалась. Я просто нахожу решения для обнаружения столкновений, но не как реагировать на это. Вы сделали мой день, соответственно. мои выходные. С уважением, германия. И счастливый новый год (когда придет время) :) снова thx sooo много. – Nimmi

+0

Нет проблем, а также einen guten Rutsch обратно из немецкого города Ратинген под Дюссельдорфом. – Rapti

+0

О, проблема с ein hab ich noch, wenn ich jetzt als spieler von einem Block falle und ganz schnell a oder d drücke um a den block ran zu kommen teleportiert es mich noch oben/unten auf der y coord, weißt du woran das liegt? – Nimmi