Javascript Bresenham算法失败——不断越界

Javascript Bresenham算法失败——不断越界,javascript,jquery,html,bresenham,Javascript,Jquery,Html,Bresenham,我正在制作一个游戏原型,使用Bresenham算法进行玩家移动。我在这里使用了“编辑”下的实现,但我不存储以下要点: 我数学很差(而且我不是开发人员!),所以这可能妨碍了我解决问题的能力。我发现了一篇很好的帖子,从更高的层面解释了算法: 下面是我的代码的一些输出。在每次循环迭代中,我检查我们是否超出了合理的范围。这种情况经常发生。我的错误计算和找分有问题,但我没有数学能力知道如何解决它 在下面的代码中,currentX和currentY应不断变化以接近targetX和targetY。您将看到,有

我正在制作一个游戏原型,使用Bresenham算法进行玩家移动。我在这里使用了“编辑”下的实现,但我不存储以下要点:

我数学很差(而且我不是开发人员!),所以这可能妨碍了我解决问题的能力。我发现了一篇很好的帖子,从更高的层面解释了算法:

下面是我的代码的一些输出。在每次循环迭代中,我检查我们是否超出了合理的范围。这种情况经常发生。我的错误计算和找分有问题,但我没有数学能力知道如何解决它

在下面的代码中,currentX和currentY应不断变化以接近targetX和targetY。您将看到,有一个点,当前坐标和目标坐标中的一个将是相同的,但另一个将是非常不同的。这没有任何意义,因为根据算法,currentX和currentY都应该非常接近目标坐标

编辑3:新输出

entering loop
 in loop. currentX,currentY = 100,100 | targetX,targetY = 27,22
 error2 = 10

 in loop. currentX,currentY = 99,99 | targetX,targetY = 27,22
 error2 = 20

 in loop. currentX,currentY = 98,98 | targetX,targetY = 27,22
 error2 = 30

 in loop. currentX,currentY = 97,97 | targetX,targetY = 27,22
 error2 = 40

 in loop. currentX,currentY = 96,96 | targetX,targetY = 27,22
 error2 = 50

 in loop. currentX,currentY = 95,95 | targetX,targetY = 27,22
 error2 = 60

 in loop. currentX,currentY = 94,94 | targetX,targetY = 27,22
 error2 = 70

 in loop. currentX,currentY = 93,93 | targetX,targetY = 27,22
 error2 = 80

 in loop. currentX,currentY = 92,93 | targetX,targetY = 27,22
 error2 = -66

 in loop. currentX,currentY = 91,92 | targetX,targetY = 27,22
 error2 = -56

 in loop. currentX,currentY = 90,91 | targetX,targetY = 27,22
 error2 = -46

 in loop. currentX,currentY = 89,90 | targetX,targetY = 27,22
 error2 = -36

 in loop. currentX,currentY = 88,89 | targetX,targetY = 27,22
 error2 = -26

 in loop. currentX,currentY = 87,88 | targetX,targetY = 27,22
 error2 = -16

 in loop. currentX,currentY = 86,87 | targetX,targetY = 27,22
 error2 = -6

 in loop. currentX,currentY = 85,86 | targetX,targetY = 27,22
 error2 = 4

 in loop. currentX,currentY = 84,85 | targetX,targetY = 27,22
 error2 = 14

 in loop. currentX,currentY = 83,84 | targetX,targetY = 27,22
 error2 = 24

 in loop. currentX,currentY = 82,83 | targetX,targetY = 27,22
 error2 = 34

 in loop. currentX,currentY = 81,82 | targetX,targetY = 27,22
 error2 = 44

 in loop. currentX,currentY = 80,81 | targetX,targetY = 27,22
 error2 = 54

 in loop. currentX,currentY = ,80 | targetX,targetY = 27,22
 error2 = 64

 in loop. currentX,currentY = ,79 | targetX,targetY = 27,22
 error2 = 74

 in loop. currentX,currentY = 77,78 | targetX,targetY = 27,22
 error2 = 84

 in loop. currentX,currentY = 76,78 | targetX,targetY = 27,22
 error2 = -62

 in loop. currentX,currentY = 75,77 | targetX,targetY = 27,22
 error2 = -52

 in loop. currentX,currentY = 74,76 | targetX,targetY = 27,22
 error2 = -42

 in loop. currentX,currentY = 73,75 | targetX,targetY = 27,22
 error2 = -32

 in loop. currentX,currentY = 72,74 | targetX,targetY = 27,22
 error2 = -22

 in loop. currentX,currentY = 71,73 | targetX,targetY = 27,22
 error2 = -12

 in loop. currentX,currentY = 70,72 | targetX,targetY = 27,22
 error2 = -2

 in loop. currentX,currentY = 69,71 | targetX,targetY = 27,22
 error2 = 8

 in loop. currentX,currentY = 68,70 | targetX,targetY = 27,22
 error2 = 18

 in loop. currentX,currentY = 67,69 | targetX,targetY = 27,22
 error2 = 28

 in loop. currentX,currentY = 66,68 | targetX,targetY = 27,22
 error2 = 38

 in loop. currentX,currentY = 65,67 | targetX,targetY = 27,22
 error2 = 48

 in loop. currentX,currentY = 64,66 | targetX,targetY = 27,22
 error2 = 58

 in loop. currentX,currentY = 63,65 | targetX,targetY = 27,22
 error2 = 68

 in loop. currentX,currentY = 62,64 | targetX,targetY = 27,22
 error2 = 

 in loop. currentX,currentY = ,64 | targetX,targetY = 27,22
 error2 = -68

 in loop. currentX,currentY = 60,63 | targetX,targetY = 27,22
 error2 = -58

 in loop. currentX,currentY = 59,62 | targetX,targetY = 27,22
 error2 = -48

 in loop. currentX,currentY = 58,61 | targetX,targetY = 27,22
 error2 = -38

 in loop. currentX,currentY = 57,60 | targetX,targetY = 27,22
 error2 = -28

 in loop. currentX,currentY = 56,59 | targetX,targetY = 27,22
 error2 = -18

 in loop. currentX,currentY = 55,58 | targetX,targetY = 27,22
 error2 = -8

 in loop. currentX,currentY = 54,57 | targetX,targetY = 27,22
 error2 = 2

 in loop. currentX,currentY = 53,56 | targetX,targetY = 27,22
 error2 = 12

 in loop. currentX,currentY = 52,55 | targetX,targetY = 27,22
 error2 = 22

 in loop. currentX,currentY = 51,54 | targetX,targetY = 27,22
 error2 = 32

 in loop. currentX,currentY = 50,53 | targetX,targetY = 27,22
 error2 = 42

 in loop. currentX,currentY = 49,52 | targetX,targetY = 27,22
 error2 = 52

 in loop. currentX,currentY = 48,51 | targetX,targetY = 27,22
 error2 = 62

 in loop. currentX,currentY = 47,50 | targetX,targetY = 27,22
 error2 = 72

 in loop. currentX,currentY = 46,49 | targetX,targetY = 27,22
 error2 = 82

 in loop. currentX,currentY = 45,49 | targetX,targetY = 27,22
 error2 = -64

 in loop. currentX,currentY = 44,48 | targetX,targetY = 27,22
 error2 = -54

 in loop. currentX,currentY = 43,47 | targetX,targetY = 27,22
 error2 = -44

 in loop. currentX,currentY = 42,46 | targetX,targetY = 27,22
 error2 = -34

 in loop. currentX,currentY = 41,45 | targetX,targetY = 27,22
 error2 = -24

 in loop. currentX,currentY = 40,44 | targetX,targetY = 27,22
 error2 = -14

 in loop. currentX,currentY = 39,43 | targetX,targetY = 27,22
 error2 = -4

 in loop. currentX,currentY = 38,42 | targetX,targetY = 27,22
 error2 = 6

 in loop. currentX,currentY = 37,41 | targetX,targetY = 27,22
 error2 = 16

 in loop. currentX,currentY = 36,40 | targetX,targetY = 27,22
 error2 = 26

 in loop. currentX,currentY = 35,39 | targetX,targetY = 27,22
 error2 = 36

 in loop. currentX,currentY = 34,38 | targetX,targetY = 27,22
 error2 = 46

 in loop. currentX,currentY = 33,37 | targetX,targetY = 27,22
 error2 = 56

 in loop. currentX,currentY = 32,36 | targetX,targetY = 27,22
 error2 = 66

 in loop. currentX,currentY = 31,35 | targetX,targetY = 27,22
 error2 = 76

 in loop. currentX,currentY = 30,34 | targetX,targetY = 27,22
 error2 = 86

 in loop. currentX,currentY = 29,34 | targetX,targetY = 27,22
 error2 = -60

 in loop. currentX,currentY = 28,33 | targetX,targetY = 27,22
 error2 = -50

 in loop. currentX,currentY = 27,32 | targetX,targetY = 27,22
 error2 = -40

 in loop. currentX,currentY = 26,31 | targetX,targetY = 27,22
 error2 = -30

 in loop. currentX,currentY = 25,30 | targetX,targetY = 27,22
 error2 = -20

 in loop. currentX,currentY = 24,29 | targetX,targetY = 27,22
 error2 = -10

 in loop. currentX,currentY = 23,28 | targetX,targetY = 27,22
 error2 = 0

 in loop. currentX,currentY = 22,27 | targetX,targetY = 27,22
 error2 = 10

 in loop. currentX,currentY = 21,26 | targetX,targetY = 27,22
 error2 = 20

 in loop. currentX,currentY = 20,25 | targetX,targetY = 27,22
 error2 = 30

 in loop. currentX,currentY = 19,24 | targetX,targetY = 27,22
 error2 = 40

 in loop. currentX,currentY = 18,23 | targetX,targetY = 27,22
 error2 = 50

 in loop. currentX,currentY = 17,22 | targetX,targetY = 27,22
 error2 = 60

 in loop. currentX,currentY = 16,21 | targetX,targetY = 27,22
 error2 = 70

 in loop. currentX,currentY = 15,20 | targetX,targetY = 27,22
 error2 = 80

 in loop. currentX,currentY = 14,20 | targetX,targetY = 27,22
 error2 = -66

 in loop. currentX,currentY = 13,19 | targetX,targetY = 27,22
 error2 = -56

 in loop. currentX,currentY = 12,18 | targetX,targetY = 27,22
 error2 = -46

 in loop. currentX,currentY = 11,17 | targetX,targetY = 27,22
 error2 = -36

 in loop. currentX,currentY = 10,16 | targetX,targetY = 27,22
 error2 = -26

 in loop. currentX,currentY = 9,15 | targetX,targetY = 27,22
 error2 = -16

 in loop. currentX,currentY = 8,14 | targetX,targetY = 27,22
 error2 = -6

 in loop. currentX,currentY = 7,13 | targetX,targetY = 27,22
 error2 = 4

 in loop. currentX,currentY = 6,12 | targetX,targetY = 27,22
 error2 = 14

 in loop. currentX,currentY = 5,11 | targetX,targetY = 27,22
 error2 = 24

 in loop. currentX,currentY = 4,10 | targetX,targetY = 27,22
 error2 = 34

 in loop. currentX,currentY = 3,9 | targetX,targetY = 27,22
 error2 = 44

 in loop. currentX,currentY = 2,8 | targetX,targetY = 27,22
 error2 = 54

 in loop. currentX,currentY = 1,7 | targetX,targetY = 27,22
 error2 = 64

 in loop. currentX,currentY = 0,6 | targetX,targetY = 27,22
 error2 = 74

 in loop. currentX,currentY = -1,5 | targetX,targetY = 27,22
 error2 = 84

 crash. x-distance from target = 29 | y-distance = 17
 in loop. currentX,currentY = 27,22 | targetX,targetY = 27,22
 loop done. currentX,currentY = 27,22 | targetX,targetY = 27,22
编辑:代码张贴在下面

编辑2:更多相关代码发布在下面

hermes.js-描述玩家的角色(hermes)以及他与2d游戏机的关系

var Hermes = function(currentX,currentY) {
this.currentX = currentX;
this.currentY = currentY;
this.targetX = currentX;
this.targetY = currentY;
this.radius = 20;
this.speed = 5;
this.health = 500;

var dir = **I removed this string to protect my privacy**
this.imgSrc = dir + "/img/hermes.jpg";

// https://stackoverflow.com/questions/4672279/bresenham-algorithm-in-javascript
// Bresenham's line algorithm
// will fall apart if i add obstacles.
this.Move = function() {

    var sx, sy;
    var dx = Math.abs(this.targetY - this.currentY);
    var dy = Math.abs(this.targetX - this.currentX);
    var error = dx - dy;

    if (this.currentX < this.targetX) {
        sx = 1;
    }
    else {
        sx = -1;
    }

    if (this.currentY < this.targetY) {
        sy = 1;
    }
    else {
        sy = -1;
    }

    console.log("entering loop");

    while (true) {  

        console.log("in loop. currentX,currentY = " + this.currentX + "," + this.currentY + " | targetX,targetY = " + this.targetX + "," + this.targetY);

        // this.Draw();
        redraw();

        if ((this.currentX == this.targetX) && (this.currentY == this.targetY)) break;
        // if ( (sx*this.currentX >= sx*this.targetX) && (sy*this.currentY >= sy*this.targetY) ) break;
        var error2 = error << 1;
        if (error2 > -dy) {
            error = error - dy;
            this.currentX = this.currentX + sx;
        }
        if (error2 < dx) {
            error = error + dx;
            this.currentY = this.currentY + sy;
        }

        console.log("error2 = " + error2);
        console.log("");

        // temp
        if (this.currentX < -1 || this.currentY < -1 || this.currentX > 600 || this.currentY > 600) {
            console.log("crash. x-distance from target = " + (this.targetX - this.currentX) + " | y-distance = " + (this.targetY - this.currentY) );
            this.currentX = this.targetX;
            this.currentY = this.targetY;
        }

    } // end while loop

    console.log("loop done. currentX,currentY = " + this.currentX + "," + this.currentY + " | targetX,targetY = " + this.targetX + "," + this.targetY);

}; // end move fxn

this.Draw = function () {
    context.drawImage(hermesAvatar, this.currentX, this.currentY, 43, 52);
}; // end draw fxn
}; // end hermes

如果我读错了,请原谅我:看起来你把你的x和y混淆在一个地方了

在代码的开头有一个块

if (this.currentX < this.targetY) {  
    sx = 1;  
}
您还可以存储
sx*this.targetX
sy*this.targetY
以避免在循环中重复计算,但这可以在代码运行后完成

我用我自己的Bresenham的js实现做了一个,它很好地从(100100)收敛到(34,26)

无法立即了解代码为何无法收敛


我想知道当算法运行时,是否有其他东西在影响对象的
.currentX'和.currentY
?尝试使用private
var currentX
var currentY
并在symapathy中设置对象的
.currentX'和.currentY
。这将消除外部影响。

您能发布您的实际代码吗?currentX和currentY的方向肯定是正确的。你是说它们最终不会收敛到目标上吗?不要担心
error2
疯狂地摇摆-这就是算法的工作方式<代码>错误2是一个中间计算,确定影响“楼梯”的方向。这不是对直线偏差大小的直接测量。添加了代码。:)@甜菜根甜菜根是的,currentX和currentY的方向正确。不过,它们并不一致。如果目标是(34,26),那么最后几个坐标不是应该是(35,27)吗?currentY首先到达它的目标(在x之前!),但一直在减少。@jfriend00代码已添加。:)这是为玩家角色创建的伪类的一部分。
如果(this.currentX
-很好。我错过了。感谢你注意到x和y的混淆。我发誓,无论我多么盯着代码思考,“哦,一定有一些愚蠢的小错误。”,我从来没有看到过它。因此,我不是一个专门的开发人员。^^另外,谢谢你的理智检查提示。我的代码仍然不起作用。>仍然不起作用??你能编辑你的帖子来反映你所做的所有更改吗?这只是个人的:)Neon关于
if(This.currentX
很可能会解决这个问题。再想一想,我的“外部影响”理论可能是一条红鲱鱼。请参阅我的更新,它作为播放器构造函数的
.slideTo()
方法实现。这应该是你自己代码的一个子集。我爱你。我改变了我的代码结构,使之与你的.slideTo()一样工作,现在,当前的x,Y会聚在targetX,Y上!现在,我只需要修复我的绘图,这样我就可以看到玩家角色幻灯片。尽管让Bresenham工作是令人满意的,但屏幕可能在达到目标点之前不会更新-换句话说,你可能看不到逐步移动。一般来说,浏览器不会尝试使用中间DOM状态更新图形界面(屏幕),但跳转到任何最终状态。解决方法是使用jQuery的
.animate()
,它使用多个连续线程提供中断,浏览器可以在中断时自由更新屏幕。
.animate()
方法还提供了在给定时间(比如500毫秒)内完成的优势。此外,请为发现X-Y错误的@soundslikeneon保留一些爱心。
if (this.currentX < this.targetY) {  
    sx = 1;  
}
if ((sx*this.currentX >= sx*this.targetX) && (sy*this.currentY >= sy*this.targetY)) break;