RPG手游中Bresenham算法推导以及应用
admin
2023-02-11 04:00:04
0

Bresenham算法是一开始用于图形学中绘制直线。无论屏幕的分辨率多么的大,它始终都是由一个个的方形像素点组成的。在屏幕上绘制一条有角度的直线时,像素点并不会都落在直线上。对于直线上的点,需要一种算法算出最接近直线上的点或者说最适合的点。BresenHam算法就是其中一种算法。这个算法只会用到较为快速的整数加法、减法和位元移位,所以非常高效。
Bresenham算法一般也用于rpg手游或者其他需要寻路的手游。这类手游的地图会被分成很小的格子(例如:32像素*32像素),利用工具,可以将地图的阻挡区域标出,然后导出地图的配置文件(例如,json或者xml等)。
当rpg手游的实体需要寻路的时候,第一步需要根据地图的阻挡信息,计算出实体到目标点是否可以直线通过,这个时候就需要用到bresenham算法。
本文只考虑直线斜率大于0并且小于1的情况。


先来看一种dda算法:
function dda(x0: number, y0: number, x1: number, y1: number) {
let output = [];
let k = (y1 - y0) / (x1 - x0);
let x = x0 + 1; //x初始值
while (x <= x1) {
let y = Math.floor(k * (x + 1) + 0.5);
output.push({ x: x, y: y });
x = x + 1;
}
return output;
}
代码很少,但是运算中用到了浮点数的乘法和加法,不是一种高效的做法。


接着来看下bresenham算法的推导过程。
Bresenham算法有2种推导方法,如下图所示:
RPG手游中Bresenham算法推导以及应用


为了简单起见,设,直线方程为y = kx,也就是以起始点为坐标原点。

  1. 设置变量,xStep = 1;totalXstep = 0;totalYstep = 0;lineY = 0;gridY = 0;preGridY = 0;deltaX = x1-x0;deltaY= y1-y0。其中lineY为直线上真实的纵坐标,girdY为选择的格子坐标,preGridY为上一个格子坐标。
  2. 由y = kx可知道,当x每增加1,y的增量为k。
  3. 由x0开始推导。
    A.当x = x0 + 1,totalXstep = totalXstep +1,lineY = y0 + k,判别式为k-0.5。
    当k - 0.5 >= 0时,gridY = y0 + 1,totalYstep = totalYstep + 1;
    当k – 0.5 < 0时,gridY = y0;
    preGridY= gridY;
    B.当x = x0 + 2,totalXStep = totalXStep + 1,lineY =y0 + totalXstep k,判别式为 totalXstep k – (totalYstep + 0.5);
    当totalXstep k – (totalYstep + 0.5) >=0时,gridY = preGridY +1,totalYstep = totalYstep + 1;
    当totalXstep
    k – (totalYstep + 0.5) < 0时,gridY = preGridY,
    preGridY= gridY;
  4. 由上可得,判别式为totalXstep k – (totalYstep + 0.5) >=0,k = deltaY / deltaX;将k代入左式,并且两边乘以deltaX,再乘以2得:
    2
    totalXstep deltaY –2deltaXtotalYstep – deltaX >=0
    也可以写成:
    2
    totalXstep deltaY > 2deltaX*totalYstep + deltaX
    由此,这个算法只剩下整数的乘法和加法。

下面我们换另外一种推导方法。
1.设置变量d1,d2,Xi,Xi+1,Yi,Yi+1,Y,X,Hi,Hi+1

  1. d1 = Y- Yi =(k(Xi +1) + b) –Yi
    d2 = Yi +1 - Yi = Yi +1 -(k(Xi +1) + b)
  2. d1-d2 = 2k(Xi +1) – 2 Yi +2b-1
    4.将k = deltaY/deltaX,代入上式得
    deltaX(d1-d2) = 2deltaY Xi -2deltaX Yi + c
    令Hi = deltaX(d1-d2) = 2deltaY Xi -2deltaX Yi + c
    则Hi+1 = 2deltaY Xi+1 -2deltaX Yi+1 + c
    Hi+1 - Hi = 2deltaY( Xi+1 - Xi) – 2deltaX( Yi+1 - Yi)
    令Xi+1 = Xi +1,
    Hi+1 = Hi +2deltaY – 2deltaX( Yi+1 - Yi)
    则:
    A. 如果选择右上方的像素,即:Yi+1 – Yi =1, 则 Hi+1 = Hi +2deltaY – 2deltaX
    B.如果选择右方像素,即Yi+1 = Yi ,则:Hi+1 = Hi +2deltaY
    在起始像素(x0,y0)的第一个参数h0为:
    h0 = 2deltaY – deltaX;
    这个算法只会用到较为快速的整数加法、减法和位元移位,是高效的算法。
    function bresenham(x0: number, y0: number, x1: number, y1: number) {
    let output = [];
    let deltaX = x1 - x0;
    let deltaY = y1 - y0;
    let err = 2
    deltaY - deltaX;
    let x = x0;
    let y = y0;
    while (x <= x1) {
    x++;
    //先假设取右方的点,说明err+2deltaY小于0;
    // 其实也可以假设取右上方的点,判断条件要不同
    err = err + 2
    deltaY;
    if (err >= 0) { //说明取右方的点是不对的,应取右上方的点
    y++;
    err = err - 2 * deltaX;
    }
    output.push({ x: x, y: y });
    }
    }

相关内容

热门资讯

德国总理:美国正在被伊朗羞辱 德国之声4月27日报道,德国总理默茨在访问一所学校时表示,在当前的持续冲突中,伊朗领导层正试图羞辱美...
理响中国|“长”歌以行,风云激... 光阴如梭,东方潮阔。这里是中国的长三角,世界的长三角。无论过去、现在还是未来,这片土地都因时代而生,...
白宫:特朗普及其国安团队开会讨... 新华社华盛顿4月27日电 美国白宫新闻秘书莱维特27日在记者会上证实,总统特朗普及其国家安全团队当天...
人民日报刊文:日本放开杀伤性武... 日本放开杀伤性武器出口推高地缘冲突风险(国际论坛)常思纯《人民日报》(2026年04月28日 第 0...
医疗保障法草案二审:明确生育保... 满足多样化健康保障需求本报记者 彭 波4月27日,医疗保障法草案二审稿提请十四届全国人大常委会第二十...
天津一景区发生自转旋翼机事故1... 澎湃新闻记者 吕新文中国民用航空华北地区管理局4月22日公布《豪客通航“10•1”天津长芦汉盐旅游区...
卡塔尔埃米尔与美国总统特朗普通... 当地时间24日,卡塔尔埃米尔塔米姆与美国总统特朗普通电话,重点就中东地区局势以及伊朗与美国谈判问题交...
男子30年前被扣押2859克黄... 澎湃新闻记者 王鑫家住辽宁省大连市的潘永嘉近日向澎湃新闻反映称,三十年前,他在大连周水子机场被盖州市...
商务部:取消反制欧盟两家金融机... 中华人民共和国商务部令二〇二六年 第1号鉴于欧盟已取消对中国两家金融机构的制裁措施,现公布《关于取消...
过去24小时共有5艘船只通过霍... 总台记者当地时间24日获悉,过去24小时内,共有5艘船只通过霍尔木兹海峡,其中包括一艘伊朗油轮。(总...