diff options
Diffstat (limited to 'not')
-rw-r--r-- | not/Hero.lua | 204 | ||||
-rw-r--r-- | not/Player.lua | 136 |
2 files changed, 205 insertions, 135 deletions
diff --git a/not/Hero.lua b/not/Hero.lua index 2b5c529..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,9 +43,9 @@ 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) @@ -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,15 +108,14 @@ 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:getFixtures()) do -- TODO: getFixtures from `PhysicalBody` or similar. @@ -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,20 +211,64 @@ 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. @@ -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) diff --git a/not/Player.lua b/not/Player.lua index b0dac75..ac5d6aa 100644 --- a/not/Player.lua +++ b/not/Player.lua @@ -1,122 +1,54 @@ -require "not.Hero" - --- `Player` --- Special `not.Hero` controllable by a player. --- TODO: move functions and properties related to controls from `not.Hero`. -Player = Hero:extends() +-- Right now this is more or less wrapper for Hero and various methods related to players' input. +-- TODO: Few more things should be exchanged between Player and Hero. +-- TODO: In the end this class could be implemented in form of more verbose and functional Controller class. Think about it. +Player = require "not.Hero":extends() Player.controllerSet =--[[Controller.sets.*]]nil --- Constructor of `Player`. -function Player:new (name, x, y, world) - Player.__super.new(self, name, x, y, world) -end - --- Controller set manipulation. +--- Assigns controller set to Player. +-- @param set one of `Controller.sets` function Player:assignControllerSet (set) self.controllerSet = set end + function Player:getControllerSet () return self.controllerSet end --- Check if control of assigned controller is pressed. +--- Wrapper for checking if passed control is currently pressed. function Player:isControlDown (control) return Controller.isDown(self:getControllerSet(), control) end --- Update of `Player`. -function Player:update (dt) - Player.__super.update(self, dt) -- TODO: It would be probably a good idea to add return to update functions to terminate if something goes badly in parent's update. - if self.body:isDestroyed() then return end - local x, y = self:getLinearVelocity() - -- Jumping. - if self.isJumping and self.jumpTimer > 0 then - self:setLinearVelocity(x,-160) - self.jumpTimer = self.jumpTimer - dt - end +--- Overridden from Hero, used by Hero:update. +function Player:isJumping () + return self:isControlDown("jump") +end - -- Walking. - if self:isControlDown("left") then - self.facing = -1 - self:applyForce(-250, 0) - -- Controlled speed limit - if x < -self.MAX_VELOCITY then - self:applyForce(250, 0) - end - end - if self:isControlDown("right") then - self.facing = 1 - self:applyForce(250, 0) - -- Controlled speed limit - if x > self.MAX_VELOCITY then - self:applyForce(-250, 0) - end - end +--- Overridden from Hero, used by Hero:update. +function Player:isWalkingLeft () + return self:isControlDown("left") +end + +--- Overridden from Hero, used by Hero:update. +function Player:isWalkingRight () + return self:isControlDown("right") end --- Controller callbacks. +--- Called when control is pressed. +-- @param set ControllerSet that owns pressed control +-- @param action action assigned to control +-- @param key parent key of control function Player:controlpressed (set, action, key) if set ~= self:getControllerSet() then return end - self.smoke = false -- TODO: temporary - -- Jumping - if action == "jump" then - if self.jumpCounter > 0 then - -- General jump logics - self.isJumping = true - --self:playSound(6) - -- Spawn proper effect - if not self.inAir then - self:createEffect("jump") - else - self:createEffect("doublejump") - end - -- Start salto if last jump - if self.jumpCounter == 1 then - self.salto = true - end - -- Animation clear - 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 - -- Remove jump - self.jumpCounter = self.jumpCounter - 1 - end - end - - -- Walking - if (action == "left" or action == "right") then - self.isWalking = true - 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 - - -- Punching if action == "attack" and self.punchCooldown <= 0 then local f = self.facing - self.salto = false if self:isControlDown("up") then - -- Punch up - if self.current ~= self.animations.damage then - self:setAnimation("attack_up") - end self:punch("up") elseif self:isControlDown("down") then - -- Punch down - if self.current ~= self.animations.damage then - self:setAnimation("attack_down") - end self:punch("down") else - -- Punch horizontal - if self.current ~= self.animations.damage then - self:setAnimation("attack") - end if f == 1 then self:punch("right") else @@ -125,22 +57,8 @@ function Player:controlpressed (set, action, key) end end end -function Player:controlreleased (set, action, key) - if set ~= self:getControllerSet() then return end - -- Jumping - if action == "jump" then - self.isJumping = false - self.jumpTimer = Hero.jumpTimer -- take initial from metatable - end - -- Walking - if (action == "left" or action == "right") then - if not (self:isControlDown("left") or self:isControlDown("right")) then - self.isWalking = false - if self.current == self.animations.walk then - self:setAnimation("default") - end - end - end -end + +--- Called when control is released. +function Player:controlreleased (set, action, key) end return Player |