我正在研究碰撞检测,希望当 Object1 向下移动屏幕并最终击中 Object2 时,它会触发 didBeginContact 方法,进而触发 Object1 上的 ResetPosition,这将使 Object1 返回屏幕顶部。我使用 NSLogs 进行测试,以确保程序是否到达 didBeginContact 方法,并且确实如此。最重要的是,该程序还通过调用的方法(resetPosition)来工作。唯一的问题是,它不会改变 Object1 的位置。我尝试看看是否可以在touchesBegan方法中调用resetPosition方法,并且它有效。 Object1 的位置实际上被重置。在 didBeginContact 方法中可以执行的操作是否有限制?如果是这样,实现我的预期目标的最佳方法是什么?
这是我的 didBeginContact 方法的示例:
-(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。
以下是 Object1 类中的 ResetPosition 方法的示例:
-(void)resetPosition{
self.position = CGPointMake(0, 200);
NSLog(@"Reached Method!");
}
你应该看看run loop。在完成物理模拟之前不会绘制任何内容。所以我想像你所做的那样改变位置会被物理模拟覆盖。
这是运行循环的顺序:
- 更新被称为
- 场景评估动作
- didEvaluateActions 被调用
- 物理模拟在这里
- didSimulatePhysics 被调用
- 场景应用约束
- didApplyConstraints 被调用
- didFinishUpdate 被调用
- 渲染帧
我敢打赌,如果您在 didSimulatePhysics 中移动节点的重新定位,而不是在 didBeginContact 中进行,那么一切都会正常。我猜发生这种情况是因为您试图在模拟完成之前更改节点的位置。您可以尝试以下代码(查看 didSimulatePhysics 部分):
#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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)