0

我正在使用 CADisplayLink 的动画和计时。当球碰到一块大石头时,它会立即被移走。我如何为石头(块)的移除设置动画,例如爆炸成小石头?这是我目前拥有的代码:

- (void)checkCollisionWithBlocks
{
    for (BlockView *bv in blocks) {
        if (CGRectIntersectsRect(bv.frame, ballRect)) {
            ballVelocity.y = -ballVelocity.y;
            [blocks removeObject:bv];
            [bv removeFromSuperview];
            break;
        }
    }
}
4

1 回答 1

0

CADisplayLink 确实有点……非常适合您的计划(用于将屏幕绘图更新同步到自定义动画)。这是我的解决方案:点燃一些东西!虽然不一定是爆炸,但这会导致你的方块喷出一些蓝色火焰(你可以通过修改来改变颜色self.fireColor)。

- (void)checkCollisionWithBlocks
{
    for (BlockView *bv in blocks) {
        if (CGRectIntersectsRect(bv.frame, ballRect)) {
            ballVelocity.y = -ballVelocity.y;
            [blocks removeObject:bv];
            [bv burpFire]
            [bv removeFromSuperview];
            break;
        }
    }
}

@interface BlockView : UIView 

@property (nonatomic, strong) CALayer *rootLayer;
@property (nonatomic, strong) CAEmitterLayer *fireEmitter;
@property (nonatomic, strong) CAEmitterLayer *smokeEmitter;
@property (nonatomic, strong) UIColor *fireColor;
@property (nonatomic, strong) UIColor *smokeColor;

-(void)burpFire;

@end
@implementation BlockView

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.rootLayer = [CALayer layer];

        //Set the root layer's background color to black
        self.rootLayer.backgroundColor = [UIColor blackColor].CGColor;

        //Create the fire emitter layer
        self.fireEmitter = [CAEmitterLayer layer];
        self.fireEmitter.emitterPosition = CGPointMake(0, CGRectGetMaxY(frame) + 50);
        self.fireEmitter.emitterMode = kCAEmitterLayerOutline;
        self.fireEmitter.emitterShape = kCAEmitterLayerLine;
        self.fireEmitter.renderMode = kCAEmitterLayerAdditive;
        self.fireEmitter.emitterSize = CGSizeMake(0, 0);

        //Create the smoke emitter layer
        self.smokeEmitter = [CAEmitterLayer layer];
        self.smokeEmitter.emitterPosition = CGPointMake(0, CGRectGetMaxY(frame) + 50);
        self.smokeEmitter.emitterMode = kCAEmitterLayerPoints;

        //Create the fire emitter cell
        CAEmitterCell* fire = [CAEmitterCell emitterCell];
        fire.emissionLongitude = M_PI;
        fire.birthRate = 0;
        fire.velocity = -80;
        fire.velocityRange = -30;
        fire.emissionRange = -1.1;
        fire.yAcceleration = -200;
        fire.scaleSpeed = 0.3;
        self.fireColor = [UIColor colorWithRed:0.425 green:0.779 blue:0.800 alpha:0.100];
        fire.color = self.fireColor.CGColor;
        fire.contents = (id)[self CGImageNamed:@"fire.png"];

        //Name the cell so that it can be animated later using keypaths
        [fire setName:@"fire"];

        //Add the fire emitter cell to the fire emitter layer
        self.fireEmitter.emitterCells = [NSArray arrayWithObject:fire] ;

        //Create the smoke emitter cell
        CAEmitterCell* smoke = [CAEmitterCell emitterCell];
        smoke.birthRate = 11;
        smoke.emissionLongitude = M_PI / 2;
        smoke.lifetime = 0;
        smoke.velocity = -40;
        smoke.velocityRange = 20;
        smoke.emissionRange = M_PI / 4;
        smoke.spin = 1;
        smoke.spinRange = 6;
        smoke.yAcceleration = 160;
        smoke.contents = (id) [self CGImageNamed:@"smoke.png"];
        smoke.scale = 0.1;
        smoke.alphaSpeed = -0.12;
        smoke.scaleSpeed = 0.7;

        //Name the cell so that it can be animated later using keypaths
        [smoke setName:@"smoke"];

        //Add the smoke emitter cell to the smoke emitter layer
        self.smokeEmitter.emitterCells = [NSArray arrayWithObject:smoke];

        //Add the two emitter layers to the root layer
        [self.layer addSublayer:self.smokeEmitter];
        [self.layer addSublayer:self.fireEmitter];

        [self burpFire];

    }
    return self;
}

//Return a CGImageRef from the specified image file in the app's bundle
-(CGImageRef)CGImageNamed:(NSString*)name {
    NSString *url = [[NSBundle mainBundle] pathForResource:name ofType:nil];
    return [UIImage imageWithContentsOfFile:url].CGImage;
}

-(void)burpFire {
    float gas = 80.0 / 100.0;
    //Update the fire properties
    [self.fireEmitter setValue:[NSNumber numberWithInt:(gas * 1000)] forKeyPath:@"emitterCells.fire.birthRate"];
    [self.fireEmitter setValue:[NSNumber numberWithFloat:gas] forKeyPath:@"emitterCells.fire.lifetime"];
    [self.fireEmitter setValue:[NSNumber numberWithFloat:(gas * 0.35)] forKeyPath:@"emitterCells.fire.lifetimeRange"];
    self.fireEmitter.emitterSize = CGSizeMake(100 * gas, 0);

    //Update the smoke properites
    [self.smokeEmitter setValue:[NSNumber numberWithInt:gas * 4] forKeyPath:@"emitterCells.smoke.lifetime"];
    self.smokeColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:gas * 0.3];
    [self.smokeEmitter setValue:(__bridge id)self.smokeColor.CGColor forKeyPath:@"emitterCells.smoke.color"];

    [self setNeedsDisplay];

    [self performSelector:@selector(burpFinished) withObject:nil afterDelay:1.5];
}

-(void)burpFinished {
    float gas = 0.0 / 100.0;
    //Update the fire properties
    [self.fireEmitter setValue:[NSNumber numberWithInt:(gas * 1000)] forKeyPath:@"emitterCells.fire.birthRate"];
    [self.fireEmitter setValue:[NSNumber numberWithFloat:gas] forKeyPath:@"emitterCells.fire.lifetime"];
    [self.fireEmitter setValue:[NSNumber numberWithFloat:(gas * 0.35)] forKeyPath:@"emitterCells.fire.lifetimeRange"];
    self.fireEmitter.emitterSize = CGSizeMake(100 * gas, 0);

    //Update the smoke properites
    [self.smokeEmitter setValue:[NSNumber numberWithInt:gas * 4] forKeyPath:@"emitterCells.smoke.lifetime"];
    self.smokeColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:gas * 0.3];
    [self.smokeEmitter setValue:(__bridge id)self.smokeColor.CGColor forKeyPath:@"emitterCells.smoke.color"];
}

CAEmitterLayers 会持续很长一段时间,所以如果你想让火关得更快一点,可以调整停止选择器的时间。如果您想要更小或更大的火,或者持续时间更长的火球,请使用 init 方法中的属性,无论哪种方式,您都会获得很酷的效果。

所有颜色都必须是对 UIColor 的强引用,否则 Core Animation 会吓坏并在调试器中引发 C++ 脾气暴躁……不愉快。

于 2012-12-22T21:58:36.897 回答