Ok, so as per @Pawel’s suggestions, I’ve done a quick refactor just to change the context of the logic functions being called.
- The slime’s own
update()
is completely removed from the script now, and I just have a simple table in which I’m storing references to the self-reference of each slime script (since I’m using it as my data container).
- In the controller I’m iterating through this table in a loop and calling the state modifications (logic) from here.
This prediction was correct, it had pretty much no impact on the frame times (pretty much the same numbers as in my above reply to @cornedbeer). So it’s likely just the logic itself then is what I concluded from that.
My game is tile-based, using a collision system based off of the methods described here. When I don’t calculate the tile collision info, I get about 250 (prev 80) with 50 slimes. With 100 slimes the improvement is from 50fps to 130.
I’ve attached the tilecollision calculation module (it’s pretty meaty → slopes are an absolute pain in the a**, especially if you want the ability to jump and drop through them, retro tilebased). One thing I tried was commenting out the last calculation function, which is the least intensive of them and I was able to get 10fps (50 slimes). Pretty much the only thing that’s happening in that function is a few tilemap.get_tile()
wrapped in an evaluation to avoid an error when the object checking is out of tilemap bounds:
function get_tile(tm, layer, x, y)
local _x, _y, _w, _h = tilemap.get_bounds(tm) -- first check if the tile exists to avoid error
if (x >= _x and x <= _w+_x-1) and ((y >= _y and y <= _h+_y-1 and _h ~= 1) or (_h == 1 and y == _y)) then
return tilemap.get_tile(tm, layer, x, y) -- returns the tile's index from tilesource
end
end
Can this be optimized somehow? I’m getting a lot of tiles this way due to how the heightmasked tile calculations work. Would it be faster than tilemap.get_tile()
to get and store every tile of the tilemap into a table and retrieve them from there?
tilecollision.lua (36.2 KB)
The other part of logic that seems to make an impact when left out is handling collision interaction with other objects (interaction.lua), and updating the data structure I’m using to group potential collisions (partition.lua).
interaction.lua (2.6 KB)
partition.lua (3.8 KB)
The calls from interaction.lua that use data.type
as the index are calling this function:
(where aabb
in this context is the state of self.aabb
, the same state accessed through data
from interaction.lua when an object checks another for collision)
function aabb.collision(data)
local collision = {}
collision.left_difference = (aabb.world_position.x + xradius) - (data.aabb.world_position.x - data.aabb.xradius)
collision.right_difference = (aabb.world_position.x - xradius) - (data.aabb.world_position.x + data.aabb.xradius)
local combined_radius_y = aabb.yradius + data.aabb.yradius
local object_diameter_y = combined_radius_y * 2
collision.top_difference = aabb.world_position.y - data.aabb.world_position.y - 4 + combined_radius_y
collision.distance_x = (aabb.world_position.x < data.aabb.world_position.x and collision.left_difference or collision.right_difference)
collision.distance_y = (aabb.world_position.y < data.aabb.world_position.y and collision.top_difference + 4 or collision.top_difference - object_diameter_y)
collision.active = not (collision.left_difference < 0 or collision.right_difference > 0 or collision.top_difference < 0 or collision.top_difference > object_diameter_y)
collision.enter = (collision.active and not table.value_exists(aabb.collision_enter, data))
if collision.enter then
table.insert(aabb.collision_enter, data)
end
collision.exit = (not collision.active and table.value_exists(aabb.collision_enter, data))
if collision.exit then
for i, v in ipairs(aabb.collision_enter) do
if v == data then
table.remove(aabb.collision_enter, i)
end
end
end
collision.eclipse = {
-- check if object is fully within the given bounds of the object in question
x = collision.left_difference > aabb.xradius * 2 and collision.right_difference < aabb.xradius * -2,
y = collision.top_difference >= aabb.yradius * 2 and collision.top_difference <= data.aabb.yradius * 2,
full = collision.eclipse_x and collision.eclipse_y
}
return collision
end
This is the slime script (not refactored to central controller) if needed to make sense of all that description on how those parts work together.
slime.script (2.5 KB)