GMLscripts.com

Discuss and collaborate on GML scripts
Invert

You are not logged in.

#1 2013-04-21 15:18:08

Marchal_Mig12
Member
Registered: 2009-05-21
Posts: 72

Isometric lighting engine

Hi everyone,

I've been developping a testing a lot of ways to render fast, efficient, and customizable isometric engines. All that came up after my friend and I released Zombie Movie

Gameplay video here :

Now in this game, I was using pure isometric collisions which means I had to calculate every diagonals collisions. Now, this method is kind of reckless because it limits the collisions. Then, I though, what if I made everything coded using top-down algorithms and then render as isometric. I found this solution to be clever. All I have to do is create blocks, and render them as isometric tile. This even gave the possibility to rotate the view in the isometric world.

4fedx1s.png
(the top-view version of the isometric render making collision much fast and easier to handle)

So here's what I did. Each block's information (x,y,depth,height,blend) were stored into a grid's list. For optimisation sake, I did not want an object for each and every isometric tile so I destroyed the top-view block's and I used tiles as isometric block. With a few simple calculations it was possible to determine each tile's x, y and depth.

var i,n,xx,yy,nx,ny,tile;
for(i=0;i<room_width/32;i+=1)
  for(n=0;n<room_height/32;n+=1)
  {
    tile = global.tile_id[i,n]
    if tile then
    {
      xx = global.tile_x[i,n];
      yy = global.tile_y[i,n];
      switch(global.iso_dir)
      {
        case 45:  nx = ( xx+yy)*1/2-16; ny = (-xx+yy)*1/4-global.tile_height[i,n]-24;break;
        case 135: nx = (-xx+yy)*1/2-16; ny = (-xx-yy)*1/4-global.tile_height[i,n]-24;break;
        case 225: nx = (-xx-yy)*1/2-16; ny = ( xx-yy)*1/4-global.tile_height[i,n]-24;break;
        case 315: nx = ( xx-yy)*1/2-16; ny = ( xx+yy)*1/4-global.tile_height[i,n]-24;break;
      }
      global.tile_depth[i,n] = -ny-global.tile_height[i,n]*2-24;
      tile_set_position(tile,nx,ny);
      tile_set_depth(tile,global.tile_depth[i,n]);
    }
  }

Given the huge customization possibilities this method gave me, I even thought of a simple lighting engine that could add up to this. It was as simple as casting a light and change the tiles blend depending on the distance between the tile and the light.

I have also made sure the engine runs as fast as possible. So far it keep hovering at about 900 fps on the debug mode of Game Maker Studio. I will be uploading a little demo and maybe the source a bit later

Here's how it looks like so far (if you look carefully you will see the view has rotated on the second image) :

vdwVAbk.pngvjQGiMt.png
uNHqnzh.png7ti8Cyd.png

I can't think of any other faster and efficient method. By the way, I am making a full game out of it. I hope I will be able to show it to you guys soon.

What do you guys think of this method? Any thoughts?

Last edited by Marchal_Mig12 (2013-04-21 15:28:17)

Offline

#2 2013-04-22 18:23:01

xot
Administrator
Registered: 2007-08-18
Posts: 1,201

Re: Isometric lighting engine

Looks good!

I think running the game in a 2D top-down manner and rendering as isometric is they way most people go. It certainly simplifies things and is what I usually recommend (not that I've successfully built an isometric game). Using tiles instead of objects is very sensible as well. Using color blending for the lighting is the way to go too.

Calculating distances for every cell might be a bit expensive, especially as the number of lights goes up. If I was doing this, my instinct would be to use ds_grids instead of arrays for the light accumulation. With grids I could use a second small grid with the lighting pre-computed (basically a circular gradient, light in the middle, dark at the edges and corners), and use it like a stamp by adding it to the light accumulation grid with ds_grid_add_grid_region(). Each light gets added as needed to the accumulation lighting grid, offset according to its position. Then when you want to light your tiles, you can read the value from the lighting accumulation grid and use it as an index to a look-up table (list or array) of blend colors.

If you wanted to get fancy, instead of a look-up table, you could use separate accumulators for red, green, and blue for full-colored lighting.


Abusing forum power since 1986.

Offline

#3 2013-04-22 18:43:38

Marchal_Mig12
Member
Registered: 2009-05-21
Posts: 72

Re: Isometric lighting engine

Pre-calculated light accumulation into a ds_grid is a clever idea. What is the most expensive so far is resetting the tiles from colored to black after the player walked on it. The best way would probably be to calculate the tile offset that the player has moved from and then only reset tiles for that region.

Now I am thinking about lights appearing on walls. I do not have a clear idea of how I will do this but I do have a few ideas on my mind. One would be to color up the floor part of an isometric block. Then, whenever a block with height's higher than player's height is in light range, swap between the two tiles and then blend the new tile (with floor colored in black) which should only affect the wall part of the block.

2d isometric lighting system can be hard to manage sometimes.

Thanks for your suggestion. I will try it out and post a small demo afterwards.

Offline

#4 2013-07-13 19:34:38

Marchal_Mig12
Member
Registered: 2009-05-21
Posts: 72

Re: Isometric lighting engine

Here's a little video showing the progress using the method you suggested me.

it is coming along pretty well although I gave up on the shadows since I had trouble with it.


I have also been thinking about something similar to 3d where a grid of points with height values stored in it would define the field. Then accessing to that grid, I could change any object's height based on those values. How would that work? Do you think it would be too heavy to process for game maker?

Offline

#5 2013-07-13 20:24:34

xot
Administrator
Registered: 2007-08-18
Posts: 1,201

Re: Isometric lighting engine

Looking good!

A height-map would be good thing to try. If you store the heights of each of cell corners in a ds_grid, you can get the height at any point within a grid cell using some bilinear interpolation.

NOTE: This would require that the heights be continuous, ie. the corner of one cell is the same height as the corners of the other three cells that share that point.

I made a script for exactly this kind of thing:
http://www.gmlscripts.com/forums/viewtopic.php?id=1718

Last edited by xot (2013-07-13 20:31:02)


Abusing forum power since 1986.

Offline

#6 2013-07-13 20:53:18

Marchal_Mig12
Member
Registered: 2009-05-21
Posts: 72

Re: Isometric lighting engine

If I understand the script correctly, that would return the adjusted height between 4 grid coordinates?

Last edited by Marchal_Mig12 (2013-07-13 20:53:56)

Offline

#7 2013-07-13 23:15:04

xot
Administrator
Registered: 2007-08-18
Posts: 1,201

Re: Isometric lighting engine

That's right.


Abusing forum power since 1986.

Offline

#8 2013-07-15 14:16:14

Marchal_Mig12
Member
Registered: 2009-05-21
Posts: 72

Re: Isometric lighting engine

Hey Xot,

I did a little experiment using the script you gave me.

Here it is : http://www.2shared.com/file/G6IfhRpX/Is … htmap.html

Heightmap is working well too. Next step is to find an efficient way to be able to cut the edges straight. Sometimes you don't want to create a slope between two points and create a wall instead. Although I could work around this with invisible walls and a different visual.

Hope you like it. Feel free to suggest any improvement that could be done.

EDIT : Just noticed, it is just not optimized at all, I did that really quick to have a running demonstration.

Last edited by Marchal_Mig12 (2013-07-15 14:17:29)

Offline

#9 2013-07-16 20:43:25

xot
Administrator
Registered: 2007-08-18
Posts: 1,201

Re: Isometric lighting engine

Getting something like this working with discontinuous terrain like cliffs and pits and such complicates it some.

I think the simplest solution, using the current system, is to use a quadrant of grid cells to store the four corner heights of a single terrain cell. Adjacent terrain cells use an adjacent quad of cells in the grid. When you look-up the bilinear height, you double the integer portions of the coordinates first.

In the figure below, each terrain cell is marked with a number, each letter is a cell in the height grid. Each terrain cell has four corner heights (A,B,C,D).

A-----B-----A-----B-----A-----B
|  1  |\\\\\|  2  |\\\\\|  3  |
C-----D-----C-----D-----C-----D
|\\\\\|\\\\\|\\\\\|\\\\\|\\\\\|
A-----B-----A-----B-----A-----B
|  4  |\\\\\|  5  |\\\\\|  6  |
C-----D-----C-----D-----C-----D

Hope that makes sense, it's kind of hard to explain. The idea just occurred to me and I haven't tested it yet.


Abusing forum power since 1986.

Offline

#10 2013-07-17 18:53:39

Marchal_Mig12
Member
Registered: 2009-05-21
Posts: 72

Re: Isometric lighting engine

Indeed, I am not sure to fully understand

Offline

#11 2013-07-18 01:54:23

xot
Administrator
Registered: 2007-08-18
Posts: 1,201

Re: Isometric lighting engine

Maybe this illustration will help make things more clear.

WNHTvXH.png

Last edited by xot (2013-07-28 08:21:24)


Abusing forum power since 1986.

Offline

#12 2013-07-18 06:35:31

icuurd12b42
Member
Registered: 2008-12-11
Posts: 303

Re: Isometric lighting engine

That means the method can be used to define slopes and pillars/plateaus... discontinuous. guess continuous would mean corners would be shared but you would loose the ability to make pillars

Last edited by icuurd12b42 (2013-07-18 06:36:03)

Offline

#13 2013-07-18 09:08:08

xot
Administrator
Registered: 2007-08-18
Posts: 1,201

Re: Isometric lighting engine

Right.


Abusing forum power since 1986.

Offline

#14 2013-07-18 13:31:40

Marchal_Mig12
Member
Registered: 2009-05-21
Posts: 72

Re: Isometric lighting engine

Got it. Thanks. Not as useful for the kind of game I am making atm but certainly will in the future.

Offline

Board footer

Powered by FluxBB