I've spent a little bit of time figuring out how to do a fade in or fade out effect for the cutscenes in my game, so I thought I'd share the results here.
-- FADE OUT --
Fade out is the easier of the two, and uses an animated player tile with transparency and increasingly darker dither patterns:
In this example, I called a custom event
fadeOut on the confirm event
on confirm do tell event.game to log "calling fadeOut event" call "fadeOut" end end
Then in the custom event, I
tell every single tile on screen to
play the fade out animation:
on fadeOut do log "fadeOut event answered" // row 0 tell 0,0 to play "fade_out" end tell 1,0 to play "fade_out" end tell 2,0 to play "fade_out" end ... ... ... etc. end
This works well enough on-device. Keep in mind I'm only planning on using these during cutscenes so there won't be any player input effected by performance dips.
In this case, there is a slight pause while the entire screen is set to play the tile, but then the tile's animation plays out smoothly at Pulp's full 20fps
-- FADE IN --
Now fading in is a little trickier and causes some performance issues on-device. But again, for my cutscene use-case that's not an issue.
*(See the end of this post for an aside on how transparency works in Pulp, and why we needed to change methods for fade in as opposed to doing the same thing as fade out)
Essentially the same dither patterns from the fade out animation are used, but instead of being in one animated tile each frame is split into their own single tile. Then we
draw those frames sequentially to get this:
Which absolutely tanks performance. But that was expected when you set a
draw over every single tile on the screen.
What is happening specifically is on A press I call a custom event, just like before. This custom event though is stepping through each individual tile at a specified rate (as if they were frames of an animation) and setting them to a variable
on fadeIn do log "fadeIn answered" ignore drawFadeIn = 1 // step through animation frames fadeInFrame = "fade_in 1" wait 0 then fadeInFrame = "fade_in 2" wait 0 then fadeInFrame = "fade_in 3" wait 0 then ... ... ... etc.
I also enable the draw flag
drawFadeIn at the start of the event and set it back to zero at the end. This allows this block of code to start drawing in the player's draw event:
on draw do // fadeIn effect if drawFadeIn==1 then // row 0 draw fadeInFrame at 0,0 draw fadeInFrame at 1,0 draw fadeInFrame at 2,0 draw fadeInFrame at 3,0 draw fadeInFrame at 4,0 ... ... ... etc.
And this code lists out
draw "_" at .x,y for every single tile on screen.
So... what do we do about the terribly slow fade in when playing on-device? Well we're not going to be able to make drawing to every single tile more performant, so I just cut out animation frames!
After going from stepping through 27 dither frames, down to 8 frames, this is now what the "sped up" fade in looks like on-device:
Which I think for my use of fading in from a cutscene is perfectly usable! (Keep in mind though if you have music playing during this it will also slow down and be very noticeable)
-- WRAP UP --
So, this is what I came up with in a night. I'm sure someone smarter than me could make better pulp script to do something like dynamically stepping through each tile coordinate so that you wouldn't need to type them all manually like I did, but as far as I know I don't think there will be any way to actually improve the performance of these methods. Hopefully they're useful to someone though!
Both of my pulp test games will be attached. If you have any questions just let me know.
*Notes on transparency in Pulp:
So, as you probably know transparency is only possible on Player tiles. But what you may not know is that when a pixel is marked to be transparent, it's not actually "revealing" what should be underneath that pixel. It simply says, "don't update this pixel."
This is fine when doing a fade out, because the entire tile starts as transparent then gradually adds more black pixels. But when going the other way (fade in), you start with an all-black tile, so adding transparent pixels to that only says, "don't change these," therefore making the whole thing remain black.
So, to get around this, we don't use one animating tile, but step through completely separate tiles to "make" our own animation. What I think is happening is since you tell it to change to a completely different tile, it sort of "refreshes" the underlying pixels between tiles, allowing the proper image to show through the transparency.
Honestly, I'm not 100% why it works, but it does!
Pulp Fade Tests.zip (12.4 KB)