Aller au contenu

Votre premier programme en sprite

Votre premier programme en sprite 

 

Là encore il y a certainement plusieurs méthode pour démarrer votre programme plus ou moins académique , je vais vous montrer la mienne , elle fonctionne et elle est simple !

Nous allons utiliser le projet que nous avions créé dans « Les Sprites ( présentation) » pour démarrer .

Pour commencer nous allons supprimer le code inutile de présentation ,ce que vous avez actuellement doit ressembler a ça :

//

//  GameScene.m

//  Arkanoid

//

//  Created by Sylvain Altmayer on 14/11/2015.

//  Copyright (c) 2015 Sylvain Altmayer. All rights reserved.

//

#import « GameScene.h »

@implementation GameScene

-(void)didMoveToView:(SKView *)view {

    /* Setup your scene here */

    SKLabelNode *myLabel = [SKLabelNode labelNodeWithFontNamed:@ »Chalkduster »];

    myLabel.text = @ »Chalkduster »;

    myLabel.fontSize = 45;

    myLabel.position = CGPointMake(CGRectGetMidX(self.frame),

                                   CGRectGetMidY(self.frame));

    [self addChild:myLabel];

}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    /* Called when a touch begins */

    for (UITouch *touch in touches) {

        CGPoint location = [touch locationInNode:self];

        SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:@ »Spaceship »];

        sprite.xScale = 1;

        sprite.yScale = 0.5;

        sprite.position = location;

        SKAction *action = [SKAction rotateByAngle:M_PI duration:1];

       [sprite runAction:action ];

        [self addChild:sprite];

    }

}

-(void)update:(CFTimeInterval)currentTime {

    /* Called before each frame is rendered */

}

@end

 

Nous allons retirer le code en orange qui devient inutile , on a maintenant quelque chose qui ressemble a ça :

 

 

//

//  GameScene.m

//  Arkanoid

//

//  Created by Sylvain Altmayer on 14/11/2015.

//  Copyright (c) 2015 Sylvain Altmayer. All rights reserved.

//

#import « GameScene.h »

@implementation GameScene

-(void)didMoveToView:(SKView *)view {

    /* Setup your scene here */

}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    /* Called when a touch begins */

    for (UITouch *touch in touches) {

        CGPoint location = [touch locationInNode:self];

            }

}

-(void)update:(CFTimeInterval)currentTime {

    /* Called before each frame is rendered */

}

@end

Si vous avez bien effectué cette première action Xcode ne vous indique pas d’erreurs avec un point d’exclamation en rouge ( ! ), en revanche vous devez avoir un point d’exclamation jaune ( ! ) comme on peut le voir sur l’image dessous :

 

Capture d’écran 2015-11-15 à 10.51.47

 

Rien de grave ! Xcode vous indique simplement que vous avez déclaré une variable « location » ( dans laquelle on a stocké les coordonnés de l’endroit ou le tactile est touché par l’utilisateur ) que vous n’utilisez pas . Pour régler ce problème il suffirait de supprimer 2 ou 3 lignes de plus mais nous ne le ferons pas car elles vont nous être utile pour la suite et il nous faudrait les réécrire .De plus sachez que les points d’exclamations jaunes ne sont que des indications et ne vous empêche pas de lancer votre programme .Nous allons le constater tout de suite en lançant le programme ( Play en haut a gauche)

Vous devez avoir quelque chose qui ressemble a ceux-ci:

Capture d’écran 2015-11-15 à 11.03.15
 Vous cliquez dessus rien ne se passe ! c’est justement ce que l’on voulait ça tombe bien du coup 🙂
Je vous conseille de lancer vos programmes régulièrement afin de voir si ce que vous écrivez fonctionne , n’attendez pas d’en avoir fait de trop vous risqueriez d’être un peu noyé dans les erreurs surtout si vous n’avez pas trop l’habitude.

Le fond d’écran 

 

Le gris ne vous plait pas ? moi non plus …,nous allons rajouter une petite ligne :

self.backgroundColor=[SKColor blackColor];

Elle indique a Xcode que vous voulez voir le fond d’écran  coloré en NOIR ce sont les couleurs standard de la palette de couleur , il en existe d’autre , « greenColor » pour le vert , » redColor  » pour le rouge , etc … Je vous invite a jouer avec pour comprendre et surtout choisir une couleur de fond qui vous plaira.
nous allons donc insérer cette ligne ici :
Capture d’écran 2015-11-15 à 11.30.22
 –
testez vous devez obtenir ceux-ci:
 –
Capture d’écran 2015-11-15 à 11.32.08
C’était prévisible le fond d’écran est passé en noir ! 🙂
Vous allez me dire que c’est très restrictif comme couleur (green,red,black , … )
c’est vrai 🙂 c’est pourquoi il existe une autre méthode :
self.backgroundColor=[SKColor colorWithRed:0.5 green:0.2 blue:0.3 alpha:1];
Grace a cette nouvelle fonction toute les couleur que vous voulez sont a votre porté de main , vous aurez simplement a les mélanger comme le ferai un peintre pour obtenir ce que vous souhaitez. On remarque un terme supplémentaire  « alpha » qui est la transparence ( jouez avec pour voir ce que cela donne ! )
Avec cette ligne, on obtient un fond d’écran avec de couleur « pinard » qui vous le remarquerez n’était pas disponible parmi la palette de couleur d’Xcode 🙂 :
 Capture d’écran 2015-11-15 à 11.41.14
Tout ça c’est bien joli … mais vous auriez bien voulu la photo de votre « Chatkapuce » en fond d’écran ….
Ca aussi c’est possible et voici comment faire :

SKSpriteNode *chatkapuce =[SKSpriteNode spriteNodeWithImageNamed:@ »IMG_8906.jpg »];

    chatkapuce.name=@ »chatkapuce »;

    chatkapuce.position=CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));

    chatkapuce.xScale=0.28;

    chatkapuce.yScale=0.28;

    [self addChild:chatkapuce];

vous devez d’abord importer votre image dans vos fichiers je vous conseil de créer un répertoire image dans votre projet afin de ne pas en avoir partout , ça sera bien plus pratique le jour ou vous voudrez déplacer votre projet .CLICK Droit sur vos fichiers un menu déroulant apparaît comme ci-dessous :

 

Capture d’écran 2015-11-15 à 11.54.14

Puis sélectionnez add Files to ‘ nom du projet ‘,vous lui indiquez ensuite l’emplacement de l’image et le fichier doit apparaître dans le template (arborescence) du projet.

le mien s’appelle « IMG_8906.jpg » faites attention a bien écrire le nom de votre fichier , on est en C les majuscules et minuscules compte ! je vous dis ça parce que c’est la cause habituelle de mes erreurs lorsque j’importe des fichiers .

SKSpriteNode *chatkapuce =[SKSpriteNode spriteNodeWithImageNamed:@ »IMG_8906.jpg »];

On écrit cette ligne pour commencer , pensez a remplacer « IMG_8906.jpg » par le nom de votre fichier.

chatkapuce.name=@ »chatkapuce »;

Donnez toujours un nom a votre sprite de cette façon , ce n’est pas utile pour le moment lais ça le sera pour la suite c’est une bonne habitude a prendre.

chatkapuce.position=CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame));

On la positionne au centre de l’écran comme on l’a vu dans l’exemple précèdent .

chatkapuce.xScale=0.28;

chatkapuce.yScale=0.28;

L’image est trop grande on va donc la réduire en X et en Y

 [self addChild:chatkapuce];

et on l’affiche ! voici ce que ça doit donner :

 

Capture d’écran 2015-11-15 à 12.44.41

 

Il faut noter que ces fonds d’écran utilisé depuis des photos prennent beaucoup de place , vous aurez donc tout intérêt a les recadrer et a les compresser le plus possible , c’est un peu le problème que j’ai eu dans KANATABS , c’est pour ça que l’application est si lourde ça fait partie des défauts a corriger .

 


 

L’application 

 

Nous allons essayé de faire un petit casse brique comme vous vous en doutiez peut être vu le nom de mon projet , Arkanoid étant un casse brique que les gens qui on eu un Amstrad cpc connaissent surement .

Nous allons donc fabriquer une petite raquette :

raquette

Il faut que se soit un fichier PNG car Xcode sait les découper ce qui evite bien de déboires avec les dessins .

« Vous pouvez récupérer le PNG ici  »

Je vous conseil de ne pas effacer le code que vous aviez inséré précédemment même si vous n’en avez plus de besoin pour le moment , je passe beaucoup de code en commentaire pour pouvoir le récupérer et faire des « copier coller » avec , je trouve que c’est bien plus pratique que de tout retaper , de même que si vous avez d’anciens projets , n’hésitez pas a les conserver et a les ouvrir en mode text pour voir comment vous aviez faire une chose ou une autre ,c’est toujours pratique . personnellement je fais beaucoup d’essais qui n’aboutissent pas forcement sur des choses a priori utile mais qui parfois quelques mois plus tard permettent d’être inséré dans un programme parce qu’on en a besoin , sans être obligé de rechercher un peu partout comment on fait .

Pour passer une ligne en commentaire si vous le ne saviez pas déjà ça se fait avec « // » , la ligne passe automatiquement en vert , elle n’est plus prise en compte dans le code a compiler .

exemple:

//commentaire 

Pour passer un paragraphe en commentaire , vu qu’il y a parfois des dizaine de ligne a désactiver ( et que c’est très pénible de le faire ligne par ligne ) on met « /*  » a l’entrée du paragraphe et « */ » a la fin du paragraphe .

exemple:

/* mon paragraphe

que je souhaite 

desactiver*/

Je vais donc désactiver le sprite chatkapuce et le coller en bas de mon programme pour la lisibilité .

Ca donne ca :

Capture d’écran 2015-11-15 à 16.56.32

Maintenant on ajoute le PNG  » raquette.png au template avec un click droit « add file to  » , puis on va créer une fonction « jeu » et une redirection , non pas que se soit spécialement utile pour le moment mais parce qu’il vaut mieux séparer les choses l’affichage des objet du jeu n’ayant rien a faire avec le choix de la couleur de fond , de plus si on veut par la suite rajouter un menu entre l’initialisation et le jeu ça sera du coup beaucoup plus simple .

 

voila a quoi ça ressemble 🙂

 

Capture d’écran 2015-11-15 à 17.04.28

Insérons notre raquette ! 

Capture d’écran 2015-11-15 à 17.12.22

j’ai simplement récupéré la déclaration de chakapuce j’ai modifié le nom ( je vous disais qu’il ne fallait pas jeter ! )

 

Voici ce que ça donne :

 

Capture d’écran 2015-11-15 à 17.16.54

 

il faut avouer qu’elle est bien notre raquette ! mais bon au milieu de l’écran …. c’est pas tout a fait ce qu’il nous faut , on va aller modifier sa position en conservant le  » center frame » pour l’axe des X .et nous y mettront 40 a la place .

 

Capture d’écran 2015-11-15 à 17.21.09

 

ce qui donne le résultat suivant :

 

Capture d’écran 2015-11-15 à 17.22.27

Bon voila , c’est bien joli d’avoir une raquette mais si elle se déplaçait maintenant ?

Il va falloir pour cela créer deux variables , une pour stocker la position actuelle de notre raquette et l’autre pour copier la nouvelle position , qui correspondra a l’emplacement ou l’utilisateur a toucher l’écran.On déclare donc nos deux variables comme ci-dessous .

Capture d’écran 2015-11-15 à 19.40.13

On va créer une fonction pour mettre a jour la position de la raquette :

-(void)maj_position{}

Et on va rajouter une condition pour récupérer la position ou l’utilisateur appui sur l’écran tactile dans la fonction du bas

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    /* Called when a touch begins */

 

    for (UITouch *touch in touches) {

        CGPoint location = [touch locationInNode:self];

        if (raquette_posx1!=location.x){raquette_posx=location.x; [self performSelector:@selector(maj_position)];}

 

    }}

On on va rajouter la ligne en orange ci-dessus .Ce qu’il faut comprendre ici c’est que si la position actuelle de la raquette est différente (!=) de la position ou l’utilisateur touche l’écran sur l’axe des X alors on stock la nouvelle position dans une variable et on lance la fonction de mise a jour de la position , ce n’est pas plus compliqué que ça 🙂

 

La mise jour de la position :

-(void)maj_position{

 

    [self enumerateChildNodesWithName:@ »raquette » usingBlock:^(SKNode *toto, BOOL *stop) {[toto removeFromParent ];}];

    SKSpriteNode *raquette =[SKSpriteNode spriteNodeWithImageNamed:@ »raquette »];

    raquette.name=@ »raquette »;

    raquette.position=CGPointMake(raquette_posx1,40);

    [self addChild:raquette];

    SKAction *mov_raquette =[SKAction moveToX:raquette_posx duration:1];

    [raquette runAction:mov_raquette];

 

    raquette_posx1=raquette_posx;

}

Alors ici il y a une petite subtilité , il n’est pas possible de faire quoi que se soit avec un Sprite affiché depuis une autre fonction , donc si vous affichez un Sprite et que vous switchez sur la fonction qui vous permet de récupère la position et revenez sur la même fonction il n’est plus reconnu ce qui nous pose un gros problème pour l’appeler avec une action et le faire déplacer …

Il y a bien évidement une solution ça ce problème , il faut l’effacer et le recréé avant de pouvoir le faire bouger , je sais que c’est étrange comme fonctionnement mais je n’ai pas trouvé d’autre solutions . Ceux-ci dit ça fonctionne très bien quand même 🙂 .

Donc voici comment l’effacer :

 [self enumerateChildNodesWithName:@ »raquette » usingBlock:^(SKNode *toto, BOOL *stop) {[toto removeFromParent ];}];

On lui demande donc de chercher un sprite nommé « raquette » et de l’effacer ( removeFromParent ) il y a une variable de transition que j’ai appelé « toto » mais elle n’a pas d’importance.

vous comprenez donc ici l’importance de donner un nom a vos sprites si vous ne le faites pas vous ne pourez plus vous en séparer a moins d’effacer tout l’écran .

donc pensez bien a « sprite.name =@ »nom »; »

on recrée ensuite la raquette que l’on repositionne ou elle était ( d’ou l’intérêt de stocker cette position dans une variable ) .

    SKSpriteNode *raquette =[SKSpriteNode spriteNodeWithImageNamed:@ »raquette »];

    raquette.name=@ »raquette »;

    raquette.position=CGPointMake(raquette_posx1,40);

    [self addChild:raquette];

on créé une action pour bouger la raquette .

SKAction *mov_raquette =[SKAction moveToX:raquette_posx duration:1];

Deplaces toi jusqu’a la nouvelle position touché par l’utilisateur en 1 seconde .

[raquette runAction:mov_raquette];

On lance l’action .

raquette_posx1=raquette_posx;

et on stock la nouvelle position .

 

Voila a quoi votre programme ressemble maintenant

 

Capture d’écran 2015-11-15 à 20.11.11

 

Voici une petite video du résultat

 

 

Nous allons maintenant habiller notre niveau a l’aide de petit cube doré comme celui ci-dessous:

Cube_gold

 

 

Nous allons pour cela créer une matrice pour piloter la position des cubes sur la page . Ne fuyez pas en voyant ce mot il s’agit en réalité d’un outil très facile a utiliser  qui va nous permettre de créer de façon très intuitive les différents niveaux de notre jeu .

Voici a quoi ça ressemble :

Capture d’écran 2015-11-22 à 12.14.12

c’est une simple déclaration d’entier ( int ) mais nous lui avons donné deux dimensions une de 10 correspondant aux X ( le positionnement sur la largeur de l’écran en mode portrait , et 50 le positionnement en Y qui sera donc la hauteur .On peut remarquer ici que cette matrice se compose de deux nombres le 0 qui correspondront aux emplacements vide et le 1 qui seront nos fameux cubes dorés .

Vous me direz c’est bien joli d’avoir définit un niveau sous cette forme mais se serait mieux si il était affiché . c’est ce que nous allons faire :

Capture d’écran 2015-11-22 à 12.21.15

Voici , ci dessus la fonction qui nous permettra d’afficher nos cubes dorés a l’écran , il s’agit d’une double boucle en  » FOR » qui permet de scanner notre variable matricielle dans ses deux dimensions , pour faire simple lorsqu’il a fini de scanner une ligne , il fait la suivante . Chaque fois qu’il rencontrera un 1 il déposera un cube doré , si vous créer ce type de fonction vous devrez ajuster deux choses , la taille de votre cube d’ou l’utilité de « xScale » et l’espacement entre les cubes qui eux se déclarent dans le « cube.position » par un « x*espace » et « y*espace  » vous remarquerez que l’on part du milieu de l’écran pour positionner nos cube ce qui évite bien des soucis de positions en cas d’utilisation d’un autre écran.

 

voyons le résultat :

 

Capture d’écran 2015-11-22 à 12.29.45

Maintenant , jetez de nouveau un coup d’oeil a la matrice , et vous verrez se dessiner ce que vous avez a l’écran , vous comprenez maintenant l’utilité de ce type de variable et de sa fonction d’affichage , ça permet d’afficher beaucoup de choses en peu de ligne 🙂

Maintenant que nous savons afficher des choses , nous allons essayé de rendre les choses moins monotones en rajoutant des briques de couleurs différentes et puis on va corriger notre matrice pour que ce niveau ressemble un peu plus a un casse brique

Voici notre nouvelle matrice

Capture d’écran 2015-11-22 à 17.00.36

vous remarquerez qu’il y a dedans des « 2 » des « 3 » des « 4 » , il sait de nos nouvelles briques il va maintenant falloir lui expliquer ce qu’il doit faire lorsqu’il rencontre l’un des ces nouveaux chiffres . Ca va se passer dans la boucle d’affichage , il va nous falloir créer des briques d’autres couleurs et les importer .

 

 

 

 

Cube_vert Cube_rouge Cube_bleu

Dans mon cas , ça sera une brique verte , une brique rouge , et une brique bleu, je m’occupe maintenant de la boucle d’affichage :

 

Capture d’écran 2015-11-22 à 17.08.09

voici maintenant a quoi elle ressemble , je sais ça a l’air compliqué mais maintenant il imaginez votre programme si vous aviez dut afficher les brique une a une , il serait simplement monstrueux !!

Ici 4 conditions , n’affiches rien si le nombre que tu obtiens est égale a 0 , affiches un cube doré si tu obtiens 1 , affiches un cube bleu si tu obtiens 2 , affiches un cube rouge si tu obtiens 3 , affiches un cube vert si tu obtiens 4 vous voyez ce n’a rien de vraiment compliqué et voila ce que ça va nous donner :

 

Capture d’écran 2015-11-22 à 17.14.57

Si vous voulez rajouter d’autres choses , ou des bulles a la place des cubes , grâce a ce système d’affichage les possibilités sont presque infinies !

Je trouve que les briques sont un peu hautes et la raquette un peu petite je vais faire corriger , en modifiant la matrice , sans avoir besoin de me demander de combien il faut déplacer chaque coordonnées voici la nouvelle matrice :

 

Capture d’écran 2015-11-22 à 19.18.12

 

et le résultat

 

Capture d’écran 2015-11-22 à 19.19.45

 

J’en ai profité pour relever un peu la raquette  , pour le moment je ne touche pas a sa taille mais elle semble petite il faudra surement l’agrandir un peu …

Le contour

Il serait bien d’avoir un encadrement autour de notre petit jeu , pour deux raisons d’abord parce que c’est plus joli , et aussi parce que lorsque nous rajouterons une balle dans ce petit jeu et bien si elle n’a rien pour rebondir elle va s’en aller loin , très loin et nous risquons fortement de ne pas la revoir ! 🙁

Pour créer ce contour rien de plus simple , nous allons utiliser un « PNG » que nous allons étirer dans le sens qui nous convient

 

barre

pour la barre de gauche :

Capture d’écran 2015-11-22 à 19.46.39

pour celle de droite :

Capture d’écran 2015-11-22 à 19.46.49

pour celle du haut :

 

Capture d’écran 2015-11-22 à 19.46.56

Ces sprites sont a insérer dans la première fonction avant la construction du niveau comme ci-dessous :

Capture d’écran 2015-11-22 à 19.50.30

 

voici le résultat :

 

Capture d’écran 2015-11-22 à 19.52.18

 

La suite bientôt ! 🙂