Fluffy's Prince of Persia

Threads about other remakes and ports.
Post Reply
FluffyQuack
Sheikh
Sheikh
Posts: 37
Joined: June 6th, 2004, 7:05 pm

Fluffy's Prince of Persia

Post by FluffyQuack »

For the heck of it, I started a project a little over a week ago to write my own engine that runs Prince of Persia.

This is what progress looks like right now:


I've got level rendering mostly done (it took a while to get the "decal textures" rendering correctly on the walls), and I've started working on player movement.

I don't know how far I'll get with the project. If I get to the point where I've got the gameplay 100% replicated, I might try to tackle stuff like adding multiplayer or try to add support for Prince of Persia 2 (which will probably have some big challenges as there's no source code I can reference to figure out how exactly how stuff is handled in that game).

I'm trying to make the gameplay as close as possible to the original POP, but when given the choice I prefer to design more straightforward structures rather than replicating what POP does. For instance, internally, my coordinate system is pretty straightforward: a position of 1 represents 1 pixel in the graphical output, instead of what POP1 does on DOS where it still uses the coordinate system designed for the Apple II original and then converts it to the DOS 320x200 resolution at render time. Those changes will probably result in very small changes to the gameplay.

I've decided to try to move some stuff into scripts to reduce the amount of hardcoded arrays in the code with gameplay information. For instance, I've got all animations defined as external scripts. Here's what the turn animation looks like:

Code: Select all

[POP1_Kid_Turn]
Action Turn
Flip
MoveX 6; ShowFrame 45; Wait
MoveX 1; ShowFrame 46; Wait
MoveX 2; ShowFrame 47; Wait
MoveX -1; ShowFrame 48; Wait
MoveX 1; ShowFrame 49; Wait
MoveX -2; ShowFrame 50; Wait
ShowFrame 51; Wait
ShowFrame 52; Wait
Anim POP1_Kid_Stand
It's still a work-in-progress. For instance, I'd rather not refer to animation frames with magic numbers, so I want to implement a system where you can refer to animation frames using names.
FluffyQuack
Sheikh
Sheikh
Posts: 37
Joined: June 6th, 2004, 7:05 pm

Re: Fluffy's Prince of Persia

Post by FluffyQuack »

I kind of put this project on the backburner the last few months, but I went back to it a few weeks ago.

First of all, for the heck of it, here are some early screenshots I made in September.

This was at the very start of the project where I've got level data loaded and I'm rendering the general layout of level 2 in POP1, but without any actual graphical assets.
Screenshot0009.png
Screenshot0009.png (3.61 KiB) Viewed 254 times

First room in POP1 with many graphical assets implemented:
Screenshot0015.png

First room again, this time with more graphical assets implemented, including correct rendering of walls:
Screenshot0022.png

Zoomed-out view of level 1:
Screenshot0024.png

And now for stuff I've done recently, during the last 1-2 weeks. I added a toggle which uses render-to-texture so I can apply aspect correction to final render:
Screenshot0039.png

I added loading of POP2 level data. I haven't implemented graphics from POP2 yet, but here's the general layout of level 3 in POP2 rendered using POP1's dungeon tileset:
Screenshot0041.png

I started implementing the POP1 palace tileset. The wall rendering was a little bit of a doozy to implement (I kept looking for the main wall texture, but then I looked into SDL-PoP code and realized it's simply rendering solid colours). Here's an early version with wrong palette applied:
Screenshot0042.png

And here it is now after loading the correct palette and figuring out how SDL-PoP handles colours for the walls (I also added code for rendering the bottom 3 pixels of walls):
Screenshot0045.png
FluffyQuack
Sheikh
Sheikh
Posts: 37
Joined: June 6th, 2004, 7:05 pm

Re: Fluffy's Prince of Persia

Post by FluffyQuack »

I did some work on optimizing my render code. Not really necessary to do as I can easily hit 12fps while rendering the same amount of tiles as POP1, but I don't like having overly inefficient code. The primary bottlenecks I had were constant binding to different textures and some unnecessary overhead when drawing tiles.

Instead of loading each graphical asset as its own texture, I started working on a system that compiles all assets into one "mega" texture atlas. This is the texture atlas the code generates right now:
POP-MegaTextureAtlas.png

Some things to note:
  • I don't need to, but I'm loading both POP1 and POP2 assets at the same time. The stuff you see in the atlas is the stuff I've added to my loading lists so far. There's still a lot missing, but I think I can actually easily fit all the graphics from POP1 and POP2 into one texture.
  • Some of POP2 assets look like gibberish because I'm loading them with the wrong palette.
  • If you zoom in, you can see pixel doubling along the edges of sub-textures. This is padding so that texture sampling won't ever grab from neighbouring sub-textures. I had that happen when I rendered graphics at a lower scale than 100%.

One of the first attempts of rendering with the texture atlas. I kind of forgot about OpenGL's texture coordinate system where 0,0 is bottomleft of a texture rather than topleft, whoopsie:
2022-12-11 14-55-28-535.png

After getting everything implemented correctly, here's a stress test at 1920x1080 rendering everything at 50% scale. With my old code, this would give me 43 FPS. With the texture atlas and other improvements to the rendering code, I now get around 700 FPS in the same scene:
2022-12-11 18-10-31-220.png

By the way, this is what rendering looks like if I don't add padding between sub-textures in the texture atlas. You can see random artifacting all over the place:
2022-12-11 15-11-50-447.png
FluffyQuack
Sheikh
Sheikh
Posts: 37
Joined: June 6th, 2004, 7:05 pm

Re: Fluffy's Prince of Persia

Post by FluffyQuack »

As one method for understanding all of the collision systems in POP, I'm modifying SDL-PoP to output debug graphics visualizing various collision data. This is the mess I'm generating right now:
prince-fluffymod 2022-12-27 23-05-31-909.png
  • White rectangle around the player is the collision box used for collision checks against walls. It only has 2 horizontal coordinates (char_x_left_coll and char_x_right_coll). It looks like the horizontal coordinates are generated from size of the image data, though certain animations frames are flagged as "thin" which means they become vastly thinner for a short amount of time (this is defined for the standing turning animation and I suspect it's done to prevent wall collision mid-turn).
  • Purple line below the player indicates the current tile the player belongs to. I think I got the horizontal length and position of it correct, so if the player steps outside of that line, the player will then belong to a different tile.
  • The small purple vertical line attached to the horizontal line represents where the prince currently has his feet placed (attained from dx_weight()). This is used to determine what tile the prince belongs to.
  • The yellow vertical lines correspond to the horizontal placement of wall collision, which is the middle point of a tile.
  • The debug text top-right show a few player coordinates. KidY is the vertical position and KidX is the horizontal position (using the dx_weight() value). Note that the X positon uses a very different coordinate system than the screen space coordinate system.
FluffyQuack
Sheikh
Sheikh
Posts: 37
Joined: June 6th, 2004, 7:05 pm

Re: Fluffy's Prince of Persia

Post by FluffyQuack »

Progress towards rendering a POP2 level:
2023-01-10 21-51-57-157.png
FluffyQuack
Sheikh
Sheikh
Posts: 37
Joined: June 6th, 2004, 7:05 pm

Re: Fluffy's Prince of Persia

Post by FluffyQuack »

Early progress towards rendering lvl6 in POP2 (the first Ruins level):
2023-01-18 14-58-54-075.png
I'm focusing on figuring out what looks like the most fiddly part with rendering each tileset, which so far is learning what the spec variables mean. The second spec byte in particular is used to define a lot of variants for graphical assets and you're supposed to do bunch of bit shifts and use bitmasks to get a real value from it.

For Caverns tileset:
  • First 3 bits are for defining what type of "bottom" variant to render for foreground walls. 7 different variants.
  • Bit shift by 3 to the right, and you get the value for the type of stalactite hanging from a ceiling or tile. Each one has a unique render offset and there are 7 different ones.
For Ruins tileset:
  • First 4 bits are for defining what type of "decal" to draw on a foreground wall or floor tile. I'm not sure how many unique ones there are. All of these have unique render offsets, and some of them need to rendered in a specific order. Most are wall decals (render last), but some are supposed to be rendered in the middle of a tile.
  • Bit shift by 4 to the right, and you get the value for the type of graffiti to draw on a background wall. Each one has a unique render offset and there are 3 different ones.
FluffyQuack
Sheikh
Sheikh
Posts: 37
Joined: June 6th, 2004, 7:05 pm

Re: Fluffy's Prince of Persia

Post by FluffyQuack »

Early progress for rendering POP2 Temple tileset:
2023-01-23 20-42-06-902.png
Took me a bit of time to figure out how exactly I'm supposed to be rendering the foreground wall tiles.

It's three textures needed:
  • Render shape #3524 as primary tile art
  • If left tile is also a wall, then also render 3561
  • If below tile is also a wall, then also render 3563 (3562 is a similar variant, but I'm not sure where that is used)
Post Reply