-- 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 = playdate.graphics local BASE_CHARGE_FACTOR = 15 local BASE_WEAPON_CHARGE_SPEED = 1000 -- the amount of charge needed to increase the shot power by 1 at each power level local WEAPON_CHARGE_LOOKUP = { [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