diff --git a/src/data/controls.lua b/src/data/controls.lua index 118e4cc..232a8a7 100644 --- a/src/data/controls.lua +++ b/src/data/controls.lua @@ -9,4 +9,6 @@ return { aim_down = "down", aim_left = "left", aim_right = "right", + + shoot = "space" } diff --git a/src/lib/nata.lua b/src/lib/nata.lua index 4d778b2..17993ae 100644 --- a/src/lib/nata.lua +++ b/src/lib/nata.lua @@ -362,6 +362,27 @@ function Pool:remove(f) end end +function Pool:removeEntity(e) + checkArgument(1, e, 'table') + for groupName, group in pairs(self.groups) do + for i = #group.entities, 1, -1 do + if group.entities[i] == e then + self:emit('removeFromGroup', groupName, e) + table.remove(group.entities, i) + group.hasEntity[e] = nil + end + end + end + for i = #self.entities, 1, -1 do + if self.entities[i] == e then + self:emit('remove', e) + table.remove(self.entities, i) + self.hasEntity[e] = nil + break + end + end +end + --- Registers a function to be called when an event is emitted. -- @string event the event to listen for -- @tparam function f the function to call diff --git a/src/main.lua b/src/main.lua index 5f42abb..2f48aaa 100644 --- a/src/main.lua +++ b/src/main.lua @@ -2,6 +2,7 @@ local Gamestate = require("lib.hump.gamestate") function love.load() love.math.setRandomSeed(love.timer.getTime()) + love.keyboard.setKeyRepeat(true) math.randomseed(love.timer.getTime()) Gamestate.switch(require("states.main")) diff --git a/src/states/main.lua b/src/states/main.lua index 9e58cc4..28a1eb7 100644 --- a/src/states/main.lua +++ b/src/states/main.lua @@ -2,18 +2,24 @@ local MainState = {} local pprint = require("lib.pprint") local nata = require("lib.nata") local Vec = require("lib.brinevector") +local data = require("data") function MainState:enter() self.ecs = nata.new{ groups = { physical = {filter = {"pos", "vel"}}, - player = {filter = {"pos", "acc", "speed", "score"}}, - sprite = {filter = {"sprite"}} + player = {filter = { + "pos", "acc", "speed", + "bolt_count", + "bolt_cooldown", "bolt_speed", "bolt_friction" + }}, + sprite = {filter = {"sprite"}}, + bolt = {filter={"pos", "vel", "bolt"}} }, systems = { require("systems.physics"), require("systems.player"), - require("systems.sprite"), + require("systems.sprite") }, data = {} } @@ -22,9 +28,14 @@ function MainState:enter() pos = Vec(100, 100), vel = Vec(0, 0), acc = Vec(), - score = 0, + sprite = {}, - speed = 100 + friction = 0.998, + speed = 800, + bolt_count = 1, + bolt_speed = 1000, + bolt_cooldown = 0.2, + bolt_friction = 0.9 } end @@ -41,6 +52,10 @@ function MainState:mousemoved(...) self.ecs:emit("mousemoved", ...) end +function MainState:keypressed(...) + self.ecs:emit("keypressed", ...) +end + function MainState:draw() self.ecs:emit("draw") end diff --git a/src/systems/physics.lua b/src/systems/physics.lua index f63df4e..2cf43c1 100644 --- a/src/systems/physics.lua +++ b/src/systems/physics.lua @@ -5,6 +5,9 @@ function Physics:update(dt) if e.acc then e.vel = e.vel + e.acc * dt end + if e.friction then + e.vel = e.vel * (1 - math.min(e.friction, 1)) ^ dt + end e.pos = e.pos + e.vel * dt end diff --git a/src/systems/player.lua b/src/systems/player.lua index 5e20e6e..fe319c3 100644 --- a/src/systems/player.lua +++ b/src/systems/player.lua @@ -35,6 +35,12 @@ function Player:getAimDirection(player) end end +function Player:addToGroup(group, e) + if group == "player" then + e.bolt_cooldown_timer = e.bolt_cooldown_timer or 0 + end +end + function Player:update(dt) local move_direction = self:getMoveDirection() @@ -42,9 +48,42 @@ function Player:update(dt) self.use_mouse_aim = false end + -- Update each player for _, e in ipairs(self.pool.groups.player.entities) do + -- Update where they are aiming/looking e.aim_dir = self:getAimDirection(e) + -- Update acceleration to make the player move e.acc = move_direction * e.speed + + -- Check if the player tried to shoot a bolt + if love.keyboard.isDown(controls.shoot) and + (e.aim_dir.x ~= 0 or e.aim_dir.y ~= 0) and + e.bolt_cooldown_timer == 0 and + e.bolt_count > 0 + then + e.bolt_cooldown_timer = e.bolt_cooldown + e.bolt_count = e.bolt_count - 1 + self.pool:queue{ + pos = e.pos + e.aim_dir * 30, + vel = e.aim_dir * e.bolt_speed, + friction = e.bolt_friction, + bolt = true, + sprite = {} + } + end + + -- Decrease bolt cooldown timer + if e.bolt_cooldown_timer > 0 then + e.bolt_cooldown_timer = math.max(0, e.bolt_cooldown_timer - dt) + end + + -- If the player is nearby a non-moving bolt, pick it up + for _, bolt in ipairs(self.pool.groups.bolt.entities) do + if (e.pos-bolt.pos).length < 30 and bolt.vel.length < 1 then + self.pool:removeEntity(bolt) + e.bolt_count = e.bolt_count + 1 + end + end end end