1

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

Community
  • 1
  • 1
Kosmetika
  • 20,774
  • 37
  • 108
  • 172
  • What's wrong with `self.rotation = math.atan2(dx, dy)` ? – Egor Skriptunoff Jan 07 '17 at 12:44
  • @EgorSkriptunoff I tried with math.atan2(dx, dy) but it makes entity rotating constantly – Kosmetika Jan 07 '17 at 13:03
  • Yes, Enemy will always look directly to the Player. Does not it exactly what you want? – Egor Skriptunoff Jan 07 '17 at 13:20
  • yes, but it didn't behave that way, I will add a gif to show you – Kosmetika Jan 07 '17 at 13:23
  • I mean **WITHOUT** `+ ANGLE_ACCELERATION * dt` – Egor Skriptunoff Jan 07 '17 at 14:34
  • @EgorSkriptunoff pls take a look on demo - https://dl.dropboxusercontent.com/u/100463011/love2d-steering-2.gif produced by `self.rotation = math.atan2(dx, dy)` – Kosmetika Jan 07 '17 at 19:12
  • Remove `- self.xvel` from `Enemy:seek()` – Egor Skriptunoff Jan 07 '17 at 20:19
  • @EgorSkriptunoff thanks, that's much better now - https://dl.dropboxusercontent.com/u/100463011/love2d-steering-4.gif but there's still problem with an image as you see on the demo – Kosmetika Jan 08 '17 at 11:39
  • @EgorSkriptunoff here is a more detailed demo with low enemy speed - https://dl.dropboxusercontent.com/u/100463011/love2d-steering-5.gif as you can see everything starts normally and enemy looks into player's side but when player turns left/right enemy starts to turn into opposite direction. – Kosmetika Jan 08 '17 at 12:30
  • Swap dx and dy: `math.atan2(dy, dx)` – Egor Skriptunoff Jan 08 '17 at 12:38
  • @EgorSkriptunoff that works! thanks! it would be nice if you'll write some explanation for your tips as switching y and x coordinates feels like magic trick :) – Kosmetika Jan 08 '17 at 12:41
  • @EgorSkriptunoff I posted related question to game dev stackexchange - http://gamedev.stackexchange.com/questions/135547/reimplemented-steering-seek-behavior-from-pygame-to-l%C3%96ve-is-much-slower-than-ori maybe you'll be interested to answer. – Kosmetika Jan 09 '17 at 16:15

1 Answers1

1

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.

Siemkowski
  • 1,351
  • 5
  • 15
  • 32