Performance issues in Pulp game - No Fill

Today I was able to get Pichuscute from rngparty.com to help me test 4 versions of my game.

Some Fill
This does fill for the 3x3 ring of light, 5x5 ring of light and the player's head.
Light Game - Small Ring Fill.zip (54.7 KB)
Indoors area was great, outdoors area was BAD.

Less Fill
Here only the head is using fill
Light Game - Head Fill.zip (55.6 KB)
Still tanking, about a second between input and the player actually moving.

No Fill
Next we removed all fill, and just used draw for the player's head.
Light Game - Transition Effect - NO FILL.zip (54.3 KB)
1 fps as you stand there idling over the course of about 15-20 seconds whether you do anything or not

At this point, we wonder if the issue is the camera follow....

No Camera Follow
Light Game FPS Test - No Camera Follow.zip (53.7 KB)
No change.

So something in the code is causing issues on real hardware but not in pulp.

My first thought is the loops I use to draw the black squares around the player.

	// This whole section controls the light around the player
	if lightRadius<0 then
		lightRadius = 0
	elseif lightRadius>lightRadiusMax then
		lightRadius = lightRadiusMax
	end
	redraw_x = 0
	while redraw_x<screen_width do
		redraw_y = 0
		while redraw_y<screen_height do
			check_x = centre_x
			check_x -= lightRadius
			if redraw_x<check_x then
				draw "black" at redraw_x,redraw_y
			end
			check_x = centre_x
			check_x += lightRadius
			if redraw_x>check_x then
				draw "black" at redraw_x,redraw_y
			end
			check_y = centre_y
			check_y -= lightRadius
			if redraw_y<check_y then
				draw "black" at redraw_x,redraw_y
			end
			check_y = centre_y
			check_y += lightRadius
			if redraw_y>check_y then
				draw "black" at redraw_x,redraw_y
			end
			redraw_y++
		end
		redraw_x++
	end

Is there something wrong with this?

Any help is greatly welcomed!

I've just replaced my looping draw code with 375 hard coded draw lines.
If someone could test on real hardware for me, that would be a huge help!

Light_Game_FPS_Test.zip (50.9 KB)

@shaun are you able to give me some direction?

I think the reason it runs fine in the browser is the Pulp web player is a simulator, not an emulator, with the full resources of your modern computer behind it.

fill is really meant to be used for a few small-ish UI elements (eg. filling a meter) not full screen drawing. An effect like this is better achieved with the full SDK using images or geometry as stencils (my game Ratcheteer actually does this extensively to much the same effect).

I think you’re on the right track thinking about your custom drawing code. Consider this: by the time your draw handler is called, the entire screen has already been drawn. Now you’re drawing on top of a fully rendered screen, updating almost twice as many pixels. Not only that, every tile you draw on top of (even if it’s just a single pixel of an 8x8 tile) is now "dirty" and has to be redrawn the next frame. In addition to the cost of drawing the same pixels twice, there are nested loops with multiple conditional expressions.

Also your hunch about camera follow is correct, camera follow effectively dirties every tile every frame causing a full redraw of the room (thinking about that now though, it should really only force a full redraw on the frame a player moves).

A good rule of thumb with PulpScript is "do less, less often."

A better way to approach this would be to play to Pulp’s strengths: tiles. For single frame tiles, switch between a light and dark frame as they pass in and out of the ring of light. For animated tiles, swap between light and dark versions. These tiles will only be redrawn when they change. Also, making this tile-based allows you to add highlights to dark frames, eg. to provide landmarks in a dark room.

For this approach I would probably use emit, with a pair of x,y coordinates (eg. startX,startY,endX,endY) denoting the tiles inside the ring of light, instead of a while loop. Then you could use event.x,event.y to check if the tile handling the event is inside the ring or not.

Thanks for your help @shaun. It's helpful to have your insights.

Do you think you could explain this in a little more detail?
I'm not sure how you would check the tiles.

Your reports about poor performance, when most of the screen is "fill"-ed scared me, and I am rewriting the way how light/darkness are done in Nightly Urges right now.
What I do is to define the light by X1,Y1 (top left corner) and X2,Y2 (bottom right corner), and then have every tile check whether it is within this area.
Like this:
In the player I call:

on draw do
   [define X1,Y1 - X2,Y2]
   emit "setlight"
end

then every tile has:

on setlight do
   if [event.x,event.y is within X1,Y1 - X2,Y1] then
      frame 0
   else
      frame 1 (all black frame)
   end
end

I think this is what @shaun meant.
However, I currently have the issue that I see the whole screen for a split second, when I use an exit, that moves the player within the same room.

1 Like

This logic is sound but you should emit setlight in the player’s update callback not draw. Calling it in draw is what’s causing it to miss the first frame after a goto (since it’s being emitted after the room has already been drawn).

And just so there’s no confusion in the future, the bracketed code above isn’t PulpScript, it’s pseudo code expressing the intent of the PulpScript you would need to write :sweat_smile:

1 Like

This fixed it!!

Apologies for my pseudocode, I figured, it's easier to read than countless stacked if clauses :grinning_face_with_smiling_eyes: