碰撞检测(教程:如何制作超级马里奥兄弟的平台游戏)

时间:2014-08-06 11:47:01

标签: sprite-kit

人!

我正在按照本教程How to make a platform game like Super Mario Brothers创建一个简单的平台游戏。在本教程中,角色精灵的大小大约是单个图块的大小,并且计算了8个周围图块的碰撞检测。我将精灵的大小修改为大约等于4个瓦片(2x2)并计算与12个周围瓦片的碰撞。它适用于底部和右侧精灵的边缘,但是在发生碰撞之前左边和上边缘与障碍物稍微重叠,这显然是错误的。

我觉得我在那里有一些错误,但由于我是Spritekit的新手,我无法发现它们。如果有人能帮助我,我真的很感激。提前谢谢。

以下是角色的更新功能:

- (void)update:(NSTimeInterval)delta
{
CGPoint gravity = CGPointMake(0.0, -450.0);
CGPoint gravityStep = CGPointMultiplyScalar(gravity, delta);

CGPoint forwardMove = CGPointMake(800.0, 0.0);
CGPoint forwardMoveStep = CGPointMultiplyScalar(forwardMove, delta);
CGPoint backwardMove = CGPointMake(-800.0, 0.0);
CGPoint backwardMoveStep = CGPointMultiplyScalar(backwardMove, delta);

if (self.forwardMarch)
{
    self.velocity = CGPointAdd(self.velocity, forwardMoveStep);
}
if (self.backwardMarch)
{
    self.velocity = CGPointAdd(self.velocity, backwardMoveStep);
}

self.velocity = CGPointAdd(self.velocity, gravityStep);
self.velocity = CGPointMake(self.velocity.x * 0.9, self.velocity.y);

// setup minimum and maximum limits for the motion speed
CGPoint minMovement = CGPointMake(0.0, -450);
CGPoint maxMovement = CGPointMake(0.0, 0.0);

// forward motion
if (self.velocity.x >= 0)
{
    minMovement = CGPointMake(0.0, -450);
    maxMovement = CGPointMake(120.0, 250.0);
}
// backward motion
if (self.velocity.x < 0)
{
    minMovement = CGPointMake(-120.0, -450);
    maxMovement = CGPointMake(0.0, 250.0);
}
self.velocity = CGPointMake(Clamp(self.velocity.x, minMovement.x, maxMovement.x), Clamp(self.velocity.y, minMovement.y, maxMovement.y));

CGPoint velocityStep = CGPointMultiplyScalar(self.velocity, delta);
self.newPosition = CGPointAdd(self.position, velocityStep);
}

此函数找到精灵的边界框

- (CGRect)collisionBoundingBox
{
CGPoint diff = CGPointSubtract(self.newPosition, self.position);

return CGRectOffset(self.frame, diff.x, diff.y);
}

我处理碰撞的功能

- (void)handleObstacleCollisionsForPlayer:(Player *)player forLayer:(TMXLayer *)layer
{
NSInteger indices[12] = {13, 14, 1, 2, 4, 8, 7, 11, 0, 3, 12, 15};
player.onGround = NO;

for (NSUInteger i = 0; i < 12; i++)
{
    NSInteger tileIndex = indices[i];

    CGRect playerRect = [player collisionBoundingBox];
    CGPoint playerCoord = [layer coordForPoint:player.newPosition];

    NSInteger tileColumn = tileIndex % 4;
    NSInteger tileRow = tileIndex / 4;
    CGPoint tileCoord = CGPointMake(playerCoord.x + (tileColumn - 1), playerCoord.y + (tileRow - 1));

    NSInteger gid = [self tileGIDAtTileCoord:tileCoord forLayer:layer];
    if (gid)
    {
        CGRect tileRect = [self tileRectFromTileCoords:tileCoord];
        if (CGRectIntersectsRect(playerRect, tileRect))
        {
            CGRect intersection = CGRectIntersection(playerRect, tileRect);

            if (tileIndex == 13 || tileIndex == 14)
            {
                //tile is below
                player.newPosition = CGPointMake(player.newPosition.x, player.newPosition.y + intersection.size.height);
                player.velocity = CGPointMake(player.velocity.x, 0.0);
                player.onGround = YES;
            }
            else if (tileIndex == 1 || tileIndex == 2)
            {
                //tile is directly above
                player.newPosition = CGPointMake(player.newPosition.x, player.newPosition.y - intersection.size.height);
            }
            else if (tileIndex == 4 || tileIndex == 8)
            {
                //tile is left
                player.newPosition = CGPointMake(player.newPosition.x + intersection.size.width, player.newPosition.y);
            }
            else if (tileIndex == 7 || tileIndex == 11)
            {
                //tile is right
                player.newPosition = CGPointMake(player.newPosition.x - intersection.size.width, player.newPosition.y);
            }
        }
    }
}

player.position = player.newPosition;
}

1 个答案:

答案 0 :(得分:0)

在GameViewController.m中启用调试物理模式

将在每个框周围绘制一个粗轮廓,并给出关于碰撞图块的确切信息,我认为你的英雄或图块大小与你跟随的教程不同

skView.showsPhysics = YES;