Pulp Game Jam dev log: Scaredy Heart

scaredy-heart

No idea where where this is going but I spent the first few hours of the jam working on the player character’s facings and animations. It started out as a cat but turned into a bunny as I shifted pixels around aimlessly. I used my patented (no, really! (not really)) Pulp bob to give it some life without having to worry about actual animation. To do that I just duplicate the first frame, hold Command and drag the entire tile down one pixel. Then I erase the top row (which is the bottom row wrapped around from the drag) and clean up the new bottom row.

I couldn’t fit the ears into an 8x8 tile so I’m using the draw function in the player’s draw event handler to draw the ear tile by name, one tile above the player. (Also making a mental note to add an invisible solid tile below any wall the player can approach from below to prevent the ears from hiding that wall.) Since I’m doing some custom drawing anyway and I was having trouble making an intelligible side view within an 8x8 tile I decided to use the same trick for the bunny’s rump (no need for the spacer trick for this because pressing left or right will always result in the rump being drawn over the unoccupied tile you just vacated, I just need to avoid one tile-wide vertical paths). I’ve stared drawing the player graphics as Sprite tiles so I can place them in a temporary “work” room to see how they connect. Then I need to manage some state to make sure that the correct tiles are drawn depending on facing. So my player PulpScript looks like this now:

on load do
	player_facing = "down"
end

on update do
	if event.dx>0 then
		player_facing = "right"
	elseif event.dx<0 then
		player_facing = "left"
	end
	
	if event.dy>0 then
		player_facing = "down"
	elseif event.dy<0 then
		player_facing = "up"
	end
end

on draw do
	swap "player {player_facing}"
	x = event.px
	y = event.py
	y -= 1
	draw "player {player_facing} ears" at x,y
	
	y += 1
	if player_facing=="left" then
		x += 1
		draw "player {player_facing} rump" at x,y
	elseif player_facing=="right" then
		x -= 1
		draw "player {player_facing} rump" at x,y
	end
end
9 Likes

I guess there’s a lot of animals up here? :thinking:

animal-kingdom

This was about 3 hours in…

4 Likes

Last night while noodling with music ideas for the story and gameplay started to solidify. This is where it stood after about 6 hours (imagine that elbow path is dressed as a beanstalk with clumps of leaves here and there):

One neat trick I did here for the dialog was to use {embed:<tile name>} to create italic text to use sparingly (I only drew the letters y,o,u,h,e, and r) and icons to indicate the speaker of the text. I also just quickly scribbled out some notes in the Sound editor and played them with sound <sound name> before the say call for a unique Zelda-like speaking voice.

Anyway, I’ve always wanted to make a small-scale RPG with Pulp. I think this is it. The player awakes in the clouds. Or is it heaven? The inhabitants are all too scared to come out. Wherever you are, it’s no place for a bunny so you start your trek down the winding (forbidden?) beanstalk. There you get into random encounters with broken hearted (or caged hearts that need breaking out?). You’ll have to experiment with different abilities like hug, listen, talk, gift and more (which you’ll learn as you level up) to figure out how to help each unique broken hearted. On the way down you’ll find more cloud platforms with more terrified inhabitants that may offer you a place to rest, sell some necessities, and offer up a few hints and story clues.

4 Likes

“Battle” HUD layout
scaredy-hearts

2 Likes

Yesterday was spent working out how to have an infinitely winding path using only four rooms while also supporting connecting to manually authored rooms. (I’m putting off doing any more graphics until I get the “battle" system working so the “maze” is super boring atm.)

winding-9

What I ended up doing was picking an arbitrary square to use as the bounds of every room:

exit_north_y = 2
exit_south_y = 12
exit_east_x = 17
exit_west_x = 7

Then each room declares its exits in an exits handler:

on exits do
	exit_north = "maze top right"
	exit_south = 0
	exit_east = 0
	exit_west = "maze bottom left"
end

Each room has a couple of tiles where a treasure can appear so to differentiate being in a room on the first pass or the umpteenth we track how deep we’ve gone by incrementing and decrementing a depth counter whenever we take an exit:

on exit_west do
	maze_depth -= 1
end
on exit_north do
	maze_depth += 1
end

Two rooms are special, one of their exits always connects to either the previous or next “town” so we store that information when we enter a “maze” eg.:

on enter_maze_2 do
	call "enter_maze"
	maze_level = 2
	town_prev_name = "town 2 north"
	town_next_name = "town 3 south"
	town_next_depth = 7
end

These rooms set a different exit depending on their depth, eg.:

on exits do
	if maze_depth==0 then
		exit_north = town_prev_name
	else
		exit_north = "maze top left"
	end
	exit_south = 0
	exit_east = "maze bottom right"
	exit_west = 0
end

Finally, whenever the player bumps into one of the invisible walls that marks the bounds of a room this is called:

on bump do
	tell event.room to
		call "exits"
	end
	
	if event.dy!=0 then
		if event.py==exit_north_y then
			if exit_north!=0 then
				tell event.room to
					call "exit_north"
				end
				goto event.px,exit_south_y in exit_north
			end
		elseif event.py==exit_south_y then
			if exit_south!=0 then
				tell event.room to
					call "exit_south"
				end
				goto event.px,exit_north_y in exit_south
			end
		end
	elseif event.dx!=0 then
		if event.px==exit_west_x then
			if exit_west!=0 then
				tell event.room to
					call "exit_west"
				end
				goto exit_east_x,event.py in exit_west
			end
		elseif event.px==exit_east_x then
			if exit_east!=0 then
				tell event.room to
					call "exit_east"
				end
				goto exit_west_x,event.py in exit_east
			end
		end
	end
end

First we call the current room’s exits handler to populate the exit data, check the player’s current position and heading and try to match it up with one of the room’s exits, and then if we find a match, send the player off on their way.

I think I’m about 20 hours in now? There’s no way I’m hitting the full 72 hours before the end of the jam :playdate_crying:

2 Likes

@shaun I wonder if you are able to show a little more detail on your sprites, the lion looks great and I would love to see how you get such nice details, I assume you are using the tile in Pulp? Thanks

Thanks Adam. Sure! All of my sprites have been created in Pulp’s tile editor (except for the larger battle sprites which I created in Photoshop and imported). Most of these sprites use 2-3 tiles. Here’s a peek with the grid overlay on:

1 Like

how do you control a character over multiple tiles. ATM my plan is to use the Pulp Tile editor and take the sprites into the SDK, so I learn a bit of both. Plus I am not sure yet but I may need to do more than Pulp will let me, and I kinda want to learn both.

Is there Pulp documentation yet ? apologies if I missed it

Apologies you discuss this a little above . I think

There are links to the current editor and PulpScript documentation in the bottom right of the Pulp editor (below the theme selector).

As for controlling a multi-tile character, with the player it’s easy, you just draw the extra tiles in the player’s draw event handler (as shown above). Multi-tile sprites are a little tricker. We never imagined sprites would move on their own so doing that with a multi-tile sprite is an exercise left to the reader but simple behaviors are pretty easy to handle on a stationary sprite.

First, pick which tile you want to be your canonical sprite tile (I usually chose the one with the head or face). Add behavior to that one. This can be as simple as adding text in the dialogue box or more advanced behaviors with PulpScript. Then for each additional tile that make up this sprite, switch their behavior to PulpScript and implement an any event handler and call mimic, like so:

on any do
    mimic "<name of the canonical sprite tile>" 
end

Now when the player interacts with any of the non-canonical tiles they will behave the same as if the player had interacted with the canonical one.

2 Likes

The kids are insisting on coloring so I took this opportunity to sketch some ideas for “foes”. These will probably be the last two bosses. (I’ll make them more menacing in post :sweat_smile:) I’m trying to integrate the heart-shape into all of the designs.

4 Likes

Still not quite as menacing as I’d like but getting there (ignore the dumb forehead heart, haven’t stretched my drawing muscles in ages):

Hello Shaun!

Im cheking all the games posted on the first game Jam.

Did you share the pdx file somewhere?

Nice stuff!

Nope, I never finished, too busy fixing bugs and implementing feature requests :playdate_cry_laugh:

2 Likes

I see.

Looking forward to whatever you work on next then :muscle:

I'm working on something modestly similar here - i create a random dungeon with paths and chambers in a single room, with an exit in the middle of one of the chambers.

did you manually drop exit tiles in your maps, or is the exit logic (which actually jumps you to another room) in the code somewhere?

i'm struggling as I want my exit to be completely dynamic - i don't know where it will be until i generate a randomized room. i've managed this fine by just re-randomizing the room when my player steps on my "exit", but the store/restore logic doesn't seem to trigger until i actually switch rooms, and i don't see a way to define an exit entirely at runtime.

it looks like you might have done this in Scaredy Heart - if so, please tell me how!

Thanks
-bit