I'd like to clarify that, although my programming is very frame-based, I do use TimeDelta() to mitigate the effects of lag (I don't have time to explain how I do that right now) and I think that it can be a very effective way to program games. I do not have a personal vendetta against the Timer system, though I do wish it's Frame-independent nature was more clearly explained.
Your use of timers sounds consistent with how features behaved at lower framerates: the gravity felt faster than the jump.
- "This already alerts me to another project where musical synchronization is important, I need to create my own timers fed by the framerate to correct possible desynchronizations. I was entrusting this function to the standard timers."
This isn't hard advice, as I've never done music synchronization, and, from what I hear, it is very difficult! But I probably would use TimeDelta() instead of framerate for synchronizing something to music, which plays according to Time and not Frames. I'm not sure if I would use the in-built Timer system (which I am very unfamiliar with), but I would use TimeDelta() in conjunction with variables for timing.
- "My strategy for the spikes was to select the closest one (this one I had to deactivate the prices, because it was generating bugs) and turn them into tiles (they were animated sprites)."
Could you clarify what "deactivate the prices" refers to?
Otherwise, that sounds reasonable. While "closest" isn't the most performant (as I'll talk about later), it shouldn't be particularly heavy. It also seems like tiles have better performance.
The sectorization is an interesting hypothesis. I don't think it would be necessary for a project like this, and it might create some weird edge cases (what if player is in quadrant Top-Left and needs to collide with a Spike on the edge of quadrant Top-Right?). Additionally, trying to program for four different kinds of spikes sounds a bit stressful. However, keeping in mind the use of unique objects to reduce load is important.
- "Does the function of selecting objects by the condition "the distance between objects is less than" does it have a big impact on performance compared to your selection box?"
Yes.
I want to preface that I don't have intimate knowledge of how these conditions work; I mostly just do testing within the engine to come to my conclusions.
"[Object A] distance to [Object B] is below X pixels" is a very good condition. It uses a distance calculation (which probably involves square roots) between the Origin of the first and second objects. Basically, it's an "imaginary circle". It's especially useful for "area of effect" type processes. However, while this calculation is very useful for logic reasons, it is not performant.
Since I wasn't entirely sure about this, I decided to make a test project.
There's one player and some spikes. The player can be moved with WASD. Inside the frame, I have 67 spikes organized semi-randomly, with a grid of Spikes close to where the player starts. Then, at the beginning of the scene, I make 50,000 spikes at -128;-128, to increase the load.
There are four different methods for picking and checking for collisions between Player and Spike. (-1): No Cull. (0): Box Method. (1): Nearest To. (2): Distance Below. I can switch between them by modifying "Mode" by pressing the 0-3 keys. Here's what the code looks like (minus a couple of group headers for readability):
(Note: The profiler is not an exact sort of thing, especially since it's measured in time it takes for my computer to process it, which is different across every machine. There's also a lot of fluctuation in the time it takes to do stuff. I've mitigated this a bit by creating 50,000 spikes to exaggerate the differences in the methods.)
So, using the four methods and 50,067 spikes, I measured using the profiler for 600 frames each.
No Cull | 10.96 ms |
Box Method | 1.83 ms |
Nearest To | 5.45 ms |
Distance Below | 10.35 ms |
(Note: I only included the time it took to process these specific events. I didn't include the massive amounts of time it took the game to process and render the objects. The actual full process time came out to about 50-70 ms to run one frame. 50,000 objects is a tad too many!)
I was very surprised that "Distance Below" is almost identical to not culling at all. I speculate that the collision algorithm already uses a similar distance calculation to "Distance Below". Again, "Distance Below" is a good logical check, but it does not improve performance.
"Nearest To" is a very useful condition. and it seems to perform quite nicely. For example, I used "Nearest To" when deciding which Lightbulb in "Logic Bulb Adventure" should be interactable, since there should be only one of those at any time. It's a distance calculation, so it's essentially "imaginary lines", where the object picked has the shortest line.
But, it can be problematic for collisions with multiple objects in close proximity. Also, if the positions being compared aren't in the "correct" place, it can produce edge cases. In the test project, the origin of the Spike and Player are both at 0;0 (Top-left), which produces situations where the player is clearly overlapping with a spike, but the "Nearest" spike is not that one.
Of course, this could all be irrelevant to the performance in Visions of Ethereal; it might be something completely unrelated! You'll have to run your own tests to find out where the heaviest loads in the code are.