【问题标题】:How to have my character "ride" along with moving platforms?如何让我的角色随着移动平台“骑行”?
【发布时间】:2014-07-28 12:25:06
【问题描述】:

我的英雄角色遇到了问题,当他降落在一个移动的平台上而不是随之移动时,他实际上站在同一个 X 位置,直到平台移出屏幕。我搜索了很多答案都无济于事。

这是我的英雄角色和移动平台的方法。

-(void)HeroAdd
{    
    _Hero = [SKSpriteNode spriteNodeWithImageNamed:@"Hero-1"];
    _Hero.name = @"Daniel";
    _Hero.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_Hero.size];
    _Hero.physicsBody.categoryBitMask = fPlayerCategory;
    _Hero.physicsBody.contactTestBitMask = fPlatformCategory | fEnemyCategory;
    _Hero.physicsBody.usesPreciseCollisionDetection = YES;
    _Hero.physicsBody.affectedByGravity = YES;
    _Hero.physicsBody.dynamic = YES;
    _Hero.physicsBody.friction = .9;
    _Hero.physicsBody.restitution = 0;
    _Hero.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
    _Hero.position = CGPointMake(_Hero.position.x - 252, _Hero.position.y + 50);

    if (self.size.width == 480) {
        _Hero.position = CGPointMake(_Hero.position.x + 44, _Hero.position.y);
    }

    [self addChild:_Hero];
}

我的移动平台代码

-(void)createPlatform {

    SKTexture *objectTexture;

    switch (arc4random_uniform(2)) {
        case (0):
            objectTexture = [SKTexture textureWithImageNamed:@"shortPlatform"];
            break;
        case (1):
            objectTexture = [SKTexture textureWithImageNamed:@"highPlatform"];
        default:
            break;
    }

    SKSpriteNode *variaPlatform = [SKSpriteNode spriteNodeWithTexture:objectTexture];
    variaPlatform.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
    variaPlatform.position = CGPointMake(variaPlatform.position.x + 500, variaPlatform.position.y - 140);
    variaPlatform.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:variaPlatform.size];
    variaPlatform.physicsBody.usesPreciseCollisionDetection = YES;
    variaPlatform.physicsBody.categoryBitMask = fPlatformCategory;
    variaPlatform.physicsBody.contactTestBitMask = fPlatformCategory |fPlayerCategory | fEnemyCategory;
    variaPlatform.physicsBody.dynamic = NO;
    variaPlatform.physicsBody.affectedByGravity = NO;

    SKAction *moveLeft = [SKAction moveTo:CGPointMake(180, variaPlatform.position.y) duration:3];
    SKAction *moveDown = [SKAction moveTo:CGPointMake(180, -700) duration:4];
    SKAction *removeFromParent = [SKAction removeFromParent];

    SKAction *AllThree = [SKAction sequence:@[moveLeft, moveDown, removeFromParent]];

    [self addChild:variaPlatform];

    [variaPlatform runAction:AllThree];

}

任何类型的信息都将不胜感激。

【问题讨论】:

  • HeroAdd方法中,self是什么? (即什么类实现了该方法?)
  • 为您的平台增加摩擦力。据我所知,只有你的英雄被分配了高摩擦。
  • @PhillipMills 我在 SKScene 的界面部分中为大多数 Sprite-kit 项目的常规布局实现了一个属性。
  • @meisenman 很遗憾,这没有用。

标签: ios objective-c sprite-kit


【解决方案1】:

我在游戏中添加传送带时遇到了同样的问题。无论添加多少阻力,Sprite Kit 都不会拖动对象。您目前有 2 个选项。

选项 1 - 在平台的每一端添加一个壁架。这是最容易实现的,但不太优雅,如果玩家落在窗台上,仍然允许他滑落。

选项 2 -

第 1 步:添加使播放器与水平移动平台同步移动的代码。您可以使用self.physicsBody.velocity = CGVectorMake(-50, self.physicsBody.velocity.dy); 之类的内容,也可以使用self.position = CGPointMake(self.position.x+10, self.position.y);。您将不得不使用 x 值来将它们与平台的速度同步。

第2步:当玩家与平台接触时激活上述代码,当失去联系时停用。

第三步:平台换向时,设置左右限位,平台换向时通过联系方式通知您。根据平台的方向,您可以对播放器应用 +x 或 -x 移动值。

我知道这个选项听起来很复杂,但事实并非如此。你只需要一步一步来。

* 编辑以提供示例代码 *

这是我在水平移动平台背后的逻辑:

平台 如果您有超过 1 个水平移动平台,则需要将它们存储在 GameScene(我的关卡)中的数组中。我为他们创建了自己的课程,但您不必这样做。

您必须设置左右限制(带有联系人的不可见 SKNode)来为平台设置一个 BOOL 属性,该属性告诉玩家类以哪种方式推送,因为每个平台的长度可能不同。这就是为什么您需要保留对每个平台的引用(因此是数组)。

玩家 当玩家在平台上跳跃时,将 Player 类属性 BOOL 设置为 TRUE,这将根据平台当前移动的方式激活恒定的左推或右推。另一方面,失去联系会取消推送。

// This code in my "Levels class" which is the default GameScene class.
- (void)didBeginContact:(SKPhysicsContact *)contact
{
    uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);

    if (collision == (CategoryPlatformHorizontal | CategoryPlayer))
    {
        [_player setPlatformHorizontalContact:true];

        for(Platform *platformObject in platformArray)
        {
            if(([platformObject.name isEqualToString:contact.bodyB.node.name]) || ([platformObject.name isEqualToString:contact.bodyA.node.name]))
            {
                _player.currentPlatform = platformObject;
            }
        }
    }
}

- (void)didEndContact:(SKPhysicsContact *)contact
{
    uint32_t collision = (contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask);

    if (collision == (CategoryPlatformHorizontal | CategoryPlayer))
    {
        [_player setPlatformHorizontalContact:false];
    }
}

// This code is in Player.h
@property (strong) Platform *currentPlatform;
@property BOOL platformHorizontalContact;

// This code is in Player.m
- (void)update:(NSTimeInterval)currentTime
{
    if(self.platformHorizontalContact == true)
    {
        if(self.currentPlatform.movingLeft == true)
        {
            self.physicsBody.velocity = CGVectorMake(-75, self.physicsBody.velocity.dy); // set your own value depending on your platform speed
        } else {
            self.physicsBody.velocity = CGVectorMake(75, self.physicsBody.velocity.dy); // set your own value depending on your platform speed
        }
    }
}

【讨论】:

  • 谢谢,这个问题实在是太烦人了。
  • @sagony 我可以问一下您使用的是哪个选项吗?因为当我尝试在我的英雄角色上使用 CGPointMake 选项时,什么都没有发生,我将代码输入到我的 SKPhysicsContact 上,并且我知道由于 NSLog 它可以正常工作。您能否向我展示一些您用于传送带的示例代码,它将证明对我有用。谢谢。
  • @Blank - 我使用了选项 2,因为我最终也使用了水平移动平台。我无法发布与此相关的所有代码,因为它太多了,但是如果您告诉我您需要帮助的具体部分,我可以为此发布一些示例代码。
  • @sagony 谢谢,所以在我的 'didBeginContact' 方法中,我创建了一个 'if' 语句,如果我的 playerCategory 和 platformCategory 都进行了接触,它将移动我的英雄角色的位置并显示一个 NSLog 消息确认它像这样 '_Hero.position = CGPointMake(_Hero.position.x - 20, _Hero.position.y);'然而,无论何时英雄确实接触,都看不到任何动作。是不是我做错了什么?如果我真的理解这个概念,我会尝试速度。
  • @sagony 非常感谢!正是我需要的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-20
  • 1970-01-01
  • 2021-10-17
  • 1970-01-01
相关资源
最近更新 更多