207 lines
4.8 KiB
Lua
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
|