【问题标题】:Obj-C and SpriteKit - Changing a sprite value that is created randomlyObj-C 和 SpriteKit - 更改随机创建的精灵值
【发布时间】:2015-01-01 16:47:24
【问题描述】:

我正在使用 SpriteKit 和 Objective-C 制作游戏。

我有四种不同的纹理水滴(蓝色、绿色、橙色和红色)随机落在屏幕上。

在我的 ANBDropNode 类中,我有这个方法:

+(instancetype)dropOfType:(ANBDropType)type {

    ANBDropsNode *drop;

    if (type == ANBDropTypeBlue) {
        drop = [self spriteNodeWithImageNamed:@"bluedrop"];
    } else if (type == ANBDropTypeGreen) {
        drop = [self spriteNodeWithImageNamed:@"greendrop"];
    } else if (type == ANBDropTypeOrange) {
        drop = [self spriteNodeWithImageNamed:@"orangedrop"];
    } else if (type == ANBDropTypeRed){
        drop = [self spriteNodeWithImageNamed:@"reddrop"];
    }

    [drop setupPhysicsBody];
    return drop;
}

在我的 GamePlayScene 中这两个:

    -(void)addDrops {

        NSUInteger randomDrop = [ANBUtil randomWithMin:0 max:4];

        self.drop = [ANBDropsNode dropOfType:randomDrop];

        float y = self.frame.size.height + self.drop.size.height;
        float x = [ANBUtil randomWithMin:10 + self.drop.size.width
                                     max:self.frame.size.width - self.drop.size.width - 10];
        self.drop.position = CGPointMake(x, y);

        [self addChild:self.drop];
    }

    -(void)update:(NSTimeInterval)currentTime {

        if (self.lastUpdateTimeInterval) {
            self.timeSinceDropAdded += currentTime - self.lastUpdateTimeInterval;
        }

        if (self.timeSinceDropAdded > 1) {
            [self addDrops];
            self.timeSinceDropAdded = 0;
        }

        self.lastUpdateTimeInterval = currentTime;

}

问题是(我知道这听起来可能有点愚蠢):在跌落落地之前,它已经改变了它的值。例如,如果 ANBDropNode *drop 是 bluedrop,则在它落地之前,该方法会随机创建另一个 drop 并将其值更改为 greendrop。但我不想要这种行为。我希望水滴继续保持它的值,直到它到达地面,这样我就可以在我的 didBeginContact 方法中检测它的颜色。

【问题讨论】:

  • 我没有遵循你想要做的事情。也许把问题简化一点?
  • 好的,让我试试看:我怎样才能保持 *drop 具有相同的值,直到它到达地面,这样我才能在我的 didBeginContact 方法中根据其颜色检测碰撞?如果水滴的颜色与地面相同,则游戏继续。如果不同,游戏结束。
  • self.drop 是对单个对象的引用,如果您需要跟踪所有 drop,请改用数组
  • 对不起@LearnCocos2D,但我是编程新手。你能解释一下你的观点吗?你认为我必须在我的 +(instancetype)dropOfType 方法或我的 -(void)addDrops 中使用一个数组吗?或者两者都不是?坦克

标签: objective-c random sprite-kit game-physics sprite


【解决方案1】:

对于任何英语错误,请提前道歉,因为我不是以英语为母语的人。

根据您的问题,我了解到您保留对水滴 (self.drop) 的引用的原因是检查它落地时的颜色。
所以你可以删除它,每次都创建一个新的 SKSpriteNode 对象,而不是仅仅改变当前属性的引用。
如果您有任何其他理由保留对该下降的引用,请仍然保留引用。
请注意,执行上述任何操作都不会影响下面的代码。

我认为您的方向是正确的(在询问 didBeginContact 时)但采取了错误的方法/心态,因为使用 didBeginContact 时无需保留参考,因为您可以获取节点从此方法联系。

不管怎样,这里是代码+解释

// MyScene.m  

// First, conform to SKPhysicsContactDelegate, so you can get didBeginContact 'calls'
@interface MyScene () <SKPhysicsContactDelegate>  
@end  

@implementation MyScene  

// Now add the following constant, that you'll use as the physics body category bit masks  
static const uint32_t groundCategory = 0x01 << 0;  
static const uint32_t dropsCategory  = 0x01 << 1;  

// Somewhere in your initialisation, set yourself to be the physicsWorld  
// contact delegate, so you'll receive the didBeginContact 'calls',  
// And also call setupGround method, that we will create in here as well
-(id)initSceneWithSize:(CGSize)size {  
    ...
    ...
    self.physicsWorld.contactDelegate = self;  
    [self setupGround];  
    ...  
}  

// Here we will create the ground node, so we can detect when a drop  
// Hits the ground.  
// The reason that, in the below code, I am setting just the ground,  
// and not the whole borders of the screen, is because the drops  
// are added above the screen 'borders', and if we would make  
// a 'frame' node, and not a 'ground' node, we will also receive  
// contact delegate calls, when the nodes first enter the scene  
// and hits the top 'border' of the frame
-(void)setupGround {  
    SKNode *groundNode     = [SKNode node];  
    groundNode.strokeColor = [SKColor clearColor];  
    groundNode.fillColor   = [SKColor clearColor];  
    // Not sure if the above two are mandatory, but better be safe than sorry...  

    // Here we set the physics body to start at the bottom left edge of the screen  
    // and be the width of the screen, and the size of 1 points  
    // Then, we also set its category bit mask
    CGRect groundRect = CGRectMake(0, 0, self.size.width, 1);
    groundNode.physicsBody = [SKPhysicsBody bodyWithEdgeLoopFromRect:groundRect];  
    groundNode.physicsBody.categoryBitMask = groundCategory;  

    [self addChild:groundNode];  
}  

// Next we will modify your current method of creating drops, to also have  
// their name property to holds the corresponding colour name  
+(instancetype)dropOfType:(ANBDropType)type {

    ANBDropsNode *drop;

    if (type == ANBDropTypeBlue) {
        drop = [self spriteNodeWithImageNamed:@"bluedrop"];
        drop.name = @"Blue";
    } else if (type == ANBDropTypeGreen) {
        drop = [self spriteNodeWithImageNamed:@"greendrop"];
        drop.name = @"Green";
    } else if (type == ANBDropTypeOrange) {
        drop = [self spriteNodeWithImageNamed:@"orangedrop"];
        drop.name = @"Orange";
    } else if (type == ANBDropTypeRed){
        drop = [self spriteNodeWithImageNamed:@"reddrop"];
        drop.name = @"Red";
    }

    [drop setupPhysicsBody];
    return drop;
}  

// In your setupPhysicsBody method of the drop, add the following to define  
// the drop's bit mask, contact test, and collision.  
// Make sure you are adding them AFTER setting the physics body, and not before.  
// Since you revealed no code regarding this method, I will assume 'self' is  
// referring to the drop, since you call this method on the drop.
-(void) setupPhysicsBody {  
    ...  
    ...  
    ...  
    self.physicsBody.categoryBitMask    = dropsCategory;  
    self.physicsBody.contactTestBitMask = groundCategory;  
    self.physicsBody.collisionBitMask   = 0;  
    // The above code sets the drop category bit mask, sets its contactTestBitMask  
    // to be of the groundCategory, so whenever an object with drop category, will  
    // 'touch' and object with groundCategory, our didBeginContact delegate will  
    // get called.  
    // Also, we've set the collision bit mask to be 0, since we only want to  
    // be notified when a contact begins, but we don't actually want them both to  
    // 'collide', and therefore, have the drops 'lying' on the ground.  
    ...  
    ...  
    ...  
}  

// Now we can set the didBeginContact: delegate method.  
// Note that, as the name of the method suggests, this method gets called when a  
// Contact is began, meaning, the drop is still visible on screen.  
// If you would like to do whatever you want to do, when the drop leaves the screen,  
// just call the didEndContact: delegate method  
-(void)didBeginContact:(SKPhysicsContact *)contact {  
    // SKPhysicsContact have two properties, bodyA and bodyB, which represents  
    // the two nodes that contacted each other.  
    // Since there is no certain way to know which body will always be our drop,  
    // We will check the bodies category bit masks, to determine which is which  
    ANBDropsNode *drop = (contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask) ? (ANBDropsNode *)contact.bodyB.node : (ANBDropsNode *)contact.bodyA.node;  
    // In the above we are checking the category bit masks,  
    // Note that we set groundCategory to be 1, and dropsCategory to be 2,  
    // So we are checking which is higher.  
    // If bodyA bit mask is lower than bodyB bit mask, that means the bodyA is  
    // the ground, and bodyB is the drop, so we set the drop to be bodyB's node  
    // Else, we set it to be bodyA's node.  

    // Now you can easily get the drop colour from the name property we've set in  
    // the beginning. you can do some sort of if-else statement, that check  
    // 'if isEqualToString'. Here I just NSLog the colour  
    NSLog(@"%@", drop.name);

}  

祝你好运。

【讨论】:

    【解决方案2】:

    您可以简单地将一个属性与 ANBDropsNode 类相关联,该类可以在实例化 drop 时设置。

    在 ANBDropsNode.h 文件中,

    @interface ANBDropsNode
    
    @property (strong, nonatomic) NSString *dropColor; //This property will hold the value associated with the color.
    

    然后在dropOfType类方法中:

    +(instancetype)dropOfType:(ANBDropType)type {
    
        NSString *strDropColor;
    
        if (type == ANBDropTypeBlue) {
            strDropColor = @"bluedrop";
        } else if (type == ANBDropTypeGreen) {
            strDropColor = @"greendrop";
        } else if (type == ANBDropTypeOrange) {
            strDropColor = @"orangedrop";
        } else if (type == ANBDropTypeRed){
            strDropColor = @"reddrop";
        }
    
        ANBDropsNode *drop = [self spriteNodeWithImageNamed:strDropColor];
        drop.dropColor = strDropColor;
    
        [drop setupPhysicsBody];
        return drop;
    }
    

    现在,在您的碰撞检测委托方法中,您可以通过简单地引用dropColor 属性来找出节点的颜色。

    【讨论】:

      猜你喜欢
      • 2015-04-15
      • 1970-01-01
      • 2019-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多