Stencyl 3.4.0 is now out. Get it now!

Merrak's Isometric Adventures -- Illumination Adventures

merrak

  • *
  • Posts: 1373
Here are rooms 9 and 10 from Temple of Idosra with the lights working  :D





For comparison, here are the rooms from the original game: Room 9 and Room 10

The lights add whole new possibilities. In the original game, you had to find a lamp to progress through certain rooms. A room could either be completely dark or lit. Now I can have a small area of lit tiles near the player, which will let me hide surprises in the dark corners  >:(

I think the cat statues in the walls show up pretty well. Unfortunately, my updated save statue needs some revision. That's a squirrel holding a 5 1/4 inch floppy.

One task I haven't been looking forward to is redoing the sprites in full color. 4-color Marika doesn't fit too well in the scenes anymore.

Jon

  • *
  • Posts: 17504
For starters, the usual platforming is tricky in isometric perspective. It's particularly hard to gauge jumps.

This. I kept dying in one room because I wasn't able to visualize how to make the correct jump.

One solution is to draw a shadow underneath the character. This is what the devs did in Super Mario RPG and is practically required at points to proceed.

CmdrWhitey13

  • Posts: 444
For starters, the usual platforming is tricky in isometric perspective. It's particularly hard to gauge jumps.

This. I kept dying in one room because I wasn't able to visualize how to make the correct jump.

One solution is to draw a shadow underneath the character. This is what the devs did in Super Mario RPG and is practically required at points to proceed.

I'll aree with this as well. You can even try to grow or shrink the shadow to guage the height of the jump. This is coming along nicely. Love reading this journal.

gurigraphics

  • Posts: 687
Quote
One solution is to draw a shadow underneath the character. This is what the devs did in Super Mario RPG and is practically required at points to proceed.
Quote
I'll aree with this as well. You can even try to grow or shrink the shadow to guage the height of the jump.

Super Mario RPG is same a good reference for this type of game.
I thought that he used only 4 directions to facilitates the jump, but use 8 same.
I did not realized that the shadow that helped.

Your style is getting cool.

merrak

  • *
  • Posts: 1373
This. I kept dying in one room because I wasn't able to visualize how to make the correct jump.

One solution is to draw a shadow underneath the character. This is what the devs did in Super Mario RPG and is practically required at points to proceed.

There are a few rooms in the void areas (the ones with no exterior walls) that are hard to clear. The platforms are narrow and spaced pretty far apart. The funny thing is that, over the summer, the shadow crossed my mind and I even went as far as to create a block for the very purpose of drawing it:



It's even used in the test scene pictured in the top image on page 1 of the thread (look under Noni)



But I didn't use lighting version of the rendering engine for the original game, which includes all the raycasting routines needed to do the computations for the shadow. I wasn't sure if that version would run in Flash. It seems the current version runs poorly on some machines. I probably could've hacked something together that just did the shadow, but at the time I didn't give the shadow enough credit for its role in helping guide the player.

The other issue with the shadow is that most of the light sources come into the room at a shallow angle with the floor, which will complicate drawing the shadow in a believable way.

Fortunately, I think moving toward the intended game (with the player character having more realistic athletic abilities) will solve a lot of the jumping problems. First, Marika won't be able to jump any higher than a real person would. This means the shadow won't be far away from the character very often. As long as the shadow is close, it doesn't need to be so realistic. She'll also be able to grab ledges, so it will be harder to make a mistake that can't be recovered from.

One thing I noticed about games like Prince of Persia is that the jumps are surprisingly predictable. A jump from idle will clear 2 tiles; jump from running will clear 3 tiles, etc. I think emulating that model (and designing the levels to take advantage of it) will make the biggest difference, since jumping would no longer be relying on releasing the jump key at the right time.

I learned pretty quickly not to design the levels to rely on jumping in a secondary direction (45 degrees off of a coordinate vector). While I want to keep 8-way movement, I'm planning to restrict platforming to cardinal directions.

The original version of the game (the one in Stencyl Arcade) has a room that requires a 30-degree jump. That jump is very hard. You can make the jump at a 45-degree angle, but it has to be almost pixel-perfect. The GameJolt version of the game fixes that. I don't remember which room it was--it was one of the void rooms toward the end of the game.

So for me, lessons learned! :)

Mebbs

  • Posts: 19
Lookin' good Merrak! I'm really enjoying this journal :)

merrak

  • *
  • Posts: 1373
Lookin' good Merrak! I'm really enjoying this journal :)

Thanks!

Update for Halloween/November: Not many visual changes, although I got the shadow to work. I was a bit surprised how much easier it made platforming--definitely should have been a feature in the original game. You can see it in the image below.



I also made a few changes to the HUD. It's now gone by default, but you can click on items to bring up a card representing its stats. I'm thinking about this version being a tablet game, and moving cards around seems like a simple way to implement object interaction. At some point I'd like to make a Steam version of the game, which would feature some of the things I've mentioned before (level editor, etc.)

Most of the updates were 'under the hood'. The way special objects (e.g. save statues, restore health statues, doors) were implemented was completely reworked. In the Stencyl Jam version of the game, each room could only have one star tile (special action). The XML files I used to retrieve game data could only modify scene behaviors. Now they can modify actor behaviors, so I can have multiple special tiles and each one its own set of parameters. This will allow for a wider variety of special actions, such as triggering traps and bonuses, switches for gates, and so on. Doors were a major PITA to implement in the Stencyl Jam version of the game. Now they're pretty easy... and they actually open.

« Last Edit: November 09, 2016, 08:32:23 pm by merrak »

merrak

  • *
  • Posts: 1373
11. Revisiting the Z-Buffer Problem

One thing I've been putting off for a long time is revising the rendering code. Early in the thread I explained how I used the so-called "Painter's Algorithm", which paints objects in order from farthest to nearest. The problem with this approach is that objects far back in the scene may be drawn over, thus wasting time.

In the current version of Temple of Idosra, tiles are 16 x 16 x 32 pixels, and rooms are 10 x 10 x 4 tiles in size. The depth of an object is the sum of its x, y, and z coordinates. The implementation of the Painter's Algorithm was described in June 2015. In particular, the screen coordinates (Sx, Sy) of an object are given by the formula below, where Gx, Gy, and Gz are the coordinates of the object in the world.

Sx = Gx - Gy + marginX,    Sy = 1/2 Gx + 1/2 Gy - Gz + marginY

An example of the problem is that an object at (64, 64, 0) and (80, 80, 16) will both be mapped to screen coordinate (0, 64). So why waste the time drawing the object at (64, 64, 0) when it will eventually be drawn over?

This isn't a problem for isometric games that have a 2D world. The Undying City is a good recent example. Because there's no height dimension in the world, there aren't that many opportunities for an object to be completely drawn over by something in front of it. There's not much waste in the drawing routine.

There is a lot of waste in rendering the rooms for Temple of Idosra, and it's even worse in the revision under development. As a consequence, I've noticed performance start to deteriorate. So I think it's time for a proper Z-buffer solution.

Most of the waste is in drawing and illuminating walls and floors. But I made a neat little observation that I can divide the screen into triangles. Any floor will perfectly fit into a diamond-shaped segment formed by two triangles, and any wall face will fit into a column of four triangles.


Looking closer at a wall:


I noticed this a while ago, but only recently figured out a way to take advantage of it. The current approach to drawing goes something like this.

Code: [Select]
1. Initialize Gx + Gy + Gz "buckets" (For Temple of Idosra, this will be 160 + 160 + 128 = 448 buckets total)
2. When an actor is placed in the scene, or moved, place it in bucket Gx + Gy + Gz
3. Loop through all 448 buckets.
   3A. Loop through all the actors in the ith bucket
   3B. Draw the actor and its lighting effects
4. End loop (3)

The importance of the quantity Gx + Gy + Gz is explained in the link above, but is basically the depth (on screen) of an object. By looping through all 448 buckets, the objects are drawn in order from farthest to nearest.

Looping through all those buckets doesn't take much time. Most of the time is spent in the actual rendering--particularly of walls. Walls and floors have multiple actors whose opacities react to lighting conditions. So the drawing of unnecessary walls and floors is a huge bottleneck.

I haven't implemented a solution yet, but I spent some time sketching out a revised algorithm on some cafe napkins... my notepad of choice  :D I'll break drawing up into three stages.

Code: [Select]
// Pre-Draw Stage I
1. Initialize Gx + Gy + Gz buckets
2. When an actor is placed in the scene, or moved, place it in bucket Gx + Gy + Gz

Code: [Select]
// Pre-Draw Stage II
1. Initialize N arrays, one for each triangle screen partition
2. Loop through each of the 448 buckets
   2A. Loop through each item in the ith bucket
   2B. If the item is a wall or floor (that completely fills a triangle), then empty the array for that partition
   2C. For each triangle partition an item fills, place a pointer to it in the partition's array.
       So a floor will have a pointer in two partitions, a wall face in 4, etc.

Code: [Select]
// Draw Stage
1. Initialize an empty list
2. Loop through each of the triangle partition arrays in order from top to bottom
3. Place each item in the draw list (if it isn't already there)
4. When all the partition arrays have been processed, draw all the items in the draw list

I'm dreading the fine-tuning process of implementing this, but I think it will be worth it. Step 2B in "Pre-Draw Stage II" is the most important part of the whole deal. That step is what eliminates objects that are overlapped by another. An object may occupy a position in multiple triangle arrays (since all objects fill at least two). If some of the pointers to the object are cleared by Step 2B, then it is only partially overlapped, and will still be drawn. But if all pointers have been cleared, then it is completely overlapped, and will not be drawn.

Part of making this strategy effective is to minimize how many triangle partitions an object fills. Walls are the worst culprit, since they occupy 8. By splitting their images in half, I can render each face separately. A wall face only occupies 4 triangles, and so I ought to be able to eliminate a lot of redundant faces this way.

merrak

  • *
  • Posts: 1373
Some updates for the new year:

The triangle z-buffer thing seemed to do a pretty good job in reducing the number of actors. I now have hundreds of actors in a scene, which is a vast improvement over thousands  :D


Unfortunately, that wasn't enough to get acceptable performance on Flash. I came to the conclusion that I'm just going to have to be careful about the number of wall segments and complexity of rooms in a Flash port.

In Temple of Idosra, each room was 12 x 12 x 4 tiles, with no camera scrolling. I implemented a camera system, which will allow me to break a larger area into smaller segments. I can use Tiled to build each segment, and a script takes each one and places it in its proper position in the larger map. As a bonus, I can now have monsters travel between rooms.

Making a map system was difficult, since the original Temple of Idosra had messy code (which tends to happen to me in game jams). So I cleaned it up and managed to optimize the game enough that it runs smoothly on my machine.

So, here is a playable version: http://www.stencyl.com/game/play/35820

Keep in mind it still doesn't run great. I have some more optimization tricks up my sleeve. To run the game, type "launch Shalan" at the prompt. In game, backtilde + 4 will display the number of actors currently visible, and backtilde + 3 will display the framerate (target is set to 30, not 60). Click on screen to clear the display cards.

I don't get any lag at all on rooms with less than 500 actors, but 500 does seem to be the magic number (for me). I also need to adjust the loading bar so that it doesn't end too early. It doesn't report the time it takes to run the wall optimization algorithms.

Screenshot:

CmdrWhitey13

  • Posts: 444
I have done the actor count check and this is what it is displaying. Roughly 10fps. Nothing running besides Chrome on Windows 10. Its lagging on this end.

merrak

  • *
  • Posts: 1373
Looks like I still have some work to do. I could cut out a ton of overhead by using pre-rendered lights instead of dynamic lighting, which is what I might have to do for Flash... and maybe even mobile. 295 actors makes a fairly modest room.

I use a lot of actor values. I wonder if I'm using enough strings that cutting them out would save time. What I really should've done was find a practical way to extend the Actor class.

CmdrWhitey13

  • Posts: 444
I could think of a way for attaching images to actors and a collision mapping possibility. The rolling ball concept i came up with only uses 3 actors the rest is drawn to actor. Mapping collisions maybe difficult though. A thought to look into. It has definitely came a long way,

Keep up the good and inspirational work.

http://community.stencyl.com/index.php/topic,47246.msg262153.html#msg262153

merrak

  • *
  • Posts: 1373
Each actor is linked to several "image actors" that don't have collisions. They merely exist so that their images are drawn. The alternative was to use bitmaps, but I ran into some issues with rendering speed that I can go into if anyone is interested. I went as far as to completely pull the image actors out of every update loop. (Use the call "Engine.engine.allActors.clr( a.ID );" to do this, but be careful--it even stops animations from updating). So that's why the actor count is so high.

I pulled out hxScout to analyze what is happening during gameplay. This is the analysis during a moment of 3.7 seconds when the level loaded and the player was standing idle.



Any of the functions that begin with IsometricActor are simply macros that call "getActorValue" and return some content. Together with "getActorValue" itself, you can see the time adds up to an appreciable fraction of 3.7 seconds.

There are other IsometricActor macros in my physics routines, so it seems those calls form one bottleneck.

The other bottleneck appears Box2D stuff. Every actor has to be set always active, and there are hundreds of "real actors" (as in, not just image actors). I need Box2D for raycast, though.

merrak

  • *
  • Posts: 1373
12. An Actual Game  :o

It feels like I've been working on this base system forever, and haven't put much thought into what I wanted to do with it... at least, not beyond some general ideas. I have quite a few ideas for future endeavors, the favorite of which is to create a roguelike (or roguelikelike). But I will accomplish more if I focus more on one thing at a time. So my first goal will be to overhaul Temple of Idosra--redo the rooms that don't make sense, polish the controls and UI, and implement the features I didn't have time to do in the original game jam.

The game is probably too short to release on something like Steam, but might do well as a Flash game or on the mobile market (if I can get a good control scheme setup). I do have some time to work on that.

In the meantime, I'm quite happy with how the revised inventory system is turning out. The main feature of the updated system is that it allows for prompts and multiple actions pet item.


The original Temple of Idosra used "star tiles" that triggered when the player stepped on them, and only allowed for one action that automatically took place. Now the player can strike the action button to receive a choice of actions. This will allow for many more opportunities to interact with the environment.

The same is true for objects in the player's inventory. "Inventory items" are represented by cards and include both tangible and non-tangible items.


Cards can now have multiple actions.


One of the best parts of the updated system can't be seen in the screenshots. Internally, object actions can be added or removed at any time. So new actions can be added when conditions in the environment call for them. The final result should be that the revised Temple of Idosra should have the adventure game feeling I felt was lacking from the original version--with an environment more open to interaction and plenty of action in between.

merrak

  • *
  • Posts: 1373
Progress has been made addressing performance issues  :D

This latest version of the code never seemed to run as fast as the 2015 version, which I just assumed was because this version allows for a true 3D world. But after reviewing some of the older pages in this thread, I realized I could take advantage of a trick I had forgotten about.

The 2015 code pre-computed all the tiles that were visible from any other tile (a lengthy process) and stored the results in a massive array of arrays... hence the long loading time for a relatively sparse and empty map. Rather than perform hundreds of raycasts whenever the camera changes position, I could perform thousands whenever the scene changes. The process takes about 45 seconds on my machine for a large map containing the first 9 rooms in Temple of Idosra. But as these rooms are static, why not just do the computation once and store the results in a permanent file? That would also allow me to use simple physics instead of Box2D, which is needed for raycasting.

So I went about making myself a set of tools for level editing, including some cheat codes and a "laboratory mode".


This could become a full-featured level editor at some point, but for now it only contains a few tools that wouldn't be of interest to anyone without access to the project files.


However, it will let anyone explore the entire map without having to worry about doors, jumps, enemies, etc.

I updated the in-development version, with these tools (but not the results). http://www.stencyl.com/game/play/35820  So now the entire map containing the first 9 rooms can be explored. Updated version also includes the now functioning inventory system, objects and weapons, stats, and a few cosmetic changes.

And the super-secret code for the "laboratory mode":