289 lines
7.8 KiB
Lua
289 lines
7.8 KiB
Lua
physics = {}
|
|
|
|
local asserts = require("shared.asserts")
|
|
local utils = require("shared.utils")
|
|
|
|
function physics.keyreleased_debug(key, _)
|
|
if key == "kp4" then
|
|
player.x = player.x -1
|
|
end
|
|
if key == "kp6" then
|
|
player.x = player.x +1
|
|
end
|
|
if key == "kp8" then
|
|
player.y = player.y -1
|
|
end
|
|
if key == "kp2" then
|
|
player.y = player.y +1
|
|
end
|
|
end
|
|
|
|
|
|
function physics.remove_solid(x, y, sizex, sizey)
|
|
asserts.number("physics.remove_solid", 4, x, y, sizex, sizey)
|
|
for coord_x=x, x + sizex-1 do
|
|
for coord_y=y, y + sizey-1 do
|
|
levelloop.Canvas.physics[coord_x*levelloop.world.x+coord_y] = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function physics.draw_solid(x, y, sizex, sizey)
|
|
asserts.number("physics.draw_solid", 4, x, y, sizex, sizey)
|
|
for coord_x=x, x + sizex-1 do
|
|
for coord_y=y, y + sizey-1 do
|
|
levelloop.Canvas.physics[coord_x*levelloop.world.x+coord_y] = {0, 0, 0, true }
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function draw_colision(x, y, x2, y2, pixelx, pixely)
|
|
utils.color_push()
|
|
love.graphics.setLineWidth(1)
|
|
love.graphics.setDefaultFilter("nearest", "nearest", 0)
|
|
love.graphics.setCanvas(levelloop.Canvas.dbg2)
|
|
if pixelx then
|
|
love.graphics.setColor(.6, 0, .6, 1)
|
|
love.graphics.rectangle("fill", x, y, x2, y2)
|
|
love.graphics.setColor(1, 0, 0, 1)
|
|
love.graphics.points(pixelx, pixely)
|
|
else
|
|
love.graphics.setColor(0, 1, 0, 1)
|
|
love.graphics.rectangle("fill", x, y, x2, y2)
|
|
end
|
|
love.graphics.setCanvas()
|
|
utils.color_pop()
|
|
end
|
|
|
|
|
|
function physics.is_blocked_x(x, y, sizex)
|
|
x, y = math.floor(x), math.floor(y)
|
|
asserts.number("physics.is_blocked_x", 3, x, y, sizex)
|
|
for coord_x=x ,x + sizex -1 do
|
|
if levelloop.Canvas.physics[coord_x * levelloop.world.x+y] and levelloop.Canvas.physics[coord_x*levelloop.world.x+y][4] then
|
|
if PHYSICS_DEBUG then draw_colision(x, y, sizex, 1, coord_x, y) end
|
|
return true
|
|
end
|
|
end
|
|
if PHYSICS_DEBUG then draw_colision(x, y, sizex, 1) end
|
|
return false
|
|
end
|
|
|
|
|
|
function physics.is_blocked_y(x, y, sizey)
|
|
x, y = math.floor(x), math.floor(y)
|
|
asserts.number("physics.is_blocked_y", 3, x, y, sizey)
|
|
for coord_y=y, y + sizey -1 do
|
|
if levelloop.Canvas.physics[x*levelloop.world.x+coord_y] and levelloop.Canvas.physics[x*levelloop.world.x+coord_y][4] then
|
|
if PHYSICS_DEBUG then draw_colision(x, y, 1, sizey, x, coord_y) end
|
|
return true
|
|
end
|
|
end
|
|
if PHYSICS_DEBUG then draw_colision(x, y, 1, sizey) end
|
|
return false
|
|
end
|
|
|
|
|
|
function physics.keypressed( key, code, isrepeat)
|
|
if isrepeat then return end
|
|
|
|
if camera.target == 0 then return end
|
|
local player = participants[levelloop.clientID]
|
|
if key == "p" then
|
|
player.flying = not player.flying
|
|
levelloop.remoteCall("moveFlying", player.flying)
|
|
if player.flying then
|
|
player.speed.y = 0
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function physics.input(dt)
|
|
if camera.target == 0 then return end
|
|
local player = participants[levelloop.clientID]
|
|
local speedModified = dt * 20
|
|
if love.keyboard.isDown("rshift") or love.keyboard.isDown("lshift")
|
|
then
|
|
speedModified = speedModified + (60 * dt)
|
|
end
|
|
if love.keyboard.isDown("a") then
|
|
player.speed.x = player.speed.x - speedModified
|
|
elseif love.keyboard.isDown("d") then
|
|
player.speed.x = player.speed.x + speedModified
|
|
end
|
|
|
|
if love.keyboard.isDown("w") and player.flying then
|
|
player.speed.y = player.speed.y - speedModified
|
|
elseif love.keyboard.isDown("s") and player.flying then
|
|
player.speed.y = player.speed.y + speedModified
|
|
end
|
|
|
|
if love.keyboard.isDown("space") and not player.flying then
|
|
local posx = player.x + player.avatar:getWidth()
|
|
local posy = player.y + player.avatar:getHeight()
|
|
if physics.is_blocked_x(posx - player.avatar:getWidth(), posy, player.avatar:getWidth()) or
|
|
player.y == levelloop.world.y - player.avatar:getHeight() then
|
|
player.speed.y = -25
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
function physics.cap_world(width, height, newx, newy, new_sx, new_sy)
|
|
if newx > levelloop.world.x - width then
|
|
newx = levelloop.world.x - width
|
|
new_sx = 0
|
|
end
|
|
if newx < 0 then
|
|
newx = 0
|
|
new_sx = 0
|
|
end
|
|
if newy > levelloop.world.y - height then
|
|
newy = levelloop.world.y - height
|
|
new_sy = 0
|
|
end
|
|
if newy < 0 then
|
|
newy = 0
|
|
new_sy = 0
|
|
end
|
|
return newx, newy, new_sx, new_sy
|
|
end
|
|
|
|
|
|
function physics.updatePlayer(dt, player, localplayer)
|
|
local new_sx, new_sy
|
|
if player.flying then
|
|
new_sy = player.speed.y - player.speed.y / 6
|
|
new_sx = player.speed.x - player.speed.x / 6
|
|
else
|
|
new_sx = player.speed.x - player.speed.x / 16
|
|
new_sy = player.speed.y - player.speed.y / 16
|
|
end
|
|
|
|
if not new_sx then new_sx = 0 end
|
|
if not new_sy then new_sy = 0 end
|
|
if (new_sx < 0.001 and new_sx > -0.001) and (new_sy < 0.001 and new_sy > -0.001) then return end
|
|
--falling
|
|
if not player.flying then
|
|
new_sy = new_sy +dt * 100
|
|
end
|
|
|
|
--new positions
|
|
local futureX = player.x + player.speed.x
|
|
local futureY = player.y + player.speed.y
|
|
assert(futureX and futureY)
|
|
|
|
-- cap boundaries
|
|
futureX, futureY, new_sx, new_sy = physics.cap_world(player.avatar:getWidth(), player.avatar:getHeight(), futureX, futureY, new_sx, new_sy)
|
|
|
|
local granularity = math.sqrt(math.abs(player.speed.x * player.speed.x)+ math.abs(player.speed.y * player.speed.y)) + 1
|
|
local stepsizeX = player.speed.x / granularity
|
|
local stepsizeY = player.speed.y / granularity
|
|
assert(granularity and stepsizeX and stepsizeY)
|
|
|
|
local currentX = player.x
|
|
local currentY = player.y
|
|
if granularity < 1 then granularity = 1 end
|
|
|
|
|
|
if player.flying then
|
|
player.x, player.y = futureX, futureY
|
|
|
|
player.speed.x = new_sx
|
|
player.speed.y = new_sy
|
|
if localplayer then
|
|
physics.send_update(player, dt)
|
|
end
|
|
return
|
|
end
|
|
|
|
local blocked_x, blocked_y = false, false
|
|
for iteration=1, granularity do
|
|
intermediateX = currentX + (stepsizeX * iteration)
|
|
intermediateY = currentY + (stepsizeY * iteration)
|
|
|
|
if intermediateY > futureY then -- UP
|
|
if physics.is_blocked_x(intermediateX, intermediateY, player.avatar:getWidth()) then
|
|
intermediateY = currentY
|
|
blocked_y = true
|
|
end
|
|
end
|
|
|
|
if intermediateY < futureY then --DOWN
|
|
local lowerY = intermediateY + player.avatar:getHeight() -1
|
|
if physics.is_blocked_x(intermediateX, lowerY, player.avatar:getWidth()) then
|
|
intermediateY = currentY
|
|
blocked_y = true
|
|
end
|
|
end
|
|
|
|
if intermediateX > futureX then -- ONLY LEFT
|
|
if physics.is_blocked_y(intermediateX, intermediateY, player.avatar:getHeight()) then
|
|
blocked_x = true
|
|
end
|
|
end
|
|
|
|
if intermediateX < futureX then -- ONLY RIGHT
|
|
local lowerX = intermediateX + player.avatar:getWidth() -1
|
|
if physics.is_blocked_y(lowerX, intermediateY, player.avatar:getHeight()) then
|
|
blocked_x = true
|
|
end
|
|
end
|
|
|
|
intermediateX, intermediateY, new_sx, new_sy = physics.cap_world(player.avatar:getWidth(), player.avatar:getHeight(), intermediateX, intermediateY, new_sx, new_sy)
|
|
if blocked_x and not blocked_y then -- X blocked
|
|
player.y = intermediateY
|
|
return
|
|
end
|
|
|
|
if blocked_y and not blocked_x then
|
|
player.x = intermediateX
|
|
return
|
|
end
|
|
|
|
if blocked_x and blocked_y then
|
|
return
|
|
end
|
|
|
|
if not blocked_x and not blocked_y then
|
|
player.x = intermediateX
|
|
player.y = intermediateY
|
|
end
|
|
end
|
|
|
|
player.speed.x = new_sx
|
|
player.speed.y = new_sy
|
|
if localplayer then
|
|
physics.send_update(player, dt)
|
|
end
|
|
end
|
|
|
|
|
|
function physics.update(dt)
|
|
for i, player in pairs(participants) do
|
|
assert(player.x and player.y and player.speed.y and player.speed.x, "Player has an invalid position!")
|
|
physics.updatePlayer(dt, player, i == levelloop.clientID)
|
|
end
|
|
local player = participants[levelloop.clientID]
|
|
ui.updateSpeed(player.speed.x, player.speed.y, player.x, player.y)
|
|
end
|
|
|
|
|
|
local last = {}
|
|
last.packet, last.x, last.y, last.speedx, last.speedy = 0, 0, 0, 0, 0
|
|
function physics.send_update(player, dt)
|
|
if last.packet > 0.03 then
|
|
if last.x ~= player.x or last.y ~= player.y then
|
|
levelloop.remoteCall("moveUpdate", player.x, player.y, player.speed.x, player.speed.y)
|
|
last.packet = 0
|
|
last.x, last.y = player.x, player.y
|
|
last.speedx, last.speedy = player.speedx, player.speedy
|
|
end
|
|
else
|
|
last.packet = last.packet + dt
|
|
end
|
|
end
|