Java Bresenham线到圆周上的点

Java Bresenham线到圆周上的点,java,line,geometry,point,bresenham,Java,Line,Geometry,Point,Bresenham,我正在尝试为2D游戏编写一个闪电引擎。和大多数游戏一样,我在地图上有一张地图[]和一张光照地图[]。没什么特别的。从一个灯光点开始,我在灯光范围内画了一个圆圈,并试图画一条布雷森汉姆线到圆圈上的点。由于某些原因,我的bresenham算法并不完美,我添加了一个图像。为什么bresenham直线算法跳过了一些对角坐标,例如从点20,20开始,跳过了点13,14和点14,13。我认为计算错误。我使用set来避免数组中的重复。圆圈算法工作正常,在数组中我得到了正确的值。图中还有一个问题:在某些情况下,

我正在尝试为2D游戏编写一个闪电引擎。和大多数游戏一样,我在地图上有一张地图[]和一张光照地图[]。没什么特别的。从一个灯光点开始,我在灯光范围内画了一个圆圈,并试图画一条布雷森汉姆线到圆圈上的点。由于某些原因,我的bresenham算法并不完美,我添加了一个图像。为什么bresenham直线算法跳过了一些对角坐标,例如从点20,20开始,跳过了点13,14和点14,13。我认为计算错误。我使用set来避免数组中的重复。圆圈算法工作正常,在数组中我得到了正确的值。图中还有一个问题:在某些情况下,水平线和有时垂直线也是错误的。我认为这也是布雷森汉姆的错误。我正在尝试调试,它显示了bresenham的错误。白色立方体是圆周上的点,红色由bresenhams line algo添加到光照图中,有一座小山挡住了光线,它工作完美,启用了我的小地图。我添加了更多图像:


我想出了用另一种方法生成阴影和灯光的方法。它更简单,工作100%。以下是点光源平铺闪电的代码:

import java.awt.Point;
import java.util.HashSet;
import java.util.Random;

public class PointLight {

Handler handler;
public int x,y;
private int plx,ply;
public int radius,intensity;
public static Point pnt;
public static HashSet<Point> circpoints;
public static HashSet<Point> bline;
public GameObject BoundToObject;

public PointLight(int x,int y,int radius,int intensity,Handler handler) {
    super();
    this.x=x;
    this.y=y;
    this.radius=radius;
    this.intensity=intensity;
    this.handler=handler;
    circpoints = new HashSet<Point>();
    bline = new HashSet<Point>();
    pnt=new Point();
}

public PointLight(GameObject GamObj,int radius,int intensity,Handler handler) {
    super();
    this.BoundToObject=GamObj;
    this.x=(int) GamObj.getX();
    this.y=(int) GamObj.getY();
    this.radius=radius;
    this.intensity=intensity;
    this.handler=handler;
    circpoints = new HashSet<Point>();
    bline = new HashSet<Point>();
    pnt=new Point();
}

public void tick() {
    Random rnd;

    rnd=new Random();
    x+=rnd.nextDouble()*4;
    y+=rnd.nextDouble()*4;

    if (BoundToObject != null) {
        x=(int) BoundToObject.getX();
        y=(int) BoundToObject.getY();
    }

    //visibility for rendering process (200 is for range, to avoid sudden light emitting)
    if (x > (int)Game.camera.getX()-200 && x < (int)Game.camera.getX()+Game.Windoww+200 && y > (int)Game.camera.getY()-200 && y < (int)Game.camera.getY()+Game.Windowh+200) {
        if (!Game.visiblepointlight.contains(this)) Game.visiblepointlight.add(this);
    } else {
        if (Game.visiblepointlight.contains(this)) Game.visiblepointlight.remove(this);
    }

    //reset visible lightmap
    for (int i=(int)((Game.camera.getX()-200)/Game.tilesize);i < (int)((Game.camera.getX()+200+Game.Windoww)/Game.tilesize);i++) {
        for (int j=(int)((Game.camera.getY()-200)/Game.tilesize);j < (int)((Game.camera.getY()+200+Game.Windowh)/Game.tilesize);j++) {
            if (i > 0 && i < Game.tiles && j > 0 && j < Game.tiles) Game.lightMap[i][j]=Game.AmbientLight;
        }
    }

    //set lights
    for (PointLight pli : Game.visiblepointlight) {
        bline.clear();
        circpoints.clear();
        Lightcalculate(pli);
    }

}

public void Lightcalculate(PointLight pl) {

    plx=pl.x/Game.tilesize;
    ply=pl.y/Game.tilesize;

    RayCast(plx,ply,pl.radius);
        for (Point bln :bline) {
            double mult = (pl.intensity / PointDistance(plx,ply,bln.x,bln.y))/(Game.tilesize*3);
            if (Game.lightMap[bln.x][bln.y] < mult) Game.lightMap[bln.x][bln.y] =     mult;
            if (Game.lightMap[bln.x][bln.y] > 1) Game.lightMap[bln.x][bln.y]= 1;
        }
}

private void RayCast(int xcord,int ycord,int range) {

    double angle = 0;
    int rays=range*10+1;

    for (int i=0; i<rays; i++) {
        angle += 2 * Math.PI / rays;
        for (int j=0;j<range;j++) {
            double xx = xcord+Math.sin(angle)*j;
            double yy = ycord+Math.cos(angle)*j;
            if ((int) xx <= 0 || (int) yy <= 0 || (int) xx >= Game.tiles-1 || (int) yy >= Game.tiles-1 ) continue;
            if (Game.map[(int) xx][(int)yy] >= 0.8) break;
            Point dir = new Point((int) Math.round(xx),(int)Math.round(yy));
            bline.add(dir);
        }
    }
}

private double PointDistance(int x1, int y1, int x2, int y2) {       
    return Math.sqrt((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1));
}
}
import java.awt.Point;
import java.util.HashSet;
import java.util.Random;

public class PointLight {

Handler handler;
public int x,y;
private int plx,ply;
public int radius,intensity;
public static Point pnt;
public static HashSet<Point> circpoints;
public static HashSet<Point> bline;
public GameObject BoundToObject;

public PointLight(int x,int y,int radius,int intensity,Handler handler) {
    super();
    this.x=x;
    this.y=y;
    this.radius=radius;
    this.intensity=intensity;
    this.handler=handler;
    circpoints = new HashSet<Point>();
    bline = new HashSet<Point>();
    pnt=new Point();
}

public PointLight(GameObject GamObj,int radius,int intensity,Handler handler) {
    super();
    this.BoundToObject=GamObj;
    this.x=(int) GamObj.getX();
    this.y=(int) GamObj.getY();
    this.radius=radius;
    this.intensity=intensity;
    this.handler=handler;
    circpoints = new HashSet<Point>();
    bline = new HashSet<Point>();
    pnt=new Point();
}

public void tick() {
    Random rnd;

    rnd=new Random();
    x+=rnd.nextDouble()*4;
    y+=rnd.nextDouble()*4;

    if (BoundToObject != null) {
        x=(int) BoundToObject.getX();
        y=(int) BoundToObject.getY();
    }

    //visibility for rendering process (200 is for range, to avoid sudden light emitting)
    if (x > (int)Game.camera.getX()-200 && x < (int)Game.camera.getX()+Game.Windoww+200 && y > (int)Game.camera.getY()-200 && y < (int)Game.camera.getY()+Game.Windowh+200) {
        if (!Game.visiblepointlight.contains(this)) Game.visiblepointlight.add(this);
    } else {
        if (Game.visiblepointlight.contains(this)) Game.visiblepointlight.remove(this);
    }

    //reset visible lightmap
    for (int i=(int)((Game.camera.getX()-200)/Game.tilesize);i < (int)((Game.camera.getX()+200+Game.Windoww)/Game.tilesize);i++) {
        for (int j=(int)((Game.camera.getY()-200)/Game.tilesize);j < (int)((Game.camera.getY()+200+Game.Windowh)/Game.tilesize);j++) {
            if (i > 0 && i < Game.tiles && j > 0 && j < Game.tiles) Game.lightMap[i][j]=Game.AmbientLight;
        }
    }

    //set lights
    for (PointLight pli : Game.visiblepointlight) {
        bline.clear();
        circpoints.clear();
        Lightcalculate(pli);
    }

}

public void Lightcalculate(PointLight pl) {

    plx=pl.x/Game.tilesize;
    ply=pl.y/Game.tilesize;

    RayCast(plx,ply,pl.radius);
        for (Point bln :bline) {
            double mult = (pl.intensity / PointDistance(plx,ply,bln.x,bln.y))/(Game.tilesize*3);
            if (Game.lightMap[bln.x][bln.y] < mult) Game.lightMap[bln.x][bln.y] =     mult;
            if (Game.lightMap[bln.x][bln.y] > 1) Game.lightMap[bln.x][bln.y]= 1;
        }
}

private void RayCast(int xcord,int ycord,int range) {

    double angle = 0;
    int rays=range*10+1;

    for (int i=0; i<rays; i++) {
        angle += 2 * Math.PI / rays;
        for (int j=0;j<range;j++) {
            double xx = xcord+Math.sin(angle)*j;
            double yy = ycord+Math.cos(angle)*j;
            if ((int) xx <= 0 || (int) yy <= 0 || (int) xx >= Game.tiles-1 || (int) yy >= Game.tiles-1 ) continue;
            if (Game.map[(int) xx][(int)yy] >= 0.8) break;
            Point dir = new Point((int) Math.round(xx),(int)Math.round(yy));
            bline.add(dir);
        }
    }
}

private double PointDistance(int x1, int y1, int x2, int y2) {       
    return Math.sqrt((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1));
}
}