154 lines
No EOL
4.2 KiB
Lua
154 lines
No EOL
4.2 KiB
Lua
-- handles object collision and updates
|
|
|
|
require 'util'
|
|
|
|
local self = {}
|
|
|
|
local steps = 4 -- the more, the higher quality the collision is, however it becomes laggier
|
|
local clipAttempts = 10000
|
|
|
|
function self.doCollision(i, o, dt)
|
|
-- check if object is already colliding and try to clip it out
|
|
|
|
-- object collision
|
|
for i2,o2 in ipairs(objects) do
|
|
local touch = rectangleTouchingRectangle(o.x, o.y, o.size, o.size, o2.x, o2.y, o2.size, o2.size) and i ~= i2
|
|
if touch then
|
|
-- clip it out, m64 style
|
|
for i = 0, clipAttempts do
|
|
if not rectangleTouchingRectangle(o.x, o.y, o.size, o.size, o2.x, o2.y, o2.size, o2.size) then break end
|
|
local diffX = (o.x - o2.x) or o.size / 10 -- `or` incase the objects are spawned inside eachother
|
|
local diffY = (o.y - o2.y) or o.size / 10
|
|
|
|
o.x = diffX * 1.1 + o2.x
|
|
o.y = diffY * 1.1 + o2.y
|
|
end
|
|
end
|
|
end
|
|
|
|
-- tile collision
|
|
for i = 0, clipAttempts do
|
|
local pass = true
|
|
local onTileId = getTile(math.floor(o.x), math.floor(o.y))
|
|
if onTileId[1] ~= 0 then
|
|
local onTile = tiles[onTileId[1]]
|
|
local a = -(onTileId.rotation or 0) * 90
|
|
|
|
if onTile.collision then
|
|
if onTile.type == 'seller' then
|
|
local movementAngle = math.deg(math.atan2(o.vely, o.velx)) - 90
|
|
if onTileId.rotation then
|
|
local sellerAngle = onTileId.rotation * 90
|
|
if not math.abs(movementAngle - sellerAngle) < 45 then
|
|
pass = false
|
|
end
|
|
end
|
|
else
|
|
pass = false
|
|
end
|
|
end
|
|
end
|
|
|
|
if pass then break end
|
|
|
|
local diffX = (o.x % 1 - 0.5) or o.size / 10 -- `or` incase the objects are spawned inside eachother
|
|
local diffY = (o.y % 1 - 0.5) or o.size / 10
|
|
|
|
o.x = diffX * 1.1 + math.floor(o.x) + 0.5
|
|
o.y = diffY * 1.1 + math.floor(o.y) + 0.5
|
|
end
|
|
|
|
-- move
|
|
for step = 1, steps do
|
|
local a = step/steps
|
|
local x = o.x + o.velx * dt * a
|
|
local y = o.y + o.vely * dt * a
|
|
|
|
local pass = true
|
|
|
|
-- tile collision
|
|
local onTileId = getTile(math.floor(x), math.floor(y))
|
|
if onTileId[1] ~= 0 then
|
|
local onTile = tiles[onTileId[1]]
|
|
local a = -(onTileId.rotation or 0) * 90
|
|
|
|
if onTile.collision then
|
|
if onTile.type == 'seller' then
|
|
local movementAngle = math.deg(math.atan2(o.vely, o.velx)) - 90
|
|
if onTileId.rotation then
|
|
local sellerAngle = onTileId.rotation * 90
|
|
if not math.abs(movementAngle - sellerAngle) < 45 then
|
|
pass = false
|
|
end
|
|
end
|
|
else
|
|
pass = false
|
|
end
|
|
end
|
|
end
|
|
|
|
-- object collision
|
|
for i2,o2 in ipairs(objects) do
|
|
local touch = rectangleTouchingRectangle(o.x, o.y, o.size, o.size, o2.x, o2.y, o2.size, o2.size) and i ~= i2
|
|
if touch then pass = false end
|
|
end
|
|
|
|
if pass then
|
|
o.x = x
|
|
o.y = y
|
|
else
|
|
o.velx = -o.velx * 0.25
|
|
o.vely = -o.vely * 0.25
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
function self.updateObject(i, o, dt)
|
|
o.x = o.x or 0
|
|
o.y = o.y or 0
|
|
o.velx = o.velx or 0
|
|
o.vely = o.vely or 0
|
|
o.size = o.size or 0.5
|
|
o.color = o.color or {1, 1, 1}
|
|
o.despawntimer = o.despawntimer or 0
|
|
|
|
local object = objectTypes[o.type]
|
|
|
|
local onTileId = getTile(math.floor(o.x), math.floor(o.y))
|
|
if onTileId[1] ~= 0 then
|
|
local onTile = tiles[onTileId[1]]
|
|
local a = -(onTileId.rotation or 0) * 90
|
|
|
|
if onTile.type == 'conveyor' then
|
|
o.velx = o.velx - math.sin(math.rad(a)) * onTile.speed * dt * 40
|
|
o.vely = o.vely - math.cos(math.rad(a)) * onTile.speed * dt * 40
|
|
elseif onTile.type == 'seller' then
|
|
local movementAngle = math.deg(math.atan2(o.vely, o.velx)) - 90
|
|
if onTileId.rotation then
|
|
local sellerAngle = onTileId.rotation * 90
|
|
if math.abs(movementAngle - sellerAngle) < 45 then
|
|
table.remove(objects, i)
|
|
money = money + object.cost
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if math.abs(o.velx) < 0.01 and math.abs(o.vely) < 0.01 then
|
|
o.despawntimer = o.despawntimer + dt
|
|
else
|
|
o.despawntimer = 0
|
|
end
|
|
|
|
if o.despawntimer > 5 then
|
|
table.remove(objects, i)
|
|
end
|
|
|
|
self.doCollision(i, o, dt)
|
|
|
|
o.velx = o.velx * 0.8
|
|
o.vely = o.vely * 0.8
|
|
end
|
|
|
|
return self |