Rain Effect in Pulp

Update: Some very kind people in the comments took time out of their day to test this code on their Playdates. It's unfortunately too resource intensive, and will tank the frame rate of your game so it's unplayable :playdate_low_battery:

I made a basic rain effect in Pulp using the draw function. Since it draws raindrops over the screen, there's no need to animate tiles individually to add rain, and you can turn the rain on or off in a room with simple logic.


Player Script

on draw do
	if raining==1 then
		x = 0
		rainY = rainT
		while x<200 do
			tell event.game to
				call "rain{x}"
			rainY += rainPhase
			if rainY>125 then
				rainY -= 130
			fill "black" at x,rainY,1,3
		rainT += 2
		if rainT>125 then
			rainT = -5

Game Script

on rain0 do
	rainPhase = 101

on rain1 do
	rainPhase = 54

on rain2 do
	rainPhase = 63

// Keep adding rain{x} events until you get to rain199, one for each x value

It basically works by looping through each x value on screen, drawing a raindrop at a certain y value for each value of x, and then stepping the whole drawing down slightly each frame.

The secret sauce is using the rain{x} events like an array to reuse the rainPhase variable during the while loop. Thanks to Shaun Inman for sharing how to do this! :playdate_heart: I used a random number generator to enter a value for each event.

You can import my version of the code (pdx and json) here:
It's Raining.zip (45.5 KB)
I you're inspired by this effect or use any of my code, I would love it if you left a comment :playdate_happy:

PS: I don't have an actual Playdate yet; it's possible calling 200 events every frame is really bad for performance! If you have some hardware to actually test my code, I would appreciate it if you let me know how well it does! :playdate_proud:

Testing it on device, it gets 1.4FPS... :smiling_face_with_tear:

I haven't worked in Pulp much yet, but I'm sure there's a way to optimize how this is being drawn.

1 Like

Yikes, worse than I expected! :playdate_dead:

It would be interesting to know whether it's the call function or the fill function which draws the raindrops which is taking up processing power; I would assume the former. It might be worth trying to half or quarter the number of raindrops to see if that makes enough of a difference, but I'll have to test that when my device arrives.

I know Pulp isn't designed for much heavy data manipulation (hence no arrays), so it might just be Pulp can't handle this kind of function; especially not every frame.

Thanks for testing my code Foster, I really appreciate it! :playdate_proud:

1 Like

I would say it’s likely the fills. You can only do so much “drawing” in the Pulp draw event before performance is impacted. Something like 60x or so I think might be the soft cap I’ve heard. But I can take a look at your demo tomorrow to double-check that.

1 Like

Well looks like both are guilty, but the calls are slightly worse. Can get up to 3fps with just the fills and no calls. Not that it helps, that's unplayable :stuck_out_tongue:

1 Like

Yes, it's probably that trying to do 200 things per frame is costly no matter what you're doing; plus event calls (when you have 200 events to check) and fills are likely some of the most resource hungry functions Pulp has to offer :playdate_low_battery:

Thank you for taking the time to test this on your hardware! It's so nice to have strangers take time out of their day to help me out :playdate_proud:

1 Like