1
0
dodge-bolt/src/systems/player.lua
2022-08-05 15:41:19 +00:00

207 lines
4.8 KiB
Lua

local Player = {}
local data = require("data")
local Vec = require("lib.brinevector")
local controls = data.controls
local BOLT_COLLIDER = {-3, -3, 3, 3}
local function getDirection(up_key, down_key, left_key, right_key)
local dx = (love.keyboard.isDown(right_key) and 1 or 0)
- (love.keyboard.isDown(left_key) and 1 or 0)
local dy = (love.keyboard.isDown(down_key) and 1 or 0)
- (love.keyboard.isDown(up_key) and 1 or 0)
return Vec(dx, dy).normalized
end
function Player:init()
-- Spawn in the entity that the local player will be using
local player = self:spawnPlayer()
player.controllable = true
end
function Player:getMoveDirection()
return getDirection(
controls.move_up,
controls.move_down,
controls.move_left,
controls.move_right
)
end
function Player:getAimDirection(player)
if self.use_mouse_aim then
local ScreenScaler = self.pool:getSystem(require("systems.screen-scaler"))
local MAX_DIRECTIONS = 8
local angle_segment = math.pi*2/MAX_DIRECTIONS
local angle = (Vec(ScreenScaler:getMousePosition()) - player.pos).angle
local new_angle = math.floor(angle/angle_segment+0.5)*angle_segment
return Vec(math.cos(new_angle), math.sin(new_angle))
else
return getDirection(
controls.aim_up,
controls.aim_down,
controls.aim_left,
controls.aim_right
)
end
end
function Player:addToGroup(group, e)
if group == "player" then
e.bolt_cooldown_timer = e.bolt_cooldown_timer or 0
e.aim_dir = e.aim_dir or Vec()
e.move_dir = e.move_dir or Vec()
end
end
function Player:update(dt)
if love.keyboard.isDown(controls.aim_up, controls.aim_down, controls.aim_left, controls.aim_right) then
self.use_mouse_aim = false
end
-- Update controls for "my" players
local move_direction = self:getMoveDirection()
for _, e in ipairs(self.pool.groups.controllable_player.entities) do
-- Update where they are aiming/looking
local aim_direction = self:getAimDirection(e)
if e.aim_dir ~= aim_direction then
e.aim_dir = aim_direction
self.pool:emit("playerAimed", e)
end
-- Update acceleration to make the player move
if e.move_dir ~= move_direction then
e.move_dir = move_direction
self.pool:emit("playerMoved", e)
end
-- Check if the player tried to shoot a bolt
if love.keyboard.isDown(controls.shoot) then
if self:tryShootingBolt(e) then
self.pool:emit("playerShot", e)
end
end
end
-- Update each player
for _, e in ipairs(self.pool.groups.player.entities) do
e.acc = e.move_dir * e.speed
-- 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 < 20 and bolt.vel.length < 3 then
bolt.collider = nil
bolt.bolt = nil
bolt.sprite.variant = "idle"
bolt.hidden = true
self.pool:queue(bolt)
table.insert(e.bolts, bolt)
end
end
if e.acc.x ~= 0 or e.acc.y ~= 0 then
e.sprite.variant = "walk"
else
e.sprite.variant = "idle"
end
if e.acc.x < 0 then
e.sprite.flip = true
elseif e.acc.x > 0 then
e.sprite.flip = false
end
if #e.bolts > 0 then
local bolt = e.bolts[1]
if e.aim_dir.x ~= 0 or e.aim_dir.y ~= 0 then
bolt.hidden = nil
bolt.pos = e.pos + e.aim_dir * 15
else
bolt.hidden = true
end
end
end
end
function Player:mousemoved()
self.use_mouse_aim = true
end
function Player:tryShootingBolt(player)
if (player.aim_dir.x ~= 0 or player.aim_dir.y ~= 0) and
player.bolt_cooldown_timer == 0 and
#player.bolts > 0
then
player.bolt_cooldown_timer = player.bolt_cooldown
self:shootBolt(player)
return true
end
end
function Player:shootBolt(player)
local bolt = table.remove(player.bolts, 1)
if not bolt then return end
bolt.pos = player.pos + player.aim_dir * 30
bolt.vel = player.aim_dir * player.bolt_speed
bolt.bolt = true
bolt.sprite.variant = "active"
bolt.collider = BOLT_COLLIDER
bolt.hidden = nil
self.pool:queue(bolt)
end
function Player:storeBolt(player, bolt)
bolt.collider = nil
bolt.sprite.variant = "idle"
bolt.hidden = true
bolt.bolt = nil
self.pool:queue(bolt)
table.insert(player.bolts, bolt)
end
function Player:spawnPlayer()
local player = self.pool:queue{
pos = Vec(100, 100),
vel = Vec(0, 0),
acc = Vec(),
sprite = {
name = "player",
variant = "walk"
},
friction = 0.998,
speed = 800,
bolt_speed = 2000,
bolts = {},
bolt_cooldown = 0.1,
collider = {-5, -5, 4, 8}
}
for _=1, 10 do
local bolt = self.pool:queue{
pos = Vec(100, 100),
vel = Vec(),
acc = Vec(),
sprite = {
name = "bolt",
variant = "idle",
},
friction = 0.98,
max_speed = 400,
}
self:storeBolt(player, bolt)
end
return player
end
return Player