Pulp how-to: two-tile-tall player

Let's say you feel cramped by the 8 × 8 px size of the player tile in Pulp. Well, you can make a player that consists of two tiles!

Here's the basic way I achieve this in PulpScript:

[player object]:

// This function runs every time the player attemps a move
on update do
	call "calculateMove"
end

on calculateMove do
	playerHeadX = event.px // event.px is where the player moved
	playerHeadY = event.py
	playerHeadY -= 1 // the head is one tile above
end

on draw do
	// the "player" (the feet) gets drawn automatically;
	// here, we manually draw the tile called "player head"
	draw "player head" at playerHeadX,playerHeadY
end

And here's the whole game, with some fancier code:
Player tricks.json.zip (4.4 KB)

In the starting room, the design is such that the head can overlap walls, for a depth effect:

image

In the second room, on the left, the player never overlaps the walls. If you want this behavior, it's achieved by simply placing invisible walls below each "real" wall tile; the head is still drawn over those invisible walls, but the player can't enter them.

This game demoes some other potentially interesting Pulp solutions:

  • I create a "blink" animation cycle on the player's head by repeating the "eyes open" frame 10 times, then having one blink frame.
  • The player faces the direction they're walking. This is done by checking which direction they attempted to move in, then swapping their frame to a flipped version. (Yes, the player can have multiple tiles for different appearances!) I also flip the other player tile—the head—based on a variable that tracks which way the player is facing.
  • I drew walk cycles as well (one for each direction). When the player moves, I switch their frame to those tiles; then after 0.3 s, I switch to the static frame. The effect is—hopefully—that of animating while walking.
  • If the player "bumps" into a wall (tries to move into it but can't) I play a bump sound effect.

Hopefully you find these useful—if you find better ways of achieving these effects, or you have other player tricks, let me know!

39 Likes

Hey, this is lovely.

Thank you!

Over on the discord we've been coming up with a way of making a 2 tall player hide behind walls and came up with this.

on draw do
	// put <tile> in foreground
	tile_name = name event.px,event.py
	
	if tile_name=="FORGROUND TILE" then
		hide
	end
end

In the test room above I changed some of the world tiles so they weren't solid

Then named the 3 tiles like so

on draw do	
	// put <tile> in foreground
	tile_name = name event.px,event.py
	
	if tile_name=="tile 21" then
		hide
	elseif tile_name=="tile 29" then
		hide
	elseif tile_name=="tile 13" then
		hide
	end
end

To get this result
Hide

This work is done by Drew-Lo#8012 & Neven on discord, I'm simply sharing it :grin:

Game attached
Foreground test.zip (4.3 KB)

14 Likes

I want to make sure I understand the logic.

So this code is in the Player script, right?

Then those tiles are no longer "walls" so you can walk on top of them, so the code checks if player is on one of those specific tiles, and if they are it 'hides' the player sprite (but not the separate 'head' sprite) which makes it look like the lower half of the player is behind the wall tiles.

2 Likes

You've got the idea.

I've updated the post with the example game/code.

Hey! I implemented the 2 tile code to my game and it works like a dream. Although when I exit a room and enter another, the player head sticks in the tile above where the exit was in the previous room until I move the player then it snaps back. Any thoughts on how to keep the head "attached" to my player? Thanks!

If you flick your code in here, we could take a look :slight_smile:

on update do
call "calculateMove"
end

on calculateMove do
playerHeadX = event.px
playerHeadY = event.py
playerHeadY -= 1
end

on draw do
draw "player head" at playerHeadX,playerHeadY

label "Health: {health}" at 0,0

end

on load do
maxHealth = 15
health = 10
end

Try adding this to your player’s PulpScript (this assumes “calculateMove” is just responsible for positioning the head):

on enter do
    call "calculateMove"
end
2 Likes

I've been using this for my project and I thought I'd post a few additions I've made to it.

My code allows the player to go partially 'behind' foreground objects, as well as animates their movement a tiny bit.

on enter do
	// the calculateMove function sets the head's position, and we want that to
	// be drawn even before the player moves in a new room; as soon as they enter
	call "calculateMove"
end

on update do
	// we abstracted the movement calculation into the calculateMove function
	// because it needs to be called more than once here
	call "calculateMove"
	
	// change player's facing position
	
	// horizontal movement
	if event.dx<0 then // if the attempted movement on the X axis was negative
		playerDirection = "left" // save this so we can use it
	elseif event.dx>0 then
		// same basic logic as above
		playerDirection = "right"
	end
	
	// Check if the player is behind any foreground objects
	call "checkisbehind"
	
	// Make the character play a walking animation if they aren't behind anything
	call "makewalk"
	
end

on draw do
	// the "player" (the feet) gets drawn automatically;
	// here, we manually draw the tile called "player head"
	draw "player head {playerDirection}" at playerHeadX,playerHeadY
end

on checkisbehind do
	// check if the player is going behind something
	
	// first set a 'isbehind' variable to 0. If we find he is behind something, set it to 1.
	// this is used to stop the code below overwriting what we are doing here.
	
	isbehind = 0
	thetile = name event.px,event.py
	
	if thetile=="outer wall h" then
		swap "outer wall h"
		isbehind = 1
	elseif thetile=="table top left" then
		swap "player {playerDirection} table top left"
		isbehind = 1
	elseif thetile=="table top mid" then
		swap "player {playerDirection} table top mid"
		isbehind = 1
	elseif thetile=="table top right" then
		swap "player {playerDirection} table top right"
		isbehind = 1
	elseif thetile=="tv top left" then
		swap "player {playerDirection} tv top left"
		isbehind = 1
	elseif thetile=="tv top mid" then
		swap "player {playerDirection} tv top mid"
		isbehind = 1
	elseif thetile=="tv top right" then
		swap "player {playerDirection} tv top right"
		isbehind = 1
	elseif thetile=="inner wall top" then
		swap "player {playerDirection} inner wall top"
		isbehind = 1
	elseif thetile=="inner wall top left" then
		swap "player {playerDirection} inner wall top left"
		isbehind = 1
	elseif thetile=="inner wall top right" then
		swap "player {playerDirection} inner wall top right"
		isbehind = 1
	elseif thetile=="umbrella stand top" then
		swap "player {playerDirection} umbrella stand top"
		isbehind = 1
	end
end

on makewalk do
	if isbehind==0 then
		swap "player walk {playerDirection}"
		// then, switch to static image
		keeptile = thetile
		wait 0.1 then
			if keeptile==thetile then
				swap "player {playerDirection}"
			end
		end
	end
end

on calculateMove do
	playerHeadX = event.px // event.px is where the player moved
	playerHeadY = event.py
	playerHeadY -= 1 // the head is one tile above
end

1 Like

Do you mind uploading the json so I can see this in context?

This is neat. I wanted to make my survival horror have a 2 tile tall character.

Hello all! I'm a little late to the party it seems, but I was wondering if anyone could explain how I can get the players head to populate on load. I'm very early in creating, so I don't have anything set up like a save state. Just working on getting the whole character to exist when I hit "Play". Right now he starts of as just a body, but once he gets moving it works as expected. Thanks for any and all help everyone!

Edit - Nevermind, I figured it out! Thank you still to anyone reading lol

my small brain is confused by this. :expressionless: