检查播放器是否在另一个节点之上?

时间:2014-07-18 17:46:16

标签: ios swift sprite-kit

我正试图让我的玩家跳起来。但是我不能让他在半空中跳跃所以我需要在施加冲动之前检查它是否站在另一个节点的顶​​部。

其他sprite-kit游戏通常如何做到这一点?


现在我正在尝试两种方法,第一种是这种方法。这很好但是我不知道怎么判断玩家正在触摸的节点是在玩家的正下方还是在玩家旁边。

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    var allowJump = false
    let bodies = player.physicsBody.allContactedBodies()
    for body : AnyObject in bodies {
        if let node = body.node {
            allowJump = true // Player is touching another node but we don't know where (the bottom of the player or it's sides)
        }
    }
}

这是另一种方法,告诉联系人是否开始以及联系人是否真的与地面(玩家下方)而不是墙壁等是有效的。但是我不知道如何判断玩家何时停止在任何节点之上,因为即使联系人结束他也可能仍在联系另一个节点。

func didBeginContact(contact: SKPhysicsContact!){
    if(contact.bodyA.node.position.y < contact.contactPoint.y) {
        println("BodyA is on top of another node")
    }

    if(contact.bodyB.node.position.y < contact.contactPoint.y) {
        println("BodyB is on top of another node")
    }
}

func didEndContact(contact: SKPhysicsContact!){
     if(contact.bodyA.node.position.y < contact.contactPoint.y) {
        println("BodyA is on no longer on top of BodyB")
    }

    if(contact.bodyB.node.position.y < contact.contactPoint.y) {
        println("BodyB is no longer on top of BodyA")
    }
}

5 个答案:

答案 0 :(得分:2)

typedef  NS_OPTIONS(uint32_t, CNPhysicsCategory)
{
    CNPhysicsCategoryChick = 1,
    CNPhysicsCategoryEdge = 2,
    CNPhysicsCategoryStrawberry = 3,
};

@interface MyScene() <SKPhysicsContactDelegate>

@end


@implementation MyScene
{
    SKSpriteNode *strawberry;
    SKSpriteNode *chick;

}

-(id)initWithSize:(CGSize)size {    
    if (self = [super initWithSize:size]) {
        /* Setup your scene here */

        self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
        self.physicsBody.categoryBitMask = CNPhysicsCategoryEdge;
        self.physicsWorld.contactDelegate = self;
        self.physicsBody.restitution = 0.0;

        chick = [SKSpriteNode spriteNodeWithImageNamed:@"chick"];
        [chick setScale:0.3];
        chick.position = CGPointMake(self.size.width/2, chick.size.height/2);
        chick.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:chick.size];
        chick.physicsBody.categoryBitMask = CNPhysicsCategoryChick;
        chick.physicsBody.collisionBitMask = CNPhysicsCategoryEdge;
        chick.physicsBody.restitution = 0.0;
        [self addChild:chick];


        strawberry = [SKSpriteNode spriteNodeWithImageNamed:@"strawberry"];
        strawberry.position = CGPointMake(chick.position.x, chick.position.y - chick.size.height/2 + strawberry.size.height/2);

        //You should make this hidden
        //strawberry.hidden = YES;

        strawberry.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize: CGSizeMake(strawberry.size.width, strawberry.size.height)];
        strawberry.physicsBody.categoryBitMask = CNPhysicsCategoryStrawberry;
        strawberry.physicsBody.collisionBitMask = kNilOptions;
        strawberry.physicsBody.contactTestBitMask = CNPhysicsCategoryEdge;
        strawberry.physicsBody.density = 0.001;
        strawberry.physicsBody.restitution = 0.0;
        [self addChild:strawberry];

        SKPhysicsJointFixed *point = [SKPhysicsJointFixed jointWithBodyA:strawberry.physicsBody bodyB:chick.physicsBody anchor:CGPointZero];
        [self.physicsWorld addJoint:point];
    }
    return self;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    [chick.physicsBody applyImpulse:CGVectorMake(0, 60)];
}

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

    if (collision == (CNPhysicsCategoryEdge | CNPhysicsCategoryStrawberry)) {
        NSLog(@"In Contact");
    }
}

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

    if (collision == (CNPhysicsCategoryEdge | CNPhysicsCategoryStrawberry)) {
        NSLog(@"Contact Is Lost");
    }
}


@end

enter image description here enter image description here

答案 1 :(得分:2)

这就是我现在正在做的事情,但它不会让我知道它所触摸的节点是在下方/左侧/右侧。我可以简单地将它的位置与我的节点进行比较,但是一些节点像edgeLoopF​​romPath一样是空心的,或者具有不同的形状。

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    var allowJump = false
    let bodies = player.physicsBody.allContactedBodies()
    for body : AnyObject in bodies {
        if let node = body.node { // Additionally check contactBitMask
            allowJump = true
        }
    }
}

答案 2 :(得分:1)

更新 Swift 5

guard let bodies = player.physicsBody?.allContactedBodies() else { return }
for body: SKPhysicsBody in bodies {
    if let node = body.node {
        if node.name == "ground" {
            isJumping = false
        }
    }
}

答案 3 :(得分:0)

使用状态来完成此任务。

让我们说你的球员可以处于两种状态 - 1. touchTheGround 2. inTheAir

  • 只有当玩家的状态触及TheGround 时才向玩家施加向上冲动,并将状态更改为 inTheAir
  • 当玩家触地时将其状态设置为触摸TheGround 。此时,您还可以检查通过玩家节点中心和接触点的线所形成的角度是否与+ x轴形成-90度(或约-90 )角。(< em>玩家站起来)
  • 如果玩家站起来,你可以将玩家发送到其他状态并为该状态编写不同的逻辑。

要实施状态,我建议使用NS_ENUM

答案 4 :(得分:0)

在播放器节点的底部添加另一个节点(如果你愿意,可以选择英尺)并使用它来检测碰撞。制作这个“脚”节点&#39;比你的播放器略窄,所以它不会触发侧面碰撞。当脚与玩家本身以外的身体接触时,你知道它正站在某物上。