• interested in more? sign up to the newsletter

     

Heroes of Loot Light system explained

Tweet about this on TwitterShare on RedditShare on Facebook

Screenshot_2013-04-11-15-37-32

I’ve been getting various questions and remarks on the “light system” I use in Heroes of Loot.. so I figure it would make for some good blog filling to talk about what and how and why.

For those who don’t know any of my code, let me just explain that I’m not a technically great coder.. I like to do simple code and just stuff that works and looks good. I’m more creative then technical, so keep that in mind cause this lighting stuff is really as simple and basic as it looks.

My engine renders the background using a simple tile-rendering. The dungeon tiles are 16×16, and the game runs in a low pixel-art-friendly resolution, I personally like to call it 160p :)

My lightning system is simply another tile-map I lay on top of the screen. The tiles in this map are 8×8, and the tiles are all black 8×8 tiles but with variations in the alpha transparency.

So if an area is fully lit, the alpha is 0, and it basically means I don’t render that light-map-tile saving some time.  In fully dark area’s the alpha is 255 and light-map-tile is fully rendered on top of the background, making it become black and covering the background fully.

This is a bit backwards as you can imagine, cause my light system will actually render fully lit area’s faster than fully dark area’s.. which is great, cause most of the action happens in the lit area’s on the screen.

This also means I can go crazy with light-sources, so bullets, flames, energy orbs, everything can create a little light area, and it will not cause any noticeable difference to the game speed, cause the calculations to make it light up are balanced out by the fact that I render a lot less pixels.

Creating the light is simply resetting the light-map every frame, and then changing the alpha values in a circle of a specific size around a specific point in the map. The result is a very rough, crude, and simple pixel-art style lighting system that doesn’t feel out of place in a pixel-art game likes Heroes of Loot :

Schermafbeelding 2013-05-06 om 17.31.47

Bookmark the permalink.
  • zoqfotpik

    You may not think you’re technical but you have some knowledge about how to get 2d games running fast on mobile hardware while looking pretty good and that’s all the technical you need.

  • indie11

    Good article!
    How do define ” if an area is fully lit” or “an area is all dark”?
    Do you define a radius within which the area is lit?
    and isn’t it costly to continuously loop through the lighting tile map?

    Thanks!

    • orangepascal

      the are is based on the player’s location, or the flames on the wall, and even some of the energy orbs and other flying things.
      I just use their “tile” location as parameter for the function that then generates a circle of fully lit blending towards darkness based on that location as center.

      By default the whole level would be dark, and I then specify where those lights are.

  • David

    If it works that is all that matters :)

    How do you do the circle calculations? Do you use Bresenham’s midpoint circle algorithm?

    • orangepascal

      very true, and yes a quick and simple Bresenham does the trick :)

      • David

        Thank you Pascal. How do you calculate the alpha for each “tile” in the circle?

        I use the Pythagorean theorem to calculate the distance from a point in the circle to the center and used the circle radius.

        Alpha at center is 0 (fully transparent)
        Alpha at radius is 255 (fully black))

        The alpha is then the relative linear distance for a given point in the circle to the radius. This works and is relatively quick, but does not give the nice fluent gradient alphas I see in HoL.

        • orangepascal

          How about this, the full “removeFog” function I wrote. This basically takes the center X and center Y and a crude “radius” value and then stores the light-alpha values in the lightmap:

          public final void removeFog(int px, int py, int lightSize) {
          px=px< <1; py=py<<1; int y1; int x1=px; int x2=px+1; int y2=py+24; if (y2>(TileMap.tileMapH< <1)) y2=(TileMap.tileMapH<<1); int shadeY; int light; int baseLight=256/(lightSize<<3); int lightX; int count=0; while (count<24) { lightX=count*count; if (x1>=0 && x1=0 && y1255) light=255;

          if (light>myWorld.fogMap[x1+(y1*(TileMap.tileMapW< <1))]) { if (myWorld.isEdge(x1>>1, y1>>1) || myWorld.getTileRenderMap(x1>>1,y1>>1)>=48) {
          myWorld.fogMap[x1+(y1*(TileMap.tileMapW< <1))]=light; } } } y1++; } } x1--; if (x2>=0 && x2=0 && y1255) light=255;

          if (light>myWorld.fogMap[x2+(y1*(TileMap.tileMapW< <1))]) { if (myWorld.isEdge(x2>>1, y1>>1) || myWorld.getTileRenderMap(x2>>1,y1>>1)>=48) {
          myWorld.fogMap[x2+(y1*(TileMap.tileMapW<<1))]=light; } } } y1++; } } x2++; count++; } }

          • David

            Thank you so much for sharing this :) That is really generous of you!

      • David

        And forgot to ask one more thing:

        If you have two overlapping “circles” from different light-sources what alpha do you use?

        1. The least transparent one?
        2. The most transparent one?
        3. Average of the two alphas?

        I would probably go with 2. since that would be the “strongest” light that would “shine” through and saves and additional calculation.

        • orangepascal

          I take the brightest value. So if the newly calculated value (of the 2nd or 3rd light) is less than the value we already stored in the lightmap, then we use the previously calculated one.

          It’s all the same color light anyway (multi-colored light would require more trickery especially with overlapping lights)