First demo commit.

This commit is contained in:
bakpakin
2015-04-27 14:12:11 +08:00
commit a63329422d
57 changed files with 5201 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
local multisource = require "lib.multisource"
local assets = {}
love.graphics.setDefaultFilter("nearest", "nearest")
assets.img_cat = love.graphics.newImage("assets/cat.png")
assets.img_catandcannon = love.graphics.newImage("assets/catandcannon.png")
assets.img_gun = love.graphics.newImage("assets/gun.png")
assets.img_bullet = love.graphics.newImage("assets/bullet.png")
assets.img_explosion = love.graphics.newImage("assets/explosion.png")
assets.img_pig = love.graphics.newImage("assets/pig.png")
assets.img_spawner = love.graphics.newImage("assets/spawner.png")
assets.snd_catjump = multisource.new(love.audio.newSource("assets/catjump.wav"))
assets.snd_cannon = multisource.new(love.audio.newSource("assets/cannon.wav"))
assets.snd_thud = multisource.new(love.audio.newSource("assets/thud.wav"))
assets.snd_meow = multisource.new(love.audio.newSource("assets/meow.ogg"))
assets.snd_oink = multisource.new(love.audio.newSource("assets/oink.ogg"))
assets.snd_yay = multisource.new(love.audio.newSource("assets/yay.wav"))
assets.snd_music = love.audio.newSource("assets/music.ogg")
assets.fnt_hud = love.graphics.newFont("assets/font.ttf", 48)
assets.fnt_smallhud = love.graphics.newFont("assets/font.ttf", 32)
assets.fnt_reallysmallhud = love.graphics.newFont("assets/font.ttf", 24)
return assets
+41
View File
@@ -0,0 +1,41 @@
local assets = require "src.assets"
local Explosion = require "src.entities.Explosion"
local Bullet = class("Bullet")
Bullet.speed = 480
Bullet.sprite = assets.img_bullet
function Bullet:init(x, y, direction)
self.pos = {x = x, y = y}
self.vel = {x = self.speed * math.cos(direction), y = self.speed * math.sin(direction)}
self.offset = {x = 4, y = 4}
self.hitbox = {w = 4, h = 4}
self.bullet = true
self.drot = math.random() - 0.5
self.rot = direction
self.isBullet = true
self.isSolid = true
self.gravity = 1300
self.bg = true
end
function Bullet:explode()
world:remove(self)
world:add(Explosion(self.pos.x - 32, self.pos.y - 60))
assets.snd_thud:play()
end
function Bullet:update(dt)
self.rot = self.rot + self.drot * dt * 10
end
function Bullet:onCollision(col)
self:explode()
if col.other.isEnemy and col.other.gotHit then
col.other:gotHit()
end
end
return Bullet
+16
View File
@@ -0,0 +1,16 @@
local assets = require "src.assets"
local anim8 = require "lib.anim8"
local Explosion = class "Explosion"
Explosion.sprite = assets.img_explosion
function Explosion:init(x, y)
self.pos = {x = x, y = y}
self.bg = true
local g = anim8.newGrid(64, 64, assets.img_explosion:getWidth(), assets.img_explosion:getHeight())
self.animation = anim8.newAnimation(g('1-10', 1), 0.05)
self.lifetime = 9 * 0.05
end
return Explosion
+20
View File
@@ -0,0 +1,20 @@
local assets = require "src.assets"
local MainHud = class "MainHud"
function MainHud:drawHud(dt)
local n = self.levelState.totalEnemiesToKill - self.levelState.enemiesKilled
local d = self.levelState.totalEnemiesToKill
love.graphics.setFont(assets.fnt_hud)
love.graphics.printf("Wave " .. self.levelState.wave, 20, 20, 300, "left")
love.graphics.setFont(assets.fnt_smallhud)
love.graphics.printf(n .. "/" .. d .. " Pigs Remaining", 20, 60, 500, "left")
love.graphics.printf("Total Pigs Killed: " .. self.levelState.score, love.graphics.getWidth() - 420, 20, 400, "right")
end
function MainHud:init(levelState)
self.levelState = levelState
self.hudBg = true
end
return MainHud
+59
View File
@@ -0,0 +1,59 @@
local assets = require "src.assets"
local anim8 = require "lib.anim8"
local Explosion = require "src.entities.Explosion"
local gamestate = require "lib.gamestate"
local Pig = class "Pig"
Pig.sprite = assets.img_pig
function Pig:init(x, y, target)
self.pos = {x = x, y = y}
self.vel = {x = 0, y = 0}
self.gravity = 1300
self.isAlive = true
self.isEnemy = true
self.isSolid = true
self.platforming = {
acceleration = 1000,
speed = 60,
jump = 250,
friction = 2000,
direction = 'r'
}
self.ai = {
}
self.hitbox = {w = 30, h = 21}
self.health = 50
self.maxHealth = 50
local g = anim8.newGrid(30, 21, assets.img_pig:getWidth(), assets.img_pig:getHeight())
self.animation_stand = anim8.newAnimation(g('1-1', 1), 0.1)
self.animation_walk = anim8.newAnimation(g('2-5', 1), 0.1)
self.animation = self.animation_stand
self.fg = true
end
function Pig:gotHit()
if self.isAlive then
self.isAlive = nil
self.lifetime = 0.25
self.fadeTime = 0.25
self.alpha = 1
self.ai = nil
self.platforming.moving = false
self.vel.y = -300
self.vel.x = 0
assets.snd_oink:play()
assets.snd_yay:play()
world:add(self)
gamestate.current().score = gamestate.current().score + 1
end
end
return Pig
+82
View File
@@ -0,0 +1,82 @@
local assets = require "src.assets"
local anim8 = require "lib.anim8"
local Bullet = require "src.entities.Bullet"
local TimerEvent = require "src.entities.TimerEvent"
local ScreenSplash = require "src.entities.ScreenSplash"
local gamestate = require "lib.gamestate"
local Player = class("Player")
function Player:draw(dt)
if self.hasGun then
local p = self.animation.position
local dy = (p ~= 2 and p ~= 3) and 0 or -1
local dx = self.platforming.direction == 'l' and 2 or -2
love.graphics.draw(assets.img_gun, self.pos.x + 16 + dx, self.pos.y + 10 + dy, self.gunAngle - math.pi / 4)
end
end
function Player:onHit()
self.isAlive = nil
self.lifetime = 0.25
self.fadeTime = 0.25
self.alpha = 1
self.ai = nil
self.platforming.moving = false
self.vel.y = -300
self.vel.x = (math.random() - 0.5) * 400
self.controlable = nil
assets.snd_meow:play()
world:add(self)
local n = gamestate.current().score
local message = "You Died."
if n == 0 then message = "You Failed Pretty Hard."
elseif n < 10 then message = "You Killed Some Pigs and They Killed you Back."
elseif n < 30 then message = "That's a lot of Bacon."
elseif n < 100 then message = "You a crazy Pig Killer."
else message = "Pigpocolypse." end
world:add(TimerEvent(1.2, function() world:add(ScreenSplash(0.5, 0.4, message .. " Press Space to Try Again.", 800)) end))
gamestate.current().isSpawning = false
gamestate.current().restartOnSpace = true
end
function Player:onCollision(col)
if self.isAlive and col.other.isEnemy and col.other.isAlive then
self:onHit()
end
end
function Player:init(args)
self.cameraTrack = {xoffset = 16, yoffset = -35}
self.pos = {x = args.x, y = args.y}
self.vel = {x = 0, y = 0}
self.gravity = 1300
self.platforming = {
acceleration = 1000,
speed = 130,
jump = 380,
friction = 2000,
direction = 'r'
}
self.isAlive = true
self.isPlayer = true
self.isSolid = true
self.controlable = true
self.hitbox = {w = 32, h = 32}
self.checkCollisions = true
self.sprite = assets.img_catandcannon
self.fg = true
local g = anim8.newGrid(32, 32, assets.img_cat:getWidth(), assets.img_cat:getHeight())
self.animation_stand = anim8.newAnimation(g('1-1', 1), 0.1)
self.animation_walk = anim8.newAnimation(g('2-5', 1), 0.1)
self.animation = self.animation_stand
self.health = 100
self.maxHealth = 100
self.shotTimer = 0
self.shotInterval = 0.45
self.gunAngle = 2 * math.pi
self.hasGun = true
end
return Player
+30
View File
@@ -0,0 +1,30 @@
local ScreenSplash = class("Screen Splash")
local assets = require "src.assets"
function ScreenSplash:drawHud()
love.graphics.setFont(self.splash.fnt or assets.fnt_hud)
local align = self.align
local w, h = love.graphics.getWidth() * self.pos.x, love.graphics.getHeight() * self.pos.y
local dx, dy = self.offset.x, self.offset.y
if align == "center" then
dx = dx - self.splash.width / 2
end
if align == "right" then
dx = dx - self.splash.width
end
love.graphics.printf(self.splash.text, w + dx, h + dy, self.splash.width, self.align)
end
function ScreenSplash:init(x, y, text, width, fnt, align, xo, yo)
self.pos = {x = x, y = y}
self.offset = {x = xo or 0, y = yo or 0}
self.hudBg = true
self.align = align or "center"
self.splash = {
text = text,
fnt = fnt,
width = width or 400
}
end
return ScreenSplash
+27
View File
@@ -0,0 +1,27 @@
local assets = require "src.assets"
local Pig = require "src.entities.Pig"
local Spawner = class "Spawner"
Spawner.sprite = assets.img_spawner
function Spawner:init(args)
self.pos = {x = args.x + 32, y = args.y + 32}
self.offset = {x = 32, y = 32}
self.scale = {x = 1, y = 1}
self.rot = 0
self.bg = true
self.isSpawner = true
end
function Spawner:update(dt)
self.rot = self.rot + 2 * dt
local s = math.random() * 0.2 + 0.9
self.scale.x, self.scale.y = s, s
end
function Spawner:spawn()
world:add(Pig(self.pos.x - 15, self.pos.y - 10, nil))
end
return Spawner
+12
View File
@@ -0,0 +1,12 @@
local TimerEvent = class "TimerEvent"
function TimerEvent:init(time, fn)
self.lifetime = time
self.timerCallback = fn
end
function TimerEvent:onLifeover()
self.timerCallback()
end
return TimerEvent
+32
View File
@@ -0,0 +1,32 @@
local gamestate = require "lib.gamestate"
local TransitionScreen = class "TransitionScreen"
TransitionScreen.hudFg = true
-- mode is true for "toblack" or false for "totransparent"
function TransitionScreen:init(mode, newState)
self.lifetime = 0.5
self.newState = newState
if mode then
self.alpha = 0
self.fadeTime = -0.5
else
self.alpha = 1
self.fadeTime = 0.5
end
end
function TransitionScreen:drawHud(dt)
local r1, g1, b1, a = love.graphics.getColor()
love.graphics.setColor(0, 0, 0, self.alpha * 255)
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
love.graphics.setColor(r1, g1, b1, a)
end
function TransitionScreen:onLifeover()
if self.newState then
gamestate.switch(self.newState)
end
end
return TransitionScreen
+52
View File
@@ -0,0 +1,52 @@
local gamestate = require "lib.gamestate"
local Level = require "src.states.Level"
local TimerEvent = require "src.entities.TimerEvent"
local ScreenSplash = require "src.entities.ScreenSplash"
local TransitionScreen = require "src.entities.TransitionScreen"
local Level = require "src.states.Level"
local assets = require "src.assets"
local sti = require("lib.sti")
local gamera = require("lib.gamera")
local Intro = class "Intro"
function Intro:load()
local tileMap = sti.new("assets/intro")
local w, h = tileMap.tilewidth * tileMap.width, tileMap.tileheight * tileMap.height
local camera = gamera.new(0, 0, w, h)
camera:setPosition(600, 600)
camera:setScale(2)
self.time = 0
self.world = tiny.world(
require ("src.systems.DrawBackgroundSystem")(140, 205, 255),
require ("src.systems.FadeSystem")(),
require ("src.systems.LifetimeSystem")(),
require ("src.systems.TileMapRenderSystem")(camera, tileMap),
require ("src.systems.SpriteSystem")(camera, "bg"),
require ("src.systems.SpriteSystem")(camera, "fg"),
require ("src.systems.HudSystem")(self, "hudBg"),
require ("src.systems.HudSystem")(self, "hudFg"),
TransitionScreen(),
ScreenSplash(0.5, 0.2, "Cammando Kibbles"),
ScreenSplash(0, 0, "Created by bakpakin for Ludum Dare 32", 300, assets.fnt_reallysmallhud, "left", 20, 20),
ScreenSplash(0.5, 0.36, "Press Space to Start", 500, assets.fnt_smallhud),
ScreenSplash(0.5, 0.45, "Controls:\nMove - WASD\nRotate Cannon - Arrow Keys\nFire - Down\nToggle Fullscreen - \\\nToggle Music - M\nPause - P\nEscape - Quit", 800, assets.fnt_reallysmallhud)
)
_G.world = self.world
_G.camera = camera
end
function Intro:update(dt)
self.time = self.time + dt
if love.keyboard.isDown(" ") and self.time > 0.55 then
world:add(TransitionScreen(true, Level("assets/lvl1")))
end
end
function Intro:draw()
end
return Intro
+129
View File
@@ -0,0 +1,129 @@
local sti = require("lib.sti")
local bump = require("lib.bump")
local gamera = require("lib.gamera")
local TimerEvent = require "src.entities.TimerEvent"
local ScreenSplash = require "src.entities.ScreenSplash"
local TransitionScreen = require "src.entities.TransitionScreen"
local Level = class "Level"
local waveTable = {4, 10, 20, 50, 80, 100, 120, 150, 180, 200, 250}
local waveSpawnSpeeds = {1, 1, 1.5, 2, 2, 2.2, 3, 3, 4, 5, 7}
function Level:init(mappath)
self.mappath = mappath
end
function Level:nextWave()
self.wave = self.wave + 1
self.enemiesKilled = 0
self.totalEnemiesToKill = waveTable[self.wave] or math.huge
self.enemiesSpawned = 0
self.spawnInterval = 3 / (waveSpawnSpeeds[self.wave] or 10)
self.isSpawning = true
if self.wave == #waveTable + 1 then
local splash = ScreenSplash(0.5, 0.5, "Kill Them ALL!!")
world:add(TimerEvent(1, function() world:add(splash) end),
TimerEvent(3, function() world:remove(splash) end))
end
end
function Level:load()
local tileMap = sti.new(self.mappath)
local bumpWorld = bump.newWorld(tileMap.tilewidth * 2)
local w, h = tileMap.tilewidth * tileMap.width, tileMap.tileheight * tileMap.height
local camera = gamera.new(0, 0, w, h)
self.wave = 0
self:nextWave()
self.score = 0
self.spawnerCount = 0
self.spawners = {}
self.tileMap = tileMap
self.bumpWorld = bumpWorld
self.camera = camera
self.aiSystem = require ("src.systems.AISystem")()
local r, g, b = tileMap.backgroundcolor[1], tileMap.backgroundcolor[2], tileMap.backgroundcolor[3]
camera:setScale(2)
local world = tiny.world(
require ("src.systems.DrawBackgroundSystem")(r, g, b),
require ("src.systems.UpdateSystem")(),
require ("src.systems.PlayerControlSystem")(),
self.aiSystem,
require ("src.systems.FadeSystem")(),
require ("src.systems.PlatformingSystem")(),
require ("src.systems.BumpPhysicsSystem")(bumpWorld),
require ("src.systems.CameraTrackingSystem")(camera),
require ("src.systems.TileMapRenderSystem")(camera, tileMap),
require ("src.systems.SpriteSystem")(camera, "bg"),
require ("src.systems.SpriteSystem")(camera, "fg"),
require ("src.systems.LifetimeSystem")(),
require ("src.systems.HudSystem")(self, "hudBg"),
require ("src.systems.HudSystem")(self, "hudFg"),
require ("src.systems.WaveSystem")(self),
require ("src.systems.SpawnSystem")(self),
require ("src.entities.MainHud")(self),
TransitionScreen()
)
local player = nil
for lindex, layer in ipairs(tileMap.layers) do
if layer.properties.collidable == "true" then
-- Entire layer
if layer.type == "tilelayer" then
local prefix = layer.properties.oneway == "true" and "o(" or "t("
for y, tiles in ipairs(layer.data) do
for x, tile in pairs(tiles) do
bumpWorld:add(
prefix..layer.name..", "..x..", "..y..")",
x * tileMap.tilewidth + tile.offset.x,
y * tileMap.tileheight + tile.offset.y,
tile.width,
tile.height
)
end
end
elseif layer.type == "imagelayer" then
bumpWorld:add(
layer.name,
layer.x or 0,
layer.y or 0,
layer.width,
layer.height
)
end
end
if layer.type == "objectgroup" then
for _, object in ipairs(layer.objects) do
local ctor = require("src.entities." .. object.type)
local e = ctor(object)
if object.type == "Player" then
player = e
end
world:add(e)
end
tileMap:removeLayer(lindex)
end
end
self.aiSystem.target = player
-- add ends to prevent objects from falling off the edge of the world.
bumpWorld:add("_leftBlock", -16, 0, 16, h)
bumpWorld:add("_rightBlock", w, 0, 16, h)
bumpWorld:add("_topBlock", 0, -16, w, 16)
-- globals
_G.camera = camera
_G.world = world
end
return Level
+26
View File
@@ -0,0 +1,26 @@
local AISystem = tiny.processingSystem(class "AISystem")
function AISystem:init(target)
self.target = target
end
AISystem.filter = tiny.requireAll("ai", "pos", "platforming")
function AISystem:process(e, dt)
if not self.target then
return
end
local targetx = self.target.pos.x
local pos = e.pos
local p = e.platforming
p.moving = self.target.isAlive
if targetx > pos.x then
p.direction = 'r'
end
if targetx < pos.x then
p.direction = 'l'
end
p.jumping = math.random() < 0.5 * dt
end
return AISystem
+105
View File
@@ -0,0 +1,105 @@
local BumpPhysicsSystem = tiny.processingSystem(class "BumpPhysicsSystem")
function BumpPhysicsSystem:init(bumpWorld)
self.bumpWorld = bumpWorld
end
BumpPhysicsSystem.filter = tiny.requireAll("pos", "vel", "hitbox")
local oneWayPrefix = "o"
oneWayPrefix = oneWayPrefix:byte(1)
local function collisionFilter(e1, e2)
if e1.isPlayer then
if e2.isBullet then return nil end
if e2.isEnemy then return 'cross' end
elseif e1.isEnemy then
if e2.isBullet then return nil end
if e2.isEnemy then return nil end
if e2.isPlayer then return 'cross' end
elseif e1.isBullet then
if e2.isPlayer or e2.isBullet then return nil end
end
if e1.isSolid then
if type(e2) == "string" then -- tile collision
if e2:byte(1) == oneWayPrefix then -- one way tile
if e1.isBullet then
return 'onewayplatformTouch'
else
return 'onewayplatform'
end
else
return 'slide'
end
elseif e2.isSolid then
return 'slide'
elseif e2.isBouncy then
return 'bounce'
else
return 'cross'
end
end
return nil
end
function BumpPhysicsSystem:process(e, dt)
local pos = e.pos
local vel = e.vel
local gravity = e.gravity or 0
vel.y = vel.y + gravity * dt
local cols, len
pos.x, pos.y, cols, len = self.bumpWorld:move(e, pos.x + vel.x * dt, pos.y + vel.y * dt, collisionFilter)
e.grounded = false
for i = 1, len do
local col = cols[i]
local collided = true
if col.type == "touch" then
vel.x, vel.y = 0, 0
elseif col.type == "slide" then
if col.normal.x == 0 then
vel.y = 0
if col.normal.y < 0 then
e.grounded = true
end
else
vel.x = 0
end
elseif col.type == "onewayplatform" then
if col.didTouch then
vel.y = 0
e.grounded = true
else
collided = false
end
elseif col.type == "onewayplatformTouch" then
if col.didTouch then
vel.y = 0
e.grounded = true
else
collided = false
end
elseif col.type == "bounce" then
if col.normal.x == 0 then
vel.y = -vel.y
e.grounded = true
else
vel.x = -vel.x
end
end
if e.onCollision and collided then
e:onCollision(col)
end
end
end
function BumpPhysicsSystem:onAdd(e)
local pos = e.pos
local hitbox = e.hitbox
self.bumpWorld:add(e, pos.x, pos.y, hitbox.w, hitbox.h)
end
function BumpPhysicsSystem:onRemove(e)
self.bumpWorld:remove(e)
end
return BumpPhysicsSystem
+27
View File
@@ -0,0 +1,27 @@
local CameraTrackingSystem = tiny.processingSystem(class "CameraTrackingSystem")
CameraTrackingSystem.filter = tiny.requireAll("cameraTrack", "pos")
function CameraTrackingSystem:init(camera)
self.camera = camera
end
local function round(x)
return math.floor(x * 32 + 16) / 32
end
function CameraTrackingSystem:process(e, dt)
local xo, yo = e.cameraTrack.xoffset, e.cameraTrack.yoffset
local x, y = e.pos.x + xo, e.pos.y + yo
local xp, yp = self.camera:getPosition()
local lerp = 0.1
self.camera:setPosition(round(xp + (x - xp) * lerp), round(yp + (y - yp) * lerp))
end
function CameraTrackingSystem:onAdd(e)
local xo, yo = e.cameraTrack.xoffset, e.cameraTrack.yoffset
local x, y = e.pos.x + xo, e.pos.y + yo
self.camera:setPosition(round(x), round(y))
end
return CameraTrackingSystem
+14
View File
@@ -0,0 +1,14 @@
local DrawBackgroundSystem = tiny.system(class "DrawBackgroundSystem")
function DrawBackgroundSystem:init(r, g, b)
self.r, self.g, self.b = r, g, b
end
function DrawBackgroundSystem:update(entities, dt)
local r1, g1, b1, a = love.graphics.getColor()
love.graphics.setColor(self.r, self.g, self.b, 255)
love.graphics.rectangle("fill", 0, 0, love.graphics.getWidth(), love.graphics.getHeight())
love.graphics.setColor(r1, g1, b1, a)
end
return DrawBackgroundSystem
+9
View File
@@ -0,0 +1,9 @@
local FadeSystem = tiny.processingSystem(class "FadeSystem")
FadeSystem.filter = tiny.requireAll("fadeTime", "alpha")
function FadeSystem:process(e, dt)
e.alpha = math.min(1, math.max(0, e.alpha - dt / e.fadeTime))
end
return FadeSystem
+12
View File
@@ -0,0 +1,12 @@
local HudSystem = tiny.processingSystem(class "HudSystem")
function HudSystem:init(levelState, layerFlag)
self.levelState = levelState
self.filter = tiny.requireAll("drawHud", layerFlag)
end
function HudSystem:process(e, dt)
e:drawHud(dt)
end
return HudSystem
+15
View File
@@ -0,0 +1,15 @@
local LifetimeSystem = tiny.processingSystem(class "LifetimeSystem")
LifetimeSystem.filter = tiny.requireAll("lifetime")
function LifetimeSystem:process(e, dt)
e.lifetime = e.lifetime - dt
if e.lifetime <= 0 then
if e.onLifeover then
e:onLifeover()
end
world:remove(e)
end
end
return LifetimeSystem
+40
View File
@@ -0,0 +1,40 @@
local assets = require "src.assets"
local PlatformingSystem = tiny.processingSystem(class "PlatformingSystem")
PlatformingSystem.filter = tiny.requireAll("pos", "vel", "platforming")
function PlatformingSystem:process(e, dt)
local pos = e.pos
local vel = e.vel
local platforming = e.platforming
local acceleration = platforming.acceleration
local friction = platforming.friction
local speed = platforming.speed
local direction = platforming.direction
e.flippedH = direction == 'l'
if platforming.moving then
if direction == 'l' then
vel.x = math.max(-speed, vel.x - acceleration * dt)
elseif direction == 'r' then
vel.x = math.min(speed, vel.x + acceleration * dt)
end
elseif e.grounded then
if vel.x > 0 then
vel.x = math.max(0, vel.x - friction * dt)
elseif vel.x < 0 then
vel.x = math.min(0, vel.x + friction * dt)
end
end
if platforming.jumping and e.grounded then
vel.y = -platforming.jump
e.grounded = false
assets.snd_catjump:play()
end
e.animation = platforming.moving and e.animation_walk or e.animation_stand
end
return PlatformingSystem
+50
View File
@@ -0,0 +1,50 @@
local assets = require "src.assets"
local Bullet = require "src.entities.Bullet"
local PlayerControlSystem = tiny.processingSystem(class "PlayerControlSystem")
PlayerControlSystem.filter = tiny.requireAll("controlable")
function PlayerControlSystem:process(e, dt)
local vel = e.vel
local p = e.platforming
local l, r, u = love.keyboard.isDown('a'), love.keyboard.isDown('d'), love.keyboard.isDown('w')
local gl, gr = love.keyboard.isDown('left'), love.keyboard.isDown('right')
local fire = love.keyboard.isDown('down')
e.shotTimer = math.max(0, e.shotTimer - dt)
if l and not r then
p.moving = true
if p.direction == 'r' then
e.gunAngle = math.pi * 3 - e.gunAngle
end
p.direction = 'l'
elseif r and not l then
p.moving = true
if p.direction == 'l' then
e.gunAngle = math.pi * 3 - e.gunAngle
end
p.direction = 'r'
else
p.moving = false
end
p.jumping = u
if gr and not gl then
e.gunAngle = math.min(2 * math.pi, e.gunAngle + 8 * dt)
elseif gl and not gr then
e.gunAngle = math.max(math.pi, e.gunAngle - 8 * dt)
end
if e.hasGun and fire and e.shotTimer == 0 then
local dx = e.platforming.direction == 'l' and 2 or -2
local bullet = Bullet(e.pos.x + 16 + dx, e.pos.y + 9, e.gunAngle)
assets.snd_cannon:play()
world:add(bullet)
e.shotTimer = e.shotInterval
end
end
return PlayerControlSystem
+37
View File
@@ -0,0 +1,37 @@
local TimerEvent = require "src.entities.TimerEvent"
local SpawnSystem = tiny.system(class "SpawnSystem")
SpawnSystem.filter = tiny.requireAll("isSpawner")
function SpawnSystem:init(levelState)
self.levelState = levelState
self.time = 0
end
function SpawnSystem:update(entities, dt)
self.time = self.time + dt
local levelState = self.levelState
if levelState.isSpawning and levelState.enemiesSpawned < levelState.totalEnemiesToKill and self.time >= levelState.spawnInterval then
local choice = math.ceil(math.random() * levelState.spawnerCount)
for spnr in pairs(levelState.spawners) do
choice = choice - 1
if choice == 0 then
spnr:spawn()
end
end
self.time = 0
end
end
function SpawnSystem:onAdd(e)
self.levelState.spawners[e] = true
self.levelState.spawnerCount = self.levelState.spawnerCount + 1
end
function SpawnSystem:onRemove(e)
self.levelState.spawners[e] = false
self.levelState.spawnerCount = self.levelState.spawnerCount - 1
end
return SpawnSystem
+36
View File
@@ -0,0 +1,36 @@
local SpriteSystem = tiny.processingSystem(class "SpriteSystem")
function SpriteSystem:init(camera, layerFlag)
self.camera = camera
self.filter = tiny.requireAll("sprite", "pos", layerFlag)
end
function SpriteSystem:preProcess(entities, dt)
self.camera:apply()
end
function SpriteSystem:postProcess(entities, dt)
self.camera:remove()
love.graphics.setColor(255, 255, 255, 255)
end
function SpriteSystem:process(e, dt)
local an = e.animation
local alpha = e.alpha or 1
local pos, sprite, scale, rot, offset = e.pos, e.sprite, e.scale, e.rot, e.offset
local sx, sy, r, ox, oy = scale and scale.x or 1, scale and scale.y or 1, rot or 0, offset and offset.x or 0, offset and offset.y or 0
love.graphics.setColor(255, 255, 255, math.max(0, math.min(1, alpha)) * 255)
if an then
an.flippedH = e.flippedH or false
an.flippedV = e.flippedV or false
an:update(dt)
an:draw(sprite, pos.x, pos.y, r, sx, sy, ox, oy)
else
love.graphics.draw(sprite, pos.x, pos.y, r, sx, sy, ox, oy)
end
if e.draw then
e:draw(dt)
end
end
return SpriteSystem
+16
View File
@@ -0,0 +1,16 @@
local TileMapRenderSystem = tiny.system(class "TileMapRenderSystem")
function TileMapRenderSystem:init(camera, tileMap)
self.camera = camera
function self.drawFn(l, t, w, h)
tileMap:update(dt)
tileMap:setDrawRange(-l, -t, w, h)
tileMap:draw()
end
end
function TileMapRenderSystem:update(entities, dt)
self.camera:draw(self.drawFn)
end
return TileMapRenderSystem
+9
View File
@@ -0,0 +1,9 @@
local UpdateSystem = tiny.processingSystem(class "UpdateSystem")
UpdateSystem.filter = tiny.requireAll("update")
function UpdateSystem:process(e, dt)
e:update(dt)
end
return UpdateSystem
+27
View File
@@ -0,0 +1,27 @@
local TimerEvent = require "src.entities.TimerEvent"
local WaveSystem = tiny.system(class "WaveSystem")
WaveSystem.filter = tiny.requireOne("isEnemy")
function WaveSystem:init(levelState)
self.levelState = levelState
end
function WaveSystem:onAdd(e)
self.levelState.enemiesSpawned = self.levelState.enemiesSpawned + 1
end
function WaveSystem:onRemove(e)
local levelState = self.levelState
levelState.enemiesKilled = levelState.enemiesKilled + 1
if levelState.enemiesKilled >= levelState.totalEnemiesToKill then
world:add(TimerEvent(1, function()
levelState:nextWave()
end))
end
end
function WaveSystem:update(entities, dt) end
return WaveSystem