Efficient 2D Tile based lighting system

后端 未结 3 1117
栀梦
栀梦 2020-12-25 08:53

What is the most efficient way to do lighting for a tile based engine in Java?
Would it be putting a black background behind the tiles and changing the tiles\' alpha?

3条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-25 09:13

    Raytracing might be the simpliest approach.

    • you can store which tiles have been seen (used for automapping, used for 'remember your map while being blinded', maybe for the minimap etc.)
    • you show only what you see - maybe a monster of a wall or a hill is blocking your view, then raytracing stops at that point
    • distant 'glowing objects' or other light sources (torches lava) can be seen, even if your own light source doesn't reach very far.
    • the length of your ray gives will be used to check amount light (fading light)
    • maybe you have a special sensor (ESP, gold/food detection) which would be used to find objects that are not in your view? raytrace might help as well ^^

    how is this done easy?

    • draw a line from your player to every point of the border of your map (using Bresehhams Algorithm http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm walk along that line (from your character to the end) until your view is blocked; at this point stop your search (or maybe do one last final iteration to see what did top you)
    • for each point on your line set the lighning (maybe 100% for distance 1, 70% for distance 2 and so on) and mark you map tile as visited

    maybe you won't walk along the whole map, maybe it's enough if you set your raytrace for a 20x20 view? NOTE: you really have to walk along the borders of viewport, its NOT required to trace every point.

    i'm adding the line algorithm to simplify your work:

    public static ArrayList getLine(Point start, Point target) {
        ArrayList ret = new ArrayList();
        int x0 =  start.x;
        int y0 =  start.y;
    
        int x1 = target.x;
        int y1 = target.y;
    
        int sx = 0;
        int sy = 0;
    
        int dx =  Math.abs(x1-x0);
        sx = x0= dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */
            if (e2 <= dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */
        }
    
        return ret;
    }
    

    i did this whole lightning stuff some time ago, a* pathfindin feel free to ask further questions

    Appendum: maybe i might simply add the small algorithms for raytracing ^^

    to get the North & South Border Point just use this snippet:

    for (int x = 0; x 

    and the raytrace works like this:

    private static void rayTrace(ArrayList line, WorldMap map, int radius) {
    
        //int radius = radius from light source     
        for (Point p: line){
    
            boolean doContinue = true;
            float d = distance(line.get(0), p);
    
            //caclulate light linear 100%...0% 
            float amountLight = (radius - d) / radius;  
            if (amountLight < 0 ){
                amountLight = 0;
            }
    
            map.setLight( p, amountLight );
    
            if ( ! map.isViewBlocked(p) ){ //can be blockeb dy wall, or monster  
                doContinue = false;
                break;
            }
    
        }
    }
    

提交回复
热议问题