object collision

This commit is contained in:
jill 2020-10-27 17:28:10 +03:00
parent ae3ee8fcb2
commit 5f1a51beac
Signed by: oat
GPG key ID: DD83A9617A252385
3 changed files with 167 additions and 67 deletions

View file

@ -8,6 +8,7 @@ tiles = {
count = 1,
},
cost = 10,
collision = true,
desc = 'An axe clicker. Used to obtain wood.',
},
@ -20,6 +21,7 @@ tiles = {
count = 0.25,
},
cost = 100,
collision = true,
desc = 'A primitive chainsaw. Automatically collects wood.'
},
@ -29,7 +31,8 @@ tiles = {
type = 'conveyor',
cost = 5,
speed = 1,
desc = 'Moves a resource from point a to point b'
desc = 'Moves a resource from point a to point b',
collision = false,
},
{
name = 'basic_seller',
@ -38,6 +41,7 @@ tiles = {
cost = 1500,
rate = 1,
desc = 'A basic seller. Automatically sells all items coming from the forward tile',
collision = false, -- custom collision for sellers
}
}

View file

@ -1,7 +1,9 @@
require 'util'
require 'drawutil'
require 'def'
-- crusty swamp ass language An Awesome Project
local obj = require 'obj'
width = 64
height = 64
@ -14,7 +16,7 @@ sprites = {}
money = 0
local objects = {}
objects = {}
local selectedTile = 1
local defaultTileRotation = 0
@ -58,6 +60,8 @@ end
local timer = 0
function love.update(dt)
--dt = dt * 0.1
for x = 1, width do
for y = 1, height do
local tileid = getTile(x, y)
@ -86,69 +90,7 @@ function love.update(dt)
timer = timer + dt
for i,o in ipairs(objects) do
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 pass = true
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
o.vely = o.vely - math.cos(math.rad(a)) * onTile.speed
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
else
pass = false
end
end
else
pass = false
end
end
--[[
for i2,o2 in ipairs(objects) do
if i ~= i2 and rectangleTouchingRectangle(o.x - o.size, o.y - o.size, o.size, o.size, o2.x - o2.size, o2.y - o2.size, o2.size, o2.size) then
pass = false
end
end
-- this doesnt work
]]
if not pass then
o.velx = -o.velx
o.vely = -o.vely
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
o.x = o.x + o.velx * dt
o.y = o.y + o.vely * dt
o.velx = o.velx * 0.8
o.vely = o.vely * 0.8
obj.updateObject(i, o, dt)
end
end
@ -261,7 +203,7 @@ function love.mousepressed(x, y, button)
if tileid[1] ~= 0 then
local tile = tiles[tileid[1]]
if tile.type == 'clicker' then
local a = -tileid.rotation * 90
local a = -tileid.rotation * 90 + math.random(-10, 10)/10
local x = math.floor(x/tilesize) + 0.5 - math.sin(math.rad(a)) * 0.7
local y = math.floor(y/tilesize) + 0.5 - math.cos(math.rad(a)) * 0.7

154
obj.lua Normal file
View file

@ -0,0 +1,154 @@
-- 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