Dialog Portraits in Pulp!


Since we’ve had some questions about the art of Terratopia, and it might be helpful to the pulp community, let’s talk about how we do our portraits!


First of all, for those of you who don’t already know, you can import a full image into pulp: Just name it “{image_name}-table-8-8”.  That tells pulp to attempt to parse it as a series of 8px by 8px tiles, which it names “{image_name} #”.  Most of our larger backgrounds were created in Aseprite and imported into pulp in this way.  Once it’s in pulp, it’s easy enough to tile a room with the background.

But portraits are a little bit harder, because we can’t just set up a room with them ahead of time: we need them to appear and disappear, draw on top of the room without changing what’s underneath it, and, of course, we need to have access to lots of different portraits.

Before we dig into portraits, two very helpful pulp tricks:

First, I use tiles to sort my code.  Even though all of my portrait drawing needs to be done through the draw function on the player tile (more on that later), I have a sprite tile called “portraits” - which exists only to be a place where all code related to portraits lives.  It’s not mandatory, but it can be a lifesaver for keeping your code straight.

Second, Pulp uses string interpolation (hat tip to Orkn for pointing that out to me when I was starting out): Any time you would use a text string, you can insert the value of a variable in memory into that string by putting the name of the variable in {curly brackets}.

Eg: say “You take {damage_taken} damage!”, swap “{name_of_tile_to_swap_to}”, loop “{next_music_track}”, etc.

Because dialog portraits appear and disappear so often, we can’t use the “swap” function in pulp.  Swap changes the tiles of a room, so in order to use it to draw portraits, we would need to remember what tiles are there currently, swap them all out, then swap back when we’re done.  It’s possible, but would be a bug prone coding nightmare.  Instead, we want to use the “draw” event on the player tile.  This event normally exists for drawing a player sprite (which appears on top of room tiles without changing/deleting the room tile underneath), but we can piggyback on this for portraits (or any kind of UI).

Before anything else, let’s import our portraits: Terratopia’s dialog portraits are 6x6 (48x48px), but nothing here is size specific.


All our portrait tiles are named with the following convention: {whose_portrait}_portrait_{x}_{y}.  We use 0,0 in the top left to match the pulp coordinate convention, but it can be anything you want as long as it's consistent.


These are “weyland_portrait_0_0” and so on.

Finally, one last thing to tackle before we get the actual drawing of the portraits:  We use standardized variables for the location of our text boxes.  Pulp has the very helpful built in “say” function, and to make better use of that, we put a handful of variables in our top level “game” script: “narration_box_x”, “narration_box_y”, “dialog_box_x”, “ask_menu_y”, and so on.  This ensures that the say box always draws offset to allow space for the portrait.

Okay, we’re finally ready to deal with drawing the portraits!

The say function pauses execution until the box is dismissed, which means we probably don’t want to use an event to start/stop drawing the portrait, at least not directly.  Instead, we put this inside the player’s draw event:

  • if whose_portrait!=0 then
    • tell "portraits" to
    • call "draw_portrait" (Get to this in a moment)

Then when we want to use a dialog portrait:

  • whose_portrait = "cedric"
    • say "Cedric: dialog" then
    • whose_portrait = 0

The very next frame after the value of whose_portrait is set, the player’s draw event notices, and raises the “draw_portrait” event every frame until the value of whose_portrait is set back to 0, which happens the first frame after the say box is dismissed.

Inside the “draw_portrait” event, you use the draw function with string interpolation.

You can do it via brute force:

  • draw "{whose_portrait}_portrait_0_0" at portrait_column_0,portrait_row_0
  • draw "{whose_portrait}_portrait_1_0" at portrait_column_1,portrait_row_0…

Or with loops:

  • current_draw_x = starting_portrait_x (the column you want to start drawing at)
  • current_draw_y = starting_portrait_y
  • portrait_x_cursor = 0
  • while current_draw_x<=portrait_width
    • portrait_y_cursor = 0
    • while current_draw_y<=portrait_height
      • Draw “{whose_portrait}_{portrait_x_cursor}_{portrait_y_cursor}” at {current_draw_x},{current_draw_y}

If you wanted to change the location of the portrait, you can add a conditional before calls of the draw function:

  • if {portrait_location}==1 then
    • starting_portrait_x = location_1_x
    • starting_portrait_y = location_1_y
  • elseif {portrait_location}==2 then
    • starting_portrait_x = location_2_x
    • starting_portrait_y = location_2_y

And so on…

Terratopia does something like this to change the location of the portrait based on whether or not the UI is being drawn or not.

Finally, a word of warning: as soon as you use string interpolation for tile names, you open yourself up to potential crashes: normally Pulp won’t compile if you script to draw a tile that doesn’t exist, but as soon as you use a variable, pulp trusts you that that tile is going to exist, and if it doesn’t (because you misspelled something, or any number of other issues) the game crashes.

To help avoid this, we keep the names of all of the portraits in comments at the top of the “portraits” tile. This is doubly important when you have more than one portrait for the same character - “Did I name the tiles {name}_sad_{x}_{y}?  Or {name}_unhappy_{x}_{y}?”

This also works with back and forth dialog as well:

  • whose_portrait = “speaker_a”
  • say “a: dialog” then 
    • whose_portrait = “speaker_b”
    • say “b: more dialog” then

And that’s how we manage and draw our dialog portraits in Terratopia without a bunch of messy hard coded tile swaps.  Hopefully this gives you a helpful starting point for implementing dynamic portraits in your own Pulp projects!

Leave a comment

Log in with itch.io to leave a comment.