Merrak's Isometric Adventures -- Dimetric Dilemna

ETHproductions

  • *
  • Posts: 430
I love how you're explaining all the hard work you're putting into this prototype as you create it! May I ask how you got the loading screen to display an accurate percentage? In one of my projects, I use loops to load a saved 100x100 tile scene, and the screen (including drawing events) doesn't update at all until it's completely loaded....
Fontstruct - Stencyl - Website (in progress)

Proud Member of the League of Idiotic Stencylers; doing things in Stencyl that probably shouldn't be done.

merrak

  • *
  • Posts: 2738
May I ask how you got the loading screen to display an accurate percentage?...

This definitely falls into the "sounds simple, but really isn't" category :P. What I ended up doing was creating a list of custom events, each of which handles one loading task. Then, in the drawing loop, I pluck the next item from this list and execute that event. When the list has been emptied, the behavior terminates itself.

Even that didn't quite work, though, since I have the same issue you did with the scene. For that, I made one event that processes a single row,column entry, and call that in the drawing loop for all rows and columns.

I attached the behavior if anyone's interested, since I think this topic came up in the forum earlier in the week. One important note--the event "LoadScene" is what loads all the actors. The reason the pause is there is so that no action takes place while the rest of the scene is loading. Some of my scene behaviors also have 'update' and 'drawing' loops that I don't want to run while the scene is loading. The 'ready' boolean handles keeping them delayed until the loading process is complete.

merrak

  • *
  • Posts: 2738

I've uploaded the first working prototype to the Stencyl Arcade.

It's nothing much in terms of content, but everything seems to be working. The upper right HUD display is framerate. I get 60 FPS on Google Chrome's Flash, but not Adobe. However, my Adobe is the last version supported for Linux, so is old.

I'm thinking that multi-story may be beyond the capabilities of a Flash version. There are a few things I can do to squeeze some more speed out of the renderer, but nothing drastic enough to fully add a third dimension. That will need to wait for a standalone, or possibly tablet version.

So, there's not much work left to do, and it's time to start working on art assets and other content. So that I don't get burned out on drawing all those frames, I'm planning to take it slowly.

There are some other (simpler) ideas I've been wanting to use the isometric renderer for. It'll be nice to think about something else for a while. At the same time, the code I'd need to write will eventually form the missing components needed for Thief of Vallas.

ceosol

  • *
  • Posts: 2279
Hey, I've found this to work in isometric to stop continually walking in a certain direction. Set xclick and yclick to the mouse x, y. Then tweak the <10 values to fit your needs. I don't really like having Marika walking into walls or continuing into a fireball. :)

merrak

  • *
  • Posts: 2738
Hey, I've found this to work in isometric to stop continually walking in a certain direction. Set xclick and yclick to the mouse x, y. Then tweak the <10 values to fit your needs. I don't really like having Marika walking into walls or continuing into a fireball. :)

Similar code is there :)  I just disabled it. The problem I ran into was that a collision would bounce her off track, and so she'd never hit the clickx, clicky point. Every 1/2 second her walking direction would adjust itself, but even that didn't seem to work well. After a while I realized I was putting too much effort into what would be a temporary solution. A real fix will have to wait until I get the rest of the turning animations.

ceosol

  • *
  • Posts: 2279
I also included modifiers where collisions against walls stop motion automatically (and shove backwards a few pixels to prevent continuous collisions).

dreph

  • Posts: 142
May I ask how you got the loading screen to display an accurate percentage?...

This definitely falls into the "sounds simple, but really isn't" category :P. What I ended up doing was creating a list of custom events, each of which handles one loading task. Then, in the drawing loop, I pluck the next item from this list and execute that event. When the list has been emptied, the behavior terminates itself.

I think I understand the custom events, and a list.  Setting the Current Step, and clearing out that line in the list.  How do you have the logic handling the "Busy" Boolean?  is _ErrorsPresent a custom attribute or is that something in stencyl code that you can use for script execution stuff?

Even that didn't quite work, though, since I have the same issue you did with the scene. For that, I made one event that processes a single row,column entry, and call that in the drawing loop for all rows and columns.

I attached the behavior if anyone's interested, since I think this topic came up in the forum earlier in the week. One important note--the event "LoadScene" is what loads all the actors. The reason the pause is there is so that no action takes place while the rest of the scene is loading. Some of my scene behaviors also have 'update' and 'drawing' loops that I don't want to run while the scene is loading. The 'ready' boolean handles keeping them delayed until the loading process is complete.

So yeah, I am not understanding how to were able to wait until list is empty to continue on.  Is it as simple as it sounds?  I am trying to empty a list (36000 items) and it takes about 2 seconds, in which the scene is unresponsive.  Can I have it check lines in the scene like (if list item # 30000 exists, display 10%, if list item #20000k exists, display 30%) or am I missing something.

I need the scene to actually refrain from becoming non-responsive while the script is running.  The script is successfully running, however it freezes as mentioned above by ETH.

merrak

  • *
  • Posts: 2738
I also included modifiers where collisions against walls stop motion automatically (and shove backwards a few pixels to prevent continuous collisions).

I thought about doing that earlier. It's hard to tell if it would be a good idea or not. It would make motion more predictable, but could make it more difficult to get down some of the narrow passages.

Collision is handled on a 2D plane. In the prototype, you can actually pull this plane up using tilde+3, then tilde+0 (in that order). Marika's collision boundary is a circle of diameter about 64, which is the length/width of a tile. Getting her to walk down a corridor of 1-tile width without a collision is near impossible.

So yeah, I am not understanding how to were able to wait until list is empty to continue on.  Is it as simple as it sounds?  I am trying to empty a list (36000 items) and it takes about 2 seconds, in which the scene is unresponsive.  Can I have it check lines in the scene like (if list item # 30000 exists, display 10%, if list item #20000k exists, display 30%) or am I missing something.

I need the scene to actually refrain from becoming non-responsive while the script is running.  The script is successfully running, however it freezes as mentioned above by ETH.

Basically, the contents of the screen aren't going to update until all other instructions have finished. So, if you tell the computer to read through all 30,000 list entries at once, the screen won't refresh until that loop has terminated. You can have hundreds of little loops instead, and increment the starting index as appropriate. In between each loop, the screen will update.

I don't know any way to manually update the screen, so this means using the On Drawing and Always events and keeping track of where to start the next loop.

The task that takes the longest in my setup is called "WallBitMap", which constructs polygons for one tile (row, column). What I did was write an event that processes a single row and column. The drawing loop itself is where the code that increments the counter is housed. So, the flow looks like this.

Code: [Select]
(on Creation)
set row = 0, col = 0

(on Drawing event)
if row, col < max row, max col
    call event to process current row, col
    increment col by 1
    if col == max
        set col to 0 and increment row by 1
end if

I realized our problems might be different in a slight, but important way. You're reading a lot of data, and I'm processing it. I can't think of a way to read just part of a file at a time. You could break your one big file into several little ones, though.

But... 2 seconds doesn't seem like a long delay. Is the problem going to get bigger? The reason I went out of my way to put the progress indicator in is because even for a relatively small map, I'm passing 15 seconds. This is a number I pulled from Apple's guidelines for app loading times.

If two seconds was my worst case scenario, I wouldn't have bothered. Using a loading screen adds a surprising number of complications, because now you have to think twice about what code you put in the 'Created' events. When I installed the loading system, I had a lot of segfaults because code in 'On Created' and 'Always' was executing before the loading process finished.

Nikkita31

  • Posts: 131
Hi Merrak.

This is some real awesome stuff. I tried to read your code but I ended up getting a migraine.  :'( I am looking forward to this.
I am also in the process of doing a game like this but I only draw collisions on map. The floor tiles are the only passable areas then the character's foot is the only part that has collision . Then I used some layering stuff to add "Depth" to the scene.

merrak

  • *
  • Posts: 2738
Hi Merrak.

This is some real awesome stuff. I tried to read your code but I ended up getting a migraine.  :'( I am looking forward to this.
I am also in the process of doing a game like this but I only draw collisions on map. The floor tiles are the only passable areas then the character's foot is the only part that has collision . Then I used some layering stuff to add "Depth" to the scene.

Thanks! :)

I got a pretty bad headache trying to debug the code, and so did my poor heroine.



What you described using floor tiles for collision is exactly what I did. The isometric-looking display is entirely an "illusion", so-to-speak. Internally, this is what the game really looks like.



And, if you run the demo and do tilde+3, then tilde+0, you see the collision bounds. The circle is the character's feet, and lines the wall edges. (Ignore the pink box, that's the area that brings up the tool-tip label).



It's definitely a good strategy if you want to do more complicated things with the art, but keep the mechanics simple. I even had an older version of this game that used layers for depth.



I abandoned it because using layers was too complicated for what I wanted--procedurally generated levels. I'm starting to think that I may have been too hasty throwing out this older version, though. It can handle hand-crafted levels pretty well. It needs a few more art assets, and some revisions to current assets, but could otherwise be a complete game. I may come back to it later.

ceosol

  • *
  • Posts: 2279
Quote
I thought about doing that earlier. It's hard to tell if it would be a good idea or not. It would make motion more predictable, but could make it more difficult to get down some of the narrow passages.

Collision is handled on a 2D plane. In the prototype, you can actually pull this plane up using tilde+3, then tilde+0 (in that order). Marika's collision boundary is a circle of diameter about 64, which is the length/width of a tile. Getting her to walk down a corridor of 1-tile width without a collision is near impossible.

I meant to draw this up a few days ago, but it slipped my mind. Since stopping at the click is out of the question because of wall angles and stopping upon is out of the question because of narrow passages, here's another thought:

Why not use your isometric calculations and stop at the intersection angle? I attached a crude drawing of what I'm talking about. The blue lines are the borders of the narrow passage. The green line is the path Marika would be walking.

merrak

  • *
  • Posts: 2738
That's a neat idea. The only question I have is how you calculate the vector from the point of click (white dot) to the stop point? I can think of a couple of ways, but was wondering what you had in mind. I think any approach could work, though. Thanks for the suggestion!

This is now starting to sound like a textbook calculus exercise: Find the point along Marika's position vector that minimizes the distance from the white "click" dot.

ceosol

  • *
  • Posts: 2279
Quote
That's a neat idea. The only question I have is how you calculate the vector from the point of click (white dot) to the stop point? I can think of a couple of ways, but was wondering what you had in mind. I think any approach could work, though. Thanks for the suggestion!

I was just using something similar in creating a basic directional pad for a game. I created two equations: y = x and y = -x + 140 (the D-pad was 140 pixels). Whenever the mouse crossed the lines, it entered into another "quadrant" of the d-pad. For your game, whenever the player clicks, you just create the boundary equations and if Marika crosses a boundary, she stops moving.

Of course, your boundary equations will be based on isometric orientation instead of a square. They would still be fairly simple y = mx + b.

merrak

  • *
  • Posts: 2738
That sounds pretty simple, actually. I'll give it a try--Thanks!

merrak

  • *
  • Posts: 2738
6. Multiple Floors

After releasing the first prototype, I took a step back--but now I'm getting ready to tackle the last significant component to the renderer: multiple floors. For a while, I was planning to put this step off until later. But as I began to draw out a few mock-ups of what I want the renderer to be able to produce, I realized I needed it, even if just to show backgrounds.

This background is just a sketch, hand-drawn on an existing screenshot. But I think it shows it makes a big difference in the visuals. I can probably round out the tiles even more, as long as I'm careful about collision shapes.



Since the background isn't interactive in any way, I don't have to worry about depth. However, I would need to make sure the player couldn't fall down into that pit, or else the illusion would be broken. Pits the player can fall into will need to have their walls drawn appropriately.

As for actual floors, here's the plan. Credit goes to Ceosol for the idea.

Since the scenes are really 2D internally, what I would need to do is partition the 2D plane. The world in the prototype is 10 x 13 isometric tiles, or 640 x 832 "grid points" ("grid coordinates" refer to the coordinates in the 3D isometric world). Setting the scene size in Stencyl is a pain at best, because it needs to be bigger than 640 x 832 pixels so that parts of the display aren't cut off. Only actors in the upper left 640 x 832-sized corner are converted to isometric actors. 2D scene for the prototype's world

If I section off another 640 x 832 area to the right of the first (call it "partition 1" and the original "partition 0"), then any actors in that second partition will be mapped to the "second floor" in the isometric world.

.

The only math involved is a simple transformation. I realized collisions can be handled by teleporting actors between the two partitions when their levels change.

As for visibility, I don't think it would be hard (famous last words). Simply don't show the levels above the player if they are above a solid floor. It should look something like this:

.

The worst part will be modifying the light/shadow code. Unfortunately, I didn't do a good enough job planning ahead, and some of the functions will need to be re-written to allow for another dimension. I've also been doing some speed testing--just how large of a scene can be constructed? The bottleneck is scene construction. I may need some sort of caching system, which also means that if I'm going to have generated levels, they'll need to be generated from a seed so they can be replayed later.