crankani/src/kani.lua

129 lines
3.9 KiB
Lua

-- Code for the player's ship.
import "CoreLibs/object"
import "CoreLibs/graphics"
import "CoreLibs/sprites"
import "CoreLibs/timer"
import "entity"
import "bullet"
import "ui"
local gfx <const> = playdate.graphics
local BASE_CHARGE_FACTOR <const> = 15
local BASE_WEAPON_CHARGE_SPEED <const> = 1000
-- the amount of charge needed to increase the shot power by 1 at each power level
local WEAPON_CHARGE_LOOKUP <const> = {
[0]=5,
[1]=15,
[2]=30,
[3]=50
}
class("Kani").extends(Entity)
function Kani:init(ui)
local img = gfx.image.new("images/kani.png")
Kani.super.init(self, img, 100)
self.vector = {x=0,y=0} -- movement direction
self:setGroupMask(0x2)
self:setCollidesWithGroupsMask(0x19)
self.reserveCharge = 100
-- controls the speed the crank recharges the player's reserves. A lower number allows faster charging.
-- should never be set to 0
self.chargeFactor = BASE_CHARGE_FACTOR
-- weapon variables
self.weaponPower = 0
self.firingMode = false
self.weaponChargeSpeed = BASE_WEAPON_CHARGE_SPEED -- speed in ms between weapon charge levels. Level 2 always takes half this time.
-- the UI gets passed in to Kani so that we can update pieces of it easily.
self.ui = ui
self.inputHandlers = {
upButtonDown = function() self.vector.y = -3 end,
downButtonDown = function() self.vector.y = 3 end,
leftButtonDown = function() self.vector.x = -3 end,
rightButtonDown = function() self.vector.x = 3 end,
upButtonUp = function() self.vector.y = 0 end,
downButtonUp = function() self.vector.y = 0 end,
leftButtonUp = function() self.vector.x = 0 end,
rightButtonUp = function() self.vector.x = 0 end,
cranked = function(change, accelChange) self:chargeReserve(change) end,
AButtonDown = function()
self.firingTimer = playdate.timer.keyRepeatTimerWithDelay(self.weaponChargeSpeed / 2,
self.weaponChargeSpeed,
self.chargeShot, self)
end,
AButtonUp = function() self:fire() end,
}
end
function Kani:chargeReserve(change)
if change <= 0 then return end
self.reserveCharge = math.min(self.reserveCharge + change / self.chargeFactor, 100)
self.ui.chargeMeter:setValue(self.reserveCharge)
end
function Kani:chargeShot()
if self.weaponPower >= 4 then
return -- weapon is fully charged
end
local requiredPower = WEAPON_CHARGE_LOOKUP[self.weaponPower]
-- We use math.ceil here so that any fractional charge rounds up.
-- This ensures we can always use our last bit of juice for a level 1 shot,
-- and smooths out play experience around fully charged values.
local effectiveCharge = math.ceil(self.reserveCharge)
if effectiveCharge >= requiredPower then
self.reserveCharge = effectiveCharge - requiredPower
self.weaponPower += 1
self.ui.chargeMeter:setValue(self.reserveCharge)
self.ui.weaponPowerMeter:setValue(self.weaponPower-1)
end
end
function Kani:fire()
self.firingTimer:remove()
if self.weaponPower <= 0 then
return
end
local bullet = Bullet(self.weaponPower)
bullet:moveTo(self.x+16, self.y)
bullet:add()
self.weaponPower = 0
self.ui.weaponPowerMeter:setValue(0)
end
function Kani:damage(amount)
Kani.super.damage(self, amount)
self.ui.healthMeter:setValue(self.health)
if self.health == 0 then
-- TODO: end game here
end
end
function Kani:addInputHandlers()
playdate.inputHandlers.push(self.inputHandlers)
end
function Kani:removeInputHandlers()
playdate.inputHandlers.pop()
end
-- move that crab!
function Kani:update()
local collisions = select(3, self:moveWithCollisions(self.x + self.vector.x, self.y + self.vector.y))
for i=0, #collisions, 1 do
-- handle player-triggered collisions
end
end