2010-07-13 5 views
1

Je suis curieux quant à la méthode « appropriée » pour atteindre les fonctionnalités suivantes à l'aide Quarts2D:iPhone Quartz2D rendent l'expansion cercle

Je veux avoir une vue et d'être en mesure d'ajouter un cercle à tout coordonner. Dès que j'ajoute le cercle, il devrait s'étendre à un rythme prédéfini; Je voudrais aussi répéter ce processus et avoir un numéro si ces cercles en expansion.

Think Missile Command:

Yellow spots keep expanding

En général, si j'écris en C++ en utilisant SDL ou une autre bibliothèque graphique je voudrais:

ont une classe pour représenter un 'cercle de plus en plus' Avoir un vecteur/tableau pour contenir des pointeurs vers tous les 'cercles en croissance' que je crée.

Tous les diamètres de cercles seraient augmentés à chaque tick, et dans mon renderloop je voudrais itérer la liste et dessiner les cercles appropriés à mon tampon. Cependant, cela ne semble pas bien cadrer avec la façon dont j'ai généralement utilisé les vues dans le développement de l'iPhone précédent.

Donc je suppose que c'est un peu ouvert, mais y a-t-il un moyen correct pour quelque chose comme ça? Serait-ce dans un style de boucle de jeu (comme décrit ci-dessus), ou devrais-je sous-classer UIView pour un objet 'cercle', et remplacer drawRect? Je suppose que je devrais alors ajouter chaque cercle en créant une vue et en l'ajoutant à ma vue principale?

La recherche initiale m'a également amené à faire référence à la classe CAShapeLayer, même si je suppose que cela pourrait être la même chose que d'implémenter la technique de sous-classement UIView.

Répondre

2

Voici une façon de le faire. Ajoutez le code suivant à votre sous-classe UIViewController et vous obtiendrez un cercle qui se développe et se fane loin partout où vous touchez:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    [self addGrowingCircleAtPoint:[[touches anyObject] locationInView:self.view]]; 
} 

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { 
    if (flag && [[anim valueForKey:@"name"] isEqual:@"grow"]) { 
     // when the grow animation is complete, we fade the layer 
     CALayer* lyr = [anim valueForKey:@"layer"]; 
     CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; 
     animation.fromValue = [lyr valueForKey:@"opacity"]; 
     animation.toValue = [NSNumber numberWithFloat:0.f]; 
     animation.duration = .5f; 
     animation.delegate = self; 
     lyr.opacity = 0.f; 
     [animation setValue:@"fade" forKey:@"name"]; 
     [animation setValue:lyr forKey:@"layer"]; 
     [lyr addAnimation:animation forKey:@"opacity"]; 
    } else if (flag && [[anim valueForKey:@"name"] isEqual:@"fade"]) { 
     // when the fade animation is complete, we remove the layer 
     CALayer* lyr = [anim valueForKey:@"layer"]; 
     [lyr removeFromSuperlayer]; 
     [lyr release]; 
    } 

} 

- (void)addGrowingCircleAtPoint:(CGPoint)point { 
    // create a circle path 
    CGMutablePathRef circlePath = CGPathCreateMutable(); 
    CGPathAddArc(circlePath, NULL, 0.f, 0.f, 20.f, 0.f, (float)2.f*M_PI, true); 

    // create a shape layer 
    CAShapeLayer* lyr = [[CAShapeLayer alloc] init]; 
    lyr.path = circlePath; 

    // don't leak, please 
    CGPathRelease(circlePath); 
    lyr.delegate = self; 

    // set up the attributes of the shape layer and add it to our view's layer 
    lyr.fillColor = [[UIColor redColor] CGColor]; 
    lyr.position = point; 
    lyr.anchorPoint = CGPointMake(.5f, .5f); 
    [self.view.layer addSublayer:lyr]; 

    // set up the growing animation 
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"]; 
    animation.fromValue = [lyr valueForKey:@"transform"]; 
    // this will actually grow the circle into an oval 
    CATransform3D t = CATransform3DMakeScale(6.f, 4.f, 1.f); 
    animation.toValue = [NSValue valueWithCATransform3D:t]; 
    animation.duration = 2.f; 
    animation.delegate = self; 
    lyr.transform = t; 
    [animation setValue:@"grow" forKey:@"name"]; 
    [animation setValue:lyr forKey:@"layer"]; 
    [lyr addAnimation:animation forKey:@"transform"]; 
} 
+0

solution Nice, j'aime l'effet :-) Ce ne serait pas trop utile si Je voulais cependant interroger l'état d'un cercle particulier? Bien que je suppose que je pourrais garder une référence à tous les calques existants et les utiliser pour interroger des choses comme les dimensions de la couche (devrais-je gérer les collisions, par exemple) – davbryn

+1

Ouais, il y a beaucoup de façons d'habiller ce chat. Jetez un coup d'œil à la méthode 'hitTest:' de CALayer. Il utilise par défaut les limites rectangulaires de la couche, mais vous pouvez sous-classer CAShapeLayer pour votre cercle en expansion et fournir une implémentation hitTest qui est intelligente en matière de transparence/géométrie. –

+0

Brillant, merci! – davbryn