Image masquée à  gratter pour la découvrir

MAGEMAGE Membre
10:21 modifié dans API UIKit #1
J'avais envie d'ajouter une interaction sur une vue : Une vue serai cachée derrière un masque et il faudrait la gratter pour découvrir ce qu'elle contient.

Après plusieurs recherches je suis tombé sur ça
J'ai également essayé de comprendre le tuto de Philippe
Troisième piste évoquée sur les forums, celle de se baser sur le code exemple d'Apple GLPaint.

Pourtant, avec toutes ces pistes, je n'arrive pas vraiment à  me lancer et je vous demande donc un peu d'aide pour les premières étapes.

Merci d'avance  ;)

Réponses

  • Philippe49Philippe49 Membre
    10:21 modifié #2
    Ma première idée serait de créer une image à  chaque nouveau touch en l'agrandissant d'une tâche.

    Essaye d'abord de construire une image avec :
    UIGraphicsBeginImageContext();
    UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
  • MAGEMAGE Membre
    10:21 modifié #3
    Merci.

    Effectivement, ça à  l'air de convenir. Je vais suivre ta piste.
  • Philippe49Philippe49 Membre
    10:21 modifié #4
    Une autre idée serait de considérer le masque comme un ensemble de tuiles, et que le touch fait tomber quelques tuiles ... Si le nombre de tuiles est raisonnable, cela doit pouvoir marcher.
  • MAGEMAGE Membre
    septembre 2009 modifié #5
    Bon, voici quelques nouvelles et je suis assez content du résultat avec ça :

    UITouch *touch = [touches anyObject];<br />//maVue est la vue qui est à  gratter<br />CGPoint currentPoint = [touch locationInView:maVue];<br />UIGraphicsBeginImageContext(maVue.frame.size);<br />// cache est l&#39;image qui est au premier plan de ma vue est qui est grattée<br />[cache.image drawInRect:CGRectMake(0, 0, maVue.frame.size.width, maVue.frame.size.height)];<br />CGContextSetLineCap(UIGraphicsGetCurrentContext(),kCGImageAlphaPremultipliedLast);	CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 10);<br />CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1, 0, 0, 10);<br />CGContextBeginPath(UIGraphicsGetCurrentContext());<br />CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);<br />CGContextClearRect (UIGraphicsGetCurrentContext(), CGRectMake(lastPoint.x, lastPoint.y, 40, 40)); <br />CGContextStrokePath(UIGraphicsGetCurrentContext());<br />cache.image = UIGraphicsGetImageFromCurrentImageContext();<br />UIGraphicsEndImageContext();<br />lastPoint = currentPoint;
    


    J'aimerai bien changer le CGContextClearRect en quelque chose de rond, mais j'ai pas encore trouvé.
  • DrakenDraken Membre
    10:21 modifié #6
    Tu n'as pas une image du grattage à  nous montrer, plutôt que des lignes de codes ?




  • MAGEMAGE Membre
    10:21 modifié #7
    Bien sûr, je peux même te faire une vidéo avec de la musique douce si tu veux  :)
    En fait je trouve l'image pas très parlante.

    Mais je te mets image, vidéo et le projet Xcode... comme ça c'est complet (sans la musique douce;))
  • keekookeekoo Membre
    10:21 modifié #8
    Bonjour,

    As-tu trouvé une solution au remplacement de la forme carrée de l'effacement (forme ronde par exemple) ?

    merci d'avance

    Keekoo

    dans 1253772925:

    Bon, voici quelques nouvelles et je suis assez content du résultat avec ça :

    UITouch *touch = [touches anyObject];<br />//maVue est la vue qui est à  gratter<br />CGPoint currentPoint = [touch locationInView:maVue];<br />UIGraphicsBeginImageContext(maVue.frame.size);<br />// cache est l&#039;image qui est au premier plan de ma vue est qui est grattée<br />[cache.image drawInRect:CGRectMake(0, 0, maVue.frame.size.width, maVue.frame.size.height)];<br />CGContextSetLineCap(UIGraphicsGetCurrentContext(),kCGImageAlphaPremultipliedLast);	CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 10);<br />CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1, 0, 0, 10);<br />CGContextBeginPath(UIGraphicsGetCurrentContext());<br />CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);<br />CGContextClearRect (UIGraphicsGetCurrentContext(), CGRectMake(lastPoint.x, lastPoint.y, 40, 40)); <br />CGContextStrokePath(UIGraphicsGetCurrentContext());<br />cache.image = UIGraphicsGetImageFromCurrentImageContext();<br />UIGraphicsEndImageContext();<br />lastPoint = currentPoint;
    


    J'aimerai bien changer le CGContextClearRect en quelque chose de rond, mais j'ai pas encore trouvé.
  • CéroceCéroce Membre, Modérateur
    10:21 modifié #9
    Essaie avec [tt]CGContextSetLineCap(context, kCGLineCapRound)[/tt].
  • MAGEMAGE Membre
    10:21 modifié #10
    Rien de nouveau de mon côté... mais toujours intéressé à  faire avancer le problème  xd
  • DrakenDraken Membre
    avril 2011 modifié #11
    J'ai bricolé un truc hier en faisant des essais avec le canal alpha et les modes de blending. Que penses-tu du rendu, Mage ?

  • DrakenDraken Membre
    10:21 modifié #12
    L'image compléte :
  • DrakenDraken Membre
    avril 2011 modifié #13
    Le masque de découpage n'est pas une primitive géométrique, mais une bitmap, ce qui permet d'avoir des "trous" de forme quelconque, en changeant l'image, sans toucher au code.

    J'ai créé celui-ci en quelques instants en gribouillant avec l'outil "pinceau" de Gimp :

  • MAGEMAGE Membre
    10:21 modifié #14
    ... des "trous" de forme quelconque, en changeant l'image, sans toucher au code.

    Et en français ça donne quoi ? B)

    Mais oui, ça me semble tout à  fait le but recherché 
  • DrakenDraken Membre
    10:21 modifié #15
    dans 1302196129:

    ... des "trous" de forme quelconque, en changeant l'image, sans toucher au code.

    Et en français ça donne quoi ? B)


    En français ça dit que le logiciel découpe des "trous" dans le masque suivant une forme, définie dans une image nommée masqueDecoupage.png. En modifiant cette image avec un logiciel graphique, on change l'allure du découpage. Par exemple, j'ai créé un nouveau masque avec une forme bien connue :


  • DrakenDraken Membre
    avril 2011 modifié #16
    Résultat des courses :

    J'améliore la présentation du iTruc et j'écris un tuto sur la manière de réaliser tout ça.

  • MAGEMAGE Membre
    10:21 modifié #17
    Impatient.. Merci  ::)
  • keekookeekoo Membre
    10:21 modifié #18
    Bonjour,

    Voici ma solution pour avoir une gomme ronde.
    la commande CGContextClearRect ne peut être que carrée (si j'ai bien compris). J'ai donc appliquée une rotation à  ce carré ce qui revient à  faire une forme ronde. ça doit être améliorable.

    <br />- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {<br />&nbsp; &nbsp; [super touchesBegan:touches withEvent:event];<br />&nbsp; &nbsp; int tailleGomme = 50;<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; UITouch *touch = [touches anyObject];<br />&nbsp; &nbsp; //maVue est la vue qui est à  gratter<br />&nbsp; &nbsp; CGPoint currentPoint = [touch locationInView:maVue];<br />&nbsp; &nbsp; lastPoint = currentPoint;// rajouté ici pour supprimer le carré à  gauche et en haut lors du chargement de la page et du premier clic<br />&nbsp; &nbsp; UIGraphicsBeginImageContext(maVue.frame.size);<br />&nbsp; &nbsp; // cache est l&#039;image qui est au premier plan de ma vue est qui est grattée<br />&nbsp; &nbsp; [cache.image drawInRect:CGRectMake(0, 0, maVue.frame.size.width, maVue.frame.size.height)];<br />&nbsp;  <br />&nbsp; &nbsp; <br />&nbsp; &nbsp; for (int i=0; i&lt;91; i++) {<br />&nbsp; &nbsp; &nbsp; &nbsp; CGContextTranslateCTM (UIGraphicsGetCurrentContext(), +lastPoint.x , +lastPoint.y);<br />&nbsp; &nbsp; &nbsp; &nbsp; CGContextRotateCTM (UIGraphicsGetCurrentContext(), i); //rotates around upper left corner of iPhone.<br />&nbsp; &nbsp; &nbsp; &nbsp; CGContextTranslateCTM (UIGraphicsGetCurrentContext(), -lastPoint.x , -lastPoint.y); <br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; CGContextClearRect (UIGraphicsGetCurrentContext(), CGRectMake(lastPoint.x-tailleGomme/2, lastPoint.y-tailleGomme/2, tailleGomme, tailleGomme));//-tailleGomme/2 : rajouté pour effacer complétement le bord gauche <br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; cache.image = UIGraphicsGetImageFromCurrentImageContext();<br />&nbsp; &nbsp; UIGraphicsEndImageContext();<br />&nbsp; &nbsp; lastPoint = currentPoint;<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; <br />}<br />
    


    maintenant il me reste à  déterminer quelle est la surface de la vue qui est effacée pour finaliser l'effacement sans devoir passer le doigt sur tout l'écran.
  • DrakenDraken Membre
    avril 2011 modifié #19
    Il y a plus simple, en utilisant la méthode CGContextFillEllipseInRect pour dessiner une ellipse.

    <br />CGContextFillEllipseInRect<br />Paints the area of the ellipse that fits inside the provided rectangle, using the fill color in the current graphics state.<br /><br />void CGContextFillEllipseInRect (<br />&nbsp;  CGContextRef context,<br />&nbsp;  CGRect rect<br />);<br />
    


    Elle dessine une ellipse pleine tenant dans les limites d'un rectangle.

    CGRect monEllipse = CGRectMake(100, 100, 64, 64);<br /><br />CGContextFillEllipseInRect(UIGraphicsGetCurrentContext(), monEllipse);<br />
    


    Si la hauteur et la largeur du rectangle de destination sont les mêmes, on obtient un cercle.

  • AliGatorAliGator Membre, Modérateur
    10:21 modifié #20
    dans 1302267459:

    la commande CGContextClearRect ne peut être que carrée
    C'est un peu pour ça qu'elle s'appelle "...Rect" !
  • keekookeekoo Membre
    10:21 modifié #21
    dans 1302270394:

    dans 1302267459:

    la commande CGContextClearRect ne peut être que carrée
    C'est un peu pour ça qu'elle s'appelle "...Rect" !


    oui, c'est pas faux  ::)
  • laudemalaudema Membre
    10:21 modifié #22
    dans 1302203561:

    J'améliore la présentation du iTruc et j'écris un tuto sur la manière de réaliser tout ça.

    Et avec les sous gagnés une tournée générale de Perrier citron ?  ::)
    Sinon j'ai trouvé ça très réussi ce que tu as fait moi qui n'aime pas trop m'aventurer dans les manipulations d'images...
  • DrakenDraken Membre
    10:21 modifié #23
    Les sous, c'est pour payer le renouvellement de ma licence de développeur iPhone, le mois prochain !  ::)

    Je m'y connais un peu en matière de manipulation d'images, c'est un prérequis pour la création de jeux vidéo, mon domaine de prédilection.

  • DrakenDraken Membre
    avril 2011 modifié #24
    Désolé Mage, mais je n'ai pas le temps de terminer le super-tuto-de-la-mort-qui-tue expliquant la manière de réaliser des effets graphiques. Je te donne le code maintenant pour ne pas te faire attendre davantage.

    Le code d'initialisation crée 2 UIIlageView et les places sur l'écran, l'une sur l'autre. Elles contiennent toutes les deux une image de 320x480 pixels, la taille de l'écran.

    - (void)viewDidLoad {<br />&nbsp; &nbsp; [super viewDidLoad];<br />	<br />		UIImage *image = [UIImage imageNamed:@&quot;Sushis.jpg&quot;];	<br />		m_imageView = [[UIImageView alloc] initWithImage:image];<br />		[self.view addSubview:m_imageView];	<br />		[m_imageView release];<br />			<br />	&nbsp; &nbsp; &nbsp; &nbsp; UIImage *imageDuHaut = [UIImage imageNamed:@&quot;imageDuHaut.png&quot;];<br />	&nbsp; &nbsp; &nbsp; &nbsp; m_imageDuHautView = [[UIImageView alloc] initWithImage:imageDuHaut];<br />		[self.view addSubview:m_imageDuHautView];<br />		[m_imageDuHautView release];<br />	<br />}<br />
    


    La méthode masquage: charge une petite image png, puis l'affiche sur l'écran à  la position courante. Le dessin n'est pas réalisé de la manière classique, mais en passant par l'opérateur de Blending kCGBlendModeDestinationOut qui utilise une formule mathématique pour "fusionner" les couleurs des images de source et de destination, en tenant compte de la couche alpha de l'image source. Il y a différents opérateurs de Blending, avec des modes de fusion différents, donnant des effets très différents. Je m'étendrais davantage sur le sujet avec le tuto sur le Blending.

    <br />- (void) masquage:(CGPoint)position<br />{ 		<br />	CGRect frameImage = m_imageDuHautView.frame;<br />	UIGraphicsBeginImageContext(frameImage.size);<br />	<br />	[m_imageDuHautView.image drawAtPoint:CGPointMake(0, 0)];<br />		<br />	UIImage *masque = [UIImage imageNamed:@&quot;masque_alpha.png&quot;];<br />	<br />	CGPoint monPoint = CGPointMake(position.x-masque.size.width/2,<br />						&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; position.y-masque.size.height/2);<br />											<br />	[masque drawAtPoint:monPoint<br />					blendMode:kCGBlendModeDestinationOut<br />					alpha:1.0f];<br />										 <br />	m_imageDuHautView.image = UIGraphicsGetImageFromCurrentImageContext();<br />	UIGraphicsEndImageContext();<br />}<br />
    


    Pour réaliser l'effet, il suffit d'appeler la méthode masquage: à  chaque contact du doigt sur l'écran.
    <br />- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {<br />	UITouch *aTouch = [touches anyObject];<br />	CGPoint currentPoint = [aTouch locationInView:self.view];	<br />	[self masquage:currentPoint];<br />}<br /><br /><br />- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{<br />	UITouch *aTouch = [touches anyObject];<br />	CGPoint currentPoint = [aTouch locationInView:self.view];<br />	[self masquage:currentPoint];<br />}	<br />
    


    La couleur de la petite image de masquage n'a aucune importance. L'opérateur de Blending kCGBlendModeDestinationOut n'utilise que sa couche alpha pour ces calculs de "fusion graphique".


  • DrakenDraken Membre
    avril 2015 modifié #25

    Nada


Connectez-vous ou Inscrivez-vous pour répondre.