The quest for FPS, optimizing, and cheating for 10x.


Soooo... Someone uploaded the first video of the game. And his game turned into a slideshow, which means I have a duty to optimize particles ! That's cool !
Here are the list of updates it prompts, those marked with an X are included in today's update


[] tie the enemy hp to the player level, at least for the first few levels, then it needs to ramp up. 
[] quicker upgrade menu apparition
[] BUG : firerate and many shots upgrade txt
[] Indicate complexity level for weapons
[] Make the player minimal display size a big bigger
[] xp chasing the player on blue is kinda hard to see, outline ?
[] update the stupid mine text color
[] make the damage computer ui more explicit somehow, especially for the add after mult
[] tune down max shake a bit
[] remove the 'cannot apply to Spiralium' from magic bullets
[] bounce effect on the particles for magic bullets
[] cap the number of bounce sounds per seconds
[] cap the number of poison sounds per seconds
[] can all upgrade description be bigger and fit in there ?
[x] steeper high end xp curve
[x] Or maybe more low level enemies to give a head start to the player?
[x] tune for a 20000 bullets target
[x] cheat for many bullets F1
[x] BUG Windows : a black square as cursor
[x] hasten time to next spawn
[X] the 'time to breath' period can be a tad too long https://youtu.be/RdqU9KyyRZI?si=NsKYuGRwoRWjNmbM&t=1079
[x] check for the bullet drawing position ??
[x] fix shooting sounds


The framerate was the one that I spent the most time on this weekned !

So I profiled the game with a 10000 bullets in mind.

0. Step 0, performance computer

introduce to the game a metric that would tell me how well the game is running, and allow me to adapt my effects accordingly. That's this tiny bit of code :

```

val delta = (previousDelta + Gdx.graphics.deltaTime) / 2f
val offset = targetDelta - delta
val steps = (offset / deltaRatingStep).toInt().coerceAtMost(1)
if (steps == 1) {
    performanceRatingF += .2f
} else {
    performanceRatingF += steps
}
performanceRatingF = performanceRatingF.coerceIn(0f, 10f)
performanceRating = performanceRatingF.toInt()
previousDelta = delta
```

So it analysis the time the current frame took to render, smooth this out a bit to avoid being tanked for a 1 off spike, and modifies a rating according to this. The rating can go down a lot more quickly than it can go up, again to avoid constant spikes. 

1. First offender : the background grid. 

Each bullet can move the grid, and thus needs to compute the distance squared (to avoid computing a square root) to the grid points. 

Which predictably makes for a lot of computations with lots of bullets. 

So it will just stop computing this above a certain treshold of number of bullets or performance indicator. 

I initially wanted something more subtle than that, but I think that the effect of having the grid all broken than recover only when you stop blasting is kinda cool


2. The damn bullets

I will no go int o details here because, in essence, it was fun but pointless.  In essence it was a lookup table for gaussian random numbers, adapting the number of particles dynamically even more than before, avoid angles draws to avoid sin and cosin computation upon flushing the batch, removing the rotating offset that was barely noticeable,.. 
Because I just ended up cheating : At runtime, I generate a bunch of textures using the same code as before, and display one of those textures at random. 
I might have to work around that in the future when I want to do more advanced effect such as wind or other stuff that would be supposed to interact directly with the particles, but that is a problem for another, if that day ever comes up. 

Files

particulitis-winX64.zip 59 MB
10 hours ago
particulitis-linuxX64.zip 62 MB
10 hours ago

Get Particulitix

Download NowName your own price

Leave a comment

Log in with itch.io to leave a comment.