conseil pour afficher des images en mouvement

macounettemacounette Membre
12:55 modifié dans API UIKit #1
Bonjour,

je débute dans mon application iPhone. J'ai de bonnes bases en développement, mais je suis une newbie en objective-C...
J'aimerais pour l'instant que mon appli affiche un nombre N d'images qui flotte en gravité sur l'écran avec gestion des collisions. Pour le moment si j'arrive à  afficher N-images qui bougent je m'en contenterais !  :P

Je suis partie de ces tutos :
http://www.bit-101.com/blog/?p=1784
et aussi ici :
http://cedsoft.blogspot.com/2007/11/dveloppement-iphone-utilisation-de.html

Pour l'instant avec mon code j'arrive bien à  afficher une balle en mouvement sur l'écran.


GTViewController.h // Ma vue principale
@interface GTViewController : UIViewController {<br />	Ball *ball;<br />	UIImageView* fireBall;<br /><br />}<br /><br />- (void)onTimer;


GTViewController.m
- (void)viewDidLoad {<br />void)viewDidLoad {<br />&nbsp; &nbsp; [super viewDidLoad];<br />		<br />	ball = [Ball alloc];<br />	ball.position = CGPointMake(100, 100);<br />&nbsp; &nbsp; &nbsp; &nbsp; ball.velocity = CGPointMake(4.0, 3.0);<br />&nbsp; &nbsp; &nbsp; &nbsp; ball.radius = 25.0;	<br />	fireBall = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@&quot;fireball.png&quot;]];<br />	[NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 target:self selector:@selector(onTimer) userInfo:nil repeats:YES];<br />}<br /><br />-(void) onTimer {<br />	[ball update];<br />	fireBall.center = CGPointMake(ball.position.x, ball.position.y);<br />	[self.view addSubview:fireBall];<br />}


Ball.h // Ma balle avec ces coordonnées
@interface Ball : NSObject {<br />	CGPoint position;<br />&nbsp; &nbsp; CGPoint velocity;<br />&nbsp; &nbsp; CGFloat radius;<br />}<br /><br />@property CGPoint position;<br />@property CGPoint velocity;<br />@property CGFloat radius;<br />@property CGColorRef color;<br /><br />- (void)update;

Ball.m
- (void)update {<br /><br />&nbsp; &nbsp; position.x += velocity.x;<br />&nbsp; &nbsp; position.y += velocity.y;<br />	<br />&nbsp; &nbsp; if(position.x + radius&gt; 320.0) {<br />&nbsp; &nbsp; &nbsp; &nbsp; position.x = 320.0 - radius;<br />&nbsp; &nbsp; &nbsp; &nbsp; velocity.x *= -1.0;<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; else if(position.x - radius &lt;0.0) {<br />&nbsp; &nbsp; &nbsp; &nbsp; position.x = radius;<br />&nbsp; &nbsp; &nbsp; &nbsp; velocity.x *= -1.0;<br />&nbsp; &nbsp; }<br />	<br />&nbsp; &nbsp; if(position.y + radius&gt; 460.0) {<br />&nbsp; &nbsp; &nbsp; &nbsp; position.y = 460.0 - radius;<br />&nbsp; &nbsp; &nbsp; &nbsp; velocity.y *= -1.0;<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; else if(position.y - radius &lt;0.0) {<br />&nbsp; &nbsp; &nbsp; &nbsp; position.y = radius;<br />&nbsp; &nbsp; &nbsp; &nbsp; velocity.y *= -1.0;<br />&nbsp; &nbsp; }<br />}


Le problème c'est que si je veux en afficher 2, je suis obliger de créer 2 instances pour Ball et pour ma UIImageView :
@interface GTViewController : UIViewController {<br />	Ball *ball;<br />	UIImageView* fireBall;<br />	Ball *ball2;<br />	UIImageView* fireBall2;<br /><br />}


Ce n'est pas du tout pratique si j'ai N images à  afficher (N étant un nombre aléatoire...)

Avant de continuer plus loin dans mon développement, j'aimerais d'abord savoir si je suis bien partie (histoire de pas tout recommencer à  la fin). Et surtout j'aimerais avoir quelques pistes pour afficher mes N-images sans trop problèmes pour la suite (l'ajout de la gravité et la gestion des collisions). Je m'embrouille assez vite avec les view, les NSobject... Je pensais à  utiliser un tableau de Ball ? Je pars mal ?

Merci de vos conseils avisés !

Macounette

Réponses

  • schlumschlum Membre
    12:55 modifié #2
    Je ne vois aucune gestion de gravité dans ce code...  ???
    Une balle soumise à  la gravité fait des paraboles, elle ne va pas tout droit...
  • CeetixCeetix Membre
    mars 2009 modifié #3
    Je suis sur le même genre d'appli que toi. Sauf que je ne gère pas de gravité.
    Voilà  une petite video de démo. Si c'est un truc dans le genre que tu veux, dis moi j'essaierai de t'expliquer :)

    Eu sinon Shlum, en admettant que la gravité "ancrée" dans le sol (la bas de son iPhone) il n'y aura pas de parabole(enfin très très très peu visible). Par contre si sa gravité s'effectue sur un point beaucoup plus petit, là  il y a bien paralabole. No?
  • macounettemacounette Membre
    12:55 modifié #4
    dans 1236201827:

    Je ne vois aucune gestion de gravité dans ce code...  ???
    Une balle soumise à  la gravité fait des paraboles, elle ne va pas tout droit...


    Normal ! Pour l'instant je ne gère pas du tout la gravité. Je souhaite juste afficher de manière intelligente 2 balles qui rebondissent sur les bords de l'écran. La trajectoire est rectiligne et différente pour chaque balle. Après je rajouterais des choses plus complexes...
    Là  j'arrive bien à  avoir mes balles, elles rebondissent bien sur les bords, mais je ne peux pas utiliser mon code pour n-balles.

    Je voudrais juste qu'on m'éclaire un peu sur la façon de gérer mes objets et mes vues de manière à  ce que je puisse utiliser N-balles. Parce que je sais pas comment m'en sortir.
  • CéroceCéroce Membre, Modérateur
    mars 2009 modifié #5
    Tu places tes Ball dans un NSMutableArray après les avoir allouées:

    // ballArray est une variable d&#39;instance<br />ballArray = [[NSMutableArray alloc] initWithCapacity:100];<br /><br />Ball* ball = [[Ball alloc] init];<br />[ballArray addObject:ball];<br />[ball release];
    


    Ta classe Ball ne possède pas de méthode d'init: c'est mal.

    Ne pas oublier la méthode -dealloc:

    - (void) dealloc<br />{<br />&nbsp; &nbsp; [ballArray release];<br />}
    


    Quand ton timer est déclenché:

    [ballArray makeObjectsPerformSelector:@selector(update)];
    


    (d'ailleurs, ce serait plutôt la méthode -[display] que -[update]).

  • schlumschlum Membre
    12:55 modifié #6
    Le truc bien avec les classes, c'est que tu peux justement les instancier à  l'infini  ;)
    Une fois que t'as ta classe balle qui bouge, tu en fais plusieurs instances (en attribuant à  chacune un point de départ et une vitesse initiale), puis tu les mets toutes à  jours à  la fois dans le timer.

    Gérer l'interactivité c'est beaucoup plus complexe là  par contre !
    Au moment où tu fais la mise à  jour, il faut récupérer les coordonnées de toutes les autres balles pour détecter les collisions (et avoir un algo efficace pour écarter très vite des calculs les balles suffisamment loin).
  • macounettemacounette Membre
    mars 2009 modifié #7
    Alors sur vos conseils, j'ai un peu refait propre.

    Ma balle ball.h est maintenant définit comme suit :

    <br />@interface Ball : NSObject {<br />	CGPoint position;<br />CGPoint velocity;<br />&nbsp; &nbsp; CGFloat radius;<br />	UIImageView* imageBall; //mon image &quot;balle&quot;<br />}<br />
    



    GTViewController.m :

    <br />- (void)viewDidLoad {<br />&nbsp; &nbsp; [super viewDidLoad];<br />		<br />	ballArray = [[NSMutableArray alloc] initWithCapacity:100];<br /><br />	Ball* ball = [Ball alloc];<br />	[ball init:100 posy:200 velx:4 vely:3 rad:25]; // initialise les coord de la balle<br />	[ball initimg:[UIImage imageNamed:@&quot;fireball.png&quot;]]; // indique le fichier image de ma balle<br />	[ballArray addObject:ball];<br />	[ball release];<br />	[NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 target:self selector:@selector(onTimer) userInfo:nil repeats:YES];<br />}<br /><br />- (void)onTimer {<br />	[ballArray makeObjectsPerformSelector:@selector(display)];<br />	Ball* ball = [ballArray objectAtIndex:0]; //bof bof<br />	[self.view addSubview:ball.imageBall];<br />}<br /><br />- (void)dealloc {<br />	[ballArray release];<br />&nbsp; &nbsp; [super dealloc];<br />}<br /><br />
    


    GTViewController.h :

    <br />@interface GTViewController : UIViewController {<br />	NSMutableArray* ballArray;<br />}<br />
    


    Ca marche bien, mais je voudrais éviter d'utiliser dans mon timer : [ballArray objectAtIndex:0];

    Là  tout va bien car je n'ai qu'une balle, mais si j'en ai plusieurs je fais comment ?
    Il y a un moyen d'utiliser autre chose qu'un objectAtIndex et une boucle ?


  • Philippe49Philippe49 Membre
    mars 2009 modifié #8
    Dans la doc, il est précisé que le selector doit prendre en argument le timer.

    aSelector
    The message to send to target when the timer fires.
    The selector must have the following signature:
    - (void)timerFireMethod:(NSTimer*)theTimer
    The timer passes itself as the argument to this method.


    Pour la balle, tu passes son numéro dans le champ userInfo, il est là  pour cela.
    [EDIT] mais bon as-tu besoin de faire cela ?
  • Philippe49Philippe49 Membre
    mars 2009 modifié #9
    Je n'ai pas suivi toute la discussion (et pas le courage de la remonter)  mais cela me semble bizarre de rajouter une vue à  chaque fois qu'on redessine
    [self.view addSubview:ball.imageBall];
    Ce n'est pas ta méthode display qui s'en occupe ?
  • AliGatorAliGator Membre, Modérateur
    12:55 modifié #10
    Ouais et puis y'a encore des trucs bizarres, genre [tt]init:posy:velx:vely:rad:[/tt] c'est quoi ton premier paramètre que tu donnes à  "init" ? Ah c'est la posx j'imagine, puisque c'est le seul que tu passes pas sinon ?! Bah il aurait mieux fallu appeler la méthode, comme d'après les conventions, [tt]initWithPosX:posY:velX:velY:radius:[/tt] non ?
    Et en fait cette méthode n'apparaà®t pas dans ton ball.h ? ou alors tu ne l'as pas recopiée ici ?!

    Et puis pourquoi tu ajoutes ta balle en tant que subview... dans ta méthode de timer ?! Tu veux ajouter une balle toutes les N secondes ? Bizarre ça

    Et enfin, tu appelles la méthode... display des tes balles/NSViews ?! Il ne faut jamais appeller display directement, ni drawRect d'ailleurs, seulement  mettre le code du dessin dans drawRect et appeler setNeedsDisplay pour forcer le réaffichage...
  • macounettemacounette Membre
    12:55 modifié #11
    Ah bah j'apprends soyez indulgents :) si je savais tout et si je savais que je faisais tout bien je viendrais pas ici demander des conseils  :P
  • Philippe49Philippe49 Membre
    12:55 modifié #12
    dans 1236286464:

    Et enfin, tu appelles la méthode... display des tes balles/NSViews ?! Il ne faut jamais appeller display directement, ni drawRect d'ailleurs, seulement  mettre le code du dessin dans drawRect et appeler setNeedsDisplay pour forcer le réaffichage...

    Oui là  Ceroce n'a pas fait attention en te conseillant ce nom  (le matin c'est moi qui  :fouf): mais le soir on me remplace  ;D ), quoique display n'apparaà®t pas dans le SDK iphone (sauf pour CALayer) contrairement au mécanisme dans NSView. Donc c'est moins grave.
  • Philippe49Philippe49 Membre
    12:55 modifié #13
    dans 1236287061:

    Ah bah j'apprends soyez indulgents :) si je savais tout et si je savais que je faisais tout bien je viendrais pas ici demander des conseils  :P


    On est aux p'tits soins !

    Au fait bienvenue sur le forum, et il faudrait voir à  payer son coup !!
  • Philippe49Philippe49 Membre
    12:55 modifié #14
    dans 1236249372:

    Au moment où tu fais la mise à  jour, il faut récupérer les coordonnées de toutes les autres balles pour détecter les collisions (et avoir un algo efficace pour écarter très vite des calculs les balles suffisamment loin).


    La méthode appelée par ton timer doit
    1) régler le problème des collisions
    2) demander la mise à  jour de l'interface

    Pour le 1) c'est ce que dis Schlum, et cela c'est pas simple à  optimiser si le nombre de balles est grand. Si tu envisages 3, 5 boules une simple double boucle suffit, sinon on pourrait penser à  utiliser une triangulation (découpage de l'écran en triangles ) ou peut-être à  la mise à  jour à  chaque temps d'horloge d'un polygone des voisins de chaque balle. Ce dernier cas signifiant que l'on charge la classe Ball d'une variable d'instance désignant le polygone des balles autour de cette balle, cosntamment mis à  jour. Il faut voir dans les problèmes d'algorithmique géométrique si il n'y a pas autre chose. 

    Le 2) c'est ce que tu fais dans [ballArray makeObjectsPerformSelector:@selector(update)]; les caluls des nouvelles positions étant faites au point 1.




  • macounettemacounette Membre
    12:55 modifié #15
    Pour le 1) c'est ce que dis Schlum, et cela c'est pas simple à  optimiser si le nombre de balles est grand. Si tu envisages 3, 5 boules une simple double boucle suffit, sinon on pourrait penser à  utiliser une triangulation (découpage de l'écran en triangles ) ou peut-être à  la mise à  jour à  chaque temps d'horloge d'un polygone des voisins de chaque balle. Ce dernier cas signifiant que l'on charge la classe Ball d'une variable d'instance désignant le polygone des balles autour de cette balle, cosntamment mis à  jour. Il faut voir dans les problèmes d'algorithmique géométrique si il n'y a pas autre chose. 
    [/quote]

    Ouep ben c'est pas gagné. J'envisage beaucoup plus de boules... Rien que le mot triangulation me fait peur.  :-\\
    Bon première étape , je remet mon code au propre en fonction de vos remarques. Et on attaque les collisions après ! On y croit !




  • schlumschlum Membre
    mars 2009 modifié #16
    Il y a des algorithmes spécifiques je crois pour gérer ce genre de problèmes (collision de nombreuses particules dans des simulations nucléaire par exemple, ou gestion du trafic aérien...)
    Faut chercher sur Google, y a sans doute des infos.
  • schlumschlum Membre
    12:55 modifié #17
    En tout cas, à  lire pour avoir une vue d'ensemble :
    http://fr.wikipedia.org/wiki/Détection_de_collision
  • macounettemacounette Membre
    12:55 modifié #18
    dans 1236286464:

    Et puis pourquoi tu ajoutes ta balle en tant que subview... dans ta méthode de timer ?! Tu veux ajouter une balle toutes les N secondes ? Bizarre ça

    Et enfin, tu appelles la méthode... display des tes balles/NSViews ?! Il ne faut jamais appeller display directement, ni drawRect d'ailleurs, seulement  mettre le code du dessin dans drawRect et appeler setNeedsDisplay pour forcer le réaffichage...


    Bon je suis désolée, il y a un truc que j'ai pas compris :(

    Alors j'ai :
    - GTViewController.h qui crée mes balles dans viewDidLoad et qui lance le timer.
    - un NSObject Ball.h qui contient une méthode update qui met à  jour les coordonnées de la balle.

    Est-ce que c'est dans Ball.h que je dois définir mon drawRect pour dessiner mon image ?
    Est-ce que setNeedsDisplay doit être appeler dans mon timer ou dans ma méthode update ?
    Parce que setNeedsDisplay rafraà®chit une UIView du coup elle ne peut pas être dans mon update d'un NSObject...

    Alors est-ce que ma balle est bien un NSObject ? Est-ce que je n'aurais pas besoin d'une UIView supplémentaire ou je peux m'en sortir sans ?

    Je crois que je me suis embrouillée aujourd'hui. J'aurais peut-être les idées plus claires demain  :o
  • schlumschlum Membre
    12:55 modifié #19
    Non, le "drawRect:", c'est dans la vue qui contient les balles...
  • macounettemacounette Membre
    12:55 modifié #20
    Alors j'avance maintenant j'ai :
    - GTViewController.h qui crée mes balles dans viewDidLoad et qui lance le timer.
    - un NSObject Ball.h qui contient une méthode update qui met à  jour les coordonnées de la balle.
    - une UIView BallView qui contient mon drawrect et qui utilise le setNeedsDisplay


    dans GTViewController.m

    <br />- (void)viewDidLoad {<br />&nbsp; &nbsp; &nbsp; &nbsp; [super viewDidLoad];<br />	ballArray = [[NSMutableArray alloc] initWithCapacity:100];<br />	Ball* ball = [Ball alloc];<br />	[ball initWithPosX:100 posy:200 velx:4 vely:3 rad:25];<br />&nbsp; &nbsp; &nbsp; &nbsp; [ballArray addObject:ball];<br />&nbsp; &nbsp; &nbsp; &nbsp; [ball release];<br />&nbsp; &nbsp; &nbsp; &nbsp; [NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 target:self selector:@selector(onTimer) userInfo:nil repeats:YES];<br />}<br /><br />- (void)onTimer {<br />	Ball* ball = [ballArray objectAtIndex:0];<br />	[ball update];<br />CGRect rect = CGRectMake(ball.position.x - ball.radius, ball.position.y - ball.radius, ball.radius * 2.0, ball.radius * 2.0);<br />&nbsp; &nbsp; &nbsp; &nbsp; [(BallView *)self.view refresh:rect];<br />}<br />
    


    dans BallView.m
    <br />- (void)refresh:(CGRect)rect {<br />&nbsp; &nbsp; ballRect = rect;<br />&nbsp; &nbsp; [self setNeedsDisplay];<br />}<br /><br />- (void)drawRect:(CGRect)rect {<br />	UIImage *image = [ UIImage imageNamed: @&quot;monimage.png&quot; ];<br />&nbsp; &nbsp; [image drawInRect: ballRect ];<br />}<br />
    


    Bon voilà  c'est mieux ? J'avance ?
    Par contre gros problème je pense que mon [(BallView *)self.view refresh:rect]; n'est pas au bon endroit. Car du coup même si je créé plusieurs instance de balles, je n'en aurais qu'une qui s'affiche.

    Ca donnerais ça avec plusieurs balles (c'est pour l'exemple car c'est pas très propre...) :

    <br />- (void)onTimer {<br />	Ball* ball = [ballArray objectAtIndex:0];<br />	[ball update];<br />CGRect rect = CGRectMake(ball.position.x - ball.radius, ball.position.y - ball.radius, ball.radius * 2.0, ball.radius * 2.0);<br />&nbsp; &nbsp; &nbsp; &nbsp; [(BallView *)self.view refresh:rect];<br /><br />Ball* ball2 = [ballArray objectAtIndex:0];<br />	[ball2 update];<br />CGRect rect2 = CGRectMake(ball2.position.x - ball2.radius, ball2.position.y - ball2.radius, ball2.radius * 2.0, ball2.radius * 2.0);<br />&nbsp; &nbsp; &nbsp; &nbsp; [(BallView *)self.view refresh:rect2];<br />}<br />
    


    Je chiante hein ? Milles merci de m'aider, je cherches beaucoup d'exemple sur le net mais je trouve tout et n'importe quoi. Alors pour savoir ce qui est bien ou pas...

  • CéroceCéroce Membre, Modérateur
    12:55 modifié #21
    dans 1236374323:


    Est-ce que c'est dans Ball.h que je dois définir mon drawRect pour dessiner mon image ?


    ça dépend, c'est une question d'architecture. On pourrait imaginer que la vue récupère les coordonnées de toutes les balles et les dessine. Cependant, il paraà®t plus commode (dans la logique "objet", s'entend) qu'un balle sache se dessiner elle-même. Dans ce cas, elle comporterait une méthode -draw " et non pas -drawRect:, puisque la balle connaà®t ses coordonnées.
    Dans ce cas, la vue n'a plus besoin d'appeler une méthode -[Ball update], puisque la mise à  jour des coordonnées se ferait juste avant le dessin de la balle.

    Certains y ont vu de la fumette  :fouf):, mais il y avait bien une intention dans ce que j'avais écris la première fois ! (Comment ça je suis de mauvaise fois ?  >:D)

    dans 1236374323:

    Est-ce que setNeedsDisplay doit être appeler dans mon timer ou dans ma méthode update ?

    Dans ton timer, d'ailleurs, c'est la seule chose que tu aies à  y mettre. Comprends que quand tu appelles -setNeedsUpdate:YES, le dessin n'est pas immédiat. Dans la prochaine boucle du runtime objC, ta view va regarder si elle a besoin d'être rafraà®chie (= needs update), et si c'est le cas, elle appellera sa méthode -drawRect:. Là , tu pourras appeler la méthode -draw de toutes tes balles.

    dans 1236374323:

    Alors est-ce que ma balle est bien un NSObject ? Est-ce que je n'aurais pas besoin d'une UIView supplémentaire ou je peux m'en sortir sans ?


    Oui, une balle hérite de NSObject.
    Tu pourrais imaginer créer une UIView pour représenter chaque balle et l'insérer dans la vue parente, mais ce n'est pas du tout la bonne approche, aussi bien en termes de performances que de complexité.
  • AliGatorAliGator Membre, Modérateur
    12:55 modifié #22
    Finalement c'est la même architecture que celle que je proposais pour dessiner le plateau de jeu aux cellules hexagonales de GreenSource, non ?

    Sauf que dans le cas de GreenSource ce n'était pas animé, mais le principe est le même, une classe "modèle" pour gérer tes balles, leur position, etc... et une classe Vue qui, dans son drawRect, demande à  chaque balle de se dessiner elle-même (mettant à  jour ses coordonnées auparavant)
  • Philippe49Philippe49 Membre
    12:55 modifié #23
    On peut signaler  CGContextDrawLayerAtPoint() qui semble optimiser la visualisation

    exemple dans CGPathFunHouse
  • macounettemacounette Membre
    12:55 modifié #24
    Voilà  ce que ça donne sur les conseils de Ceroce.
    Je publie mon code ici pour aider comme moi les gens qui galère :)

    Ma UIView BallView :

    <br /><br />@interface BallView : UIView {<br />	NSMutableArray * ballArray;<br />}<br /><br />@implementation BallView<br /><br />- (id)initWithFrame:(CGRect)frameRect {<br />	self = [super initWithFrame:frameRect];<br />	<br />	ballArray = [[NSMutableArray alloc] initWithCapacity:100];	<br />	Ball* ball = [Ball alloc];<br />	ball = [[Ball alloc] init];<br />	[ball initWithPosX:100 PosY:200 VelX:4 VelY:3 Rad:25];	<br />	[ball initimg:[UIImage imageNamed:@&quot;fireball.png&quot;]];	<br />	[self addSubview: ball.imageBall];<br />	[ballArray addObject:ball];<br />	[ballrelease];<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; [NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 target:self selector:@selector(repaint) userInfo:nil repeats:YES];<br />	return self;<br />}<br /><br />- (void)drawRect:(CGRect)rect {<br />	CGContextRef context = UIGraphicsGetCurrentContext();<br />	Ball* ball = [ballArray objectAtIndex:0];<br />	[ball draw:context];<br />}<br /><br />- (void)repaint {<br />	// on met à  jour les coordonnées du layer<br />	Ball* ball = [ballArray objectAtIndex:0];<br />	[ball move];<br />	<br />	// force le rafraichissement de la vue<br />	// appellera la methode drawRect qui mettra à  jour le layer<br />	[self setNeedsDisplay];<br />}<br />
    


    Mon Objet Ball :

    <br />@interface Ball : NSObject {<br />	CGPoint position;<br />&nbsp; &nbsp; &nbsp; &nbsp; CGPoint velocity;<br />&nbsp; &nbsp; &nbsp; &nbsp; CGFloat radius;<br />	UIImageView* imageBall;<br />}<br /><br />@implementation Ball<br /><br />- (void)initimg:(UIImage *)img {<br />	imageBall = [[UIImageView alloc] initWithImage:img];<br />	imageBall.frame = CGRectMake(0, 0, 32, 32);<br />}<br /><br />- (void)initWithPosX:(int)x PosY:(int)y VelX:(int)vx VelY:(int)vy Rad:(int)r {<br />	position = CGPointMake(x, y);<br />&nbsp; &nbsp; &nbsp; &nbsp; velocity = CGPointMake(vx, vy);<br />&nbsp; &nbsp; &nbsp; &nbsp; radius = r;	<br />}<br /><br />// met a jour la position du cercle à  dessiner<br />- (void)move {<br />	position.x += velocity.x;<br />&nbsp; &nbsp; &nbsp; &nbsp; position.y += velocity.y;<br />	<br />&nbsp; &nbsp; &nbsp; &nbsp; if(position.x + radius&gt; 320.0) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  position.x = 320.0 - radius;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  velocity.x *= -1.0;<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; &nbsp; &nbsp; else if(position.x - radius &lt;0.0) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  position.x = radius;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  velocity.x *= -1.0;<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />	<br />&nbsp; &nbsp; &nbsp; &nbsp; if(position.y + radius&gt; 460.0) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  position.y = 460.0 - radius;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  velocity.y *= -1.0;<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; &nbsp; &nbsp; else if(position.y - radius &lt;0.0) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  position.y = radius;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  velocity.y *= -1.0;<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />}<br /><br />// redessine le cercle à  la position x,y<br />- (void)draw:(CGContextRef) context {<br />	 imageBall.frame = CGRectMake(position.x - radius, position.y - radius, radius * 2.0, radius * 2.0);<br />}<br /><br />
    

  • macounettemacounette Membre
    12:55 modifié #25
    J'écris mon problème dans ce post, car c'est toujours le même code...
    J'avais réussi à  afficher dans 1 vue BallView, des balles en mouvement. C'était l'étape 1.

    L'étape 2 consiste à  avoir sur l'écran, 2 zones distinctes, dans lesquelles des balles vont se déplacer.
    Imaginons que l'on coupe l'écran en 2. Dans ma "zone" supérieure j'aurais par exemple 3 balles en mouvement qui ne se déplaceront que dans cette zone (en rebondissant sur les bords de la zone). Dans ma "zone" inférieure, j'aurais 1 balle en mouvement.

    La problématique est donc d'afficher 2 zone distinctes indépendantes contenant des balles qui rebondissent. Je n'y arrive pas.

    J'ai un TestViewController.m qui me permettrait d'afficher mes 2 vues
    <br />- (void)loadView {<br />	<br />	UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];<br />	self.view = contentView;<br />	[contentView release];<br />	<br />	CGRect zone1 = CGRectMake(0, 0, 320, 200);<br />	BallView *ballView = [[[BallView alloc]&nbsp; initWithFrame:zone1:3] autorelease]; //il y aura 2 balles dans ma zone 1<br />	[self.view addSubview: ballView];<br /><br />&nbsp; &nbsp; &nbsp; &nbsp; CGRect zone2 = CGRectMake(0, 200, 320, 400);<br />	BallView *ballView = [[[BallView alloc]&nbsp; initWithFrame:zone2:1] autorelease]; //Il y aura 2 balles dans ma zone 2<br />	[self.view addSubview: ballView];<br />	self.view = contentView;<br />}<br />
    


    Mon UIView BallView.m permet de créer un tableau de NSObject Ball et de les mouvoir
    <br />- (id)initWithFrame:(CGRect)frameRect:(int)coord {<br />	self = [super initWithFrame:frameRect];<br />	<br />	ballNumber = coord;<br />	ballArray = [[NSMutableArray alloc] initWithCapacity:ballNumber];<br />	<br />	for(int i=0; i&lt;ballNumber; i++) {<br />		[self createBallWithPosX:100*i PosY:200 VelX:4 VelY:3 Rad:20 Image:[UIImage imageNamed:@&quot;icon.png&quot;]]; <br />	}<br />	<br />	// on declare un timer qui appellera la methode repaint 30 fois par seconde<br />	timer = [NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 target:self selector:@selector(repaint) userInfo:nil repeats:YES];<br />	return self;<br />}<br />
    


    Avec ça, le résultat est horrible  :-\\ Je n'ai même pas 2 vues qui s'affiche.
    Je soupçonne que mon TestViewController.m n'est pas comme il faut.

    Un coup de main ne serait pas de refus, ça fait des jours que je cherche en vain...

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