Change angle (rotation) of entity in steering (seeking) behavior in 2d game

539 views Asked by At

I'm developing 2d space shooter with LOVE2D in Lua and as I'm not math and physics expert I got some questions with implementing steering behavior for enemies.

I finally managed to make enemy "seeking" for a player and it looks like:

Code that makes it work (formula is taken from this answer - https://stackoverflow.com/a/2561054/2117550):

function Enemy:seek ()
  local dx = self.player.x - self.x - self.xvel
  local dy = self.player.y - self.y - self.yvel

  -- normalize
  local len = math.sqrt(dx * dx + dy * dy)
  dx, dy = dx / len, dy / len

  return dx, dy
end

Then I use my seek function in update:

function Enemy:update (dt)
  -- seeking acceleration
  local dx, dy = self:seek()

  -- what is the proper way of calculating enemies rotation?
  -- self.rotation = math.atan2(dx, dy) + ANGLE_ACCELERATION * dt

  -- update velocity
  self.xvel = self.xvel + dx * MAX_SPEED * dt -- * math.cos(self.rotation) it's not needed anymore? 
  self.yvel = self.yvel + dy * MAX_SPEED * dt -- * math.sin(self.rotation) it's not needed anymore? 

  -- moving entity in camera
  _.checkWorldBounds(self)

  local futureX = self.x + self.xvel * dt
  local futureY = self.y + self.yvel * dt
  local nextX, nextY, collisions, len = self.world:move(self, futureX, futureY, self.collisionFilter)

  self.x = nextX
  self.y = nextY
  self.xvel = self.xvel * 0.99
  self.yvel = self.yvel * 0.99
end

So the only problem now is that enemy's rotation is not changing though the front of the spaceship should always look into player's side.

I tried with math.atan2(dx, dy) but it makes entity rotating constantly.

What is missing or what am I doing wrong?

I'm not looking for someone to code this for me (although it would be very nice) but some formula or piece of advice will be highly appreciated.

If you're interested the source code is available at - https://github.com/voronianski-on-games/asteroids-on-steroids-love2d

1

There are 1 answers

0
Siemkowski On BEST ANSWER

I can't tell you what is wrong with your code, but hopefully this will help you out.

-- these are the coordinates of the point to which your object should be facing
local playerx, playery = 100, 100
-- these are the current coordinates of the object that needs to have its facing changed
local shipx, shipy = 200, 200

-- the angle to which your object should be rotated is calculated
angle = math.atan2(playery - shipy, playerx - shipx)

Note that by using body:setAngle(angle) ('body' is your objects body) your objects will be instantly rotated to given angle. If you want them to rotate at certain pace you could use:

local currentAngle = body:getAngle()
local adjustedAngle

if currentAngle > angle then
  adjustedAngle = currentAngle - rotationSpeed * dt
elseif currentAngle < angle then
  adjustedAngle = currentAngle + rotationSpeed * dt
else
  adjustedAngle = currentAngle
end
body:setAngle(adjustedAngle)

Also note that the 'front' of your ship/body/object is to the right along the x-axis. In other words the angle is calculated from the x-axis and 0 means that the object is facing right.