Stencyl 3.4.0 is now out. Get it now!

Merrak's Isometric Adventures -- Renderer Result

merrak

  • *
  • Posts: 1407
I definitely appreciate the support  :D If anyone's willing to post a flyer or two then I'll invest more time into polishing it.  But the full desktop game may be a further ways out. To render in any appreciable screen size for a desktop game, I'll need hardware support. I do have a fallback for software-only rendering in large scale, but there are some upcoming features in Stencyl that should let me expand on what I have.

In the meantime, I'm tossing a couple of other ideas around. I really should do something with the original 6-color tileset. Completing a couple of small-scale projects with this engine would be a good way to see what really works and what needs revision before attempting something larger scale.

Speaking of which, I'm now this far:


Other than the "trim" on the tops of the walls, it may not look much different than earlier screenshots. But there is one important difference. That scene is put together with about 15 individual images, rather than one large image. In addition, the images are sorted from front-most to back-most--so I have proper z-order. If you read some of my earlier posts, you may have caught that I was on the route to abandoning z-order. After all, if I follow my own level design parameters, z-order isn't an issue. But that's not actually true. While the player should be in view, other moving actors don't necessarily have to be.

So I split the walls so that each wall has its own dedicated image. The really nice thing about this is that I don't need to replace "DrawStack" to render them. I can integrate my new tile system with the current rendering method for actors.

For anyone who hasn't seen me use that word, "DrawStack" is the rendering process I've been using since Page 1. It's based on an idea I read in a post by captaincomic (but maybe not the actual code, which I never saw but was posted to StencylForge). A more recent example would be Isotiles (I'm assuming, based on what rob1221 wrote about his strategy in that post).

"DrawStack" is a very effective strategy for rendering isometric graphics in Stencyl. But there is a limit to its reach, and that appears to be a 2.5D game world with "hundreds" of tiles. I have a 3D world with "thousands" of tiles, albeit with 2.5D rendering. That difference in the order of magnitude of tile count is the catch.

The scene shown has 24 walls, and roughly 15 or so visible. (The invisible walls are the ones behind pillars, under floors, etc. They're present for shadow computational purposes, collisions, etc., but not rendered). If I throw in some moving actors, then the number of elements "DrawStack" is managing is now one order of magnitude less than the limit, as opposed to one above. Dropping two orders of magnitude is a significant improvement, leaving much more computing power free for lighting effects, smarter AI, etc.

So, advice for anyone making an isometric game with Stencyl-- The "DrawStack" method works very well until your number of actors reaches "thousands". After that point, I suggest you have a plan in mind on how to combine them.

« Last Edit: July 10, 2017, 11:04:43 pm by merrak »

merrak

  • *
  • Posts: 1407
Renderer Result. Here it is.


The two blemishes on the left and right are to be expected, since I haven't yet defined the geometries for the invisible walls.

Moving the light to a position in front of the pillar:


And two lights:


merrak

  • *
  • Posts: 1407
So I'm finally at the fun part :D But also it's the annoying part... chasing down all the little bugs that only occur under specific circumstances. I spent the better part of this afternoon and evening chasing down a bug that turned out to be a problem in one of the most essential functions: projecting a point onto a plane. If you read the part about AABB projection (the linear algebra that is involved in shadow projection), there's an evil nuance. Projection doesn't work on a coordinate plane. What are the coordinate planes? They're the back of the back-most walls in the image below.


It's a non-issue if the light source is inside the scene. But if the light is outside, a shadow needs to be projected against the back wall into the room.

But having fixed that, it was time to start adding features! Here's a single-light source. Where did the door go?  :o


One reason I put so much time into the lighting system is that a large part of the game is based on the idea of hiding things in shadows. I want the player to be surprised, but I want it to feel fair, too. Enemies shouldn't just come out of nowhere, and I want to use shadows to put the player on guard.

Also... colored lights!


Most of the windows in Temple of Idosra are green, so I'd like to have a greenish tint.

And speaking of windows, there's now directional lighting. Got a flashlight?


merrak

  • *
  • Posts: 1407
I've been (slowly) going through the rest of the tileset from Temple of Idosra and configuring the tile geometries. This is an incredibly tedious process. Setting the image offsets, in particular, is frustrating.

To explain what that is, imagine a regular 2D tile or actor located at (x,y) in your scene. The image starts drawing at (x,y). This gets more complicated when your scene is 3D, since you have to project a point to 2D space and use that as the anchor point for the tile's image.

When things go wrong, well, this is the single most frequently posted image in this thread:


But it's also the most frequently recurring problem. It's made worse when structures are different sizes.


What's going wrong is this: I have a tile (stairs) located at (x, y, z). The steps themselves are defined by a sloping plane with four vertices. One of the vertices is (x0, y0, z0). To figure out where to draw the steps, I project (x0, y0, z0) to screen coordinates (Sx, Sy). I then add an x offset and y offset and draw the image at the resulting point. The offset is not easily calculated, because it depends on where that first plane vertex is--which is unique to the tile's geometry.

At least z-ordering is working. I never really talked about how that works, but I had to change strategies. My first solution assumed every actor and tile was the same size, so images could be sorted based on their (x + y + z) coordinate sum.

The new solution sorts walls (2D planes), not tiles (3D structures). Basically, I loop through all walls and compute the intersection of their respective on-screen polygons (compute Sx,Sy for all four vertices). The intersection is computed using the same Sutherland-Hodgman implementation I used for the shadows. If there is an intersection, I just need to pick a (x,y,z) point in the intersection and compare the depths using the (x + y + z) approach. Once again it's critical that all walls be convex quadrilaterals. An easy way to guarantee that is to make all walls rectangles (in grid coordinates)--hence the necessity of the "growing squares" algorithm.

The downside is that I couldn't get the built-in Array sort to work, since I have to compare each wall to every other wall. That's a lot of comparisons (quadratic time). While I only need to sort visible walls, there's still potential trouble in a complex room.

Sorting walls only needs to happen once, but sorting moving actors would have to occur every frame. What I might end up doing is partitioning the map's graph into three sub-sectors: visible, partially visible, and hidden. The first and third sub-sectors have simple rules. If a moving actor is in the "visible" sub-sector, then draw it. If it is in the "hidden" sub-sector, then don't draw it.  The "partially visible" sub-sector will be the pain to deal with. I'd prefer to find a way to use the painter's algorithm, since it's simple. The alternative would be to deal with more image clipping.

Edit. Here's what the scene is supposed to look like.


I used an red-orangeish light, which would be more appropriate for deeper areas away from the windows. The shadow follows the stairs rather nicely. This is a significant improvement over previous versions of the renderer, which were unable to work with any plane not parallel to a coordinate plane. This room has 77 walls, with about 30 visible. The Spring 2017 version of the engine (0.9.0, featured in March-May) would've used about 300-400 images to render this scene.

« Last Edit: Yesterday at 12:23:34 pm by merrak »