1

我正在使用 cocos2d-iphone 制作一个简单的 iPhone 游戏。我有一系列恶魔,“fiendSet”必须在充满障碍的场地中导航。我花了最后三个晚上试图让我的 A* 寻路工作。我在 stackoverflow 上找到了实际的 A* 实现,它运行良好。然而,一旦我试图移动我的恶魔,我就会遇到麻烦。

我的每个恶魔都有一个名为 motionTarget 的 CGPoint,其中包含恶魔必须去的位置的 x 和 y 值。如果每秒只将位置 x 和 y 设置为绝对值,它可以工作,如下所示:

-(void) updateFiendPositions:(ccTime)dt {
    for (MSWFiend *currFiend in fiendSet) {
         currFiend.position = ccp(currFiend.motionTarget.x,currFiend.motionTarget.y);
    }
}

然而,这看起来不太好,恶魔只是每秒“跳跃”20px,而不是很好地制作动画。我仅将其实现为占位符方法来验证寻路。现在我想要流畅的动画。这就是我所做的:

-(void) updatePositions:(ccTime) dt {
    for (MSWFiend *currFiend in fiendSet) {
        if (currFiend.motionTarget.x != -1 && currFiend.motionTarget.y != -1) {
            float x,y;      

            if ((int)floor(currFiend.position.x) < (int)floor(currFiend.motionTarget.x)) {
                x = currFiend.position.x+(currFiend.speed*dt);
            }
            if ((int)floor(currFiend.position.x) > (int)floor(currFiend.motionTarget.x)) {
                x = currFiend.position.x-(currFiend.speed*dt);
            }
            if (abs((int)floor(currFiend.position.x)-(int)floor(currFiend.motionTarget.x)) < 2) {
                x = currFiend.motionTarget.x;
            }

            if ((int)floor(currFiend.position.y) < (int)floor(currFiend.motionTarget.y)) {
                y = currFiend.position.y+(currFiend.speed*dt);
            }
            if ((int)floor(currFiend.position.y) > (int)floor(currFiend.motionTarget.y)) {
                y = currFiend.position.y-(currFiend.speed*dt);
            }
            if (abs((int)floor(currFiend.position.y)-(int)floor(currFiend.motionTarget.y)) < 2) {
                y = currFiend.motionTarget.y;
            }

            currFiend.position = ccp(x,y);
        }
    }
}

这对于朝一个方向移动的恶魔非常有用。一旦恶魔应该绕过弯道,麻烦就开始了。而不是例如先向上,然后向右,然后向下;我的恶魔会把上/右运动合二为一,他们是“偷工减料”。我只希望我的恶魔在每次位置更新时都向北/向南或向东/向西移动,而不是同时向两者移动。换句话说,我不想同时对 x 和 y 的变化进行动画处理。我希望这个解释足够清楚..

我很确定我在某个地方有一个逻辑错误..我只是在下班后的最后三个不眠之夜无法弄清楚..帮助!

4

2 回答 2

1

您必须跟踪目标路径中的每个节点。这样,您只需将运动动画到下一个节点。您也可以使用 CCMoveTo 动作代替自己制作动画。

于 2010-10-22T20:30:44.083 回答
0

@Aleph 感谢您的建议。我发现是代码决定了何时分配一个新的motionTarget,这是错误的,而不是我发布的代码。当您提到跟踪每个节点的位置时,我想到了我的 motionTarget 确定代码,并在 2-3 小时后发现了错误。我最终这样做了:

-(void) updatePositions:(ccTime) dt {
for (MSWFiend *currFiend in fiendSet) {
    int fiendGX,fiendGY,targetGX,targetGY,dGX,dGY;
    float x,y,snappedX,snappedY;
    BOOL snappedIntoPosition = FALSE;

    fiendGX = (int)round(100.0f*(currFiend.position.x/20));
    fiendGY = (int)round(100.0f*(currFiend.position.y/20));
    targetGX = (int)round(100.0f*(currFiend.motionTarget.x/20));
    targetGY = (int)round(100.0f*(currFiend.motionTarget.y/20));

    snappedX = currFiend.position.x;
    snappedY = currFiend.position.y;

    dGX = abs(fiendGX-targetGX);
    dGY = abs(fiendGY-targetGY);

    float snappingThreshold; //1 = snap when 0.1 from motionTarget.
    snappingThreshold = currFiend.speed/10;

    if (dGX < snappingThreshold && dGY < snappingThreshold) {
        snappingThreshold = currFiend.motionTarget.x;
        snappingThreshold = currFiend.motionTarget.y;
        int newPathStep;
        newPathStep = currFiend.pathStep + 1;
        currFiend.pathStep = newPathStep;
    }

    int gX,gY; 
    gX = [[currFiend.path objectAtIndex:currFiend.pathStep] nodeX];
    gY = (tileMap.mapSize.height-[[currFiend.path objectAtIndex:currFiend.pathStep] nodeY])-1;

    currFiend.motionTarget = ccp(gX*20,gY*20);          //Assign motion target to the next A* node. This is later used by the position updater.

    if (currFiend.motionTarget.x != -1 && currFiend.motionTarget.y != -1) {
        x = currFiend.motionTarget.x;
        y = currFiend.motionTarget.y;

        if ((int)floor(currFiend.position.x) < (int)floor(currFiend.motionTarget.x)) {
            //Move right
            x = snappedX+(currFiend.speed*dt);
            if (x > currFiend.motionTarget.x) {
                x = currFiend.motionTarget.x;
            }
            y = snappedY;
        }
        if ((int)floor(currFiend.position.x) > (int)floor(currFiend.motionTarget.x)) {
            //Move left
            x = snappedX-(currFiend.speed*dt);
            if (x < currFiend.motionTarget.x) {
                x = currFiend.motionTarget.x;
            }
            y = snappedY;
        }

        if ((int)floor(currFiend.position.y) < (int)floor(currFiend.motionTarget.y)) {
            //Move up
            y = snappedY+(currFiend.speed*dt);
            if (y > currFiend.motionTarget.y) {
                y = currFiend.motionTarget.y;
            }
            x = snappedX;
        }
        if ((int)floor(currFiend.position.y) > (int)floor(currFiend.motionTarget.y)) {
            //Move down
            y = snappedY-(currFiend.speed*dt);
            if (y < currFiend.motionTarget.y) {
                y = currFiend.motionTarget.y;
            }
            x = snappedX;
        }
    }
    currFiend.position = ccp(x,y);
}
}
于 2010-10-23T20:29:22.463 回答