IOS SpriteKit 碰撞检测:重置对象的位置 [英] IOS SpriteKit Colision Detection: Resetting Position of an Object

查看:14
本文介绍了IOS SpriteKit 碰撞检测:重置对象的位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究碰撞检测,希望当 Object1 向下移动屏幕并最终击中 Object2 时,它会触发 didBeginContact 方法,反过来,Object1 上的 resetPosition 会将 Object1 带回屏幕顶部.我已经使用 NSLogs 进行测试以确保程序是否到达了 didBeginContact 方法,并且确实到达了.最重要的是,该程序还通过调用的方法(resetPosition)工作.唯一的问题是,它不会改变 Object1 的位置.我试图查看是否可以在 touchesBegan 方法中调用方法 resetPosition,并且它有效.Object1 的位置实际上已重置.在 didBeginContact 方法中可以做什么有限制吗?如果是这样,尝试实现我的预期目标的最佳方式是什么.

I'm working on Collision Detection where the hope is when Object1 moves down the screen and eventually hits Object2 it triggers the didBeginContact method and in turn, the resetPosition on Object1 which will bring Object1 back to the top of the screen. I've used NSLogs to test to make sure if the program reaches the didBeginContact method, and it does. On top of that, the program also works through the called upon method (resetPosition) as well. The only problem is, it does not change the position of Object1. I the tried to see if I could call the method resetPosition in the touchesBegan method, and it works. Object1's position is actually reset. Are there limitations to what you can do in the didBeginContact method? And if so, what would be the best way of trying to achieve my intended goal.

这是我的 didBeginContact 方法的示例:

Here is a sample of my didBeginContact Method:

-(void)didBeginContact: (SKPhyicsContacts *)contact { 
SKPhysicsBody *firstBody, *secondBody;
if(contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask){
    firstBody = contact.bodyA;
    secondBody = contact.bodyB;
} else {
    firstBody = contact.bodyB; 
    secondBody = contact.bodyA;
}

if(firstBody.categoryBitMask == Category1 && secondBody.categoryBitMask == Category2){
    NSLog(@"Collision Detected!");
    [Object1 resetPosition];
}

为了澄清任何混淆,Category1 对应 Object1,Category2 对应 Object2.

To clarify any confusion, Category1 corresponds to Object1, Category2 corresponds to Object2.

这是我的 Object1 类中的 resetPosition 方法的示例:

Here is a sample of my resetPosition method inside of my Object1 class:

-(void)resetPosition{
    self.position = CGPointMake(0, 200);
    NSLog(@"Reached Method!");
}

推荐答案

你应该看看 运行循环.在物理模拟完成之前没有绘制任何东西.所以我想像你这样改变位置会被物理模拟覆盖.

You should take a look at run loop. Nothing is drawn before physics simulation is done. So I guess that changing position like you are doing is overwritten by physics simulation.

这是运行循环的顺序:

  • 更新被调用
  • 场景评估动作
  • didEvaluateActions 被调用
  • 这里是物理模拟
  • didSimulatePhysics 被调用
  • 场景应用约束
  • didApplyConstraints 被调用
  • didFinishUpdate 被调用
  • 渲染框架

我敢打赌,如果您在 didSimulatePhysics 中移动节点的重新定位而不是在 didBeginContact 中进行,那么一切都会正常工作.我想这是因为您试图在模拟完成之前更改节点的位置.你可以试试这段代码(看看 didSimulatePhysics 部分):

I could bet if you move repositioning of node in didSimulatePhysics instead of doing it in didBeginContact that everything will work. I guess this is happening because you are trying to change node's position before simulation is done. You can try this code (look at didSimulatePhysics part):

#import "GameScene.h"

typedef enum uint_8{
    ColliderWall = 1,
    ColliderPlayer = 2,
    ColliderBrick =  4
}CollisionCategory;


@interface Object1 : SKSpriteNode

@end

@implementation Object1

-(instancetype)initWithColor:(UIColor *)color size:(CGSize)size{

    if(self = [super initWithColor:color size:size]){


        self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:size];

        self.physicsBody.categoryBitMask = ColliderPlayer;
        self.physicsBody.contactTestBitMask = ColliderBrick;
        self.physicsBody.collisionBitMask = ColliderBrick | ColliderWall;
        self.physicsBody.dynamic = YES;
        self.physicsBody.affectedByGravity = YES;
        self.physicsBody.allowsRotation = NO;

    }
    return self;
}



@end

@interface GameScene  ()<SKPhysicsContactDelegate>

@property (nonatomic, strong) Object1 *player;
@property (nonatomic, strong) SKSpriteNode *brick;

@property (nonatomic, assign) BOOL shouldMove;

@end

@implementation GameScene

-(void)didMoveToView:(SKView *)view {
    /* Setup your scene here */

    _shouldMove = NO;

    self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
    self.physicsBody.contactTestBitMask = 0;
    self.physicsBody.collisionBitMask =  ColliderPlayer;
    self.physicsBody.categoryBitMask = ColliderWall;

    self.physicsWorld.contactDelegate = self;

    _player = [[Object1 alloc] initWithColor:[SKColor greenColor] size:CGSizeMake(50,30)];
    _player.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMaxY(self.frame)- _player.size.height-30);
    [self addChild:_player];

    _brick = [SKSpriteNode spriteNodeWithColor:[SKColor greenColor] size:CGSizeMake(330,80)];
    _brick.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:_brick.size];
    _brick.position = CGPointMake(CGRectGetMidX(self.frame),100);
    _brick.physicsBody.contactTestBitMask = ColliderPlayer;
    _brick.physicsBody.collisionBitMask = ColliderPlayer;
    _brick.physicsBody.categoryBitMask = ColliderBrick;
    _brick.physicsBody.affectedByGravity = NO;
    _brick.physicsBody.dynamic = NO;

    [self addChild:_brick];


}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    /* Called when a touch begins */

    for (UITouch *touch in touches) {

        [self.player.physicsBody applyImpulse:CGVectorMake(0,55)];

    }
}

-(void)didBeginContact:(SKPhysicsContact *)contact{

    NSLog(@"Contact");

    self.shouldMove = YES;

}

-(void)didSimulatePhysics{

    if(self.shouldMove){


        self.player.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMaxY(self.frame)- _player.size.height-30);


        self.shouldMove = NO;
    }
}


@end

这篇关于IOS SpriteKit 碰撞检测:重置对象的位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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