I need to do some general performance optimising
Here's a small but interesting one with the HUD!
Before, my event for drawing the HUD (called from the player's draw
event) looked like this:
on drawHud do
x = 18.5
label "Lolife" at x,1
label "Health" at x,10
label "Target" at x,12
label "Lvl {2, :player_level}" at x,7
label "<===>" at 19,8
fill "white" at 153,66,level_px,4
label "<===>" at 19,11
fill "white" at 153,90,health_px,4
label "<===>" at 19,13
fill "white" at 153,106,target_px,4
end
Performance wise these are all quite expensive functions. There aren't too many calls here, but as I'm not hitting a solid 20fps with multiple entities on screen every little helps.
As a side note, the <===>
labels (which are for the border boxes of the xp/health/target bars) are already a little optimised in that using font characters is cheaper than embedding tiles.
Generally though I could see there were improvements to be made.
The obvious alternative is to bake the fixed HUD elements into each room. The problem there is that changing the HUD then becomes annoying as I'd have to manually go through each room to change the baked-in appearance. I'd also have to create tiles for the HUD text as font tiles can't be placed into rooms, which is a bit messy.
Luckily a third option occurred to me, and it takes advantage of that x = 18.5
line at the top and some exploits of the pulp engine!
Officially you should only be able to place labels or draw tiles at integer coordinates. If you try to call e.g. label "test" at 10.5,12.5
or similar, it will get flagged as invalid pulpscript. You can however get around this by assigning those non-integer values to variables and then passing those variables to the function. This lets you draw tiles and labels "off-grid", but with the downside that pulp's internal handling of partial screen refreshes - something you don't normally have to know or worry about - breaks when you do this.
While normally a label will only be displayed for the frame you actually call the label function in, an off-grid label won't get cleaned up until something else triggers that area of the screen to be refreshed. In other situations this is a problem that needs to be accounted for, but in this case I can make use of it! I realised I only actually need to call those labels in the first frame of entering a room. Being off-grid they won't get refreshed by subsequent frames as nothing else is causing a refresh in that area of the screen.
With that in mind, my event now looks like this:
on drawHud do
if draw_offgrid_labels==1 then
x = 18.5
label "Lolife" at x,1
label "Health" at x,10
label "Target" at x,12
label "Lvl {2, :player_level}" at x,7
draw_offgrid_labels = 0
end
label "<===>" at 19,8
fill "white" at 153,66,level_px,4
label "<===>" at 19,11
fill "white" at 153,90,health_px,4
label "<===>" at 19,13
fill "white" at 153,106,target_px,4
end
That's four less labels per frame, while keeping all of the advantages of not having any HUD baked in!