Platformer Demo

This is a platformer demo made with Pulp. It uses the fill command as it is pixel-based instead of tile-based (This means that the entire player has to be drawn with the fill commands instead of with built-in graphics editor). The rest is just scripting platformer physics. You can open the JSON file in Pulp to see how it was made or to play it.
JSON file: Platformer (3.8 KB)


That's cool! I like how you added texture to the sky! :playdate_happy:

1 Like

Woah this is pretty cool, movement seems pretty smooth! It would be cool to see a full game with the script.

I love the idea of the B button making the world inverted. Thats a great idea for a "switch world" mechanic kind of like "mighty switch force" type switching mechanic. maybe you can make platforms appear and disappear with the inverting the world. Please keep us updated how this evolves!

1 Like

I will admit I had some trepidation about the performance of this on the device, but on my Playdate, this runs at a steady 20 fps, and feels super smooth! Amazing work!

1 Like

This is very impressive. I wonder how far fill can be pushed to create off grid movement.

After chatting with people on discord, we were wondering if you could use fill to fake an alpha channel on a non 8x8 sprite.

Would this be possible @Yousurname ?

By using fill, you can definitely choose certain pixels of the 8x8 (or bigger) sprite to be fully transparent instead of opaque white or black. However, semi-transparency is not possible unless you fake it with some sort of flickering (also possible with the fill bug where it uses anti-aliasing).

Oh sorry, I can see how my example is confusing now.

I certainly wasn't looking to hack some semi-transparency, that was just to show the layers.

Would you be willing to do a write up on your fill code?

All the code is inside the JSON file attached, but here is the code to draw the player at (px, py) in the player's draw event:

	// draw player
	fill "black" at px,py,8,8
	x = px
	y = py
	fill "white" at x,y,6,6
	fill "black" at x,y,4,4
	fill "white" at x,y,4,1
	fill "white" at x,y,2,3

The four parameters after at represent the X position, Y position, width, and height, respectively, each one in terms of pixels instead of tiles.

That I'm following but what I'm not following is drawing tiles behind the "player"
And how pulp works out what it's targeting when you are off grid.

You don't have to do anything special with the tiles behind the player; they're already drawn on their own. fill just draws over everything else in the game.

fill also doesn't really target anything—it really just draws a rectangle where you tell it to. It doesn't know or care what you're trying to draw. You could use it to draw a progress bar, or a box, or the player (as in this case).

It looks like redrawing the background tiles behind the player addresses a bug where the dirty rects behind the fill rect are not updated properly. This is what it looks like if you comment out those calls:

Yea, that's what I thought might happen.

So on every frame, you would need to tell pulp to read and redraw a tile, then fill over top of it right?

You shouldn’t need to, those artifacts left over from the previous frame are definitely a runtime bug (which I’m looking into right now :playdate:).

Oh I see. Does that bug show up on the hardware also?

So to be clear, on draw, the code is using fill to make the player character. And on the next frame, it basically clears the screen and fills again?

BTW, Thanks for talking to me about this stuff.

1 Like

Yup, that will appear on the hardware as well since it’s a runtime bug. When you use fill to draw a rectangle, it (is supposed to anyway :sweat_smile:) mark all the cells that you are drawing on top of as dirty so on the next frame they can be redrawn (this way we’re not redrawing the entire screen every frame). Because it’s not working as intended Yousurname is redrawing the dirtied tiles manually.

1 Like

You can see the problem clearly here (the red overlays are tiles that were identified as dirtied on the previous frame):

And this is what it should look like:

I made the mistake of assuming that the width of the rect divided by the tileWidth was the number of dirty tiles but that can’t be assumed to be true when they are the same width.

Except even this is wrong, it’s too greedy. :playdate_crying: Even when perfectly aligned to a tile it still dirties the next column and row.

Here we go:


When the player is perfectly aligned with the tile grid (like when they’re against the left side of the screen) they only dirty a single tile as expected. We got there! :playdate_cry_laugh:


And that fix is now live. If you add n = name tx,ty to the collect_coin handler you can delete the calls to draw_tiles. (Note that you’ll need to download a new pdx in order to pick up the runtime fix for this.)


Thanks for your work @shaun!

Incredible. Thanks for sharing the source code!