diff options
Diffstat (limited to 'not/Hero.lua')
-rw-r--r-- | not/Hero.lua | 212 |
1 files changed, 182 insertions, 30 deletions
diff --git a/not/Hero.lua b/not/Hero.lua index a97a2b1..676dc4a 100644 --- a/not/Hero.lua +++ b/not/Hero.lua @@ -4,8 +4,6 @@ Hero = require "not.PhysicalBody":extends() -- Few are left... -Hero.jumpTimer = 0.16 -Hero.jumpCounter = 2 Hero.sfx = require "config.sounds" Hero.QUAD_FRAME = love.graphics.newQuad(0, 15, 32,32, 80,130) @@ -19,6 +17,8 @@ Hero.PUNCH_LEFT = {-2,-6, -20,-6, -20,6, -2,6} Hero.PUNCH_RIGHT = {2,-6, 20,-6, 20,6, 2,6} Hero.PUNCH_UP = {-8,-4, -8,-20, 8,-20, 8,-4} Hero.PUNCH_DOWN = {-8,4, -8,20, 8,20, 8,4} +Hero.JUMP_TIMER = 0.16 +Hero.JUMP_COUNT = 2 -- TODO: Portrait managment in Hero and config passed from Menu should be reviewed! -- TODO: Clean-up, see `menus/select`. @@ -43,13 +43,13 @@ function Hero:new (config, x, y, world) self.salto = false self.smoke = false self.isAlive = true - self.isWalking = false - self.isJumping = false self.spawntimer = 2 + self.jumpTimer = Hero.JUMP_TIMER + self.jumpCounter = Hero.JUMP_COUNT self.punchCooldown = 0 -- TODO: Pass loaded portrait from menu to Hero. self.portrait = love.graphics.newImage(config.portrait) - self:setAnimationsList(require("config.animations.hero")) + self:setAnimations(require("config.animations.hero")) -- Post-creation self:createEffect("respawn") end @@ -70,13 +70,18 @@ function Hero:newFixture () fixture:setGroupIndex(self.group) end --- Update callback of `Hero` +--- Called each game iteration. +-- @param dt time since last iteration +-- TODO: Cut this method into smaller parts. function Hero:update (dt) Hero.__super.update(self, dt) + if self.body:isDestroyed() then return end + self:dampVelocity(dt) + -- Salto if self.salto and (self.current == self.animations.walk or self.current == self.animations.default) then self.angle = (self.angle + 17 * dt * self.facing) % 360 @@ -84,7 +89,7 @@ function Hero:update (dt) self.angle = 0 end - -- Could you please die? + -- Death -- TODO: World/Map function for testing if Point is inside playable area. local m = self.world.map local x, y = self:getPosition() @@ -95,7 +100,7 @@ function Hero:update (dt) self:die() end - -- Respawn timer. + -- Respawn if self.spawntimer > 0 then self.spawntimer = self.spawntimer - dt end @@ -103,18 +108,17 @@ function Hero:update (dt) self:respawn() end - -- Trail spawner + -- Trail -- TODO: lower the frequency of spawning - currently it is each frame. if self.smoke and self.inAir then local dx, dy = love.math.random(-5, 5), love.math.random(-5, 5) self:createEffect("trail", dx, dy) end - -- # PUNCH - -- Cooldown + -- Punch cooldown self.punchCooldown = self.punchCooldown - dt if not self.body:isDestroyed() then -- TODO: This is weird - for _,fixture in pairs(self.body:getFixtureList()) do -- TODO: getFixtures from `PhysicalBody` or similar. + for _,fixture in pairs(self.body:getFixtures()) do -- TODO: getFixtures from `PhysicalBody` or similar. if fixture:getUserData() ~= self then fixture:setUserData({fixture:getUserData()[1] - dt, fixture:getUserData()[2]}) if fixture:getUserData()[1] < 0 then @@ -124,7 +128,27 @@ function Hero:update (dt) end end - -- Stop vertical + -- Walking + -- TODO: Walking is still not satisfactiory. Think of way to improve it. + if self:isWalking() then + if not self._already_walking then + self._already_walking = true + self:onWalkingStarted() + end + else + if self._already_walking then + self._already_walking = false + self:onWalkingStopped() + end + end + if self:isWalkingLeft() then + self:walk(-1) + end + if self:isWalkingRight() then + self:walk(1) + end + + -- Set predefined velocity when attack animations are playing local currentAnimation = self:getAnimation() if self.frame < currentAnimation.frames then if currentAnimation == self.animations.attack_up or currentAnimation == self.animations.attack_down then @@ -134,11 +158,43 @@ function Hero:update (dt) self:setLinearVelocity(38*self.facing, 0) end end + + -- Jumping + if self:isJumping() then + if self.jumpTimer > 0 then + if not self._jumping then + self._jumping = true + self:onJumpStarted() + end + if self.jumpCounter == 0 or self.jumpCounter == 1 then + local x = self:getLinearVelocity() + self:setLinearVelocity(x,-160) + self.jumpTimer = self.jumpTimer - dt + end + end + else + if self._jumping then + self._jumping = false + self:onJumpStopped() + end + end +end + +function Hero:walk (face) + local x, y = self:getLinearVelocity() + self.facing = face + self:applyForce(250 * face, 0) + if x > self.MAX_VELOCITY then + self:applyForce(-250, 0) + end + if x < -self.MAX_VELOCITY then + self:applyForce(250, 0) + end end --- Damps linear velocity every frame by applying minor force to body. function Hero:dampVelocity (dt) - if not self.isWalking then + if not self:isWalking() then local face local x, y = self:getLinearVelocity() if x < -12 then @@ -155,27 +211,71 @@ function Hero:dampVelocity (dt) end end --- TODO: comment them and place them somewhere properly -function Hero:getAngle () - return self.angle +--- Called each time Hero starts walking. +-- Is not called when direction of walking is changed. +function Hero:onWalkingStarted () + if (self.current ~= self.animations.attack) and + (self.current ~= self.animations.attack_up) and + (self.current ~= self.animations.attack_down) then + self:setAnimation("walk") + end end -function Hero:getHorizontalMirror () - return self.facing + +--- Called when Hero stops walking. +-- Is not called when direction of walking is changed. +function Hero:onWalkingStopped () + if not (self:isControlDown("left") or self:isControlDown("right")) then + if self.current == self.animations.walk then + self:setAnimation("default") + end + end end -function Hero:getOffset () - return 12,15 + +function Hero:onJumpStarted () + self.smoke = false + + if self.jumpCounter == 1 then + self.salto = true + end + + self.jumpCounter = self.jumpCounter - 1 + + if self.jumpCounter > 0 then + if not self.inAir then + self:createEffect("jump") + else + self:createEffect("doublejump") + end + + if (self.current == self.animations.attack) or + (self.current == self.animations.attack_up) or + (self.current == self.animations.attack_down) then + self:setAnimation("default") + end + end +end + +function Hero:onJumpStopped () + self.jumpTimer = Hero.JUMP_TIMER end function Hero:draw (debug) if not self.isAlive then return end Hero.__super.draw(self, debug) + if debug then + local x, y = self:getPosition() + love.graphics.setColor(255, 50, 50) + love.graphics.setFont(Font) + local msg = string.format("%d %s %s", self.jumpCounter, tostring(self.jumpTimer > 0), tostring(self:isJumping())) + love.graphics.print(msg, x + 10, y) + end end -- TODO: Hero@drawTag's printf is not readable. function Hero:drawTag () local x,y = self:getPosition() love.graphics.setFont(Font) - love.graphics.setColor(255, 255, 255) + love.graphics.setColor(1, 1, 1) love.graphics.printf(string.format("Player %d", math.abs(self.group)), math.floor(x), math.floor(y)-26 ,100,'center',0,1,1,50,0) end @@ -184,7 +284,7 @@ end function Hero:drawHUD (x,y,scale,elevation) -- hud displays only if player is alive if self.isAlive then - love.graphics.setColor(255,255,255,255) + love.graphics.setColor(1, 1, 1, 1) love.graphics.draw(self.IMAGE_FRAME, self.QUAD_FRAME, (x)*scale, (y)*scale, 0, scale, scale) love.graphics.draw(self.portrait, (x+2)*scale, (y+3)*scale, 0, scale, scale) local dy = 30 * elevation @@ -199,7 +299,7 @@ end function Hero:goToNextFrame () if self.current.repeated or not (self.frame == self.current.frames) then self.frame = (self.frame % self.current.frames) + 1 - elseif self.isWalking then + elseif self:isWalking() then self:setAnimation("walk") elseif self.current == self.animations.damage then self:setAnimation("default") @@ -221,23 +321,75 @@ end -- Called by World when Hero starts contact with Platform (lands). function Hero:land () self.inAir = false - self.jumpCounter = 2 + self.jumpCounter = Hero.JUMP_COUNT self.salto = false self.smoke = false self:createEffect("land") end +function Hero:getAngle () + return self.angle +end + +function Hero:getHorizontalMirror () + return self.facing +end + +function Hero:getOffset () + return 12,15 +end + +function Hero:isJumping () + return false +end + +function Hero:isWalking () + return self:isWalkingLeft() or self:isWalkingRight() +end + +function Hero:isWalkingLeft () + return false +end + +function Hero:isWalkingRight () + return false +end + -- Creates temporary fixture for hero's body that acts as sensor. -- direction: ("left", "right", "up", "down") -- Sensor fixture is deleted after time set in UserData[1]; deleted by `not.Hero.update`. +-- TODO: While it's good that punch animation changes are here, it is still bad. There is too much similar code in this method. function Hero:punch (direction) self.punchCooldown = Hero.PUNCH_COOLDOWN - -- Choose shape based on punch direction. + self.salto = false + self.smoke = false + local shape - if direction == "left" then shape = Hero.PUNCH_LEFT end - if direction == "right" then shape = Hero.PUNCH_RIGHT end - if direction == "up" then shape = Hero.PUNCH_UP end - if direction == "down" then shape = Hero.PUNCH_DOWN end + if direction == "left" then + shape = Hero.PUNCH_LEFT + if self.current ~= self.animations.damage then + self:setAnimation("attack") + end + end + if direction == "right" then + shape = Hero.PUNCH_RIGHT + if self.current ~= self.animations.damage then + self:setAnimation("attack") + end + end + if direction == "up" then + shape = Hero.PUNCH_UP + if self.current ~= self.animations.damage then + self:setAnimation("attack_up") + end + end + if direction == "down" then + shape = Hero.PUNCH_DOWN + if self.current ~= self.animations.damage then + self:setAnimation("attack_down") + end + end + -- Create and set sensor fixture. local fixture = self:addFixture(shape, 0) fixture:setSensor(true) |