在SpriteKit中移动相机 [英] Moving a camera in SpriteKit

查看:98
本文介绍了在SpriteKit中移动相机的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

//更新
已添加的更新代码可按预期工作。请参阅下面更新的代码中的didSimulatePhysics方法。在我的例子中,我只关心在x轴上向左或向右移动一个字符,其中x轴上的0是x轴上的绝对左边和右边是可配置的值。苹果冒险游戏确实也有很大的帮助。



//以下的原始帖子



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



  #define cameraEdge 150 

- (id)initWithSize:(CGSize )size
{
if(self = [super initWithSize:size])
{
/ *在这里设置场景* /
// 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 bodyWithEdgeLoopF​​romRect: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]];

}

返回自我;
}

- (无效)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;
返回leftButton;
}

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


- (void)touchesBegan:(NSSet *)触及withEvent:(UIEvent *)事件
{
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)] ;
}
}


解决方案

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



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



2)添加worldNode [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月更新:



如果您使用的是使用Tiled Map Editor创建的地图,则可以使用免费< a href =https://github.com/SpriteKitAlliance/SKAToolKit =noreferrer> SKAToolKit框架。功能包括玩家相机自动跟踪,测试播放器,测试HUD和精灵按钮。


//UPDATE The updated code has been added that works as I expected. See didSimulatePhysics method in the updated code below. In my case, I only care about moving a character left or right on the x axis where 0 on the x axis is the absolute left and right on the x axis is a configurable value. The Apple adventure game really helped a lot too.

//ORIGINAL POST BELOW

I'm working with Apple SpriteKit and I'm struggling to implement a camera as I would like it to behave. What I've done in the code is load a sprite character, two buttons, and a red box that is off to the right outside of the view at the start. What I'd like to be able to do is move the character with the buttons, and once the player reaches the middle or end of the screen, the camera will then re-adjust to uncover what couldn't be seen in the view. So moving to the right should eventually show the red box that is off outside of the view initially once the player gets there. However, with the code I'm using below, I'm unable to get the camera to follow and adjust the coordinates to the main character at all. I've looked at Apple's advanced scene processing doc as well as a few other stack overflow posts but can't seem to get it right. If anyone could offer some advice it would be appreciated.

#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)];
    }
}

解决方案

If you want the view to always be centered on your player's position, modify your code with these points in mind:

1) Create a SKNode and call it myWorld, worldNode or any other name like that.

2) Add the worldNode [self addChild:worldNode];

3) Add all other nodes to the worldNode, including your player.

4) In the didSimulatePhysics method, add this code:

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

Your view will now always be centered on your player's position.

Update May 2015:

If you are using a map created with Tiled Map Editor, you can use the free SKAToolKit framework. Features include player camera auto follow, test player, test HUD and sprite buttons.

这篇关于在SpriteKit中移动相机的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆