Search code examples
luarotationlove2d

Shoot from same point of a rotating image


I am trying to make a basic prototype for a top down shooter in LOVE but I am having some issues getting the bullet to shoot from the same point of the image when it is rotated. This is the code I have so far which works fine as the bullet shoots from the center of the image but I want it to shoot from the right hand side of the sprite where the gun is:

function love.load()
love.graphics.setBackgroundColor(54, 172, 248)

player = love.graphics.newImage('/assets/images/player.png')
  playerX = 300
  playerY = 300
  playerSpeed = 200

  bullets = { }
  bulletSpeed = 250

  cursor = love.mouse.newCursor('assets/images/crosshair.png', 24, 24);
  love.mouse.setCursor(cursor);
end

function love.update(dt)
  -- Get mouse position to rotate player
  local mouseX, mouseY = love.mouse.getPosition()
  playerRotation = math.atan2(mouseY - playerY, mouseX - playerX);

  -- Keyboard input to move the player
  if love.keyboard.isDown('s') then
    playerY = playerY + playerSpeed * dt
  elseif love.keyboard.isDown('w') then
    playerY = playerY - playerSpeed * dt
  end

  if love.keyboard.isDown('a') then
    playerX = playerX - playerSpeed * dt
  elseif love.keyboard.isDown('d') then
    playerX = playerX + playerSpeed * dt
  end

  -- update all bullets position
  for i, v in ipairs(bullets) do
    v.x = v.x + (v.dx * dt)
    v.y = v.y + (v.dy * dt)
  end
end

function love.draw(dt)
  -- Draw player
  love.graphics.draw(player, playerX, playerY, playerRotation, 0.5, 0.5, player:getWidth() / 2, player:getHeight() / 2);

  -- Draw all bullets
  love.graphics.setColor(128, 128, 128)
  for i, v in ipairs(bullets) do
    love.graphics.circle("fill", v.x, v.y, 3);
  end
end

function love.mousepressed(x, y, button)
  if button == 1 then
    local startX = playerX;
    local startY = playerY;
    local mouseX = x
    local mouseY = y

    local angle = math.atan2((mouseY - startY), (mouseX - startX))

    local bulletDx = bulletSpeed * math.cos(angle)
    local bulletDy = bulletSpeed * math.sin(angle)

    table.insert(bullets, {x = startX , y = startY, dx = bulletDx, dy = bulletDy})
  end
end

How do I draw it from the same point of the sprite as it is rotated?


Solution

  • If I got you correctly you have an image representing your player. (playerX, playerY) is the position of your player where the center of your image is.

    Atm you start your bullets at the image center. So the starting point of your bullets is invariant to player rotation.

    If you move the gun away from the player center it rotates around that point where the radius is the distance of the gun position to the player position.

    For distance 1 you can refer to the unit circle Unit Circle

    So simply multiply that with your radius so:

    local gunXRotated = playerX + r * math.cos(t)
    local gunYRotated = playerY + r * math.sin(t)
    

    where t is your rotation angle and r is the Euclidean distance between player center and gun muzzle.

    Then simply use the new gun coordinates as the origin of your bullets.