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 に答える