I'm working on a "Tank" game where you control a Tank (top-down view) with a controller, where you turn in the game by holding down one of the individual triggers on a controller (in this case, an Xbox 360 controller).
What I have right now
What I have right now is that the rotation happens in the middle of the "Tanks" body (The sprite size is 60 x 40) which is fine for testing purposes but that's not what I want.
What I want to happen
What I want to happen is that when you press one of the Triggers (left or right) the point of "rotation" changes to either the left or the right side of the Tank. When that happens (when you for example hold down the left trigger) it gives the Tank a wider turning radius. When you release the Trigger or hold down both, the point of rotation is in the "middle".
What I've tried
What I've tried is to mess around with the "Tank" Sprites origin offset (white "body" in the same link above) but that messes up from where the Tank is drawn from, making the "Tanks" body offset from everything else. There's this thread from 6 years ago that might(?) be similar to what I'm trying to do but I'm having difficulties to "translate" it to my needs and if it's applicable to today.
Also for this project, I'm using the "Baton" library.
Please let me know if something is unclear, I sometimes have the habit explaining problems vaguely.
Code
Code: Select all
local baton = require 'baton'
local input = baton.new {
controls = {
left = {'key:left'},
right = {'key:right'},
up = {'key:up'},
down = {'key:down'},
fire = {'key:x', 'button:a'},
aimLeft = {'axis:leftx-', 'key:q'},
aimRight = {'axis:leftx+', 'key:e'},
aimUp = {'axis:lefty-'},
aimDown = {'axis:lefty+'},
turnTankLeft = {'axis:triggerright+', 'key:d'},
turnTankRight = {'axis:triggerleft+', 'key:a'},
forwardVelocity = {'axis:triggerleft+' and 'axis:triggerright+'}
},
pairs = {
move = {'left', 'right', 'up', 'down'},
aim = {'aimLeft','aimRight','aimUp','aimDown'}
},
joystick = love.joystick.getJoysticks()[1],
deadzone = .33,
}
-- Common values
theta = 4.71
speed = 5
Tank = {}
-- Basically a new sprite (60x40)
Tank.Sprite = love.graphics.newImage("Graphics/tankBody.png")
-- Tank's position on X/Y
Tank.posX = love.graphics:getWidth() * 0.5
Tank.posY = love.graphics:getHeight() * 0.5
-- Tank Radians (or Rotation)
Tank.Radians = 0
-- Scales up (or down) the size of sprite on X/Y
Tank.scaleFactorX = 1
Tank.scaleFactorY = 1
-- Changes origin from where the Sprite is drawn
--[[ MEMO to self: Consider moving originX/Y to original position
and find out how to rotate in the middle without moving
the origin offset
]]
Tank.originOffsetX = Tank.Sprite:getWidth() * 0.5
Tank.originOffsetY = Tank.Sprite:getHeight() * 0.5
-- Tank's Width/Height
Tank.Width = Tank.Sprite:getWidth()
Tank.Height = Tank.Sprite:getHeight()
Tank.halfWidth = Tank.Width * 0.5
Tank.halfHeight = Tank.Height * 0.5
-- Tank Speed/Velocity
Tank.rotationSpeed = 5
Tank.Velocity = 0
-- Tank Direction
Tank.Direction = 1
Tank.currentDirection = Tank.Direction
Tank.Theta = theta -- Angle / Angle area
Turret = {}
-- Turret (Sprite 40x34)
Turret.Sprite = love.graphics.newImage("Graphics/tankTurret.png")
-- Turret's X/Y (Shares the same as the Tank)
-- MEMO to self: Move turret's x/y "forwards a little
Turret.posX = Tank.posX
Turret.posY = Tank.posY
-- Turret Radians (or Rotation)
Turret.Radians = 0
-- Scales up (or down) the size of sprite on X/Y
Turret.scaleFactorX = 1
Turret.scaleFactorY = 1
-- Changes origin from where the Sprite is drawn
Turret.originOffsetX = Turret.Sprite:getWidth() * 0.5
Turret.originOffsetY = Turret.Sprite:getHeight() * 0.5
-- Turret's Width/Height
Turret.Width = Turret.Sprite:getWidth()
Turret.Height = Turret.Sprite:getHeight()
-- Turret's Speed/Velocity
Turret.Velocity = 0
-- Turret's Direction
Turret.Direction = 0
Turret.Theta = theta
Barrel = {}
-- Barrel Sprite (46x12)
Barrel.Sprite = love.graphics.newImage("Graphics/tankBarrel.png")
-- Barrel's X/Y (Shares the same as the Turret)
Barrel.posX = Tank.posX
Barrel.posY = Tank.posY
-- Barrel' Radians (or Rotation)
Barrel.Radians = 0
-- Scales up (or down) the size of sprite on X/Y
Barrel.scaleFactorX = 1
Barrel.scaleFactorY = 1
-- Changes origin from where the Sprite is drawn
Barrel.originOffsetX = -20
Barrel.originOffsetY = Barrel.Sprite:getHeight() * 0.5
-- Barrel's Width/Height
Barrel.Width = Barrel.Sprite:getWidth()
Barrel.Height = Barrel.Sprite:getHeight()
-- Barrel's Speed/Velocity
Barrel.Velocity = 0
-- Barrel's Direction
Barrel.Direction = 0
Barrel.Theta = theta
Track = {}
-- Track Sprite (50x12)
Track.Sprite = love.graphics.newImage("Graphics/tankTrack.png")
-- Track's X/Y (Shares the same as the Tank)
Track.posX = Tank.posX
Track.posY = Tank.posY
-- Track's Radians (or Orientation)
Track.Radians = 0
-- Scales up (or down) the size of sprite on X/Y (two extra values to draw the sprite mirrored)
-- REV = reverse
Track.scaleFactorX = 1
Track.scaleFactorY = 1
Track.scaleFactorX_REV = -1
Track.scaleFactorY_REV = -1
-- Changes origin from where the Sprite is drawn
Track.originOffsetX_LEFT = Track.Sprite:getWidth() - 25
Track.originOffsetY_LEFT = Tank.Sprite:getHeight() - 8
Track.originOffsetX_RIGHT = Track.Sprite:getWidth() - 25
Track.originOffsetY_RIGHT = Tank.Sprite:getHeight() - 8
-- Track's Width/Height
Track.Width = Track.Sprite:getWidth()
Track.Height = Track.Sprite:getHeight()
-- Track's Speed/Velocity
Track.Velocity = 0
-- Track's Direction
Track.Direction = 0
Track.Theta = theta
function Tank:update(dt)
input:update()
if input:pressed 'left' then
print("left active")
end
if input:pressed 'right' then
print("right active")
end
if input:pressed 'up' then
print("up active")
end
if input:pressed 'down' then
print("down active")
end
if input:pressed 'fire' then
print("fire active")
end
if input:down 'turnTankLeft' then
print("rotating left")
Tank.Theta = Tank.Theta - 5 * dt
Track.Theta = Track.Theta - 5 * dt
end
if input:down 'turnTankRight' then
print("rotating right")
Tank.Theta = Tank.Theta + 5 * dt
Track.Theta = Track.Theta + 5 * dt
end
local x, y = input:getRaw'aim'
turretAngle = math.atan2((y), (x))
if input:pressed 'aim' then
turretAngle = math.atan2((y), (x))
end
--[[ forward velocity
if input:down 'forwardVelocity' then
print("forward velocity")
Tank.Velocity = Tank.Velocity + 5 * dt
Turret.Velocity = Turret.Velocity + 5 * dt
else
Tank.Velocity = 0
Turret.Velocity = 0
end
]]
if input:down 'turnTankLeft' and input:down 'turnTankRight' then
Tank.Velocity = Tank.Velocity + speed * dt
Track.Velocity = Track.Velocity + speed * dt
else
Tank.Velocity = 0
Track.Velocity = 0
end
-- m = math
local mCos = math.cos
local mSin = math.sin
Tank.posX = Tank.posX + mCos(Tank.Theta) * Tank.Velocity
Tank.posY = Tank.posY + mSin(Tank.Theta) * Tank.Velocity
Turret.posX = Turret.posX + mCos(Tank.Theta) * Tank.Velocity
Turret.posY = Turret.posY + mSin(Tank.Theta) * Tank.Velocity
Barrel.posX = Barrel.posX + mCos(Tank.Theta) * Tank.Velocity
Barrel.posY = Barrel.posY + mSin(Tank.Theta) * Tank.Velocity
Track.posX = Track.posX + mCos(Tank.Theta) * Tank.Velocity
Track.posY = Track.posY + mSin(Tank.Theta) * Tank.Velocity
end
function Tank:draw()
love.graphics.print("angle: "..turretAngle, 10, 10)
-- Tank Graphics
love.graphics.draw(Tank.Sprite,
Tank.posX,
Tank.posY,
Tank.Theta,
Tank.scaleFactorX,
Tank.scaleFactorY,
Tank.originOffsetX,
rotPoint_CURRENT)
-- Track Graphics (LEFT)
love.graphics.draw(Track.Sprite,
Track.posX,
Track.posY,
Track.Theta,
Track.scaleFactorX,
Track.scaleFactorY,
Track.originOffsetX_LEFT,
Track.originOffsetY_LEFT)
-- Track Graphics (RIGHT)
love.graphics.draw(Track.Sprite,
Track.posX,
Track.posY,
Track.Theta,
Track.scaleFactorX,
Track.scaleFactorY_REV,
Track.originOffsetX_RIGHT,
Track.originOffsetY_RIGHT)
-- Turret Graphics
love.graphics.draw(Turret.Sprite,
Turret.posX,
Turret.posY,
turretAngle,
Turret.scaleFactorX,
Turret.scaleFactorY,
Turret.originOffsetX,
Turret.originOffsetY)
-- Barrel Graphics
love.graphics.draw(Barrel.Sprite,
Barrel.posX,
Barrel.posY,
turretAngle,
Barrel.scaleFactorX,
Barrel.scaleFactorY,
Barrel.originOffsetX,
Barrel.originOffsetY)
love.graphics.rectangle("fill", Turret.posX, Turret.posY, 2, 2)
end
return Tank