Физика Non-Box2D с Corona SDK

Я создаю платформенную игру на основе плитки с Corona SDK. Я решил отказаться от встроенного механизма ядра Box2D (по ряду причин), и я пытаюсь создать свою собственную физическую систему. Опять же, моя игра построена на плитки, что позволяет легко собирать возможные коллайдеры. Кроме того, единственным объектом, который должен сталкиваться с плитками, является мой плеер, который должен сделать его еще проще.

У меня гравитация и скорость работы, и теперь я начинаю с столкновений. Я читал на нескольких сайтах, как это сделать, но, похоже, это не работает для меня. Процесс, который я видел, выглядит примерно так:

  1. Найдите возможные коллайдеры (легко с играми на основе плитки)
  2. Проверьте наличие коллизий (AABB в моем случае)
  3. Рассчитать глубину проникновения X и Y
  4. Переместить объект по сумме проникновения
  5. Настроить скорость, основанную на проникновении

У меня есть шаги 1-3 вниз, но по какой-то причине, когда я начинаю шаги 4 и 5, ничего не работает, как говорится в учебниках. При столкновении с полом игрок мгновенно перемещается влево. Я знаю, почему он это делает - он вычисляет ширину игрока как глубину проникновения, но когда я пытаюсь его исправить, все становится странным.

Я вызываю эту функцию для каждой плитки, которая сталкивается с игроком (после того, как ее обнаружили с помощью простой проверки AABB):

local resolveCollision = function(guy, tile)
 local guyX, guyY, tileX, tileY = guy.x, guy.y, tile.x, tile.y
 local guyHW, guyHH = guy.width * 0.5, guy.height * 0.5
 local tileHW, tileHH = tile.width * 0.5, tile.height * 0.5

 local distX = guyX - tileX
 local minDistX = guyHW + tileHW

 local absDistX = (distX < 0 and -distX) or distX

 -- Calculate X penetration
 local xPen = 0
 if absDistX >= minDistX then
 xPen = 0
 else
 xPen = (distX > 0 and minDistX - distX) or -minDistX - distX
 end

 local distY = guyY - tileY
 local minDistY = guyHH + tileHH
 local absDistY = (distY < 0 and -distY) or distY

 -- Calculate Y penetration
 local yPen = 0
 if absDistY >= minDistY then
 yPen = 0
 else
 yPen = (distY > 0 and minDistY - distY) or -minDistY - distY
 end

 local absXPen = (xPen < 0 and -xPen) or xPen
 local absYPen = (yPen < 0 and -yPen) or yPen

 -- Trim off larger penetration
 if absXPen > absYPen and absYPen ~= 0 then
 xPen = 0
 guy.setYVel(0)
 elseif absYPen > absXPen and absXPen ~= 0 then
 yPen = 0
 guy.setXVel(0)
 end

 guy:translate(xPen, yPen)
end

Кто-нибудь знает, как правильно реагировать на столкновение? FYI, моя "физическая" структура дает следующие методы/ценности (среди прочего):

obj.setXVel(n) - Set X-velocity
obj.setYVel(n) - Set Y-velocity
obj.setVelocity(x, y) - Set both velocities at once
obj.xVel - Read-only, X-velocity value
obj.yVel - Read-only, Y-velocity value
1 ответ

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

Я предлагаю вам изменить его на время движения. Для этого вам нужно найти время дельты (прошедшее время между кадром и следующим) и изменить его по сумме вашего перемещения. Используйте этот учебник, чтобы получить deltaTime: http://coronalabs.com/blog/2013/06/18/guest-tutorial-delta-time-in-corona/

Когда у вас есть dT, используйте его следующим образом:

moveAmount = velocity * deltaTime

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

licensed under cc by-sa 3.0 with attribution.