Dans Interface Builder, sélectionnez la vue en question et, dans l’onglet Identity de l’Inspecteur, indiquez un nom de classe pour votre vue dans le champ Class (par exemple : GameView
). Sélectionnez File > Write Class Files… dans le menu principal de Interface Builder pour générer cette classe dans le projet.
De retour dans Xcode, ouvrez le fichier de déclaration de cette classe (GameView.h
) et faites étendre la classe de NSView
:
@interface GameView : NSView { NSImage *background; } @end |
Ensuite, éditez le fichier d’implémentation de la classe (GameView.m
) et implémentez la méthode -drawRect:
:
- (void)awakeFromNib { // La variable "background" est déclarée dans le fichier header (.h). background = [NSImage imageNamed:@"background.png"]; } - (void)drawRect:(NSRect)rect { [background dissolveToPoint:NSMakePoint(0, 0) fraction:1.0]; } |
Notez que l’image est initialisée dans la méthode -awakeFromNib
, qui est appelée lors de l’initialisation de la vue.
Pour animer le contenu de la vue, et donc pour forcer le rafraîchissement de la vue, il est possible d’utiliser un NSTimer
pour indiquer à la vue qu’elle doit se re-dessiner :
- (void)awakeFromNib { background = [NSImage imageNamed:@"background.png"]; [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(refresh:) userInfo:nil repeats:YES]; } - (void)refresh:(NSTimer*)timer { [self setNeedsDisplay:YES]; } |
La méthode -refresh:
sera appelée toutes les 0,01 seconde (100 fois par secondes, donc) et demandera à la vue de se re-dessiner, via l’appel à setNeedsDisplay:YES
. Évidemment, ceci n’a de sens que si l’image (ou sa position) change.
Côté performances, j’ai fait quelques tests : j’affiche 1000 fois la même image (26×26 pixels) toutes les 0.01 seconde en la décalant de 1 pixel et ça ne gêne pas du tout mon iMac, l’animation est impeccable !
Je précise que ce n’est pas ici une technique très avancée pour animer du contenu, car cela ne tient pas compte de la puissance de la machine. En vérité, dans la méthode -refresh:
, il faudrait vérifier si l’image doit être déplacée (ou modifiée) en fonction du temps qui s’est écoulé depuis la dernière modification de cette image. Ainsi, peu importe la résolution du timer utilisée, ou la capacité de la machine à afficher du contenu graphique, l’image sera toujours correcte (en fonction du temps écoulé), même si l’animation n’est pas fluide. Il est aussi possible d’utiliser NSAnimation
pour des animations complexes « finies ».
Pour terminer, si votre but est de faire de l’animation complexe (2D ou 3D), comme pour la programmation d’un jeu, je ne peux que vous conseiller de vous tourner vers OpenGL. Je suis en train de m’y mettre, je publierai donc prochainement des articles à ce propos.