【问题标题】:How can i make a node collide with the sides of moving scene?如何使节点与移动场景的侧面发生碰撞?
【发布时间】:2014-07-19 01:48:29
【问题描述】:

嗨,我想知道我的节点如何与移动的场景发生碰撞。我有一个主节点,可以沿 x 轴移动,并且可以与其他节点发生碰撞。我想让非主节点与移动场景的侧面发生碰撞。我怎样才能做到这一点? (相机只跟随主节点)。

我有一个障碍类。

在我的 MLObstacle.m 中

-(id)init
{
if(self = [super init])
{
int aux = arc4random()%3;
switch (aux) {
    case 0:
        self = [MLObstaculo spriteNodeWithColor:[UIColor greenColor] size:CGSizeMake((aux+1)*10,(aux+1)*13 )];
        break;
    case 1:
        self = [MLObstaculo spriteNodeWithColor:[UIColor blueColor] size:CGSizeMake((aux+1)*10,(aux+1)*15 )];
        break;
    case 2:
        self = [MLObstaculo spriteNodeWithColor:[UIColor redColor] size:CGSizeMake((aux+1)*10,(aux+1)*14 )];
        break;
}
self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.size];
self.physicsBody.affectedByGravity = NO;

self.physicsBody.categoryBitMask = obstacleCategory;
self.physicsBody.contactTestBitMask = visibleSidesCategory;
self.physicsBody.collisionBitMask = visibleSidesCategory;   
[self setDx:0.0];
[self setDy:2.4];
}
return self;
}

所以我在我的 WorldClass 中添加了障碍

在我的 WorlGen.m 中

-(void)GenerateWorld
{
SKSpriteNode *Ground = [SKSpriteNode spriteNodeWithColor:[UIColor greenColor] size:CGSizeMake(self.scene.frame.size.width,100)];
Ground.position = CGPointMake(0, -self.scene.frame.size.height/2 + Ground.size.height/2);
Ground.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:Ground.size];
Ground.physicsBody.dynamic = NO;


[self addChild:Ground];
for(int i = 0; i < 3; i++)
{

    MLObstaculo * auxobs= [[MLObstaculo alloc]initObstaculo];
    auxobs.position = CGPointMake((i+1)*50, Ground.position.y + Ground.size.height/2 +auxobs.size.height/2 );
    [self.Obstaculos addObject:auxobs];
    [self addChild:auxobs];
    auxobs = NULL;

}
}

然后我将世界添加到我的场景中

场景.m

-(id)initWithSize:(CGSize)size
{
     if(self = [super initWithSize:size]
     {
        WorldGen * world = [[WorldGen alloc] init];
        self.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame];
        self.physicsWorld.contactDelegate = self;
        self.physicsBody.categoryBitMask = VisibleSidesCategory
        self.physicsBody.collisionBitMask = ObstacleCategory;
        self.anchorPoint = CGPointMake(0.5,0.5);
        [self addChild:world];
        [world GenerateWorld];
     }
}

更新...

-(void)didSimulatePhysics
{
    [self centerOnNode:hero];
}

-(void)centerOnNode:(SKNode *)node
{
    CGPoint pointinScene = [self convertPoint:node.position fromNode:node.parent];
    world.position = CGPointMake(world.position.x -pointinScene.x , world.position.y);

}

我用这种格式(static const uint32_t ObstacleCategory = 0x1 &lt;&lt;1;)初始化了所有类别变量

【问题讨论】:

    标签: ios objective-c sprite-kit game-physics skphysicsbody


    【解决方案1】:

    通过定义您的碰撞位掩码进行第一次编辑

    -(id)init
    {
        self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.size];
        self.physicsBody.categoryBitMask = ObstacleCategory;
        self.physicsBody.contactTestBitMask = VisibleSidesCategory;
        self.physicsBods.collisionBitMask = VisibleSidesCategory;
    }
    

    第二次在 Xcode 中执行此步骤 -> File -> New -> File -> C 和 C++ -> 头文件

    命名 Physics.h 并在其中添加这些行:

    typedef enum : uint8_t {
        ObstacleCategory            = 1,
        VisibleSidesCategory        = 2,
    
    } ColliderType;
    

    然后将 Physics.h 导入所有类(您不需要为 Physics.h 分配或初始化,只需使用 ObstacleCategory 和 VisibleSidesCategory)

    【讨论】:

    • 你是否也将物理添加到非主节点?
    • 我试过你的代码。我知道这应该可行,因为它也在 Ios 开发人员文档中,但它不起作用。我已经在 didBeginContact 方法中编写了代码。但还是什么都没有。
    • 你把这段代码写到 -(id)initWithSize:(CGSize)size { if (self = [super initWithSize:size]) { 而且你所有的节点都有物理吗?是的,这段代码应该可以工作,我也在我的应用程序中使用
    • 是的,我所有的节点都有物理。我的节点实际上可以与除了移动场景的侧面之外的所有物体发生碰撞。
    • 你所有的节点是否都有唯一的 categoryBitMasks 并且你也可以检查你所有节点的 collisionBitMasks,这可能是问题的根源
    【解决方案2】:

    从this和another question的问题,我终于确定API有错误。具体来说,如果使用基于 WithRect:FromRect: 的初始化程序(但不是基于 RectOfSize:center: 的初始化程序),则在初始化期间会考虑节点的锚点 (0,0),因此您会遇到意外行为。

    因此,即使场景和其他对象的anchorPoint设置为(0.5,0.5),节点的左下角也相对于父节点的中点放置,而不是子节点的中点相对于父节点的中点放置.

    具体来说,这可以通过以下三种方式中的任何一种来解决:

    1. 使用 (0,0) 的锚点。
    2. 在不使用基于 Rect 的初始化程序的情况下创建节点。您可以使用shapeNodeWithRectOfSize: 代替shapeNodeWithRect:bodyWithEdgeLoopFromPath: 代替bodyWithEdgeLoopFromRect:
    3. 将 Rect 的初始位置设置为左下角,如下所示:

    node.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:CGRectMake(-node.size.width/2, -node.size.height/2, node.size.width, node.size.height)];

    【讨论】:

    • 好的,我将障碍设置为处理碰撞。但问题依然存在。
    • 到底发生了什么?从您的代码和您描述的所有内容来看,如果位掩码设置和应用正确,则障碍不应忽略边缘,因此有助于准确了解您在运行代码时看到的内容。
    • 另外,你的 Obstacle 的单位没有调用它的 super 的 init 有什么原因吗?
    • @XtDiego 我编辑了我的答案,以便为您所说的问题提供解决方案。我相信第二点,缺少anchorPoint,可能是你遇到的问题。
    • 我的锚点设置在我的项目代码以及我的类的超级初​​始化调用中。问题仍然存在。真正发生的是,当我的障碍物与我的主节点碰撞并飞走时,当它们与我的场景边缘接触时,它们应该发生碰撞,但节点只是通过了。
    猜你喜欢
    • 1970-01-01
    • 2014-08-12
    • 2015-11-11
    • 1970-01-01
    • 2018-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-02
    相关资源
    最近更新 更多