noble animations

This commit is contained in:
assada 2024-06-02 20:25:27 +03:00
parent f19610e458
commit 3ca6427583
Signed by: assada
GPG Key ID: D4860A938E541F06
15 changed files with 218 additions and 192 deletions

View File

@ -13,10 +13,22 @@
"os": "disable", "os": "disable",
"package": "disable" "package": "disable"
}, },
"runtime.nonstandardSymbol": ["+=", "-=", "*=", "/=", "//=", "%=", "<<=", ">>=", "&=", "|=", "^="], "runtime.nonstandardSymbol": [
"+=",
"-=",
"*=",
"/=",
"//=",
"%=",
"<<=",
">>=",
"&=",
"|=",
"^="
],
"runtime.version": "Lua 5.4", "runtime.version": "Lua 5.4",
"workspace.library": [ "workspace.library": [
"/home/ut3usw/src/playdate-luacats" "/home/ut3usw/src/playdate-luacats",
"/home/ut3usw/Projects/VSCode-PlaydateTemplate/source/libraries" "/home/ut3usw/Projects/VSCode-PlaydateTemplate/source/libraries"
] ]
} }

View File

@ -1 +1,7 @@
# FPV Run # FPV Run
## TODO:
- [ ] Menu audio
- [ ] Tags, zOffset from constants
- [ ] Add global game state (?)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -49,7 +49,6 @@ Noble.Animation = {}
-- end -- end
-- @see NobleSprite:init -- @see NobleSprite:init
function Noble.Animation.new(__view) function Noble.Animation.new(__view)
local animation = {} local animation = {}
--- Properties --- Properties
@ -117,11 +116,10 @@ function Noble.Animation.new(__view)
-- animation.["jump"].next -- "float" -- animation.["jump"].next -- "float"
-- animation.idle.next -- nil -- animation.idle.next -- nil
function animation:addState(__name, __startFrame, __endFrame, __next, __loop, __onComplete, __frameDuration) function animation:addState(__name, __startFrame, __endFrame, __next, __loop, __onComplete, __frameDuration)
local loop = true local loop = true
local frameDuration = 1 local frameDuration = 1
if (__loop ~= nil) then loop = __loop end if (__loop ~= nil) then loop = __loop end
if(__frameDuration ~= nil) then frameDuration = __frameDuration end if (__frameDuration ~= nil) then frameDuration = __frameDuration end
self[__name] = { self[__name] = {
name = __name, name = __name,
startFrame = __startFrame, startFrame = __startFrame,
@ -140,7 +138,6 @@ function Noble.Animation.new(__view)
self.currentName = __name self.currentName = __name
self.frameDuration = frameDuration self.frameDuration = frameDuration
end end
end end
--- Methods --- Methods
@ -180,7 +177,6 @@ function Noble.Animation.new(__view)
-- groundedLastFrame = grounded -- groundedLastFrame = grounded
-- end -- end
function animation:setState(__animationState, __continuous, __unlessThisState) function animation:setState(__animationState, __continuous, __unlessThisState)
if (__unlessThisState ~= nil) then if (__unlessThisState ~= nil) then
if (type(__unlessThisState) == "string") then if (type(__unlessThisState) == "string") then
if (self.currentName == __unlessThisState) then return end if (self.currentName == __unlessThisState) then return end
@ -228,25 +224,26 @@ function Noble.Animation.new(__view)
-- animation:draw(100,100) -- animation:draw(100,100)
-- end -- end
function animation:draw(__x, __y, __advance) function animation:draw(__x, __y, __advance)
--print(self.currentName .. " > " .. self.currentFrame .. " >> " .. tostring(self.current.loop)) --print(self.currentName .. " > " .. self.currentFrame .. " >> " .. tostring(self.current.loop))
if (__advance == nil) then __advance = true end if (__advance == nil) then __advance = true end
if(self.currentFrame < self.current.startFrame or self.currentFrame > self.current.endFrame + 1) then if (self.currentFrame < self.current.startFrame or self.currentFrame > self.current.endFrame + 1) then
self.currentFrame = self.current.startFrame -- Error correction. self.currentFrame = self.current.startFrame -- Error correction.
elseif(self.currentFrame == self.current.endFrame + 1) then -- End frame behavior. elseif (self.currentFrame == self.current.endFrame + 1) then -- End frame behavior.
if (self.current.next ~= nil) then if (self.current.next ~= nil) then
self.currentFrame = self.current.next.startFrame -- Set to first frame of next animation. self.currentFrame = self.current.next.startFrame -- Set to first frame of next animation.
self.frameDurationCount = 1 -- Reset ticks. self.frameDurationCount = 1 -- Reset ticks.
self.previousFrameDurationCount = self.frameDuration self.previousFrameDurationCount = self.frameDuration
self:setState(self.current.next) -- Set next animation state. self:setState(self.current.next) -- Set next animation state.
elseif (self.current.loop == true) then elseif (self.current.loop == true) then
self.currentFrame = self.current.startFrame -- Loop animation state. (TO-DO: account for continuous somehow?) self.currentFrame = self.current
.startFrame -- Loop animation state. (TO-DO: account for continuous somehow?)
self.frameDurationCount = 1 -- Reset ticks. self.frameDurationCount = 1 -- Reset ticks.
self.previousFrameDurationCount = self.frameDuration self.previousFrameDurationCount = self.frameDuration
elseif(__advance) then elseif (__advance) then
self.currentFrame = self.currentFrame - 1 -- Undo advance frame because we want to draw the same frame again. self.currentFrame = self.currentFrame -
1 -- Undo advance frame because we want to draw the same frame again.
end end
if (self.current.onComplete ~= nil) then if (self.current.onComplete ~= nil) then
@ -260,7 +257,7 @@ function Noble.Animation.new(__view)
if (__advance == true) then if (__advance == true) then
self.frameDurationCount += 1 self.frameDurationCount += 1
if((self.frameDurationCount - self.previousFrameDurationCount) >= self.current.frameDuration) then if ((self.frameDurationCount - self.previousFrameDurationCount) >= self.current.frameDuration) then
self.currentFrame = self.currentFrame + 1 self.currentFrame = self.currentFrame + 1
self.previousFrameDurationCount += self.current.frameDuration self.previousFrameDurationCount += self.current.frameDuration
end end

View File

@ -56,9 +56,7 @@ class("NobleSprite").extends(Graphics.sprite)
function NobleSprite:init(__view, __viewIsSpritesheet, __singleState, __singleStateLoop) function NobleSprite:init(__view, __viewIsSpritesheet, __singleState, __singleStateLoop)
NobleSprite.super.init(self) NobleSprite.super.init(self)
self.isNobleSprite = true -- This is important so other methods don't confuse this for a playdate.graphics.sprite. DO NOT modify this value at runtime. self.isNobleSprite = true -- This is important so other methods don't confuse this for a playdate.graphics.sprite. DO NOT modify this value at runtime.
if (__view ~= nil) then if (__view ~= nil) then
-- __view is the path to an image or spritesheet file. -- __view is the path to an image or spritesheet file.
if (type(__view) == "string") then if (type(__view) == "string") then
self.animated = __viewIsSpritesheet -- NO NOT modify self.animated at runtime. self.animated = __viewIsSpritesheet -- NO NOT modify self.animated at runtime.
@ -76,7 +74,6 @@ function NobleSprite:init(__view, __viewIsSpritesheet, __singleState, __singleSt
if (__singleState == true) then if (__singleState == true) then
self.animation:addState("default", 1, self.animation.imageTable:getLength(), nil, singleStateLoop) self.animation:addState("default", 1, self.animation.imageTable:getLength(), nil, singleStateLoop)
end end
else else
-- Create a new Graphics.image object. -- Create a new Graphics.image object.
self:setImage(Graphics.image.new(__view)) self:setImage(Graphics.image.new(__view))
@ -92,9 +89,7 @@ function NobleSprite:init(__view, __viewIsSpritesheet, __singleState, __singleSt
self.animated = true self.animated = true
self.animation = __view self.animation = __view
end end
end end
end end
function NobleSprite:draw() function NobleSprite:draw()

View File

@ -13,7 +13,24 @@ import "libraries/playout"
import 'utilities/enum' import 'utilities/enum'
import 'utilities/ui' import 'utilities/ui'
ZIndex = {
player = 4,
enemy = 3,
props = 3,
fx = 6,
ui = 10,
alert = 12
}
CollideGroups = {
player = 1,
enemy = 2,
props = 3,
items = 4,
wall = 5
}
import "scripts/player" import "scripts/player"
import "scripts/bigBoomSprite"
import "scripts/groundSprite" import "scripts/groundSprite"
import "scripts/balebaSprite" import "scripts/balebaSprite"
import "scripts/dangerSprite" import "scripts/dangerSprite"

View File

@ -20,20 +20,21 @@ end
function scene:setValues() function scene:setValues()
scene.background = Graphics.image.new("assets/sprites/bg") scene.background = Graphics.image.new("assets/sprites/bg")
scene.telemLostSound = playdate.sound.fileplayer.new( "assets/audio/telemko" ) scene.telemLostSound = playdate.sound.fileplayer.new("assets/audio/telemko")
scene.telemLostSoundPlayed = false scene.telemLostSoundPlayed = false
scene.resultShowed = false
scene.musicEnabled = Noble.Settings.get("music")
scene.balebas = {} scene.balebas = {}
scene.t = playdate.timer.new(10000) scene.balebaSpawner = playdate.timer.new(10000)
scene.t.repeats = true scene.balebaSpawner.repeats = true
scene.tankTimer = playdate.timer.new(1000)
scene.fp = playdate.sound.fileplayer.new( "assets/audio/war" )
scene.fp:setVolume(0.7)
scene.hello = playdate.sound.fileplayer.new( "assets/audio/hello" )
scene.levelAudio = playdate.sound.fileplayer.new("assets/audio/war")
scene.levelAudio:setVolume(0.7)
scene.helloAudio = playdate.sound.fileplayer.new("assets/audio/hello")
end end
function scene:init() function scene:init()
@ -49,112 +50,86 @@ function scene:start()
end end
function scene:spawnBaleba() function scene:spawnBaleba()
local baleba = Baleba(math.random(410, 900), math.random(10, 210), scene.player, true) local balebaCount = #scene.balebas
baleba:add() if balebaCount >= 6 then
return
end
return baleba scene.balebas[balebaCount + 1] = Baleba(math.random(410, 900), math.random(10, 210), scene.player, true)
return scene.balebas[balebaCount + 1]
end end
function scene:enter() function scene:enter()
scene.super.enter(self) scene.super.enter(self)
scene.player = Player(30, 30) scene.player = Player(150, 100)
scene.player:add() scene.ground = Ground(0, 225, scene.player)
scene.ground = Ground(400, 225, scene.player) scene.balebaSpawner.timerEndedCallback = function()
scene.ground:add()
scene.t.timerEndedCallback = function()
if #scene.balebas >= 6 then
return
end
local k = #scene.balebas+1
--scene.balebas[k] = scene:spawnBaleba() --scene.balebas[k] = scene:spawnBaleba()
end end
for i=1, 3 do for i = 1, 3 do
scene.balebas[i] = scene:spawnBaleba() scene:spawnBaleba()
end end
local musicEnabled = Noble.Settings.get("music") scene.helloAudio:play(1)
scene.hello:play(1) if scene.musicEnabled then
if musicEnabled then scene.levelAudio:play(0)
scene.fp:play(0)
end end
scene.tankTimer.timerEndedCallback = function() playdate.timer.performAfterDelay(1000, function()
scene.tank = Tank(550, 190, scene.player, scene.ground) scene.tank = Tank(550, 190, scene.player, scene.ground)
scene.tank:add() scene:addSprite(scene.tank) -- Raw sprite
end end)
end end
function scene:update() function scene:update()
scene.super.update(self) scene.super.update(self)
if scene.player == nil then if scene.player == nil then
Noble.Text.draw("Telemetry Lost", 200, 110, Noble.Text.ALIGN_CENTER, false, font)
return return
end end
if scene.player.isDead() then
if scene.resultShowed ~= true then
Noble.Text.draw("Telemetry Lost", 200, 110, Noble.Text.ALIGN_CENTER, false, font)
end
else
Noble.Text.draw("Bat: " .. math.floor(scene.player.getBat() / 100), 10, 215, Noble.Text.ALIGN_LEFT, false, font)
end
if scene.player.isDead() and not scene.telemLostSoundPlayed then if scene.player.isDead() and not scene.telemLostSoundPlayed then
scene.telemLostSound:play(1) scene.telemLostSound:play(1)
scene.telemLostSoundPlayed = true scene.telemLostSoundPlayed = true
screenShake(500, 5) screenShake(1000, 5)
playdate.timer.performAfterDelay(4000, function()
local et = playdate.timer.new(6000) scene.resultShowed = true
et.timerEndedCallback = function() c = notify("Nice", function()
Noble.transition(Menu) Noble.transition(Menu)
end c:remove()
end)
c:moveTo(200, 120)
c:add()
end)
return return
end end
local bat = scene.player.getBat()
bat = math.floor(bat/100)
Noble.Text.draw("Bat: " .. bat, 10, 215, Noble.Text.ALIGN_LEFT, false, font)
end
function scene:destroyPlayer()
if scene.player ~= nil then
scene.player:remove()
scene.player = nil
end
end end
function scene:exit() function scene:exit()
scene.super.exit(self) scene.super.exit(self)
scene:destroyPlayer()
scene.ground:remove()
scene.ground = nil
scene.tank:remove() scene.tank:remove()
scene.ground = nil
for i=1, #scene.balebas do
scene.balebas[i]:destroy()
scene.balebas[i] = nil
end
scene.telemLostSound:stop() scene.telemLostSound:stop()
scene.telemLostSoundPlayed = false scene.levelAudio:stop()
scene.balebaSpawner:remove()
scene.fp:stop()
scene.t:remove()
scene.t = nil
scene.tankTimer:remove()
scene.tankTimer = nil
Noble.showFPS = false Noble.showFPS = false
end end
function scene:finish() function scene:finish()
scene.super.finish(self) scene.super.finish(self)
playdate.display.setScale(1) playdate.display.setScale(1)

View File

@ -1,24 +1,24 @@
Baleba = {} Baleba = {}
class('Baleba').extends(AnimatedSprite) class('Baleba').extends(NobleSprite)
function randomFloat(lower, greater) function randomFloat(lower, greater)
return lower + math.random() * (greater - lower); return lower + math.random() * (greater - lower);
end end
local balebaImageTable = Graphics.imagetable.new("assets/sprites/baleba")
function Baleba:init(x, y, player, loop) function Baleba:init(x, y, player, loop)
Baleba.super.init(self, balebaImageTable) Baleba.super.init(self, "assets/sprites/baleba", true)
-- Animation properties -- Animation properties
self:addState("run", 1,4, {tickStep = 2}) self.animation:addState("run", 1, 4)
self:setDefaultState("run") self.animation.run.frameDuration = 2
self:playAnimation()
self.animation:setState("run")
-- Collision properties -- Collision properties
self:setZIndex(11) self:setZIndex(11)
self:setCollideRect(3, 25, 40, 15) self:setCollideRect(3, 25, 40, 15)
self:setTag(154) self:setTag(154)
self:setSize(64, 64)
-- Sprite properties -- Sprite properties
self.standrate = randomFloat(0.3, 2) self.standrate = randomFloat(0.3, 2)
@ -28,15 +28,13 @@ function Baleba:init(x, y, player, loop)
-- Danger properties -- Danger properties
self.danger = Danger(366, y, self) self.danger = Danger(366, y, self)
self.danger:add()
self:add()
-- Move to initial position -- Move to initial position
self:moveTo(x, y) self:moveTo(x, y)
end end
function Baleba:update() function Baleba:update()
self:updateAnimation()
-- Speedup when player is moving right -- Speedup when player is moving right
if self.player == nil or self.player.isMovingRight() == false then if self.player == nil or self.player.isMovingRight() == false then
self.xVelocity = self.standrate self.xVelocity = self.standrate
@ -44,7 +42,7 @@ function Baleba:update()
self.xVelocity = 2 + self.standrate self.xVelocity = 2 + self.standrate
end end
self:moveTo(self.x-self.xVelocity, self.y) self:moveTo(self.x - self.xVelocity, self.y)
-- Danger arrow management -- Danger arrow management
if self.x < 430 and self.danger ~= nil then if self.x < 430 and self.danger ~= nil then
@ -52,7 +50,6 @@ function Baleba:update()
self.danger = nil self.danger = nil
elseif self.danger == nil and self.x > 430 then elseif self.danger == nil and self.x > 430 then
self.danger = Danger(366, self.y, self) self.danger = Danger(366, self.y, self)
self.danger:add()
end end
-- Lifeciycle management -- Lifeciycle management

View File

@ -0,0 +1,28 @@
BigBoom = {}
class("BigBoom").extends(AnimatedSprite)
local bigBoomImageTable = Graphics.imagetable.new("assets/sprites/bigboom")
function BigBoom:init()
BigBoom.super.init(self, bigBoomImageTable)
-- Animation properties
self:addState("play", 1, 3, { tickStep = 4, loop = 3 })
self:setDefaultState("play")
self:playAnimation()
self:setCenter(0, 0)
self:setSize(playdate.display.getSize())
self:setZIndex(120)
self:moveTo(0, 0)
self:add()
end
function BigBoom:update()
self:updateAnimation()
end
function BigBoom:stopAnimation()
self:remove()
end

View File

@ -1,24 +1,21 @@
Danger = {} Danger = {}
class("Danger").extends(AnimatedSprite) class("Danger").extends(NobleSprite)
local dangerImageTable = Graphics.imagetable.new("assets/sprites/danger")
function Danger:init(x, y, dangerousObject) function Danger:init(x, y, dangerousObject)
Danger.super.init(self, dangerImageTable) Danger.super.init(self, "assets/sprites/danger", true)
self.dangerousObject = dangerousObject self.dangerousObject = dangerousObject
-- Animation properties -- Animation properties
self:addState("run", 1,5, {tickStep = 2}) self.animation:addState("run", 1, 5)
self:setDefaultState("run") self.animation.run.frameDuration = 2
self:playAnimation()
self.animation:setState("run")
-- Collision properties -- Collision properties
self:setZIndex(11) self:setZIndex(11)
self:setTag(7) self:setTag(7)
self:setSize(64, 64)
self:add()
self:moveTo(x, y) self:moveTo(x, y)
end end
function Danger:update()
self:updateAnimation()
end

View File

@ -1,21 +1,20 @@
Ground = {} Ground = {}
class("Ground").extends(Graphics.sprite) class("Ground").extends(NobleSprite)
local groundImage = Graphics.image.new("assets/sprites/groundFin")
function Ground:init(x, y, player) function Ground:init(x, y, player)
Ground.super.init(self, groundImage) Ground.super.init(self, "assets/sprites/groundFin")
-- Collision properties -- Collision properties
self:setZIndex(100) self:setZIndex(100)
self:setTag(3) self:setTag(3)
self:setCollideRect(0, 28, 800, 10) self:setCollideRect(0, 28, 800, 10)
self:setSize(800, 32)
-- Main properties -- Main properties
Ground.moveSpeed = 2 Ground.moveSpeed = 2
Ground.player = player Ground.player = player
-- Move to initial position self:add()
self:moveTo(x, y) self:moveTo(x, y)
end end
@ -24,7 +23,6 @@ function Ground:setMoveSpeed(speed)
end end
function Ground:update() function Ground:update()
-- Stop ground -- Stop ground
if Ground.moveSpeed == 0 then if Ground.moveSpeed == 0 then
return return
@ -43,5 +41,5 @@ function Ground:update()
end end
-- Move ground -- Move ground
self:moveWithCollisions(self.x-Ground.moveSpeed, self.y) self:moveWithCollisions(self.x - Ground.moveSpeed, self.y)
end end

View File

@ -1,20 +1,26 @@
Player = {} Player = {}
class("Player").extends(AnimatedSprite) class("Player").extends(NobleSprite)
local playerImageTable = Graphics.imagetable.new("assets/sprites/player")
function Player:init(x, y) function Player:init(x, y)
Player.super.init(self, playerImageTable) Player.super.init(self, "assets/sprites/player", true)
-- Animation properties -- Animation properties
self:addState("run", 1, 7, { tickStep = 2 }) self.animation:addState("run", 1, 7)
self:addState("up", 1, 7, { tickStep = 6 }) self.animation.run.frameDuration = 2
self:addState("down", 1, 7, { tickStep = 6 }) self.animation:addState("up", 1, 7)
self:addState("boom", 15, 21, { tickStep = 10, loop = false }) self.animation.up.frameDuration = 6
self:setDefaultState("down") self.animation:addState("down", 1, 7)
self:playAnimation() self.animation.down.frameDuration = 6
self.animation:addState("boom", 15, 21)
self.animation.boom.frameDuration = 10
self.animation.boom.loop = false
self.animation:setState("down")
self:add()
-- Collision properties -- Collision properties
self:setSize(64, 64)
self:moveTo(x, y) self:moveTo(x, y)
self:setZIndex(10) self:setZIndex(10)
self:setCollideRect(3, 19, 63, 33) self:setCollideRect(3, 19, 63, 33)
@ -65,9 +71,9 @@ function Player:handleInput()
if crankChange ~= 0 then if crankChange ~= 0 then
local force = 0.01 local force = 0.01
if crankChange > 0 then if crankChange > 0 then
self:changeState("up") self.animation:setState("up")
else else
self:changeState("down") self.animation:setState("down")
force = 0.05 force = 0.05
end end
self.yVelocity = self.yVelocity - acceleratedChange * force self.yVelocity = self.yVelocity - acceleratedChange * force
@ -83,25 +89,25 @@ function Player:changeToDownState()
Player.moveRight = false Player.moveRight = false
self.yVelocity = self.fallSpeed self.yVelocity = self.fallSpeed
self.xVelocity = 0 self.xVelocity = 0
self:changeState("down") self.animation:setState("down")
self:setRotation(0) self:setRotation(0)
end end
function Player:changeToRunState(direction) function Player:changeToRunState(direction)
if direction == "left" then if direction == "left" then
self.xVelocity = -self.maxXSpeed self.xVelocity = -self.maxXSpeed
self.globalFlip = 1 self.animation.direction = Noble.Animation.DIRECTION_LEFT
self:changeState("run") self.animation:setState("run")
elseif direction == "right" then elseif direction == "right" then
self.xVelocity = self.maxXSpeed self.xVelocity = self.maxXSpeed
self.globalFlip = 0 self.animation.direction = Noble.Animation.DIRECTION_RIGHT
self:changeState("run") self.animation:setState("run")
end end
end end
function Player:boom(collisionObject) function Player:boom(collisionObject)
Player.dead = true Player.dead = true
self:changeState("boom") self.animation:setState("boom")
local particleB = ParticlePoly(self.x, self.y) local particleB = ParticlePoly(self.x, self.y)
particleB:setThickness(2) particleB:setThickness(2)
@ -159,11 +165,12 @@ function Player:handleMovementAndCollisions()
return return
elseif collisionTag == 2 then -- Tank elseif collisionTag == 2 then -- Tank
self:boom() self:boom()
BigBoom()
local particleC = ParticlePoly(collisionObject.x, collisionObject.y) local particleC = ParticlePoly(collisionObject.x, collisionObject.y)
particleC:setThickness(5) particleC:setThickness(5)
particleC:setAngular(-15, 15) particleC:setAngular(-15, 15)
particleC:setSize(1, 5) particleC:setSize(1, 10)
particleC:setSpeed(1, 3) particleC:setSpeed(1, 3)
particleC:setMode(Particles.modes.STAY) particleC:setMode(Particles.modes.STAY)
particleC:setBounds(0, 0, 400, 240) particleC:setBounds(0, 0, 400, 240)
@ -207,16 +214,13 @@ function Player:handleDischarge(state)
end end
function Player:update() function Player:update()
self:updateAnimation()
self:handleMovementAndCollisions() self:handleMovementAndCollisions()
if Player.dead then if Player.dead then
print("Player is dead")
return return
end end
local state = self:getCurrentState()["name"] self:handleDischarge(self.animation.currentName)
self:handleDischarge(state)
self:handleInput() self:handleInput()
end end

View File

@ -51,5 +51,5 @@ function Tank:update()
Tank.moveSpeed = 1 Tank.moveSpeed = 1
end end
self:moveTo(self.x-Tank.moveSpeed, self.y) self:moveTo(self.x - Tank.moveSpeed, self.y)
end end