【问题标题】:Moving a camera in SpriteKit在 SpriteKit 中移动相机
【发布时间】:2014-05-25 01:46:10
【问题描述】:

//更新 添加了更新的代码,可以按我的预期工作。请参阅下面更新代码中的 didSimulatePhysics 方法。就我而言,我只关心在 x 轴上向左或向右移动字符,其中 x 轴上的 0 是绝对左侧,而 x 轴上的右侧是可配置值。 Apple 冒险游戏也确实帮了很多忙。

//下面是原帖

我正在使用 Apple SpriteKit,并且我正在努力实现我希望它表现的相机。我在代码中所做的是加载一个精灵字符、两个按钮和一个红色框,该框在开始时位于视图右侧。我想做的是用按钮移动角色,一旦玩家到达屏幕的中间或末端,相机就会重新调整以发现在视图中看不到的东西。因此,一旦玩家到达那里,向右移动最终应该会显示最初在视图之外关闭的红色框。但是,使用我在下面使用的代码,我根本无法让相机跟随并调整主角的坐标。我查看了 Apple 的高级场景处理文档以及其他一些堆栈溢出帖子,但似乎无法正确理解。如果有人可以提供一些建议,将不胜感激。

#define cameraEdge 150

-(id)initWithSize:(CGSize)size
{
    if (self = [super initWithSize:size])
    {
        /* Setup your scene here */
        //320 568
        
    
        self.backgroundColor = [SKColor whiteColor];
        
        myWorld = [[SKNode alloc] init];
        [self addChild:myWorld];
        
        mainCharacter = [SKSpriteNode spriteNodeWithImageNamed:@"0"];
        mainCharacter.physicsBody.dynamic = YES;
        mainCharacter.name = @"player";
       
        mainCharacter.position = CGPointMake(20, 20);
        
        CGRect totalScreenSize = CGRectMake(0, 0, 800, 320);
        
        SKSpriteNode *box = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(60, 60)];
        
          SKSpriteNode *boxTwo = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(60, 60)];
           SKSpriteNode *boxThree = [SKSpriteNode spriteNodeWithColor:[SKColor blueColor] size:CGSizeMake(60, 60)];
        boxThree.position = CGPointMake(40, 50);
        
        [myWorld addChild:boxThree];
        
        boxTwo.position = CGPointMake(1100, 50);
        
        box.position = CGPointMake(650, 50);
        
        [myWorld addChild:box];
        [myWorld addChild:boxTwo];
        
       
       self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:totalScreenSize];
        
        self.physicsWorld.gravity = CGVectorMake(0, -5);
        mainCharacter.name = @"mainCharacter";
  
   
        mainCharacter.physicsBody.linearDamping = 0;
        mainCharacter.physicsBody.friction = 0;
        mainCharacter.physicsBody.restitution = 0;
        mainCharacter.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:mainCharacter.size];
        
       [myWorld addChild:mainCharacter];
      
        [self addChild:[self buildLeftButton]];
        [self addChild:[self buildRightButton]];

    }
    
    return self;
}

- (void)didSimulatePhysics
{
    SKSpriteNode *hero = mainCharacter;
    
    if(hero)
    {
        CGPoint heroPosition = hero.position;
        CGPoint worldPosition = myWorld.position;
        
        NSLog(@"%f", heroPosition.x);
        
        CGFloat xCoordinate = worldPosition.x + heroPosition.x;
        
        if(xCoordinate < cameraEdge && heroPosition.x > 0)
        {
            worldPosition.x = worldPosition.x - xCoordinate + cameraEdge;
            self.worldMovedForUpdate = YES;
        }
        
        else if(xCoordinate > (self.frame.size.width - cameraEdge) && heroPosition.x < 2000)
        {
            worldPosition.x = worldPosition.x + (self.frame.size.width - xCoordinate) - cameraEdge;
            self.worldMovedForUpdate = YES;
        }
        
        myWorld.position = worldPosition;
    }
}

-(SKSpriteNode *)buildLeftButton
{
    SKSpriteNode *leftButton = [SKSpriteNode spriteNodeWithImageNamed:@"left"];
    leftButton.position = CGPointMake(20, 20);
    leftButton.name = @"leftButton";
    leftButton.zPosition = 1.0;
    return leftButton;
}

-(SKSpriteNode *)buildRightButton
{
    SKSpriteNode *leftButton = [SKSpriteNode spriteNodeWithImageNamed:@"right"];
    leftButton.position = CGPointMake(60, 20);
    leftButton.name = @"rightButton";
    leftButton.zPosition = 1.0;
    return leftButton;
}


-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint location = [touch locationInNode:self];
    SKNode *node = [self nodeAtPoint:location];
    
    if([node.name isEqualToString:@"leftButton"])
    {
             [mainCharacter.physicsBody applyImpulse:CGVectorMake(-120, 0)];
    }
    
    else if([node.name isEqualToString:@"rightButton"])
    {
       [mainCharacter.physicsBody applyImpulse:CGVectorMake(120, 10)];
    }
}

【问题讨论】:

    标签: ios sprite-kit


    【解决方案1】:

    如果您希望视图始终以玩家的位置为中心,请记住以下几点修改您的代码:

    1) 创建一个 SKNode 并将其命名为 myWorld、worldNode 或任何其他类似名称。

    2) 添加世界节点[self addChild:worldNode];

    3) 将所有其他节点添加到 worldNode,包括您的播放器。

    4) 在didSimulatePhysics 方法中,添加以下代码:

    worldNode.position = CGPointMake(-(player.position.x-(self.size.width/2)), -(player.position.y-(self.size.height/2)));
    

    您的视图现在将始终以玩家的位置为中心。

    2015 年 5 月更新:

    如果您使用的是通过平铺地图编辑器创建的地图,您可以使用免费的SKAToolKit framework。功能包括播放器相机自动跟随、测试播放器、测试 HUD 和精灵按钮。

    【讨论】:

    • 感谢 sangony 的回复。我已经修改了原始帖子中的代码以反映您建议的更改。但是,该角色出现在右上角,并且移动按钮消失了。我假设我必须以某种方式将移动按钮锚定在当前视图中,以便它们在视图调整时移动,但不太确定按钮是否应该锚定到场景、世界或相机。
    • @zic10 - 您可以直接将控制按钮添加到视图中,这样它们就不会移动。如果您需要修改与播放器相关的中心位置,您可以添加偏移值。例如:((player.position.x-(self.size.width/2)+20) 偏移量为+20。
    • 这是否意味着我可以丢弃相机节点而只在 myWorld 节点中执行所有操作?
    • @zic10 - 是的。把“worldNode”想象成一个巨大的画布,你可以在你的视图前四处移动,它有点像一扇窗户。应该与 worldNode 一起移动的所有内容都应该是 worldNode 的子节点。请记住,当窗口(您的视图)保持静止时,您正在移动画布(worldNode)。
    • 抱歉耽搁了,已接受为答案。我还想补充一点,Apple 的“冒险”游戏示例中的一些代码也确实有帮助。将在原始帖子中添加此代码。
    猜你喜欢
    • 2016-12-16
    • 1970-01-01
    • 1970-01-01
    • 2015-05-07
    • 1970-01-01
    • 2017-03-28
    • 1970-01-01
    • 2021-03-10
    • 1970-01-01
    相关资源
    最近更新 更多