Prince of Persia on Phaser 3

Yekaterina Railian
The Rollins Scopes School
10 min readJul 20, 2020

Prince of Persia (1989) — A 2.5D platform loosely based on an “Arabian Nights” theme. You play as a Prince who must escape from an elaborate dungeon to save the Princess from the evil Vizier — Jaffar.

Level 7 play-through

TL;DR

This is a link to the Prince of Arabia deploy.

PS. Please note that this is still a project under development, even though the course I’ve been making it for is done.

A little bit of history…

Prince of Persia is a platform game originally created by Jordan Mechner and published by Broderbund in 1989 for the Apple II. Its success was due, in part, to the remarkable fluidity of animation achieved in the characters, through a technique called rotoscoping. Because of its success, the game was later published in a wide range of platforms.

Prince battling an evil guard

In 2012, over 20 years after the first version of the game was published, Jordan Mechner released the source code. The story is curious: Jordan backed up onto floppy disks the original source code of the game and left forgotten them. 22 years later, Jordan’s father sent him a box containing the floppies with the original source code. Curious story, for a fantastic game…

The Game

It is a time of darkness. While the Sultan is off fighting a foreign war, his Grand Vizier Jaffar has seized the reins of power. Throughout the land, people groan under the yoke of tyranny, and dream of better days.

You are the only obstacle between Jaffar and the throne. An adventurer from a foreign land, innocent of palace intrigues, you have won the heart of the Sultan’s lovely young daughter. And in doing so, you have unwillingly made a powerful enemy.

On Jaffar’s orders, you are stripped of your sword and possessions, and thrown into the Sultan’s dungeons. As for the Princess, Jaffar gives her a
choice, and an hour to decide: Marry him — or die.

Locked in her room high in the palace tower, the Princess rests all her hopes
on you. For when the last sands drain from the hourglass, her choice can bring only a throne for the Grand Vizier… a new reign of terror for his long-suffering subjects… and death for the brave youth who might have been… the Prince of Persia

The Project

I am finishing my semester in RS School and a a final project I chose to try and recreate the original Prince of Persia using contemporary frameworks. It goes without saying that I landed on Phaser 3. For my humble purposes it served just right. After a couple night hours of searching I also stumbled upon the official game specifications and file formats. It’s a lengthy dry document containing tile drawing algorithms, room mappings, event handling and so on. I was positively amused to discover how much RAM used to matter and how much did it take to reduce the amount of bytes it consumed.

Now, Phaser 3 came out quite recently and the documentation is perilously vague. Yet I believe I’ve managed to navigate those dark waters with if not grace then at least one last hit-point intact. All and all I had less than 2 months to complete this project, which is my way of apologizing for not actually having done it to immaculate completion. I had to cut corners with cut-scenes, ignore those pesky collision bugs and even completely write off some features all together. I solemnly swear that I will finish birthing Prince of Persia: The ES6 Version but for now, it’s as good as it gets.

Project Organization

Initially I tried to organize myself in Trello, create those fancy cards and so on, but since this was a solo-project, soon it really seemed like wasted time. Besides, I’m truly a pen-and-paper kind of gal. So after roughly marking the deadlines vs. features in my notebook I took to coding.

My initial idea was to make this a cross-platform game using Cordova but after at least a week of tinkering I realized I simply don’t have the time. For now Prince of Arabia (original, huh?) is browser-only and since it runs on WebGL2.0, also Chrome-preferably.

Entities

With the help of aforementioned specification document I laid out a couple of charts for how I want the game to flow. First off we have the action commands. These bad boys control every movement, every key press.

Then, these commands are generated and then bidden into this.commands array:

registerCommand(value, func) {
this.commands[value] = func.bind(this);
}
registerCommands() {
this.registerCommand(0xFF, this.CMD_GOTO);
this.registerCommand(0xFE, this.CMD_FLIP);
this.registerCommand(0xFB, this.CMD_CHAR_X);
this.registerCommand(0xFA, this.CMD_CHAR_Y);
this.registerCommand(0xF2, this.CMD_TAP);
this.registerCommand(0x00, this.CMD_FRAME);
}

A hexadecimal system is used to identify the commands, this is modeled from the official documentation. Then these functions are written down and processed:

processCommand() {
this.processing = true;
if (this.sequencePointer > this.animation.sequence[this.action].length) {
this.sequencePointer = 0;}
while (this.processing) {
const data = this.animation.sequence[this.action[this.sequencePointer];
this.commands[data.cmd](data);
this.sequencePointer += 1;
}}

In Prince of Persia there are a total of 5 active entities: Prince, Jaffar, Guards, Shadow and Skeleton. I say active because during the cut-scenes we also see Princess and Mouse but they aren’t animated or controlled.

Entity organization

Every one of these entities is an Actor and a Fighter, Prince is an instance of Kid and Guards, Shadow and Jaffar are Enemy entities.

All of these characters are animated through a sequence of action commands held in JSON’s. These are original to the actual game and I pulled them out through Apoplexy 3.0, a custom level builder app for DOS Emulator. This below is an example of “strike” animation sequence for our Prince.

"strike": [
{ "cmd": 249, "p1": 1 },
{ "cmd": 0, "p1": 151 },
{ "cmd": 0, "p1": 152 },
{ "cmd": 0, "p1": 153 },
{ "cmd": 0, "p1": 154 },
{ "cmd": 0, "p1": 155 },
{ "cmd": 0, "p1": 156 },
{ "cmd": 0, "p1": 157 },
{ "cmd": 255, "p1": "engarde", "p2": 9 }
],

All of the Prince’s states can be summarized in this chart. Granted, it’s not the best quality and I’ll edit-in a link to a flowchart once I digitize it, but this will give you an approximate idea of how entangled the movement states became by the end of development.

Prince / Shadow movement state chart

These states are translated into the action manager which pulls up the respective frames from the respective Actor’s spritesheet.

Prince sprite sheet

Which in turn drags this snowball into the switch statement which later corrects and dictates the behavior:

Another fascinating entity is Guard. They are not the same and even the same level can have up to 4 different guards with different stats and abilities. I found a table that was used to create the original game and based my Enemy entity on that.

We have strike probability different colors, attack strength and even range. Goes without saying it was mad fun testing them in action. I truly never thought how much detail goes into game development. For an OCD’er like me this is heaven.

Levels

Each level is composed of a maximum of 24 rooms. Each room is constructed with 30 tiles (10 tiles for each of the three stages). Each tile is identified with a code representing its type: floor, wall, door, torch… In addition, each tile has a modifier that lets you define certain aspects as the object (eg, walls decoration or activation of doors when you step over plates). Each level also contains other information that allows linking the room, defines guard’s position and strength, prince’s initial position, and so on…

I have a LevelBuilder class that reads the JSON’s also pulled from Apoplexy and creates tiles with that retro overlap to create the illusion of depth, the pseudo-2.5D effect we are all so nostalgic about. Due to the unique perspective of the rooms, these should be drawn from left to right and bottom to top.

Dungeon spritesheet

For the dungeon levels, Jordan implemented an algorithm that allowed, from a reduced tile-set, generating different types of walls giving a sense of variety to the rooms. Basically the algorithm constructs the walls from a basic block and then applies a design modifier according to the position of the tile on the screen. In my case, for simplicity, I have not implemented this algorithm, but I’ve just created a sprite-sheet with all possible wall designs (not an issue now-a-days computers can’t handle).

Tile classes organization

Levels have Interactive tiles, and for each one we have a special class inherited from Base tile. These classes depict specific behavior and animations, emit commands to listeners and interact with players stats.

LevelBuilder collects all the tile instances and Level builder the layer into the Game Scene.

One of the most fun tiles for sure was Potion. It’s a tricky little fella’ that required it;s own flowchart in my notebook. Prince will find potions that Add Life, Remove Live, Restore Live and even flip the game screen…

Truth be told, I had no idea about these minute details when I picked this game to clone.

Game

The game scene itself collects all these beauties together and updates them through a custom update loop. This was a result of a major technical difficulty I faced during the production of this game but on this later.

In Phaser 3, like in many game development engines and frameworks, scenes are what you end up seeing and perceiving as the game screen. It’s populated by Game Objects and, depending on the physics, enacts collisions and other desired behaviors between them. My game scene is this, but also not this.

Since I had to reenact the fake-3D look and feel of the game, it meant I had to sacrifice the ability to create physics-enabled bodies as they would overlap each other in a unoriginal manner. The game scene very precisely aligns the background layer tiles with the Prince sprite and foreground masks to emulate the skewed perspective. As a result, I simulate collisions depending on the X and Y axis of tile blocks and respective player position.

All this eclectic preamble led to explain why on Earth I had to think of a custom update loop. It’s artlessly simple- it was too fast. Prince hopped around like a high grasshopper and it threw off my process for a week to find an adequate solution. Slowing down the FPS did squat so I ended up creating a timer that would update the frames once every 60 ms. Here’s the solution. Does’t look like a week’s worth of headache, does it?

setUpTimer() {
this.gameUpdateTimer = this.time.addEvent({
delay: 60,
callback: this.updateGame,
callbackScope: this,
loop: true
});

Technical Difficulties

Like I mention already, the most challenging issues to solve were:

  1. This may seem odd, but the cuts-scenes are a pain in the rear. I ended up uploading a video of original ones and simply playing them in-between specific levels. The idea was completely different. They were a whole different scene from Game Scene, operated by sequence of action sequences aligned in similar manner as levels are. Orchestrated by a couple of JSON’s I head ready to go. I took this idea from Scaling and aligning was taking too much of precious development time so I had to think on my feel and cut corners.
  2. Game Object collision. It’s still not perfect, up to today I still can’t catch one pesky little bug that emerges from bumping the player into the specific tile element during a specific action. This is my Moby Dick, but hopefully I’ll find a way to resolve this.
the glorious bug. to recreate it, lean into the right wall on jump
  1. The aligning of the camera to player to tiles… its an incredibly precise bond that if miscalculated will throw off your whole behavior patterns. I am at awe and in deep respect to the original creators of the game since it must have been miles harder than it was for me with modern JS and a framework to bring it to life.

There are still a number of things I didn’t get to finish in time:

  1. There’s barely any audio in this game. I plan on adding all of the original special effects with time.
  2. Shadow entity appears only on Level 4 stealing your Life Extension potion right before your nose. It’s supposed to appear 3 more times according to the original.
  3. The last level is a New-Rules level. You trigger tiles according to your position and not by pressing on specific tiles. It requires a whole new batch of logic, down to the next level signal emitters that here are triggered by killing a specific guard.
  4. I wanted to add a small personal touch and create a Game Menu where you could view the controls beforehand and adjust settings however you saw fit, the buttons were added but that’s about it.

Gameplay Example

Conclusion

Overall this project was a brilliant learning exercise and it reminded me why I chose to pursue web-development in the first place. It was extremely challenging but immensely rewarding in the end.

During the course of this project I learned that careful planning is absolutely vital to the success of a project. I got to understand the basics of the whole game production process on a small scale. And as exhausting as this race was, I’d do it again in a heartbeat.

--

--