Open collinsmith opened 5 years ago
Initial tests implementing box2d look good -- I'm able to render out DS1s. I'm making an effort to keep the scale 1:1, so 1 unit in box2d will be 1 unit in-game (1 subtile) -- however this gets skewed with projection (physics are simulated without isometric), so I'm worried how this could effect physics simulation compared to the original game, so I might require some kind of scalar. Because of the large number of subtiles (act 1 town is 280x200
subtiles), I'm going to look into combining adjacent walls on a DS1 scale (initially I might test with individual tiles for simplicity) -- so a polygon will never be larger than its backing Map.Zone
grid size.
It should be possible to clean this up eventually and do things like create better bounds for level boundaries using fewer rectangles since these will be well-defined once level generation is added.
I integrated MapRenderer
onto my Box2D test module and it works good after scaling is adjusted. Performance for town zone is decent on desktop (41186
bodies, 300 fps), however once I add the additional zones the performance becomes quite bad (107522
bodies from only 3 zones) -- so I'm going to assume even the town zone would be too much for mobile. I think I either need to dynamically create/destroy static wall objects that are within a certain range of player or find a good wall aggregation strategy that's cheap.
The more I think about it, I really would like to find a way to make this work to leverage the advanced functionality of box2d, but I want to take advantage of the existing in-memory collision arrays which are O(1)
access and makes the most logical sense (each cell is a subtile, array index is local x,y coordinate of subtile within zone) -- also, a 400x400 zone only needs 160KB to store world collision data. If I decide to take this route without finding appropriate optimizations, perhaps it's plausible to use both systems and let box2d handle entity collisions.
Box2d lighting works really well and looks good, except will eventually require customized shader for collision with walls to cast light on them properly (not designed for isometric games). It will also require drawing the shadows under some specific layers to make it look correct (e.g., roofs, walls in some cases).
I implemented a basic aggregation algorithm that combines subtiles in the same row with the same flags which has significantly reduced the number of bodies to 2209
for all 3 zones -- It's also really cheap. I'm betting including column will cut that down to ~200.
Further optimization with column aggregation has reduced the number of bodies for the first 3 zones to 4509
(roughly 4% of the starting amount) at the cost of 1MB of temp memory while the map is built which is reset for each zone. I think this is much more manageable for mobile -- remains to be seen how much of a hitch this will be for different zones (how many zones at once?). I think Body#setActive
could help here, but the building of the box2d world could take some time on mobile -- benchmarking is needed here. From box2d manual
Note that activating a body is almost as expensive as creating the body from scratch. So you should not use activation for streaming worlds. Use creation/destruction for streaming worlds to save memory.
Entity update loop has become a bit messy since adding
screen
vector, which updates duringEntity#act(float)
but is actually occasionally required duringEntity#update(float)
(the names of these methods are also a bit confusing --update(float)
is supposed to update position/logic,act(float)
is supposed to update animation frames).This seems like a good opportunity to look into integrating a native physics solution like Box2D, which may improve performance and greatly simplify a lot of the problems I'm currently having with collision detection and movement. One specific optimization that may be required is wall aggregation -- walls are subdivided into 1yd squares which Box2D will prefer represented as a single body (these walls will be needed when I want to detect rooms to fade walls). This also will help add light ray casting.
One problem I've been having is that I originally assumed player movement was based with the underlying 1yd grid, but that assumption seems to be incorrect to a point. I tested this by using a character with extremely slow walk speed, walking and then casting a spell after a short enough distance where the next subtile could not have been reached. The characters stops instantly indicating that their position is not locked to the grid. I also noted that their networked position data seems to only update positions based on the grid -- so this may be a client-local behavior.
I also started looking into unit sizes, and assuming the information I was looking at was correct, they are not using axis-aligned boxes seem to be a selection of horizontal boxes (this would explain
SizeX
andSizeY
columns inmonstats2
, but they are always same as far as I've seen). With Box2D, this might be better implemented as a circle with diameter ofSizeX
.