project-witchy/imperium-porcorum.love/scenes/levels/entities/player.lua

343 lines
7.5 KiB
Lua

local Entity = require "scenes.levels.entities.parent"
local Player = Entity:extend()
local PLAYER_W, PLAYER_H = 32, 24
local TEMP_PLAYERID = 1
-- INIT functions
-- Initialize the player
function Player:new(world, x, y)
self.direction = 1
self.startx, self.starty = x, y
self:setSpawnPoint(x, y)
Player.super.new(self, world, "player", x, y, PLAYER_W, PLAYER_H)
self.manager = self.scene.playermanager
self.center = {
x = self.x,
y = self.y,
}
self.stats = {}
self:initStats(TEMP_PLAYERID)
self:initWeapon()
self:initHUD()
self.currentWeapon = 1
self:setDebugColor(0,255,0)
self:setSprite(self.stats.race, PLAYER_W/2, -PLAYER_H/2)
end
function Player:getStats(playerID)
self.pigID = playerID
self.stats = game.pigmanager:getPig(1)
self.playerID = playerID
end
function Player:initStats(playerID)
self:getStats(playerID)
self:resetLife()
self.itemList = {}
self.score = 0
self.gold = 0
self.maxxsp = 16*60
self.maxysp = self.maxxsp
self.topsp = 4.5*60
self.acc = 0.046875*60*1.5
self.dec = 0.5*60
self.xfrc = self.acc*60*4
self.jmp = -5*60
self:setGravityFlag(true)
self.isJumping = false
end
function Player:initWeapon()
self.weaponID = 1
self:setWeapon()
end
-- UPDATE and COLLISION functions
-- Physics and function called every game update
function Player:update(dt)
if (self.isAlive) then
Player.super.update(self, dt)
else
-- Only update timers if the player is dead
self:updateTimers(dt)
end
end
function Player:updateStart(dt)
self.keys = self.scene.sources[1].keys
-- Gameplay movement functions
self:actionMove(dt)
self:shoot(dt)
self:limitMovement()
end
function Player:updateEnd(dt)
self.center.x, self.center.y = self:getCenter()
local _, height = self.world:getDimensions()
if self.y >= (height + 64) then
self:die()
end
-- Cosmetic changes are grouped at the end of the step
-- to be sure they reflect as good as possible the actual situation
self:getDirection()
self:setCustomSpeed(math.abs(self.xsp / 60))
self:setAnimation()
end
function Player:timerResponse(timer)
if (timer == "respawn") then
self:respawn()
end
end
function Player:setFilter()
self.filter = function(item, other)
if (other.type == "wall") then return 'slide'
elseif (other.type == "block") then return 'slide'
elseif (other.type == "platform") and
(self.ysp > 0) and
((self.y+24) <= other.y) then return 'slide'
elseif (other.type == "loot") then return 'cross'
else return nil
end
end
end
function Player:collisionResponse(collision)
local other = collision.other
if (other.type == "loot") then
other:takeLoot(self)
end
end
function Player:limitMovement()
if (math.abs(self.xsp) >= self.maxxsp) then
self.xsp = self.maxxsp * utils.math.sign(self.xsp)
end
if (math.abs(self.ysp) >= self.maxysp) then
self.ysp = self.maxysp * utils.math.sign(self.ysp)
end
end
-- GAMEPLAY functions
-- Where the player act and move
function Player:shoot()
if self.keys["B"].isPressed then
self:launchWeapon()
end
if self.keys["C"].isPressed then
self:changeWeapon(self.weaponID+1)
end
end
function Player:actionMove(dt)
local dx, dy = 0, 0
if self.keys["right"].isDown and not (self.keys["left"].isDown) then
if (self.xsp < self.topsp) then
if (self.xsp < 0) then
self.xsp = self.xsp + self.dec
else
self.xsp = self.xsp + self.acc
end
end
elseif self.keys["left"].isDown and not (self.keys["right"].isDown) then
if (self.xsp > -self.topsp) then
if (self.xsp > 0) then
self.xsp = self.xsp - self.dec
else
self.xsp = self.xsp - self.acc
end
end
else
self:applyFriction(dt)
end
if (self.grav == 0) then
if self.keys["down"].isPressed and (self.y < 1000) then
self.ysp = 160
elseif self.keys["up"].isPressed and (self.y > 0) then
self.ysp = -160
end
end
if (self.onGround == true) then
self.isJumping = false
end
multijump = true
if ((self.onGround == true) or multijump) and self.keys["A"].isPressed then
self.ysp = self.jmp
self.isJumping = true
self.scene.assets:playSFX("jump")
end
if (self.isJumping == true) and (self.ysp < (-4 * 60)) and (not (self.keys["A"].isDown)) then
self.ysp = -4 * 60
end
return dx, dy
end
function Player:launchWeapon()
self.obj.Weapon(self.world, self.center.x, self.center.y, self.weapon, 350 * utils.math.sign(self.direction), 0, self)
end
function Player:changeWeapon(id)
local maxWeapon = #self.stats.weaponList
self.weaponID = utils.math.wrap(id, 1, maxWeapon)
self:setWeapon()
end
function Player:setWeapon()
self.weapon = self.stats.weaponList[self.weaponID]
end
-- DRAW functions
function Player:draw()
if (self.isAlive) then
Player.super.draw(self)
end
end
function Player:setAnimation()
local animation = "idle"
self:setSpriteScallingX(self.direction)
if (self.onGround) then
if (self.xsp == 0) then
self:changeAnimation("idle", false)
else
if (self.keys["left"].isDown and (self.xsp > 0)) or
(self.keys["right"].isDown and (self.xsp < 0)) then
self:changeAnimation("brake", true)
else
self:changeAnimation("walk", false)
end
end
else
if (self.ysp < 0) and (self.isJumping) then
self:changeAnimation("jump", true)
else
self:changeAnimation("fall", true)
end
end
end
-- HUD FUNCTIONS
-- All functions related to the HUD
function Player:initHUD()
local mediumfont, smallfont
mediumfont = self.scene.assets.fonts["medium"]
smallfont = self.scene.assets.fonts["small"]
self.hpbar = game.gui.newProgressBar("greenbar", mediumfont, smallfont, "HP", 96)
self.mpbar = game.gui.newProgressBar("bluebar", mediumfont, smallfont, "MP", 96)
self.itembox = game.gui.newTextBox("assets/sprites/gui/textbox/yellowbox.png", 24,24)
end
function Player:drawHUD()
utils.graphics.resetColor()
local hp = 0
local mp = 0
local weapon = 0
love.graphics.draw(self.itembox, 16, 16)
if (self.isAlive) then
hp = self.hp / self.stats.maxHP
mp = self.mp / self.stats.maxMP
weapon = self.weapon
end
if (weapon ~= 0) and (weapon ~= nil) then
self.scene.assets.tileset["weapon"]:drawTile(weapon,28,28,0,1,1,8,8)
end
self.hpbar:draw(68, 14, hp)
self.mpbar:draw(68, 30, mp)
self.scene.assets.fonts["medium"]:set()
love.graphics.printf( utils.math.numberToString(self.score, 6), 373, 10, 96, "right")
love.graphics.printf( utils.math.numberToString(self.gold, 4), 373, 25, 96-18, "right")
love.graphics.setColor(1, 1, 85/256)
love.graphics.printf( "G", 373, 25, 96, "right")
utils.graphics.resetColor()
end
function Player:addScore(score)
self.score = self.score + score
end
function Player:addGold(gold)
self.gold = self.gold + gold
end
-- DEATH and HIT functions
-- All function related to damage management
function Player:setSpawnPoint(x, y)
self.spawn = {}
self.spawn.x = x
self.spawn.y = y
end
function Player:goToSpawnPoint( )
self.x = self.spawn.x
self.y = self.spawn.y
self.world:changeActorData(self)
end
function Player:respawn()
self.isAlive = true
self:goToSpawnPoint( )
end
function Player:resetLife()
self.hp = self.stats.maxHP
self.mp = self.stats.maxMP
self.isAlive = true
end
function Player:takeHit(damage)
if (self.hp <= damage) then
self:die()
else
self.hp = self.hp - damage
end
end
function Player:die()
self:addTimer("respawn", 1)
self.isAlive = false
end
return Player