流畅的蛇运动

时间:2014-03-09 23:53:35

标签: ios sprite-kit

这是与语言无关的问题,更多是关于我游戏的模型。

我有一个带元素的蛇游戏,但是我平滑地移动元素,它们不是每次只移动1个块,而是每帧移动一些像素。

我有一个更新循环来计算元素的位置,但我仍然坚持正确的计算。

我已找到每个元素:

typedef NS_ENUM(int, kElementHeading)
{
    kElementHeadingNorth = 1,
    kElementHeadingSouth,
    kElementHeadingEast,
    kElementHeadingWest
};

我也有速度(x,y)来确定蛇的走向。我有蛇运动的问题,因为我的元素处于错误的位置。我设法为2个元素本地化了东西,但是我的解决方案在更多元素上失败了。

我尝试的第一个解决方案是保存头部改变方向的旋转点。这有效,但由于不同的情况,元素每回合可以移动不同数量的像素。通常该元素会跳过这一点。我尝试增加它应该旋转的区域,但它会增加错误。我尝试修复此错误,但元素仍然会与snake(经常)分开。

在第二次尝试时,我决定将蛇头保持在屏幕的中心,并将周围的世界移动。它适用于2个元素,因为我只是平滑地将下一个元素移动到相对于头部的所需位置。但这在更多元素上失败了。如果你快速转弯,他们就会开始跳舞,而不是沿着这条路走。

我尝试的第三件事是留下其他元素的路径。但这不起作用,因为我打算将我的蛇放在屏幕的中心,从技术上讲,它永远不会移动创建路径。

我希望像Nimble Quest(或任何蛇)一样复制运动模式。

我应该如何实现蛇元素移动以避免错误?

这是第一种方法的代码,问题在于元素通常会脱落。代码非常明显。旋转点是改变方向的地方。

CFTimeInterval delta = self.lastTime - currentTime;

CGPoint currentPosition = self.playerSnake.head.sprite.position;
CGPoint velocity = self.playerSnake.velocity;

self.playerSnake.head.sprite.position = CGPointMake(currentPosition.x + velocity.x * delta * CONSTANTSPEEDFACTOR , currentPosition.y + velocity.y * delta * CONSTANTSPEEDFACTOR);

for (SnakeElement *element in self.playerSnake.elements) {

    CGPoint currentPositionE = element.sprite.position;
    CGPoint velocityE = element.velocity;

    element.sprite.position = CGPointMake(currentPositionE.x + velocityE.x * delta * CONSTANTSPEEDFACTOR , currentPositionE.y + velocityE.y * delta * CONSTANTSPEEDFACTOR);
}

BOOL markToDelete = NO;
NSDictionary *deleteDictionary;

for (NSDictionary *dict in self.playerSnake.rotationPoints) {

    CGPoint positionCoordinate = CGPointFromString(dict[@"position"]);
    CGPoint velocityNew = CGPointFromString(dict[@"velocity"]);
    double newAngle = [dict[@"angle"] doubleValue];

    for (SnakeElement *element in self.playerSnake.elements) {

        int xDifference = element.sprite.position.x - positionCoordinate.x;
        int yDifference = element.sprite.position.y - positionCoordinate.y;

        if ((xDifference > -2 && xDifference < 2) && (yDifference > -2 && yDifference < 2)   ) {

            element.velocity = velocityNew;
            element.sprite.position = CGPointMake(element.sprite.position.x + xDifference, element.sprite.position.y + yDifference);
            SKAction *action = [SKAction rotateToAngle:newAngle duration:0.2 shortestUnitArc:YES];
            [element.sprite runAction:action];
            if ([element isEqual:[self.playerSnake.elements lastObject]]) {
                markToDelete = YES;
                deleteDictionary = dict;
            }
        }
    }
}

[self.playerSnake.rotationPoints removeObject:deleteDictionary];

如果我尝试增加转折点的捕获区域,则元素倾向于更频繁地下降,然后当它为1或2像素宽时。我不确定为什么会这样。

1 个答案:

答案 0 :(得分:1)

这就是我建议你在处理启用点的评论中所做的建议:

1 ..根据速度和自上一帧起经过的时间计算元素应移动该帧的距离。 (delta)

2 ..计算从元素当前位置到转折点的距离。这是我在评论中提到的beforeDistance

3 ..计算元素在转弯后朝向新目标转折点移动的距离

afterDistance = distanceToMoveThisFrame - beforeDistance

4 ..使用afterDistance计算元素的新位置,从当前转折点开始朝向元素的下一个目标转折点

如果您遵循此逻辑,您将永远不会超过或低于转折点。