Inspecting Snakes in Pulp
Tags: gamedev, beginners, playdate, pulp
Published: 2023-01-15 01:02:26

In the last article I downloaded 21 games.

Two of those games made their `JSON` files available for download, too.

That means:
- Their game was built in Pulp
- I can import the file to inspect all of their game assets

## Inspecting Snakes
I'll study each view carefully.

### Font
![Custom font](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1jthp1qy15rwyrf6xprp.png)

I can't tell whether this set of ligatures is custom-made for the game or something the developer downloaded.

But it sure feels appropriate for the material.

Very cool, and shows that even with an 8x8 square pixel region, a lot of creativity is possible.

### Script
![Custom scripts](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r9xrg984oop18iw7glhb.png)

It looks like there are eight tile scripts in addition to the required game script.

Each of the exit scripts are identical. Interesting.

```
on openExit do
  if goldLeft==0 then
    swap "white"
    sound "opened"
  end
end
```

- `openExit` is some custom event
- Then a condition
- And two actions
- I'm not sure what `swap` does. Maybe changes a tile?
- `sound` likely plays that sound

The `darkness` script is similar:
```
on lightHallway do
  if goldLeft==0 then
    swap "white"
  end
end
```

The `gold bar` script has two event listeners:
```
on checkForGold do
  // figure this out
  goldLeft = 1
end

on collect do
  sound "beep"
  tell event.px,event.py to
    swap "snake left"
  end
end
```

- A value assignment to a variable
- Another sound played
- Hmm, I wonder what `tell` does
- If its arguments are X,Y positions, then maybe it is a command to once again change a tile object?

The `tongue 2` script is a series of text prompts.

Since they end with `playEnding = 1` I assume this script runs after the boss is defeated.

The `player` script is over 100 lines!

Although, it only includes three event functions:
- `confirm` seems to reset the game state
- `cancel` seems to prompt the player to decide whether to reset the game state or continue
- `update` features all the fun logic

Here I go, line-by-line.

#### on `update` do...
```
playerX = event.tx
playerY = event.ty
	
prevX = event.px
prevY = event.py
```

- Four variables
- Each tracking an `X` or `Y` position
- Two for where the player moved to
- Two for where the player was
- An `event` object with built-in properties
- Not sure what the `t` and `p` stand for. Maybe `target` and `position`?

```
// check for any gold bar items left in room
goldLeft = 0
emit "checkForGold"
```

- Set value of variable to 0
- Run a function that updates the value of that variable
- Attached to each `gold bar` tile
- When run, it sets `goldLeft` to `1`
- Maybe that happens only if `gold bar` is the tile that the player just tried to move to?

```
// swap exit tile if no gold left
emit "openExit"
```

- Run the function `openExit`
- Attached to each `exit` tile
- That checks the value of `goldLeft`
- If it is `0` then the exit tile is swapped for a white tile

```
emit "lightHallway"
```

- Run the function `lightHallway`
- Attached to each `darkness` tile
- That checks the value of `goldLeft`
- If it is `0` then swap that tile for a white one

```
if event.room!="room 18" then
```

- If the current room is not `room 18`, continue

Next are four `if` clauses that are largely similar:
```
if event.dy==-1 then
elseif event.dx==1 then
elseif event.dy==1 then
elseif event.dx==-1 then
```

- `dx` or `dy` are either `1` or `-1`
- Maybe `d` stands for `direction`?
- `N`, `E`, `S`, and `W` are signified as either `-1` or `1` for each axis?

```
// make sure tile gets drawn behind player
prevY++
prevY--
prevX++
prevX--
```

- This increments or decrements the earlier variable's value
- I'm not sure how this is working yet

```
tileNameBelow = name playerX,prevY
```

- This sets a variable's value
- Perhaps to a string that is a combination of two variables' values?

```
swap "player moving"
```

- This changes the tile displayed...I think at the player's current position

```
// draw wire tile behind player when moving up/right/down/left
if tileNameBelow!="gold bar" then
  if tileNameBelow!="obstacle" then
    if tileNameBelow!="lantern left" then
      if tileNameBelow!="lantern right" then
        if tileNameBelow!="tree" then
	  tell playerX,prevY to
	    swap "snake up"
	  tell prevX,playerY to
	    swap "snake right"
	  tell playerX,prevY to
	    swap "snake down"
	  tell prevX,playerY to
	    swap "snake left"
```

- As long as the name of some tile is one of the open tile names
- Replace the contents of the previous tile with a snake pointing in the direction of movement

#### Keywords I learned
- `on ... do`
- `if ... then`
- `elseif ... then`
- `event.`: `tx`, `ty`, `px`, `py`, `dx`, `dy`
- `emit`
- `swap`
- `tell ... to`
- `name`
- `end`
- `ask ... then`
- `option ... then`
- `toss`
- `fin`
- Events: `update`, `cancel`, `confirm`, custom names

The `game` script is nearly 80 lines.

It features seven functions.

#### `on load do`
```
on load do
  // Game config
  config.inputRepeatDelay = 0.2
  config.inputRepeatBetween = 0.15
	
  call "init"
end
```

- Sets some configuration flags
- Calls another function, `init`

#### `on init do`
```
on init do
  restore
  if room!=0 then
    goto playerXSaved,playerYSaved in room
  end
  if hasPlayed==1 then
    log "welcome back!"
  else
    log "nice to meet you."
  end
  hasPlayed = 1
  store "hasPlayed"
  goldLeft = 0
  playEnding = 0
end
```

- Reset the game's variables' values
- If the room is any other than 0, recall the X,Y coordinates of the player's most recently saved position in the current room
- Greet the player accordingly in the console
- Mark the player as greeted
- Initialize the amount of gold collected
- Mark the game as not having ended

#### `on loop do`
```
on loop do
  if playEnding==1 then
    call "playEnding"
  end
end
```

- Routinely check for whether the player has marked the game-ending flag, and call the function if so

#### `on start do`
```
on start do
  loop "djent"
end
```

- Perhaps this triggers the `on loop do`?
- I'm confused by this logic

#### `on enter do`
```
on enter do
  room = event.room
  playerXSaved = event.px
  playerYSaved = event.py
  store "room"
  store "playerXSaved"
  store "playerYSaved"
	
  tell "player" to
    swap "player"
  end
end
```

- I assume this code runs when a different room is entered
- Per the comments: store latest room the player is in so we can easily reset/restore the game
- Per the comments: put player back to original state

#### `on playEnding do`
```
on playEnding do
  randomX = random 6,18
  randomY = random 3,11
  ignore
  tell "player" to
    swap "black"
    goto 0,0 in "room final"
  end
  wait 5 then
    tell randomX,randomY to
      swap "black"
    end
  end
  wait 30 then
    // end game and reset saved room
    toss
    fin "The End"
  end
end
```

- This is the function called in the loop when the flag is marked, indicated by a variable storing the value 1
- Two random values are assigned to variables
- Move the player to the final room in one of the corners?
- Delay the action of switching a tile to black
- Delay the action of ending the game

#### Keywords learned
- `config` API
- `restore`
- `ignore`
- `store`
- `loop`
- `random`
- `goto ... in {room}`
- `wait {amount} then`
- Events: `load`, `init`, `start`, `enter`, `loop`, `finish`

### Room
This game has over 20 rooms.
![Rooms in Snakes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zp3tlon111cdzlpu1883.png)

- All rooms other than `card` are levels in the game
- Each level features a maze to traverse, gold bars to collect, and an exit that unlocks when all gold bars are collected

The room labeled `start` has an added star by its name, possibly marking it as the first room of the game?
![Start room](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g0quyagwglvc059ebdpk.png)

#### Layers

##### World
There are many tiles used to paint the world of Snakes.
![World tiles](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w5mk3tlwsfywn7urlu1g.png)

##### Items
Snakes features a single item: a gold bar.
![Gold bar item](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lopdcrv4rn8l1n0e8o6n.png)

##### Sprites
Snakes features six sprites: an exit in four orientations, darkness, and a snake tongue.
![Sprites](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tninv9jzixumu91wp3qr.png)

I now see that the white tile provided as a default tile by Pulp is called 'white'.

Thus, in each exit tile's script where it says `swap "white"`, that does indeed mean to replace the exit tile with a white tile, thereby enabling movement onto that tile.

The same action happens on the darkness tiles.

The snake tongue only appears in room 18 attached to a giant snake.

It now makes sense that all of the prompts are inside that sprite's `on interact do` function.

##### Player
Snakes features six player tiles: one static player, one moving player, one moving snake in each of the four orientations.

![Player tiles](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kmjd52yqz3poyx8bgpfg.png)

Only the static player tile has the large script as its behavior.

Each of the other tiles seem to be referenced in the script.

Though I'm not sure how a tile named `snake up player` is selected when the script only says `swap 'snake up'`.

By that I mean, how does it find the tile when its name isn't an exact match?

##### Exits
![Room 1's exit](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jwzfuuy62qfa2n2g6mge.png)

Each room's exit connects to another room.

The UI makes it easy to choose which room. And to choose one of three options for an exit:
1. Connect to room
2. Connect room edges (Metroidvania style!)
3. Show ending

### Other revelations
- `djent` is a song
- `playEnding` is `0` until the last level where, after the snake says everything, it becomes `1`, thus triggering the end of the game
- The background of the `Font` view is always the currently selected room

## Before I slither away
- Inspecting this game's code in Pulp has been so enlightening
- I learned a ton of PulpScript syntax
- I learned how pieces fit together in Pulp
- I learned more about layers and their tiles

I'm sure all this knowledge will make reading the PulpScript documentation easier.

Hopefully the next game, Rescues, will reveal even more about building Playdate games!