Merrak's Isometric Adventures -- Dimetric Dilemna

merrak

  • *
  • Posts: 2738
Merrak's Isometric Adventures


Revised Intro: 2017-August-25: This journal has continued longer than I originally thought it would. It's pretty massive now, so here are some highlights.

What is going on here? I'm working on an isometric perspective game engine (Vallas Engine). It's gone through three major revisions, conveniently spaced a year apart (2015, 2016, 2017). Each revision brings re-evaluations of old ideas, explores their pros/cons, and hopefully comes with improvements.

I like to write about ideas, particularly math (I'm a mathematician and mathematics professor), programming, and algorithm design. I share a lot of algorithms and strategies to accomplish different objectives and explain how they work. I always hope that people will share back, especially if they find something doesn't work or can be improved.

Keep in mind that this is a journal, not a how-to guide. There are plenty of ideas I thought were great, only to later realize fall short in some way. I always tell my math students to never do math in pencil--always use pen, because I don't want them erasing ideas. There's always something to be learned from an idea that falls short. So here's my record of evolution of solutions to various problems regarding (psuedo) 3D game engine design.

Thread Highlights

  • Isometric perspective and conversion between isometric grid, 2D scene, and screen coordinates
  • Line of sight
  • Using Box2D features in isometric scenes
  • Shadow casting
  • Painter's Algorithm for actor depth resolution
  • Dynamic lighting
  • Proper 3D navigable scenes using split 2D scenes
  • 3D raycasting
  • Software-based actor illumination (revision of "dynamic lighting" above)
  • When and why Painter's Algorithm falls short
  • Various linear algebra problems
  • Garbage collection and Box2D
  • Shadow casting rendering
  • Optimizing representation of world
  • Graph Theory and Application to the Actor Depth Problem and Artificial Intelligence
  • Utility-AI

Of course, there's a game involved, too. The original title was "Thief of Vallas", but there is a spin-off title in the works (Temple of Idosra). That game started in the 2016 Stencyl Jam. The original version was written in 10 days, 5 of which without power.

The journal is dominated by programming, though, because I keep running into problems that need to be solved.

Original Post: 2015-May-08

With LD and StencylJam nearly over, I have some free time to spend on a larger project. I had a few ideas that would require some sort of physics in an isometric view. I'll give documenting my attempt here a go.

So far, I don't have anything playable, but I've made some progress. Motion and gravity were fairly simple. Drawing and z-order were less so... particularly the projection. The best solution I could think of was to come up with some kind of hash table and continually pull actors in and out of it. While I've yet to crunch any real numbers, I am able to have a "lot" of actors on the screen before noticing any real slow-down.


The biggest hurdle will be collision detection. I've set up bounding boxes and an isometric version of debug draw, so that's a start. Once I get collision detection to work, I can make some real games  :D

« Last Edit: September 15, 2019, 09:20:46 pm by merrak »

jlevstein

  • Posts: 1
This is a really cool idea, good luck with it!

I've just started tooling around with Stencyl and want to take a stab at isometrics too, but I don't really know where to begin. Would it be possible to see a slice of what you've got so far?

merrak

  • *
  • Posts: 2738
This is a really cool idea, good luck with it!

I've just started tooling around with Stencyl and want to take a stab at isometrics too, but I don't really know where to begin. Would it be possible to see a slice of what you've got so far?

I got sidetracked by another project, but I did get pretty far. Collisions and movement work! The ball in the image does bounce across the floor.

Unfortunately, "working" and "working well" are two different matters. The main roadblock I've hit is speed.

I think if I work out some compromises, I can work around the added difficulty of checking three dimensions for collisions. For instance, only allowing for spherical or rectangular collision shapes. I've done some research on ways to get around checking every actor against every actor, but I've yet to implement anything.

All this means that, at the moment, the still image is a pretty good approximation of the real thing  :-\

If you're unsure where to begin, I started with the drawing code. That wasn't terribly difficult, actually. This helped me: http://gamedev.stackexchange.com/questions/3454/most-efficient-3d-depth-sorting-for-isometric-3d-in-as3/3532#3532

merrak

  • *
  • Posts: 2738
I made some progress! Given the limit on the number of moving actors, I think some kind of golf game would work well. This is a (very) early build, with the gravity and bouncing mechanics in place. I can't say it's "playable" at this point. Obviously, there's not even a goal!

But, I'm pretty happy with the performance. You can try it out below if you want. See if you can hit the other "island" with the ball. Click and drag to set its power + direction, then release! Push 'x' to reset.

Original flash file replaced (next post)

There are some quirks I haven't yet fixed. The ball can "fly" to the middle island if it is well below it, but still close enough the isometric system can detect it. If you go too far left/right, you'll get an "error 0111". I essentially built a 3D array of tiles. Going outside of this array would, of course, be problematic. In the actual game I'd just have the ball drop off, so it's really a non-issue.

The angle is relative to the grid coordinates. Positive X is down and to the right, positive Y is down and to the left, and positive Z is up.

« Last Edit: May 20, 2015, 10:50:50 pm by merrak »

merrak

  • *
  • Posts: 2738
More progress. I now have collision detection! One thing I've noticed is that it's hard to tell exactly where the actors are without shadows, so that feature may be bumped up in the priority list.

I'm pretty pleased with the results so far. It seems surprisingly smooth on the file running on the web. My outdated flash player was struggling to keep up, which had me worried--but on Chrome the framerate seems acceptable.

While I have collision detection, there's no real reaction yet. Bouncing, etc. will be next, as soon as I figure out how to make proper use of the normals.

The demo below lets you use the arrow keys to move the box. Z will jump, but on-ground detection is buggy right now. If you hold down the ` key (tilde key--same that used to run the old Flixel console) and "1" simultaneously, you'll enter debug mode. That doesn't do much, but holding ` and "2" at the same tile will enter collision debug mode, which may reveal how collision detection is working.

<a href="http://static.stencyl.com/games/30916-0.swf" target="_blank" class="new_win">http://static.stencyl.com/games/30916-0.swf</a>

I spent a while trying to figure out how to do collision detection from scratch, when I realized there's no reason to reinvent the wheel. Stencyl already does a good job with collision detection, so why not take advantage of it?

Each actor projects a "shadow" onto both the XZ and YZ planes. In the debug mode, the XZ shadow is red, and YZ a lovely sky blue. When two actors' shadows collide on both the XZ and YZ planes, a collision is registered.

merrak

  • *
  • Posts: 2738
I've settled on designing a golf game using the "Isometric Physics" code... mainly because I like drawing landscapes. I could have fun with the art  :)  Of course, I need to get the engine finished...

For this type of game, isometric tiles seem a bit too limiting. I did a lot of work with tiles, though. So that it doesn't go to waste, I'll probably package the code up for use next time... maybe make an extension if anyone would be interested in an isometric tile collision package.

So that I'm not limited to blocks, I replaced the tile system with a pixel-based floor system. The downside is that I can have only one "level". But, for this type of game, that won't be an issue.

ETHproductions had a very handy color utility extension that I managed to put to good use. This is a height map (red denotes non-existent pieces of the floor)



And, rendered in 3D:



I made the transformation code public. This code maps each pixel on the height map to a floor height on the isometric grid. The drawing in the render above wouldn't be seen by the player. Rather, it'd be used to calculate where the ball lands, rolls, etc. A pre-drawn landscape will be drawn in its place. However, having these renders will help me draw the landscape accurately.

merrak

  • *
  • Posts: 2738
Chapter 2 in the Isometric Adventure!

When we left off, our protagonist--merrak--was working out a game to make with the isometric engine. In today's episode, we see how that is going...

As neat as a golf game sounded, I think I'm running into a conflict between "can it be done?" and "should it be done?" The code works--which is great. Unfortuantely, I'm hitting the point where I have to rewrite so much that there's no point to using Stencyl at all. Of course, Stencyl is a 2D game engine, so it shouldn't come as a surprise that 3D is impractical in most situations.

Case in point: if the mountain in the above screenshot were a real screen--what would happen if the ball went behind it? I could implement rotations, but this would involve drawing each scene four times--or using a 3D model. In that case, why not use a 3D game engine?

If I learned anything from Ludum Dare, it's how to gauge what I can and can't do in a given time frame. I think it's time to take the code, which I worked pretty hard on, and do something a little more reasonable with it.

Fortunately, I do have a nice isometric game engine now. And while I'm shelving one project for now, I think I can breathe some new life in another one.  There was a game called Thief of Vallas that functions more as a programming sandbox than a real game project. I made some progress, got stuck, then higher priorities came along.

Here's the problem I ran into:



The shadows were an exercise in frustration. Layers only provide one dimension for ordering, but I really needed two. Ordering needs to be dependent on both depth and horizontal position. The "isometric" engine provides this functionality.

An isometric projection is just a linear transformation. The extension I wrote can be reconfigured for another projection (or any linear transformation, for that matter). After all, applying a linear transformation is just a matter of computing a matrix-vector product.

The new crossroad is whether or not to keep the 2D sidescroller, or create a 2.5D isometric game with a 3D world.

The latter seems more appropriate for my original vision--a rogue-like adventure game with generated worlds. The former is more convenient, because it's much less work in the graphics department. While the original tiles transfer very nicely to 2.5D, the character sprites do not. But, they were originally throw-away graphics in need of a serious overhaul--so I'd have to start over anyway.



The best way to figure it out will be to make some character sprites, and time how long it takes. I figured that an isometric game would have 8 directions, 36 states for the main character, and (probably) 8 frames per state. That's 2,304 images. The original "Thief of Vallas" had more states (about 60), but only two directions. Fortunately, laziness and resourcefulness are good allies. Since there's no penalty for drowning, there's no better way to find out if something is doable than jumping into the pool and seeing if you can swim.

merrak

  • *
  • Posts: 2738
Today's Isometric Adventure: Art!

With all the math worked out last post, now it's time to switch brain hemispheres and start making art! The previous calculation was 2,304 frames. I had to revise that count to 2,688, since there needs to be 42 individual character states (I left out various ways the heroine could fall off a platform).

While that producing number of sprite frames seems daunting, there are a number of ways to reduce the workload. First, The left views and right views are, up to a few details, mirror images of each other. That reduces the number of frames by nearly 3/8. Now we're down to 1,680. Many of the states are modifications of the basic walk/run states. Also, many states share common frames.

Still, there are at least a few hundred unique frames to draw. To make the workload more manageable still, this time I'm putting careful thought into the character design. The original character was supported with throw-away graphics. I'll keep the same basic design, but re-draw from the ground up... this time with an eye for ease in animation. This was an important point I never considered before: Design the character for the time and workload constraints you have.

First, I struggle with basic human anatomy. To help myself, I've recruited MakeHuman, which is a great modelling tool. I acquired Daz4 studio when they were doing a software giveaway. Between the two tools, I can model various poses.

Here's a pose I'm using for the heroine's (let's give her a name--Marika) basic "standing" state.



In a new layer, I'm going to add some clothes. I drew a simple green tunic in various perspectives. It'll be easier to animate in various configurations because of the way it drapes/hangs off her body. Drawing clothed figures isn't a strong point in my artistic abilities, so I'm trying to give myself a wider margin of error.



I drew the rest of her clothes. Now I have a "skeleton" I can pose, and clothes I can place on a separate layer. When everything is put together, I can merge the layers and hand-draw any changes needed to make the figure look right.

Here's the completed Marika:



and, rotated:



I'm pretty happy with the result. I like her design a lot better than the original. Animating her shouldn't be too unmanageable. As the game progresses, I can always go back and fix any errors. The important thing is to get something down.

My first model was drawn in the wrong perspective (oops!) But having some art for loading screens, etc. doesn't hurt.



I find the loading screen oddly inspiring. Perhaps having the blank loading screen was just a reminder of how much there is left to do to get a full game running.

The other important lesson with any project in an "experimental" stage is to give yourself an "out". In this case, I'm starting with frames I can re-use on a simpler, 2D game if the 3D world is too difficult to work with. If I have to throw in the towel, my efforts so far won't be wasted.



merrak

  • *
  • Posts: 2738
Today's Isometric Adventure: Bringing Marika to Life

It's probably a good thing I never tried much animation on a Ludum Dare game. It is a tedious, slow process. I've managed to get a good workflow down, and made a noticeable dent in the to-do list.

Last time, I re-designed Marika, the heroine of the game, using a mix of 3D models and hand-drawn components.


She was (re)-designed with "ease of animation" in mind... so, let's see how that worked. Let's bring her to life. We'll get her to walk.


First, I started with a few sketches. I didn't actually need the stick figure. It was added later, so that I could line up future animations, such as when she turns or jumps. Knowing where the feet are is important, so that she doesn't "teleport" a few pixels when the animations change.

The first step was to create the 3D models. I already drew the clothes, so I can start to copy-and-paste. They'll need some modifications, though. The bottom half of the tunic, for example, will need to flap a bit when her legs move.

If simplicity was a strict goal, I already made a mistake with her clothing. The tunic is in a screenshot above. That little slit on (our) right complicates things. Without it, the tunic would be symmetric, and getting her to walk in the lower-right direction would be a simple matter of flipping all the frames horizontally. I thought about taking it out, but I think she looks a little better with some asymmetry. Still, it's a good example of how character design affects simplicity/difficulty of animation.

Next are the feet. The feet can be particularly difficult because they're small--only a few pixels. A single misplaced pixel can really stand out. Giving her thick boots helps quite a bit here, since the nuances of the geometry of the foot can be hidden behind the folds.

Here is the result:  Edit: Revised version on right

   

I have to say I'm pretty happy with it. A professional artist could do much better (and faster), but for a one-man team teaching himself basic animation principles, I don't think it's bad at all.

Once I get all the animations done, I can go back and make minor tweaks. I'm not too concerned with perfection right now, since some adjustments will probably be necessary to get the various states to line up correctly. So, getting something workable is my goal.

« Last Edit: June 03, 2015, 09:20:58 pm by merrak »

ceosol

  • *
  • Posts: 2279
That's pretty good. Normally when I animate walking, it looks more like skating. A little critique, set the left foot a little bit more forward and give it a slight delay to give the illusion of pressing it down during the step.

merrak

  • *
  • Posts: 2738
That's pretty good. Normally when I animate walking, it looks more like skating. A little critique, set the left foot a little bit more forward and give it a slight delay to give the illusion of pressing it down during the step.

Thanks!

Which left foot do you mean? (ours of hers). There is a pause on her left foot between frames 7 and 0, but no pause on her right because of the distance it covers between frames 3 and 4.

ceosol

  • *
  • Posts: 2279
Her left. It looks vaguely like she is limping. Maybe the right foot needs a slight delay then?

edit: oh, its a delay on the second frame of her left foot step. Its slightly too long, giving it a short stumble.

merrak

  • *
  • Posts: 2738
Her left. It looks vaguely like she is limping. Maybe the right foot needs a slight delay then?

edit: oh, its a delay on the second frame of her left foot step. Its slightly too long, giving it a short stumble.

I realized it might help to have the frame numbers I had in mind :)



But I think I see what you're talking about. Her leg doesn't move at all between 7 and 0.

Edit:

Shifted her foot a bit, and angled her thigh in frame 7 so that it's not straight in both frames 7 and 0. I think that takes care of the limp.


« Last Edit: June 03, 2015, 09:22:20 pm by merrak »