当精灵移动朝向物体时,使精灵运动变得平滑

时间:2014-07-16 12:42:23

标签: javascript html5 canvas sprite

我正在研究鱼精灵动画。目前,当我添加一块食物时,精灵动画将向前移动以吃掉它。但我无法让它顺利地游向食物。有时,精灵动画会上下移动直到它到达食物。

以下是精灵动画如何向食物移动:

Fish.prototype.chaseFood = function(index) {
    if (this.xPos > foodArray[index].x + foodWidth) {
        this.speedX = -1 * Math.abs(this.speedX);
    } else if (this.xPos < foodArray[index].x) {
        this.speedX = Math.abs(this.speedX);
    }
    if (this.yPos > foodArray[index].y + foodHeight) {
        this.speedY = -1 * Math.abs(this.speedY);
    } else if (this.yPos < foodArray[index].y) {
        this.speedY = Math.abs(this.speedY);
    }
};

无论如何都要让它更顺畅地游向食物而不是向上和向下移动。

2 个答案:

答案 0 :(得分:0)

我计算鱼和食物之间的角度,让鱼朝这个角度移动。

以下是一些帮助你的帮助函数:

function distanceBetweenPoints(a, b)
{
    return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
}

function angleBetweenPoints(a, b)
{
    return Math.atan2(b.y-a.y,b.x-a.x)*180/Math.PI;
}

用法:

var angle = angleBetweenPoints({ x: fish.x, y: fish.y }, { x: food.x, y: food.y });

然后你可以做类似的事情:

fish.x += Math.sin(angle * Math.PI / 180) * 10;
fish.y += Math.cos(angle * Math.PI / 180) * 10;

答案 1 :(得分:0)

我想你希望你的精灵从一组坐标(它的位置)直接移动到另一组坐标(食物的位置)。
http://coolmath.com/algebra/08-lines/06-finding-slope-line-given-two-points-01.htm

因此,如果您的x坐标是6像素的差异而您的y坐标是4的差异,那么当我们增加我们快乐的小鱼的x和y偏移时,我们希望保持6到4的比率。

在这种情况下,我们可以更改程序,一次将x移动1个像素,然后一次将y移动4/6像素,从而沿着直接朝向目标的路径前进。如果我们将y增加一个完整的像素,它将直接到达目标下方,然后直接向上。这将是一个间接的路径,看起来不太现实。

实际上我认为它会到达目标的左边,然后如果你使用1比1的比例直接进入旧版本,但我认为你知道我的意思。

我会尝试调整我的代码示例:

int fishSpeed = 2;
float xOffset = fishSpeed;
float yOffset = fishSpeed;
float xDis = abs(this.xPos-(foodArray[index].x + foodWidth));
float yDis = abs(this.yPos-(foodArray[index].y + foodWidth));
//each offset changes depending on how far it is from goal
xOffset = xOffset * (xDis / (xDis + yDis));
yOffset = yOffset * (yDis / (xDis + yDis));

if(this.xPos > foodArray[index].x) this.xPos+=xOffset;
if(this.yPos > foodArray[index].y) this.yPos+=yOffset;
if(this.xPos < foodArray[index].x) this.xPos-=xOffset;
if(this.yPos < foodArray[index].y) this.yPos-=yOffset;

抱歉,我无法使用您的示例。我不知道它是否会有所帮助,但这里有一个完整的.htm文件,它有一个由鼠标控制的兔子wabbit和一个被另一个wabbit直接追逐的兔子wabbit。 wabbit将直接进入其目标。该文件需要在同一目录中的processing.js。

<!DOCTYPE html>
<html>
<body bgcolor="lightblue"   style="margin:0;">
<center>
<script src="processing.js"></script>
<script type="application/processing">

void setup(){
    size(screen.width*.9,screen.height*.9);
    blueWabbit = new wabbit(600,600,105);
    pinkWabbit = new wabbit(100,100,100);
    blueWabbit.blue = 255;
    blueWabbit.red = 128;
    blueWabbit.green = 128;

    wabbitSpeed = 5;
    }

void draw() { 

    float xOffset = wabbitSpeed;
    float yOffset = wabbitSpeed;
    float xDis = abs(pinkWabbit.xpos-blueWabbit.xpos);
    float yDis = abs(pinkWabbit.ypos-blueWabbit.ypos);
    xOffset = xOffset * (xDis / (xDis + yDis));
    yOffset = yOffset * (yDis / (xDis + yDis));

    if(pinkWabbit.xpos > blueWabbit.xpos) blueWabbit.xpos+=xOffset;
    if(pinkWabbit.ypos > blueWabbit.ypos) blueWabbit.ypos+=yOffset;
    if(pinkWabbit.xpos < blueWabbit.xpos) blueWabbit.xpos-=xOffset;
    if(pinkWabbit.ypos < blueWabbit.ypos) blueWabbit.ypos-=yOffset;

    if (xDis+yDis<wabbitSpeed){
        for(int a =0;a<20; a++)babyWabbit();
    }
    else background(0,0,0,0);

    pinkWabbit.show();
    blueWabbit.show();
    pinkWabbit.xpos = mouseX;
    pinkWabbit.ypos = mouseY;


    /*
    fill(0);
    text("blue x = "+(int)blueWabbit.xpos,10,10);
    text("blue y = "+(int)blueWabbit.ypos,10,20);
    text("pink x = "+pinkWabbit.xpos,10,30);
    text("pink y = "+pinkWabbit.ypos,10,40);
    text("xOffset = "+xOffset,10,50);
    text("yOffset = "+yOffset,10,60);
    text("xDis = "+(int)xDis,10,70);
    text("yDis = "+(int)yDis,10,80);
    */
    } 


class wabbit { 
    //declare the properties that will be used as variables for the object
    float xpos, ypos, diameter; 
    int red, blue, green;
    //define the parameters for the creation of a new class
    wabbit (float x, float y, float wSize) {  
        xpos = x;
        ypos = y; 
        diameter = wSize;
        //radius = .5 * diameter;
        //make it pink if user did not define colors
        if (!(0>red>256)) red = 255;
        if (!(0>green>256))green = 200;
        if (!(0>blue>256)) blue = 200;
        } 
  void show() { 
    noStroke();
    for(a = diameter; a > 0; a-=5){
        fill(red-a,green-a,blue-a);
        //belly and head
        ellipse(xpos, ypos, a, a); 
        ellipse(xpos, ypos-diameter*.7, a*.7,a*.7);
        //feets
        ellipse(xpos-.2*diameter, ypos+diameter*.4, a*.4,a*.4);
        ellipse(xpos+.2*diameter, ypos+diameter*.4, a*.4,a*.4);
        //ears
        ellipse(xpos-.2*diameter, ypos-diameter, a*.2,a*.8);
        ellipse(xpos+.2*diameter, ypos-diameter, a*.2,a*.8);
        }
  } 
}

void babyWabbit(){
 noStroke();
var red=random(1,255);
var green=random(1,255);
var blue=random(1,255);
var xpos=random(1,width);
var ypos=random(1,height);
var diameter = random(20,80);
    for(var a = diameter; a > 0; a-=5){
        fill(red-a,green-a,blue-a);
        //belly and head
        ellipse(xpos, ypos, a, a); 
        ellipse(xpos, ypos-diameter*.7, a*.7,a*.7);
        //feets
        ellipse(xpos-.2*diameter, ypos+diameter*.4, a*.4,a*.4);
        ellipse(xpos+.2*diameter, ypos+diameter*.4, a*.4,a*.4);
        //ears
        ellipse(xpos-.2*diameter, ypos-diameter, a*.2,a*.8);
        ellipse(xpos+.2*diameter, ypos-diameter, a*.2,a*.8);
        }
}

</script><canvas></canvas> 
</body>
</html>