Vous êtes sur la page 1sur 290

Devenez un des

petit gnie
Dveloppez facilement des jeux vidos multiplates-formes
http://www.free-livres.com/

jeux vido

7 97
Ian Cinnamon

e D ! ans

L E P R O G R A M M E U R

Devenez un petit gnie des jeux vido


Ian Cinnamon

Pearson Education France a apport le plus grand soin la ralisation de ce livre an de vous fournir une information complte et able. Cependant, Pearson Education France nassume de responsabilits, ni pour son utilisation, ni pour les contrefaons de brevets ou atteintes aux droits de tierces personnes qui pourraient rsulter de cette utilisation. Les exemples ou les programmes prsents dans cet ouvrage sont fournis pour illustrer les descriptions thoriques. Ils ne sont en aucun cas destins une utilisation commerciale ou professionnelle. Pearson Education France ne pourra en aucun cas tre tenu pour responsable des prjudices ou dommages de quelque nature que ce soit pouvant rsulter de lutilisation de ces exemples ou programmes. Tous les noms de produits ou marques cits dans ce livre sont des marques dposes par leurs propritaires respectifs.

Publi par Pearson Education France 47 bis, rue des Vinaigriers 75010 PARIS Tl. : 01 72 74 90 00 Mise en pages : TyPAO ISBN : 978-2-7440-4090-0 Copyright 2009 Pearson Education France Tous droits rservs

Titre original : Programming Video Games for the Evil Genius Traduit et adapt de lamricain par Isabelle Hurbain-Palatin ISBN : 978-0-07-149752-7 Copyright 2008 by The McGraw-Hill Companies, Inc. All rights reserved

Aucune reprsentation ou reproduction, mme partielle, autre que celles prvues larticle L. 122-5 2 et 3 a) du code de la proprit intellectuelle ne peut tre faite sans lautorisation expresse de Pearson Education France ou, le cas chant, sans le respect des modalits prvues larticle L. 122-10 dudit code. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from Pearson Education, Inc.

Sommaire

Prface .......................................................... VII propos de lauteur .................................... VIII Introduction .................................................. Le compilateur ............................................. 1. Java dans les starting-blocks .................. 2. Jeux de course .......................................... 1 5 9 39

3. Jeux de plateau ........................................

91

4. Jeux de tir ................................................. 125 5. Jeux de stratgie ...................................... 143 6. Anciens jeux... revisits ........................... 187 7. Jeux de rexion ...................................... 229 Index ............................................................. 275

Table des matires

Prface ............................................................

VII

CHAPITRE 3. Jeux de plateau ......................... La chasse aux mauvais gnies Projet 13 : Le laboratoire ............................ Projet 14 : Attrapez-les vite ! ..................... Projet 15 : Plus intelligent... ...................... Le morpion boxeur Projet 16 : Le ring ...................................... Projet 17 : Combat ! ................................... Projet 18 : K.-O. ! ......................................

91 92 97 101 105 110 116

propos de lauteur ...................................... VIII Introduction .................................................... Remerciements ........................................... Le compilateur ............................................... CHAPITRE 1. Java dans les starting-blocks ... Projet 1 : Le perroquet ................................ Projet 2 : Devinez le mot de passe ! ........... Projet 3 : Calcul mental .............................. Projet 4 : Une bibliothque virtuelle de jeux Projet 5 : Devinez le nombre ! ................... Java dans les starting-blocks : le rsum .... CHAPITRE 2. Jeux de course ........................... La course du courage Projet 6 : La piste ....................................... Projet 7 : Les voitures ................................ Projet 8 : Collisions ! ................................. Projet 9 : Personnalisation ......................... Le skieur Projet 10 : La piste ...................................... Projet 11 : Piste verte ................................. Projet 12 : La comptition ......................... 72 77 83 40 47 53 61 1 4 5 9 10 14 23 30 35 37 39

CHAPITRE 4. Jeux de tir .................................. 125 Destructeurs de lespace Projet 19 : Le paysage .............................. 126 Projet 20 : Lasers ....................................... 129 Projet 21 : La vengeance ............................ 135 CHAPITRE 5. Jeux de stratgie ....................... 143 Dmineurs Projet 22 : Le petit nouveau de lquipe ..... Projet 23 : Dmineur expert ....................... Projet 24 : BOUM ! ................................... Projet 25 : Promotions ............................... Piges Projet 26 : Dplacements .......................... Projet 27 : Mise en place des piges .......... 144 148 153 159 166 170

VI

Devenez un petit gnie des jeux vido

Projet 28 : Pig ! ....................................... 175 Projet 29 : Le spectacle .............................. 180 CHAPITRE 6. Anciens jeux... revisits ............ 187 Oiram Projet 30 : La plate-forme ......................... Projet 31 : Allez Oiram ! ............................ Projet 32 : Les mchants ............................ Projet 33 : Un monde compliqu ............... Javaman Projet 34 : Lunivers de Javaman ............... Projet 35 : Javaman vit ! ............................ Projet 36 : Lattaque du C++ ...................... 188 192 198 205 214 217 222

CHAPITRE 7. Jeux de rexion ....................... 229 Jeu de mmoire Projet 37 : Dessin de la grille .................... 230 Projet 38 : Correspondances ...................... 235 Projet 39 : Battez le chronomtre .............. 240 Ian a dit Projet 40 : Jeu de couleurs ......................... 248 Projet 41 : Surchauffe de cerveau .............. 252 Projet 42 : Plus de niveaux ! ...................... 259 Projet 43 : Accessoires de jeu .................... 265 Index ............................................................... 275

Prface

Il y a plusieurs annes, Ian Cinnamon a assist aux iD Tech Camps de UCLA (University of California, Los Angeles). Ian y a appris programmer en C++ et en Java. Anne aprs anne, Ian a continu assister aux camps et sa matrise de la programmation sest visiblement amliore. Mais il est apparu quil dpassait ses pairs et quil avait besoin de nouveaux ds. Ses instructeurs disaient de lui quil absorbait et assimilait rapidement les notions de programmation, comme sil rentrait chez lui, lisait et rsolvait des problmes sur son temps libre. Il se trouve que cest exactement ce quil faisait. Jai eu loccasion de rencontrer Ian il y a deux ans lUniversit de Stanford. Cest un jeune homme formidable avec de bonnes manires, dexcellentes capacits sociales et, bien sr, un grand talent de programmeur. Il est un des meilleurs programmeurs que jai vus aux iD Tech Camps, ce qui est impressionnant au vu des milliers de programmeurs qui ont reu leur diplme des iD Tech Camps pendant toutes ces annes. Ian, qui a aujourdhui tout juste quinze ans, est devenu un modle pour sa gnration. Son livre, Devenez un petit gnie des jeux vido , offre une approche tape par tape la programmation de jeux vido, ce qui est un rve pour de nombreux jeunes. Jentends souvent des phrases comme "Jaimerais savoir programmer mon propre jeu" et "Je ne sais pas par o commencer". Ma suggestion est de participer aux id Tech Camps et de se procurer un exemplaire du livre de Ian. Savoir o aller et y plonger sont des tapes cruciales. Ian lve sa gnration et dmystie le code des jeux vido. Je suis trs impatient de voir o Ian en sera dans cinq ou dix ans. Prparez-vous.
Pete Ingram-Cauchi Prsident et CEO, iD Tech Camps, internalDrive, Inc.

propos de lauteur
Ian Cinnamon est un phnomne de 15 ans qui programme depuis plus de sept ans et qui est certi en Java et en C++. Il est actuellement lycen la Harvard-Westlake School de Los Angeles, Californie.

Introduction

Matriser lunivers des jeux


Quoi de mieux que jouer aux jeux vido ? Crer vos propres jeux vido ! Des jeux que vous concevez, des jeux que vous contrlez... des jeux selon vos rgles. Lorsque vous achetez un jeu en magasin, ce jeu est souvent le rsultat de mois, voire dannes defforts dune petite quipe de professionnels crant des programmes extrmement complexes aids des ordinateurs les plus rcents et les plus puissants. Mais il leur manque quelque chose pour crer le jeu parfait : vous-mme, le crateur de jeux. Vous tes le matre de votre univers de jeu. Vous pouvez crer le monde que vous voulez. Vous pouvez choisir les couleurs de fond, les niveaux de difcult, la forme du plateau de jeu et les codes de triche. Vous pouvez inventer des personnages, concevoir des ds, choisir comment les points sont distribus et comment un joueur gagne... ou perd. Vous pouvez programmer tout ce quoi vous pensez.

Votre borne darcade personnelle


Vous est-il dj arriv de vous ennuyer force de jouer au mme jeu, encore et encore ? Ce ne sera bientt plus le cas. Vous pouvez crer un assortiment de jeux avec des variantes illimites. Vous trouverez dans ces pages le secret de la construction de jeux de course, de jeux de plateau, de jeux de tir, de jeux de stratgie, danciens jeux revisits et de jeux de rexion.

Devenez un petit gnie des jeux vido

Jeux de course. Attention ladrnaline ! Construisez des jeux dans lesquels vous ferez une course contre la montre, contre un adversaire ou mme contre vousmme. La vitesse et la prcision seront vos atouts cls lorsque vous vous dplacerez, que votre moyen de transport soit une voiture, une fuse, un balai, une paire de skis ou tout autre moyen de transport qui puisse tre imagin par un petit gnie de la programmation. Jeux de plateau. Des terrains mentaux mins pour vous rendre fou ! Des jeux et des labyrinthes qui vous demanderont des prouesses de rexion, dastuce et de manuvres pour battre vos adversaires ! Frustrez vos ennemis et mettez-les genoux. Le concept : un jeu du morpion dop aux strodes ! Jeux de tir. Des jeux mettant rude preuve vos rexes et vos nerfs ! Transformez-vous en soldat, en charmeur de serpent, en guerrier alien ou en homme de Neandertal jetant des pierres tandis que vous visez dans le monde que vous crez. Jeux de stratgie. Pigez vos adversaires dans une bote dont il sera impossible de sortir ou dsamorcez une bombe avant quelle puisse dtruire la Terre ! Dans tous les cas, relevez le d. Une tte froide et une rexion rapide seront ncessaires. Jeux anciens revisits. Revoyez les classiques votre sauce ! Crez des variations de Mario et de Pac-Man en programmant de nouvelles fonctionnalits et astuces qui renouvelleront ces jeux. Jeux de rexion. Avez-vous une bonne mmoire ? Grez-vous bien la pression ? Nous lesprons, car dans ces jeux, vous vivrez ou mourrez en fonction de ce que vous vous rappelerez. Rglez la difcult en fonction de votre courage.

La programmation : le langage des jeux


En musique, il existe des notes ; en mathmatiques, des quations ; dans une langue, des mots. Dans le monde des jeux vido, il existe des commandes qui donnent vie vos jeux. Cela sappelle la programmation. Cest ainsi que vous indiquez lordinateur ce quil doit faire. Tous les jeux que vous allez crer seront programms en Java, le langage de programmation le plus universel. Et quen est-il si vous ne savez absolument pas programmer ? Si vous navez aucune ide de la manire dont lordinateur transforme vos ides en actions et en images ? Pas dinquitude ! Je vous guiderai tape par tape travers les bases de ce langage trs polyvalent. Lorsque vous en aurez termin avec Devenez un petit gnie des jeux vido , vous aurez non seulement une bibliothque de jeux personnaliss fantastique, mais vous serez aussi un habile crateur de jeux.

Introduction

Les briques de la cration de jeux


La programmation se compose de plusieurs briques. Vous apprendrez facilement vous en servir, nous les dtaillerons tape par tape. Les captures dcrans sont vos guides lorsque vous apprenez matriser ces outils importants car elles sont infaillibles. Et, comme rouler bicyclette, lorsque vous savez vous en servir, cela ne soublie pas. Si vous tes dbutant en programmation, la section 1 vous permettra de partir trs rapidement sur de bonnes bases. Si vous avez dj un peu dexprience, vous pouvez passer directement la section 2. Les briques utilises dans la cration de jeux incluent :

Les instructions. Centre nvralgique et squelette de tous les jeux. Les commentaires. Ils permettent dannoter votre code pour savoir ce que fait chaque ligne. Les contrles de ux. Ils vous permettent de rpter du code. Ils sont trs pratiques pour relancer un jeu. Les variables. Elles permettent de garder une trace des scores, des noms des joueurs, des niveaux, etc. Les instructions if. Elles permettent de tester vos variables grce des conditions. Par exemple, si vous tuez un ennemi, votre score augmente.

JOptionPane. Ils permettent de grer les entres et les sorties, par exemple pour afcher le score dun joueur ou pour rcuprer son nom pour la liste des scores les plus levs.
Les nombres alatoires. Ils sont la base de lintelligence articielle. Pour dplacer un ennemi de manire alatoire, les nombres alatoires sont ce quil vous faut. Les pauses. Elles permettent dinuencer le rafrachissement de lcran pour que vos graphismes restent clairs et nets. Les tableaux et les ArrayList. Ils servent grouper des objets similaires (ennemis, recharges, etc.) et ainsi gagner du temps. Les accs aux chiers (lecture et criture). Ils permettent de sauvegarder le jeu, ce qui est pratique lorsque votre chef arrive de manire impromptue et que vous tes en train de jouer au lieu de travailler.

Devenez un petit gnie des jeux vido

Remerciements
Vous ne seriez pas en train de lire ce livre sans le dvouement et le soutien des personnes suivantes :

Mes parents : leur amour inbranlable, leurs encouragements, leur aide et mme leurs plaisanteries ont t vitaux lcriture de ce livre. Ils ont toujours t l pour moi et je sais quils le seront toujours. Maman, papa, je vous aime. Ma petite sur, Molly : elle est mon agent publicitaire ofcieux et dit tous ceux quelle rencontre dacheter ce livre. Judy Bass, mon ditrice McGraw-Hill : son enthousiasme pour le projet et sa foi en moi ds le dpart compteront toujours pour moi. Pete Ingram-Cauchi, le CEO de iD Tech Camps : ses cours UCLA et Stanford ont nourri ma passion pour tout ce qui touche la programmation.

Le compilateur

Faire obir votre ordinateur


Vous navez besoin que de trois choses pour commencer crer vos propres jeux : un ordinateur (PC, Mac), ce livre... et un compilateur. Ce logiciel traduit votre code en un langage que votre ordinateur pourra comprendre. Si vous navez pas encore de compilateur, il peut tre tlcharg gratuitement sur Internet. Sous Windows et sous Linux, allez ladresse http://java.sun.com et cliquez sur Java SE sous Popular Downloads. Cliquez sur le bouton Download situ ct du titre JDK 6 Update 6 with NetBeans 6.1 . Dans la page qui safche, cliquez sur le bouton Download. Choisissez votre plateforme et acceptez laccord de licence avant de cliquer sur Continue. Cliquez sur le lien pour tlcharger linstalleur. Mac OS X dispose dj dun compilateur Java et il suft donc dinstaller NetBeans. Allez ladresse http://download.netbeans.org/netbeans/6.1/nal/, choisissez votre plate-forme dans le menu en haut droite et cliquez sur le bouton Download de la premire colonne (Web & Java EE). JDK signie Java Development Kit (kit de dveloppement Java). Ce logiciel permettra lordinateur de comprendre le code. NetBeans est un environnement de dveloppement intgr qui facilite lcriture du code. Installez NetBeans en cliquant sur licne dinstallation (sous Linux, NetBeans peut galement faire partie de votre base de paquetages par dfaut, auquel cas il nest pas ncessaire de le tlcharger et il sinstallera comme tout autre logiciel).

Devenez un petit gnie des jeux vido

Examinons maintenant linterface. Cliquez sur File > New Project.


Figure 0.1 Le menu File de NetBeans

Cliquez sur Java Application.


Figure 0.2 La fentre de cration de projets

Le compilateur

Cliquez sur Next et saisissez le nom du projet dans Project Name. Ce nom devrait commencer par une majuscule et ne pas contenir despace.

Figure 0.3 Nommer le projet

Cliquez sur Finish. Pour crer un environnement dans lequel vous pourrez crire votre code, commencez par supprimer Main.java, puis cliquez sur le rpertoire parent et cliquez sur New > Java Class...

Devenez un petit gnie des jeux vido

Figure 0.4 Suppression du chier Main.java

Figure 0.5 Cration dune nouvelle classe Java

Et voil... Vous navez plus qu conqurir le monde des jeux vido !

1
Java dans les starting-blocks
Au sommaire de ce chapitre :

Projet 1 : Le perroquet Projet 2 : Devinez le mot de passe ! Projet 3 : Calcul mental Projet 4 : Une bibliothque virtuelle de jeux Projet 5 : Devinez le nombre !

10

Devenez un petit gnie des jeux vido

Projet 1 : Le perroquet
Projet Nouvelles briques Tapez un message, appuyez sur deux boutons, et lordinateur le rptera. Classes, instructions et variables

Lorsque lon apprend programmer en Java, il faut connatre quatre types de code essentiels : les commentaires, les instructions, les dclarations et le contrle de ux.

Les commentaires
Les commentaires commencent toujours par //. Les compilateurs ne prennent pas en compte ces commentaires. Ils ne sont utiles quaux programmeurs qui peuvent ainsi documenter le code. Une bonne documentation (de bons commentaires) permet de modier le code plus facilement ultrieurement. Lorsquun programme atteint quelques centaines de lignes, il est difcile de se souvenir quoi sert chaque ligne. Les commentaires sont trs utiles dans ce cas.

Les instructions
Les instructions permettent de "faire des choses", par exemple afcher quelque chose lcran. Elles se terminent toujours par un point-virgule.

Les dclarations
Les dclarations sont des instructions qui crent ou modient des variables. Les variables sutilisent comme en mathmatiques (x = 4), ceci prs quelles peuvent contenir dautres lments que des nombres. Nous en parlerons plus longuement dans le prochain projet.

Le contrle de ux
Le contrle de ux sert manipuler les instructions utilises. Nous en parlerons plus tard (Projet 3). Tous les programmes Java sont contenus dans ce que lon appelle une classe ( class). On cre une classe avec le code suivant :
public class <nom de la classe>

Chapitre 1

Java dans les starting-blocks

11

Le nom de la classe doit correspondre au nom du chier, il doit toujours commencer par une lettre majuscule et ne doit pas contenir despace. Par exemple, la classe Pingouin sera contenue dans le chier Pingouin.java. Pour dlimiter le code appartenant une classe, on utilise les caractres { et } au dbut et la n du code, respectivement. Au sein dune classe, Java cherche la mthode principale, appele main. Une mthode est un morceau de code qui peut tre appel plusieurs fois. La mthode main est une mthode spciale : Java lappelle toujours en premier (cest--dire excute le code qui sy trouve). Voici ce quoi elle ressemble :
public static void main (String[] args)

Vous pouvez pour linstant considrer que cette ligne de code doit introduire la mthode main. Nous discuterons des diffrents lments de cette ligne plus tard. En dehors des mthodes, il ne peut y avoir dans une classe que des dclarations et des commentaires. Les dclarations sont appeles les variables de la classe. Dans la mthode dune classe, on peut trouver des dclarations, des commentaires, du contrle de ux et des instructions. On peut accder aux variables dune classe partir de toutes les mthodes, mais les variables lintrieur dune mthode ne sont accessibles que depuis cette mthode. Voici une instruction simple, galement illustre la Figure 1.1, permettant dafcher un message lcran :
System.out.println("Ce message entre guillemets est affich.");

Figure 1.1 Ce code afche du texte lcran

Ce code est une mthode fournie par Java. Il suft de lui indiquer le texte afcher, entre guillemets. lintrieur des guillemets, il existe des squences dchappement qui sont des suites de caractres permettant de manipuler le texte. Ajoutez-les simplement dans le texte entre guillemets.

12

Devenez un petit gnie des jeux vido

Tableau 1.1 : Squences dchappement

Squence dchappement
\n \t \"

Rsultat
Cre un retour la ligne Indente la ligne (ajoute une tabulation) Permet dajouter un guillemet lintrieur des guillemets

Crer le jeu
Pour que le programme rpte le texte que vous avez saisi, vous devez donc crer une classe, crire la mthode main et ajouter le code System.out.println(). Tout ce que vous placerez entre guillemets sera rpt par lordinateur. Essayez de faire cela tout seul. Si cela fonctionne, vous avez gagn et vous pouvez passer au projet suivant ! Si vous avez besoin daide, le code complet est indiqu ci-aprs :
// cre une classe nomme S1P1 public class S1P1 { // ceci est la mthode main public static void main (String[] args) { // ceci affiche ce qui est crit entre guillemets System.out.println("Ce que vous tapez ici... sera rpt!"); } }

Cliquez sur Build > Build Main Project > OK. Ceci compile votre jeu, comme le montre la Figure 1.2. Cliquez sur Run > Run Main Project. Ceci lance le projet, comme le montre la Figure 1.3. La Figure 1.4 illustre lafchage de votre premier jeu !
Figure 1.2 Compiler le projet

Chapitre 1

Java dans les starting-blocks

13

Figure 1.3 Lancer le projet

Figure 1.4 Afchage du projet

Dans le projet suivant, vous apprendrez comment enregistrer des informations importantes (telles que le score actuel) et comment obtenir une saisie de lutilisateur.

14

Devenez un petit gnie des jeux vido

Projet 2 : Devinez le mot de passe !


Projet Programmez lordinateur pour vrier que le mot de passe a bien t tap. Dans cet exercice deux joueurs, un joueur donne des indices pendant que lautre tape des essais de mots de passe. Lordinateur prvient le joueur lorsquil a gagn. Le mot de passe peut tre chang par le biais de fentres pop-up et il est sauv dans un chier. Variables (cration et utilisation), blocs if, transtypage, saisie utilisateur, accs des chiers

Nouvelles briques

lheure actuelle, vous savez crer un programme simple qui afche un message lcran. Vous allez maintenant apprendre crer des variables, les manipuler et les tester.

Cration de variables
Ces lignes se terminent toujours par des points-virgules ! Voici les types de variables de base que vous utiliserez le plus souvent :

Integer (entier) int. Un entier positif ou ngatif. Double (nombre virgule ottante) double. Un nombre dcimal positif ou ngatif. Character (caractre) char. Une lettre. String (chane) String. Un ensemble de caractres. Boolean (boolen) boolean. Une valeur vraie (true) ou fausse (false).

Comment crer (dclarer et initialiser) une variable ? Les variables de type int, double ou char se dclarent comme ceci :
int <nom> = <valeur>;

int peut tre remplace par double ou par char. <nom> est remplacer par nimporte quel nom commenant par une lettre minuscule (pas de nombre ni de symbole).
Pour les variables de type int, <valeur> peut contenir nimporte quel nombre (par exemple 10, 9 999 ou 298). Pour les variables de type char, <valeur> est une lettre entre apostrophes (par exemple, char lettre = k;). Pour les variables de type String, <valeur> est une chane de caractres entre guillemets (par exemple, String texte = "Je suis une chane de caractres.";).

Chapitre 1

Java dans les starting-blocks

15

Vous pouvez aussi crer une variable sans indiquer sa valeur (cela sappelle une dclaration). Il suft pour cela de terminer la ligne prmaturment avant linitialisation de la variable grce un point-virgule :
int number;

Si la variable est dj dclare et si vous voulez modier (ou initialiser) sa valeur, utilisez le code suivant (cela sappelle une initialisation) :
nombre = 1;

On peut aussi modier la valeur dun entier int ou dun ottant double en utilisant les syntaxes qui suivent. Pour ajouter 1 nombre :
nombre++;

Pour enlever 1 nombre :


nombre--;

Pour ajouter 5 (ou toute autre valeur/variable) nombre :


nombre +=5;

Pour donner nombre la valeur de la somme de deux variables :


nombre = <variable1> + <variable2>

variable1 et variable2 peuvent tre remplaces par un nombre ou par une autre variable de type int ou double. + peut tre remplac par -, *, / ou %. Loprateur % renvoie le reste de la division du premier nombre par le second.
On peut concatner des variables de type String. La concatnation est la combinaison de deux chanes. Par exemple, la chane txt rsultant de String txt = "Ceci est ajout " + " cela." contiendra "Ceci est ajout cela.".

Tester des variables


Utilisez des instructions if pour tester des variables, comme le montre le code suivant :
if(<variable1>==<variable2>){}

<variable1> et <variable2> peuvent tre remplaces par nimporte quelle variable ou valeur.

16

Devenez un petit gnie des jeux vido

On peut aussi utiliser dautres comparateurs la place de == :


!= teste lingalit. > teste si la premire variable est strictement suprieure la seconde. < teste si la premire variable est strictement infrieure la seconde. >= teste si la premire variable est suprieure ou gale la seconde. <= teste si la premire variable est infrieure ou gale la seconde.

Lorsque les variables sont de type String, il ne faut pas utiliser ==. Il faut utiliser la syntaxe suivante :
if(<String1>.equals(<String2>))

Pour tester si elles sont diffrentes :


if(!<String1>.equals(<String2>))

Linstruction if excute le code contenu entre accolades lorsque la condition est vraie. Comment faire si vous dsirez que du code soit excut lorsque la condition est fausse ? Java permet de faire cela de la manire suivante :
if(<condition1> ) { // code lorsque condition1 est vrifie } else if(<condition2> ) { //code lorsque condition1 nest pas vrifie mais que condition2 lest } else { //code lorsque ni condition1 ni condition2 ne sont vrifies }

Vous pouvez utiliser tout ou partie du code ci-dessus pour autant que linstruction if soit la premire et que le bloc else (si vous en avez un) soit le dernier. On ne peut utiliser un boolen b que de deux manires avec une instruction if: if(b) signie "si b a la valeur true" (vrai) et if(!b) signie "si b a la valeur false" (faux). On peut initialiser une variable de type boolean comme toute autre variable :
boolean b = true; boolean b = false;

Chapitre 1

Java dans les starting-blocks

17

Saisie de lutilisateur
Vous savez maintenant comment comparer des valeurs. Vous devez maintenant accder la saisie de lutilisateur. Ajoutez dabord une ligne (quil vous suft de mmoriser, nous lexpliquerons plus tard) au tout dbut de votre programme, avant la dclaration de la classe :
import javax.swing.*;

Ajoutez ensuite le code suivant lendroit o vous dsirez que lutilisateur saisisse quelque chose :
String saisie = JOptionPane.showInputDialog("Quel est votre nom?");

Ceci cre une fentre de dialogue, demandant "Quel est votre nom ?" et permettant de rpondre dans zone de saisie (voir Figure 2.1).
Figure 2.1 Bote de dialogue de saisie

saisie contient la valeur saisie par lutilisateur. Cette valeur est toujours une valeur de type String, mais peut tre transforme en dautres valeurs.
Cette mthode peut diminuer le nombre de valeurs coder en dur. Coder en dur signie insrer la valeur dune variable directement dans le programme. Lorsque vous obtenez une saisie dun utilisateur, vous pouvez initialiser des variables aprs la compilation du programme.

Transtypage
Le transtypage permet de modier un type de variable (par exemple String) en un autre type de variable (par exemple int). Pour faire cela, utilisez le code suivant (en supposant que vous ayez dj une variable de type String nomme saisie) :
int saisieSousFormeInt = Integer.parseInt(input); double saisieSousFormeDouble = Double.parseDouble(input);

Vous pouvez maintenant manipuler des entres utilisateur !

18

Devenez un petit gnie des jeux vido

Crer des chiers


Tous les types de chiers sont sauvs de la mme manire. La seule diffrence est lextension (.doc, .txt, .avi, .jpg, etc.). Les extensions servent indiquer lordinateur et lutilisateur quel programme doit tre utilis pour ouvrir le chier. Dans notre exemple, le mot de passe sera enregistr dans un chier.mdp. Mais nous aurions aussi bien pu lenregistrer dans un chier.petitGenie ou .nimportequoi. Crez dabord un chier grce au code suivant :
File fichier = new File("motdepasse.mdp");

Cette ligne ne fait pour linstant pas grand-chose. Elle se contente dallouer un espace pour un chier nomm motdepasse.mdp. Nous allons maintenant voir comment sauver ce chier sur votre ordinateur. Vous devez pour cela crire le code suivant :
FileOutputStream fluxSortie = new FileOutputStream(<nom du File>);

<nom du File> est le nom de lobjet File cr prcdemment (dans notre cas, Fichier). fluxSortie est le nom de la variable ; cest un nom arbitraire.
PrintWriter sortie = new PrintWriter(fluxSortie);

fluxSortie est le nom de lobjet FileOutputStream dni prcdemment. sortie est galement un nom de variable.
Jusquici, nous avons allou de lespace pour un chier et prpar lordinateur lenregistrer. La ligne suivante enregistre effectivement le chier :
sortie.println("Ce texte est crit dans le fichier");

"Ce texte est crit dans le fichier" est habituellement une variable de type String.
Une fois le chier cr, il faut indiquer lordinateur que tout est ni. Utilisez pour cela les lignes suivantes :
sortie.flush(); sortie.close(); fluxSortie.close();

Voil, vous savez prsent comment crire et enregistrer un chier.

Chapitre 1

Java dans les starting-blocks

19

Accder des chiers


Crez nouveau un objet File :
File fichier = new File("motdepasse.mdp");

Cette fois, la variable de type String (ici, "motdepasse.mdp") est le nom du chier que vous allez ouvrir. Ensuite, crez un objet de type FileReader. La classe FileReader sert ouvrir le chier et en prparer la lecture.
FileReader fr = new FileReader(fichier);

fichier est lobjet File cr prcdemment auquel nous accdons. fr est le nom de la variable.
Crez alors un objet de type BufferedReader. La classe BufferedReader sert lire le texte dun chier ouvert.
BufferedReader tampon = new BufferReader(fr);

fr est le nom de lobjet FileReader. tampon est le nom de la variable.


Pour lire la premire ligne de votre chier, utilisez la ligne :
String ligne = tampon.readLine();

Lorsque vous avez termin daccder un chier, vous devez indiquer lordinateur que vous avez ni :
tampon.close(); fr.close();

Vous devez aussi ajouter un throw Exception (dont nous parlerons dans le Projet 3) dans la dclaration de la mthode main et une ligne import java.io.*; pour pouvoir accder aux chiers.

Crer le jeu
Lorsque le joueur lance le jeu, deux options soffrent lui : jouer ou rinitialiser le jeu. Sil dcide de rinitialiser le jeu, il doit saisir un nouveau mot de passe (qui sera sauvegard dans un chier).

20

Devenez un petit gnie des jeux vido

Sil dcide de jouer, il pourra essayer de deviner le mot de passe. Pour crire le jeu, nous utiliserons la classe JOptionPane pour proposer les diffrents choix au joueur. Lorsque le joueur dcide de saisir un nouveau mot de passe, il faut utiliser le code dcriture de chier pour sauvegarder le nouveau mot de passe dans un chier. Si le joueur prfre essayer de trouver le mot de passe, accdez au chier et testez lgalit des essais du joueur avec le texte du chier. Afchez un message positif (par exemple "Bravo, vous avez devin : vous tes un petit gnie !") grce System.out.println() si lutilisateur a devin le mot de passe. Sinon, afchez un message dchec (par exemple : "Rat !").
//permettre la saisie utilisateur import javax.swing.*; // permettre laccs aux fichiers import java.io.*; //cre une classe nomme S1P2 public class S1P2 { //mthode main. throws Exception est ncessaire pour les accs aux fichiers public static void main(String[] args) throws Exception { //cette chaine contiendra la saisie utilisateur String saisie; //saisie utilisateur saisie = JOptionPane.showInputDialog("1 pour initialiser le mot de passe,\n"+"2 pour chercher le message"); //fichier modifi et lu File fichier = new File("motdepasse.mdp"); //faut-il saisir ou lire le mot de passe? if(saisie.equals("1")) { //on veut modifier le mot de passe //rcupre le nouveau mot de passe String p = JOptionPane.showInputDialog("Saisissez le nouveau mot de passe"); //ces deux lignes initialisent lcriture dans le fichier FileOutputStream fluxSortie = new FileOutputStream(fichier); PrintWriter sortie = new PrintWriter(fluxSortie); //crit le mot de passe dans le fichier sortie.println(p); //on ferme tout sortie.flush(); sortie.close(); fluxSortie.close(); }

Chapitre 1

Java dans les starting-blocks

21

//si lutilisateur veut trouver le mot de passe else { //il faut dabord le rcuprer FileReader fr = new FileReader(fichier); BufferedReader tampon = new BufferedReader(fr); //le mot de passe du fichier String passe = tampon.readLine(); //rcupre lessai de lutilisateur String passeUtilisateur; passeUtilisateur = JOptionPane.showInputDialog("Saisissez votre essai..."); //tester le mot de passe if(passe.equals(passeUtilisateur)) { //si cest correct JOptionPane.showMessageDialog(null,"CORRECT!!!!"); } else { //si cest faux JOptionPane.showMessageDialog(null,"RAT:("); } } } }

Les Figures 2.2 2.6 illustrent le jeu.


Figure 2.2 Rinitialiser ou deviner le mot de passe

Figure 2.3 Saisir le nouveau mot de passe

Figure 2.4 Deviner le mot de passe enregistr

22

Devenez un petit gnie des jeux vido

Figure 2.5 Bonne rponse

Figure 2.6 Mauvaise rponse

Chapitre 1

Java dans les starting-blocks

23

Projet 3 : Calcul mental


Projet Le programme afche des quations mathmatiques. Lutilisateur doit rsoudre le problme avant que lordinateur nait ni son dcompte depuis 3 et nafche la rponse correcte. Pouvez-vous battre lordinateur ? Nombres alatoires, pauses, boucles.

Nouvelles briques

Nombres alatoires
Les nombres alatoires sont de type double car ils sont compris entre 0 (inclus) et 1 (exclus). Pour crer un nombre alatoire entre 0 et 1, utilisez cette instruction :
Math.random()

Elle renvoie une valeur, de la mme manire que JOptionPane, ceci prs que la valeur renvoye est de type double et non String. Pour crer un nombre alatoire dun chiffre, essayez ce code :
int rand = (int) (Math.round(Math.random()*10));

(int) permet de sassurer que la variable rsultante est bien de type int. Math.round() arrondit lentier le plus proche.

Faire une pause


Vous pouvez imposer lordinateur de faire une pause dune dure donne avec une commande trs simple :
Thread.sleep(100);

100 est le nombre de millisecondes de la pause (cette valeur peut tre remplace par une variable de type int). Vous devez aussi ajouter un lment la n de la dclaration de la mthode main. Aprs (String[] args), ajoutez throws Exception. La ligne complte ressemblera alors ceci :
public static void main (String[] args) throws Exception

24

Devenez un petit gnie des jeux vido

Boucles
Il est temps dapprendre quelques techniques de contrle de ux. Le contrle de ux permet de rpter et dexcuter diffrentes parties du code diffrents moments en fonction dune condition (par exemple, x==4). Il existe trois types de boucles.

Boucles for
Les boucles for permettent dexcuter le code lintrieur des accolades jusqu ce quune condition donne soit satisfaite. En voici le format :
for (<init variable>; <condition>; <iterateur>) { // le code rpt se trouve ici }

<init variable> est une dclaration de variable classique (par exemple int i = 0;). <condition> peut tre i<0, i>0, i>=0 ou i<=0 ou encore une instruction quelconque pouvant se trouver lintrieur des parenthses dune instruction if. <iterateur> peut tre par exemple i++ (cest souvent le cas).

Fonctionnement dune boucle for


Lorsque le JRE (Java Runtime Environment, Environnement dexcution Java) atteint la dclaration de la variable, il cre la variable (qui nexiste quau sein du bloc for). Si la condition est vrie, le code est excut. Puis, le code de litrateur est excut. La condition est nouveau vrie et le processus est rpt. Par exemple, dans le cas suivant, si la variable i nest pas modie dans le bloc de la boucle for, le code entre accolades sera excut dix fois :
for (int i=0; i<10; i++) {}

Boucles while
Les boucles while sont similaires aux boucles for, ceci prs quelles nincluent pas la dclaration de la variable ni litration. Elles nincluent que la condition. Lquivalence de la boucle for prcdente sous la forme dune boucle while serait :
int i = 0; while (i < 10) { i++; }

Chapitre 1

Java dans les starting-blocks

25

Fonctionnement dune boucle while


Lorsque le compilateur rencontre une boucle while, la condition est teste. Si elle est vrie, le compilateur entre dans la boucle et reteste la condition chaque itration. Si la condition nest pas vrie, la boucle est arrte.

Boucles do ... while


Les boucles do ... while sont presque identiques aux boucles while. En voici un exemple :
int i = 0; do { i++; } while (i<10);

Fonctionnement dune boucle do ... while


Les boucles do ... while fonctionnent de la mme manire que les boucles while, mais le code entre accolades est toujours excut une fois avant mme que la condition ne soit teste.

Mots cls
Le mot cl le plus important lorsquon travaille avec des boucles est break qui sort immdiatement de la boucle. En voici un exemple :
for (int i=0; i<10; i++) { if(i==1) { break; } }

Dans ce cas, le compilateur passe une premire fois (pour i=0) dans la boucle, puis une seconde fois (pour i=1) et sort de la boucle (en raison de la condition i==1).

Crer le jeu
Vous pouvez prsent crer un jeu utilisable dans des comptitions mathmatiques dans le monde entier ! Crez une quation mathmatique avec deux nombres en utilisant nimporte laquelle de ces oprations : addition, soustraction, multiplication, division ou modulo.

26

Devenez un petit gnie des jeux vido

Dclarez et initialisez deux variables de type int avec un nombre alatoire entre 0 et 9. Puis, crez une nouvelle variable de type int avec un nombre alatoire entre 0 et 4 :

Si le nombre est 0, lopration sera * (multiplication). Si le nombre est 1, lopration sera / (division). Si le nombre est 2, lopration sera + (addition). Si le nombre est 3, lopration sera (soustraction). Si le nombre est 4, lopration sera % (modulo).

Crez une nouvelle variable contenant la solution du problme mathmatique. Puis, mettez le programme en pause pour laisser lutilisateur le temps de rpondre la question. Afchez la variable qui contient la solution. Si le joueur peut calculer la rponse correcte avant que lordinateur ne lafche, il gagne la partie. Pour rendre les choses un peu plus amusantes, nous pouvons laisser lutilisateur choisir son niveau de difcult en modiant le dcompte de temps (de 1, petit gnie, 10, nul en mathmatiques) : plus le niveau est bas, moins le joueur a de temps pour rpondre. Nous pouvons aussi demander lutilisateur sil dsire continuer grce une boucle do... while. Les plus malins dentre vous se demanderont ce quil se passe si le gnrateur de nombres alatoires propose une division pour le signe et un 0 comme second oprande de lopration. Dans ce cas, le programme lance une exception, ce qui le fait terminer avec une erreur. Pour viter cela, il suft de placer le code de gnration du second oprande dans une boucle do... while ; si le rsultat est 0, il suft de le modier. Voici le code :
//permettre la rcupration de saisies utilisateur import javax.swing.*; //cre une classe nomme S1P3 public class S1P3 { //mthode main. (throw Exception) est ncessaire pour Thread.sleep() public static void main(String[] args) throws Exception { //nombre de demi-secondes accordes lutilisateur int difficulte;

Chapitre 1

Java dans les starting-blocks

27

difficulte = Integer.parseInt(JOptionPane.showInputDialog(" quel point tes-vous dou ?\n" + "1 = je suis un petit gnie !\n"+ "10 = je ne suis pas vraiment dou.")); //indique la boucle sil faut continuer ou pas boolean cont = false; //le contenu de la mthode main est encadr dans une boucle while do { //rinitialise la variable cont false cont = false; //nombres alatoires pour lquation int num1 = (int)(Math.round(Math.random()*10)); //la boucle do... while sert viter lexception. num2 doit tre //dclar lextrieur de la boucle do... while pour tre visible // lextrieur de cette boucle. int num2; do { //initialisation de num2 num2 = (int)(Math.round(Math.random()*10)); } while(num2 == 0); //si num2 vaut zro, on recommence //nombre alatoire pour le signe int signe = (int)(Math.round(Math.random()*3)); //contiendra la rponse int reponse; //rend laffichage plus lisible System.out.println("\n\n*****"); if(signe==0) { //affiche la question et calcule la rponse System.out.println(num1+" fois "+num2); reponse = num1*num2; } else if(signe == 1) { //affiche la question et calcule la rponse System.out.println(num1+" divis par "+num2); reponse = num1/num2; } else if(signe == 2) { //affiche la question et calcule la rponse System.out.println(num1+" plus "+num2); reponse = num1+num2; } else if(signe == 3) { //affiche la question et calcule la rponse System.out.println(num1+" moins "+num2); reponse = num1-num2; } else { //affiche la question et calcule la rponse System.out.println(num1+" % "+num2); reponse = num1%num2; } //rend laffichage plus lisible System.out.println("*****\n");

28

Devenez un petit gnie des jeux vido

//dcompte pour la difficult - on utilise une boucle for for(int i = difficulte; i >= 0; i--) { //affichage du temps restant System.out.println(i+"..."); //on attend une demi-seconde par //niveau de difficult Thread.sleep(500); } //affiche la rponse System.out.println("RPONSE: "+reponse); //demande lutilisateur sil veut rejouer String encore; encore = JOptionPane.showInputDialog("Rejouer? (oui/non)"); //si lutilisateur rpond oui, on passe la valeur de cont true if(encore.equals("oui")) cont = true; } while(cont); //on continue tant que cont a la valeur true } }

Les Figures 3.1 3.3 illustrent le jeu.


Figure 3.1 Saisie du niveau de difcult

Figure 3.2 quation, dcompte et rsultat

Chapitre 1

Java dans les starting-blocks

29

Figure 3.3 Rejouer ?

Pour aller plus loin...


Vous devez avoir remarqu que les rponses ne sont pas toujours exactes. Par exemple, 3/4 renvoie 1 et non 0,75. Pour corriger ce comportement, il suft de modier toutes les variables de type int (sauf celle contenant le signe) en variables de type double.

30

Devenez un petit gnie des jeux vido

Projet 4 : Une bibliothque virtuelle de jeux


Projet Nouvelles briques Une archive des jeux que vous avez crs. Tableaux, ArrayList.

Nous avons vu comment crer des jeux basiques ; nous allons maintenant apprendre les enregistrer pour y accder facilement. Pour cela, nous avons besoin de structures de donnes. La structure de donnes dont nous allons parler dans ce projet sappelle un tableau (array). Un tableau permet denregistrer de nombreuses variables du mme type (par exemple int, double ou String). Vous pourrez alors rcuprer la valeur dune variable dun tableau en fonction de sa position. Linconvnient des tableaux est quil est difcile dy ajouter de nouvelles variables (appeles, dans un tableau, des lments). Cest pour cette raison que nous allons galement introduire les objets ArrayList.

Tableaux
Pour crer et initialiser un tableau en une seule instruction, utilisez ce type de ligne :
int pleinDEntiers[] = {-981, 45, -6, 7};

Cette instruction cre un tableau nomm pleinDEntiers contenant les valeurs 981, 45, 6 et 7. Pour crer un tableau sans en initialiser les lments, on utilise cette syntaxe :
int sixEntiers = new int[6];

Ceci cre un tableau pouvant contenir six lments de type int ; pour linstant, les valeurs du tableau sont vides. Il faut toujours dnir la taille dun tableau, qui dans notre cas est six. Pour accder une valeur/un lment dun tableau ou pour la modier, il faut se souvenir dune notion importante : les numros dlments commencent zro. Par exemple, dans le tableau pleinDEntiers, le premier lment ( la position 0) est 981. Le second lment ( la position 1) est 45. Et, bien sr, llment la position 2 est 6.

Modier une valeur dans un tableau Pour modier une valeur dans un tableau, on utilise une syntaxe de ce type :
<nom du tableau>[<position de llment modifier>] = <valeur>;

Chapitre 1

Java dans les starting-blocks

31

Par exemple, pour modier le premier lment ( la position 0) du tableau pleinDEntiers et lui donner la valeur 50, on utilisera :
pleinDEntiers[0] = 50;

Rcuprer une valeur dans un tableau


Pour rcuprer une valeur dans un tableau, on utilise une syntaxe du type :
<variable> = <nom du tableau>[<position de llment rcuprer>];

Pour rcuprer la valeur du premier lment de pleinDEntiers, on utilisera donc :


int num = pleinDEntiers[0];

Objets ArrayList
Un ArrayList contient des classes (aussi appeles objets). Il sagit bien de la mme chose que les classes que vous dclarez lorsque vous crez un programme (dans le code public class). Pour linstant, nous nutiliserons cependant que des classes dj programmes. Nous avons dj utilis les syntaxes Integer.parseInt() et Double.parseDouble(). Double et Integer sont deux classes pouvant tre contenues dans un ArrayList. Pour simplier, nous ne parlerons pour linstant que de ces deux classes. Toutes les classes appartiennent une hirarchie. Le membre le plus lev de toutes les classes est appel Object. Un ArrayList ne contient que des Object que lon peut ensuite transtyper dans la classe de lobjet dorigine (dans notre cas, Integer ou Double). Voici le code utilis pour crer un ArrayList. Notez quil nest fait aucune mention du type des objets qui seront contenus dedans.
ArrayList structure = new ArrayList();

Il nest pas possible dinitialiser des valeurs sur la mme ligne. Pour ajouter une valeur, on utilise :
structure.add(new Integer(5));

Vous pouvez ajouter autant dlments que vous le dsirez. Pour rcuprer une valeur (dont vous connaissez la position, qui commence toujours par 0), utilisez le code suivant :

32

Devenez un petit gnie des jeux vido

Object objTemp = structure.get(0); Integer intTemp = (Integer)tempObj; int numFinal = intTemp.intValue();

La premire ligne rcupre l Object la position 0 de lArrayList. La deuxime ligne transforme lobjet en entier (pour le transformer en Double, remplacez Integer par Double). La dernire ligne transforme lobjet Integer en variable de type int (si vous travaillez avec des Double, changez intValue en doubleValue et int en double).

Crer le jeu
Nous allons crer une bibliothque virtuelle pour enregistrer le nom des jeux que vous avez crs. La bibliothque permet daccder aux jeux en saisissant le numro dlment du jeu. Elle permet galement de crer des lments. Pour cela nous allons utiliser un ArrayList. Demandez lutilisateur, grce un JOptionPane, sil dsire ajouter un nouveau jeu ou accder un jeu. Sil saisit 1, ajoutez la nouvelle chane de caractres l ArrayList. Sil saisit 2, utilisez un nouveau JOptionPane pour obtenir le numro dlment, puis un troisime JOptionPane pour afcher le nom du jeu. Le tout est encapsul dans une boucle do... while pour que lutilisateur puisse relancer le programme sil le dsire.
//on importe les lments ncessaires import javax.swing.*; import java.util.*; public class S1P4 { public static void main (String[] args) { //dfinition de lArrayList ArrayList jeux = new ArrayList(); //utilis comme condition darrt de la boucle boolean cont = false; do { cont = false; //rinitialiser cont //que veut faire lutilisateur? int choix = Integer.parseInt(JOptionPane. showInputDialog("Saisissez\n"+"1 pour ajouter un nouveau jeu\n"+ "2 pour accder un jeu")); if(choix == 1) { //rcupre le nom String nom; nom = JOptionPane.showInputDialog("Nom du jeu?");

Chapitre 1

Java dans les starting-blocks

33

//on lajoute jeux.add(nom); } if(choix ==2) { //on demande lutilisateur quel nom renvoyer int element = Integer.parseInt(JOptionPane. showInputDialog("Quel lment?")); //ceci est affich dans un nouveau JOptionPane String sortie = "Le nom du jeu est:\n"; //concatnation et rcupration de llment sortie+=((String)jeux.get(element)); //on affiche dans le JOptionPane JOptionPane.showMessageDialog(null,sortie); } //saisie utilisateur pour la rptition String repeter = JOptionPane.showInputDialog("Recommencer? (oui/non)"); if(repeter.equals("oui")) cont = true; } while(cont); //continuer tant que cont a la valeur true } }

Les Figures 4.1 4.5 illustrent les diffrentes phases du programme. Dans le projet suivant, nous rsumerons tout ce que nous avons appris dans un jeu de devinettes de nombres !
Figure 4.1 Choix du mode : ajout dun jeu ou afchage dun jeu

Figure 4.2 Saisie dun nouveau nom de jeu

34

Devenez un petit gnie des jeux vido

Figure 4.3 Continuer le programme

Figure 4.4 Accder un jeu en indiquant son numro

Figure 4.5 Afchage du jeu demand

Chapitre 1

Java dans les starting-blocks

35

Projet 5 : Devinez le nombre !


Projet Lordinateur gnre un nombre alatoire entre 0 et 100 et vous devez le trouver. Aprs chaque essai, lordinateur offre un indice : trop grand ou trop petit. Pour ce projet, vous devrez assembler plusieurs briques des projets prcdents : les classes, les instructions, les variables, la saisie utilisateur, les boucles, les commentaires, lafchage, le transtypage et les instructions if.

Crer le jeu
Commencez par gnrer un nombre alatoire. Puis, utilisez une boucle do... while. Rcuprez une saisie utilisateur (son essai) et comparez-la au nombre correct avec des instructions if. Cela fournira les indices pour le joueur. La boucle do... while se termine lorsque la tentative est couronne de succs.
import javax.swing.*; public class S1Resume { public static void main (String[] args) { //contient les essais de lutilisateur int essai = -1; //nombre dessais int nombre = 0; //cration du nombre int num = (int) (Math.random()*100); //boucle pour interroger lutilisateur do { essai = Integer.parseInt(JOptionPane. showInputDialog("Devinez un nombre entre 0 et 100")); if(essai>num) JOptionPane.showMessageDialog(null,"Trop grand"); if(essai<num) JOptionPane.showMessageDialog(null,"Trop petit"); nombre++; } //continuer jusqu ce que lutilisateur trouve le nombre while(num!=essai); JOptionPane.showMessageDialog(null,"Vous avez devin le nombre, " + num + ", en " + nombre + " essai(s)!"); } }

36

Devenez un petit gnie des jeux vido

Les Figures 5.1 5.4 montrent le jeu Devinez le nombre ! Si vous avez des problmes avec ce code, ne dsesprez pas ! Revoir les projets prcdents pourra vous aider rafrachir vos connaissances. Si vous avez pu crire ce code tout seul, bravo, vous tes sur le bon chemin pour devenir un petit gnie de la programmation de jeux vido !
Figure 5.1 Tentative pour deviner le nombre

Figure 5.2 Lessai tape trop haut

Figure 5.3 Lessai tape trop bas

Figure 5.4 Vous avez trouv la bonne rponse !

Chapitre 1

Java dans les starting-blocks

37

Java dans les starting-blocks : le rsum

Commentaires. Les commentaires permettent de documenter le code pour savoir ce que fait chaque partie de votre jeu. Instructions. Les instructions sont des commandes. Elles sont la base de tout jeu. Contrle de ux. Les boucles permettent de rpter du code. Elles sont utiles lorsquun utilisateur veut ressayer un jeu lorsquil a perdu. Variables. Les variables permettent de garder trace du score du joueur, des points, etc. Instructions if. Les instructions if permettent de tester des variables. Vous pouvez par exemple tester si un joueur a encore des vies ou sil est dnitivement mort.

JOptionPane. Un JOptionPane permet dobtenir des saisies et dafcher des messages. Un exemple de message peut tre le score dun utilisateur. Un exemple de saisie peut tre le nom de lutilisateur pour la liste des scores records.
Nombres alatoires. Les nombres alatoires servent lintelligence articielle (faire bouger un ennemi de manire alatoire, etc.). Pauses. Les pauses permettent dattendre que lcran se rafrachisse pour que les graphismes du jeu aient une qualit optimale. Tableaux. Les tableaux peuvent garder trace de lenvironnement du jeu (par exemple la liste des voitures dans un jeu de course, une liste de munitions dans un jeu de tir).

ArrayList. Les ArrayList peuvent tre utiliss pour enregistrer les noms et scores des joueurs.
Accs aux chiers. Les accs aux chiers servent garder une liste de records permanents pour les jeux.

2
Jeux de course
Au sommaire de ce chapitre :

La course du courage

Projet 6 : La piste Projet 7 : Les voitures Projet 8 : Collisions ! Projet 9 : Personnalisation

Le skieur

Projet 10 : La piste Projet 11 : Piste verte Projet 12 : La comptition

40

Devenez un petit gnie des jeux vido

Projet 6 : La course du courage La piste


La course du courage Des voitures de course que vous avez conues roulant sur une piste que vous avez dessine, avec des graphismes et des effets sonores sensationnels !
Projet Nouvelles briques Crez lenvironnement : une piste de course virtuelle avec une interface graphique. JFrame, mthodes.

JFrame
Un JFrame est une des mthodes les plus simples pour crer une interface graphique (GUI, Graphical User Interface). Il cre une fentre (similaire un JOptionPane) dune taille donne. Vous pouvez y ajouter des graphismes, des boutons, des champs de texte, des libells, etc. La Figure 6.1 reprsente un JFrame avant tout ajout de graphismes ou dimages. Pour crer un JFrame, ajoutez extends JFrame la n de la ligne public class... Par exemple, si votre classe sappelle Jeu, la ligne ressemblerait ceci :
public class Jeu extends JFrame

Modiez galement la mthode main an quelle ne contienne quune ligne de code :


<nom de la classe> <nom de la variable> = new <nom de la classe>();

Dans notre classe Jeu, la mthode main ne contiendrait donc que la ligne :
Jeu j = new Jeu();

Cette ligne de code excute le constructeur de la classe. Un constructeur est similaire la mthode main, ceci prs quil est appel automatiquement lorsquon cre une instance de la classe (en utilisant le code ci-dessus). Par consquent, tout le code ncessaire pour faire fonctionner le jeu doit se trouver dans le constructeur et non dans la mthode main. On programme un constructeur avec cette syntaxe :
public <nom de la classe>() {

Chapitre 2

Jeux de course

41

// le code est ajout ici }

Le code du constructeur de la classe Jeu commencerait donc ainsi :


public Jeu() { }

Dans le constructeur, il faut ajouter ces quatre lignes de code pour crer le JFrame et en indiquer le titre et la taille :
super("voici le titre"); setSize(400,400); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Et voil : vous avez cr votre toute premire interface graphique ! Une interface graphique est un canevas blanc auquel vous pouvez facilement ajouter des formes, des images, des boutons, des champs de texte ou tout ce que vous pouvez imaginer. Dans ce qui suit, nous expliquerons comment inclure des ennemis menaants, des hros audacieux ou des aliens dgotants.
Figure 6.1 Un JFrame vide

Tapez le code suivant lextrieur du constructeur, mais lintrieur de la classe :


public void paint(Graphics g) { super.paint(g); }

42

Devenez un petit gnie des jeux vido

Cette mthode permet de dessiner des formes quelconques : des rectangles, des carrs, des cercles, des arcs ou mme des lettres gantes. Pour linstant, nous allons nous intresser deux commandes pour choisir une couleur et dessiner un rectangle. Pour choisir une couleur, on utilise le code suivant (il faut aussi ajouter une ligne import java.awt.*) :
g.setColor(Color.<une couleur>);

<une couleur> est le nom dune couleur en anglais ; NetBeans afche la liste des couleurs disponibles lorsque vous tapez "Color.". Cette liste est illustre la Figure 6.2.
Figure 6.2 Quelques-unes des nombreuses couleurs disponibles

Pour dessiner un rectangle, il faut utiliser cette syntaxe :


g.fillRect(<x>, <y>, <largeur>, <hauteur>);

<x>, <y>, <largeur> et <hauteur> sont des variables de type int.


Dessinez un rectangle vert comme celui de la Figure 6.3, la position 100, 100, large de 100 et haut de 200. Vous savez maintenant comment tracer une piste de course simple ! Attention, il arrivera un moment o vous devrez vrier si la voiture sort des limites du rectangle. Pour anticiper cela, sauvez les points dans un objet Rectangle. Cela rendra les collisions plus faciles dtecter. Vous pourrez ensuite tracer le rectangle en rcuprant ses valeurs, comme ceci :
Rectangle r1 = new Rectangle(100,100,100,200); g.fillRect(r1.x, r1.y, r1.width, r1.height);

Chapitre 2

Jeux de course

43

Figure 6.3 Un rectangle vert dans un JFrame

Et, pour redessiner le JFrame, il suft dutiliser le code suivant dans votre programme :
repaint();

Le code public void paint... est toujours excut au dmarrage du programme.

Mthodes
Les mthodes contiennent du code qui peut tre excut plusieurs fois. On utilise des mthodes pour pouvoir rpter du code plus facilement. Vous pouvez appeler (cest--dire excuter) une mthode partir du constructeur ou depuis une autre mthode, mais pas depuis la mthode main. Une mthode peut prendre en entre une variable (aussi appele argument) ou renvoyer une variable, non exclusivement et non obligatoirement. Pour crer une mthode, on utilise cette syntaxe :
public <type de retour> <nom> (arguments) { //code }

<type de retour> doit tre remplac par void si la mthode ne renvoie pas de rsultat. Si elle retourne un lment de type int, il doit tre remplac par int. Si elle retourne un objet de type Integer, il doit tre remplac par Integer. <type de retour> peut tre un type primitif (int, double, char, etc.) ou un objet.

44

Devenez un petit gnie des jeux vido

<nom> est le nom de la mthode. Ce nom est votre convenance, pour autant quil commence par une lettre. arguments reprsente les variables en entre de la mthode lorsquelle est appele. Ces arguments sont spars par des virgules. Si votre mthode prend deux arguments, un de type int et un de type double, vous devez crire ceci :
public void exemple (int i, double d){}

lintrieur de la mthode, i et d sont les noms de variables via lesquels les arguments sont accessibles. Pour renvoyer une valeur, utilisez ceci :
return <variable>;

<variable> doit tre du type que vous avez indiqu lorsque vous avez dclar la mthode.
Pour appeler une mthode, en loccurrence la mthode exemple, il faut utiliser cette syntaxe pour passer les arguments 1 et 4.563. :
exemple(1, 4.563)

Si exemple renvoie une valeur de type int, vous pouvez rcuprer la valeur renvoye comme ceci :
int i = exemple(1, 4.563);

Crer le jeu
Tracez prsent une piste de course virtuelle. Le code complet se trouve ci-aprs :
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; //cre la classe en utilisant JFrame public class Course extends JFrame { //constantes contenant la taille de lcran final int LARGEUR = 900, HAUTEUR = 650; /* *Le code suivant (crant les rectangles) peut sembler compliqu * premire vue, mais cela nest d qu lutilisation de LARGEUR *et HAUTEUR pour crer les morceaux. Vous pouvez aussi utiliser *des valeurs codes en dur. */

Chapitre 2

Jeux de course

45

/*Dfinition de tous les rectangles dessiner*/ /* *Le code suivant (crant les rectangles) peut sembler compliqu premire vue, *mais cela nest d qu lutilisation de LARGEUR et HAUTEUR pour crer les *morceaux. Vous pouvez aussi utiliser des valeurs codes en dur. */ //cre les rectangles gauche, droite, en haut, en bas et au centre Rectangle gauche = new Rectangle(0,0,LARGEUR/9,HAUTEUR); Rectangle droite = new Rectangle((LARGEUR/9)*8,0,LARGEUR/9,HAUTEUR); Rectangle haut = new Rectangle(0,0,LARGEUR, HAUTEUR/9); Rectangle bas = new Rectangle(0,(HAUTEUR/9)*8,LARGEUR,HAUTEUR/9); Rectangle centre = new Rectangle((int)((LARGEUR/9)*2.5),(int) ((HAUTEUR/9)*2.5), (int)((LARGEUR/9)*5),(HAUTEUR/9)*4); //obstacles sur la route rendant la navigation plus difficile Rectangle obstacle = new Rectangle(LARGEUR/2,(int)((HAUTEUR/9)*7),LARGEUR/10,HAUTEUR/9); Rectangle obstacle2 = new Rectangle(LARGEUR/3,(int)((HAUTEUR/9)*5),LARGEUR/10,HAUTEUR/4); Rectangle obstacle3 = new Rectangle(2*(LARGEUR/3),(int)((HAUTEUR/9)*5),LARGEUR/10,HAUTEUR/4); Rectangle obstacle4 = new Rectangle(LARGEUR/3,HAUTEUR/9,LARGEUR/30,HAUTEUR/9); Rectangle obstacle5 = new Rectangle(LARGEUR/2,(int)((HAUTEUR/9)*1.5),LARGEUR/30,HAUTEUR/4); //ligne darrive pour les deux joueurs Rectangle arrivee = new Rectangle(LARGEUR/9,(HAUTEUR/2)-HAUTEUR/9, (int)((LARGEUR/9)*1.5), HAUTEUR/70); //ligne de dpart pour le joueur extrieur Rectangle ligneO = new Rectangle(LARGEUR/9,HAUTEUR/2,(int)((LARGEUR/9)*1.5)/2,HAUTEUR/140); //ligne de dpart pour le joueur intrieur Rectangle ligneI = new Rectangle(((LARGEUR/9)+((int)((LARGEUR/9)*1.5)/2)), (HAUTEUR/2)+(HAUTEUR/10), (int)((LARGEUR/9)*1.5)/2, HAUTEUR/140); //constructeur public Course() { //cre le JFrame super("La Course du courage"); setSize(LARGEUR,HAUTEUR); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } //dessine les voitures et la piste public void paint(Graphics g) { super.paint(g); //dessine le fond pour la piste g.setColor(Color.DARK_GRAY); g.fillRect(0,0,LARGEUR,HAUTEUR); //la bordure des dessins est verte g.setColor(Color.GREEN); //on dessine grce aux rectangles g.fillRect(gauche.x,gauche.y,gauche.width,gauche.height);

46

Devenez un petit gnie des jeux vido

g.fillRect(droite.x,droite.y,droite.width,droite.height); g.fillRect(haut.x,haut.y,haut.width,haut.height); g.fillRect(bas.x,bas.y,bas.width,bas.height); g.fillRect(centre.x,centre.y,centre.width,centre.height); g.fillRect(obstacle.x,obstacle.y,obstacle.width,obstacle.height); g.fillRect(obstacle2.x,obstacle2.y,obstacle2.width,obstacle2.height); g.fillRect(obstacle3.x,obstacle3.y,obstacle3.width,obstacle3.height); g.fillRect(obstacle4.x,obstacle4.y,obstacle3.width,obstacle4.height); g.fillRect(obstacle5.x,obstacle5.y,obstacle5.width,obstacle5.height); //pour les lignes de dpart on dessine en blanc g.setColor(Color.WHITE); //on dessine les lignes de dpart g.fillRect(ligneO.x,ligneO.y,ligneO.width,ligneO.height); g.fillRect(ligneI.x,ligneI.y,ligneI.width,ligneI.height); //la ligne darrive est en jaune g.setColor(Color.YELLOW); //on dessine la ligne darrive g.fillRect(arrivee.x,arrivee.y,arrivee.width,arrivee.height); } //ceci dmarre le programme en appelant le constructeur public static void main (String[] args) { new Course(); } }

La Figure 6.4 prsente une copie dcran de la piste complte.


Figure 6.4 La piste complte

Dans le prochain projet, nous donnerons vie la course du courage. Nous allons crer deux voitures qui acclrent vers lavant. Vroum, vroum !

Chapitre 2

Jeux de course

47

Projet 7 : La course du courage Les voitures


Projet Maintenant que vous savez comment crer une interface graphique, vous allez lveiller la vie. Grce des Thread (ls dexcution, grce auxquels plusieurs choses peuvent arriver en mme temps), vous allez faire acclrer deux voitures vers lavant. Thread, classes internes.

Nouvelles briques

Thread et classes internes


Pour crer un Thread, vous devez dabord programmer une classe interne. Pour faire cela, saisissez le code suivant lintrieur dune classe, mais en dehors de toute mthode ou de tout constructeur :
public class <nom> extends Thread { }

<nom> peut tre remplac par un nom quelconque diffrent du nom de la classe principale.
Dans cette nouvelle classe, il faut crer une mthode run, obligatoire pour que le programme puisse compiler :
public void run(){}

Dans cette mthode, nous allons faire avancer une des voitures. Il faut y crer une boucle while innie :
while (true) { }

Dans la boucle while, ajoutez le code suivant :


try { //code } catch (Exception e) { break; }

48

Devenez un petit gnie des jeux vido

Ces quelques lignes permettent de vrier sil y a des erreurs dans le bloc encadr par try. Si une erreur survient, lordinateur excute le code se trouvant dans le bloc encadr par catch. Dans ce cas, on appelle break, ce qui permet de sortir de la boucle innie. Les contrles faisant avancer la voiture doivent tre placs la place de //code. Une fois ce Thread termin, appelez-le depuis le constructeur avec la syntaxe suivante, dans laquelle Mouvement est le nom de votre classe interne :
Mouvement m = new Mouvement(); m.start();

Crer le jeu
Commencez par dessiner un Rectangle pour reprsenter la voiture (nous les personnaliserons dans le Projet 10). Puis, programmez un Thread (grce une classe interne). Ajoutez la mthode run, la boucle while et le code try.... Crez ensuite une variable globale pour contenir la vitesse de la premire voiture. Dans le code try..., augmentez lentement la vitesse jusqu la vitesse nale (ici, 4). Puis, faites bouger la voiture en modiant la valeur y de son rectangle en y ajoutant la valeur de la vitesse de la voiture. Pour nir, rafrachissez lcran et ajoutez un dlai (grce Thread.sleep(75);). Lorsque tout ceci fonctionne, essayez dajouter la deuxime voiture. Le code complet se trouve ci-aprs :
//on importe tout ce qui est ncessaire import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; //cre le JFrame public class Course extends JFrame { //constantes pour la taille de lcran final int LARGEUR = 900, HAUTEUR = 650; //vitesse des deux joueurs double vitesseJ1 =.5, vitesseJ2 =.5; //rectangles reprsentant la gauche, la droite, le haut, le bas et le centre Rectangle gauche = new Rectangle(0,0,LARGEUR/9,HAUTEUR); Rectangle droite = new Rectangle((LARGEUR/9)*8,0,LARGEUR/9,HAUTEUR); Rectangle haut = new Rectangle(0,0,LARGEUR,HAUTEUR/9); Rectangle bas = new Rectangle(0,(HAUTEUR/9)*8,LARGEUR,HAUTEUR/9); Rectangle centre = new Rectangle((int)((LARGEUR/9)*2.5),(int) ((HAUTEUR/9)*2.5),(int) ((LARGEUR/9)*5), (HAUTEUR/9)*4);

Chapitre 2

Jeux de course

49

//obstacles sur le chemin rendant la navitation plus difficile Rectangle obstacle = new Rectangle(LARGEUR/2,(int)((HAUTEUR/9)*7), LARGEUR/10,HAUTEUR/9); Rectangle obstacle2 = new Rectangle(LARGEUR/3,(int)((HAUTEUR/9)*5),LARGEUR/10,HAUTEUR/4); Rectangle obstacle3 = new Rectangle(2*(LARGEUR/3),(int)((HAUTEUR/9)*5),LARGEUR/10,HAUTEUR/4); Rectangle obstacle4 = new Rectangle(LARGEUR/3,HAUTEUR/9,LARGEUR/30,HAUTEUR/9); Rectangle obstacle5 = new Rectangle(LARGEUR/2,(int) ((HAUTEUR/9)*1.5),LARGEUR /30,HAUTEUR/4); //ligne darrive pour les deux joueurs Rectangle arrivee = new Rectangle(LARGEUR/9,(HAUTEUR/2)-HAUTEUR/9, (int) ((LARGEUR/9)*1.5),HAUTEUR/70); //rectangle pour la voiture du joueur 1 Rectangle j1 = new Rectangle(LARGEUR/9,HAUTEUR/2, LARGEUR/30,LARGEUR/30); //rectangle pour la voiture du joueur 2 Rectangle j2 = new Rectangle(((LARGEUR/9)+((int)((LARGEUR/9)*1.5)/2)), (HAUTEUR/2)+ (HAUTEUR/10), LARGEUR/30,LARGEUR/30); //constructeur public Course() { //cration du JFrame super("La Course du courage"); setSize(LARGEUR,HAUTEUR); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); //dmarrage de la classe interne, qui a un fonctionnement indpendant //puisquil sagit dun Thread Mouvement1 m1 = new Mouvement1(); Mouvement2 m2 = new Mouvement2(); m1.start(); m2.start(); } //dessine les voitures et la piste public void paint(Graphics g) { super.paint(g); //dessine le fond de la piste g.setColor(Color.DARK_GRAY); g.fillRect(0,0,LARGEUR,HAUTEUR); //la bordure de ce quon dessine est verte g.setColor(Color.GREEN); //ligne de dpart pour le joueur 1 Rectangle ligne1 = new Rectangle(LARGEUR/9,HAUTEUR/2,(int)((LARGEUR/9)*1.5)/2,HAUTEUR/140); //ligne de dpart pour le joueur 2 Rectangle ligne2 = new Rectangle(((LARGEUR/9)+((int)((LARGEUR/9)*1.5)/2)), (HAUTEUR/2)+(HAUTEUR/10),(int)((LARGEUR/9)*1.5)/2,HAUTEUR/140); //on dessine la piste g.fillRect(gauche.x,gauche.y,gauche.width,gauche.height); g.fillRect(droite.x,droite.y,droite.width,droite.height); g.fillRect(haut.x,haut.y,haut.width,haut.height); g.fillRect(bas.x,bas.y,bas.width,bas.height);

50

Devenez un petit gnie des jeux vido

g.fillRect(centre.x,centre.y,centre.width,centre.height); g.fillRect(obstacle.x,obstacle.y,obstacle.width,obstacle.height); g.fillRect(obstacle2.x,obstacle2.y,obstacle2.width,obstacle2.height); g.fillRect(obstacle3.x,obstacle3.y,obstacle3.width,obstacle3.height); g.fillRect(obstacle4.x,obstacle4.y,obstacle3.width,obstacle4.height); g.fillRect(obstacle5.x,obstacle5.y,obstacle5.width,obstacle5.height); //les lignes de dpart sont en blanc g.setColor(Color.WHITE); //on dessine les lignes de dpart g.fillRect(ligne1.x,ligne1.y,ligne1.width,ligne1.height); g.fillRect(ligne2.x,ligne2.y,ligne2.width,ligne2.height); //la ligne darrive est en jaune g.setColor(Color.YELLOW); //on dessine la ligne darrive g.fillRect(arrivee.x,arrivee.y,arrivee.width,arrivee.height); //le joueur 1 est dessin en bleu g.setColor(Color.BLUE); //dessin du joueur g.fill3DRect(j1.x,j1.y,j1.width,j1.height,true); //le joueur 2 est dessin en rouge g.setColor(Color.RED); //dessin du joueur g.fill3DRect(j2.x,j2.y,j2.width,j2.height,true); } private class Mouvement1 extends Thread { public void run() { //tout est dans une boucle infinie pour que le processus soit while(true) { //le code est dans un bloc try pour pouvoir sortir sil y a try { //rafrachit lcran repaint(); //augmente un peu la vitesse if(vitesseJ1<=5) vitesseJ1+=.2; j1.y-=vitesseJ1; //diminue le taux de rafrachissement Thread.sleep(75); } catch(Exception e) { //sil y a une exception, sort de la boucle break; } } } } private class Mouvement2 extends Thread { public void run() { //tout est dans une boucle infinie pour que le processus soit while(true) { //le code est dans un bloc try pour pouvoir sortir sil y a try {

rpt une erreur

rpt une erreur

Chapitre 2

Jeux de course

51

//rafrachit lcran repaint(); //augmente un peu la vitesse if(vitesseJ2<=5) vitesseJ2+=.2; j2.y-=vitesseJ2; //diminue le taux de rafrachissement Thread.sleep(75); } catch(Exception e) { //sil y a une exception, sort de la boucle break; } } } } //ceci dmarre le programme en appelant le constructeur public static void main(String[] args) { new Course(); } }

Les Figures 7.1 et 7.2 illustrent la course du courage. Dans le Projet 8, nous verrons comment ajouter la dtection des collisions et comment transformer votre clavier en volant.
Figure 7.1 La course du courage

52

Devenez un petit gnie des jeux vido

Figure 7.2 Les voitures acclrent vers lavant

Chapitre 2

Jeux de course

53

Projet 8 : La course du courage Collisions !


Projet Programmez les voitures pour quelles rebondissent et ralentissent lorsquelles se percutent lune lautre ou lorsquelles percutent les murs. Transformez aussi votre clavier en volant en attribuant des touches aux voitures. Dtection de collisions et KeyListener.

Briques

Dtection de collisions
La dtection de collisions (dtecter si des objets se touchent, comme lillustre la Figure 8.1) est simple en Java. Comme vous avez cr tous vos graphiques avec des classes Rectangle, dtecter des collisions est facile : la classe Rectangle fournit une mthode intersects.
Figure 8.1 Exemple de dtection de collisions

Pour vrier une collision entre r1 et r2, on utilise cette mthode de la manire suivante :
if(r1.intersects(r2))

Pour grer plusieurs collisions, vous pouvez utiliser les oprateurs && (et) et || (ou) dans la condition du bloc if. Par exemple, pour voir si r1 est en contact avec r2 ou avec r3, on crit :
if(r1.intersects(r2) || r1.intersects(r3))

KeyListener
La classe KeyListener permet de recevoir des saisies clavier venant de lutilisateur. Celles-ci peuvent par exemple servir contrler les directions des voitures. Pour utiliser un KeyListener, il faut ajouter les lments suivants la dclaration de votre classe (ligne public class...) :

54

Devenez un petit gnie des jeux vido

implements KeyListener

Cela sapplique aussi aux classes internes drives de Thread. Puis, dans le constructeur (ou dans la mthode run si vous utilisez des Thread), ajoutez cette ligne :
addKeyListener(this);

Elle indique au clavier de se "rveiller" et de commencer couter les commandes. Vous devez aussi ajouter trois mthodes votre code :
public void keyPressed(KeyEvent e){} public void keyReleased(KeyEvent e){} public void keyTyped(KeyEvent e){}

Ces mthodes sont appeles automatiquement lorsquune touche est tape. keyPressed est appele lorsque lutilisateur appuie sur une touche. keyReleased est appele lorsquune touche est relche. keyTyped est appele lorsquune touche est presse puis relche. keyTyped est probablement la mthode que vous utiliserez le plus. Vous pourrez alors modier le jeu en changeant certaines valeurs comme la direction de la voiture en fonction de la touche. Pour savoir quelle touche a t tape, on utilise :
e.getKeyChar()

Crer le jeu
Crez des variables globales de type int pour la direction de la voiture. Si leur valeur est 0, la voiture va vers le haut, si sa valeur est 1, la voiture va vers la gauche, etc. Pour simplier, crez des constantes avec lattribut final ; par exemple une valeur de type int nomme HAUT dont la valeur est 0. Pour savoir si la voiture va vers le haut, il suft alors de comparer sa direction avec HAUT plutt quavec 0. Puis, utilisez un KeyListener pour que le joueur puisse modier sa direction. Modiez la direction en testant la direction actuelle de la voiture et modiez x si la voiture va vers la gauche ou vers la droite, y si elle va vers le haut ou vers le bas. Vriez galement si le joueur est entr en collision avec un mur ou avec une autre voiture. Si cest le cas, la vitesse du joueur doit tre ngative pour que la voiture recule avant de pouvoir reprendre de la vitesse.

Chapitre 2

Jeux de course

55

Voici le code complet :


//on importe tout ce quil faut import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; //cre la classe et le JFrame public class Course extends JFrame { //constantes pour les dimensions de lcran final int LARGEUR = 900, HAUTEUR = 650; //vitesse des joueurs double vitesseJ1 =.5, vitesseJ2 =.5; //constantes reprsentant les directions final int HAUT = 0, DROITE = 1, BAS = 2, GAUCHE = 3; //garde trace de la direction du joueur (par dfaut, vers le haut) int directionJ1 = HAUT; int directionJ2 = HAUT; //cre des rectangles pour les parties gauche, droite, haute, basse et centre Rectangle gauche = new Rectangle(0,0,LARGEUR/9, HAUTEUR); Rectangle droite = new Rectangle((LARGEUR/9)*8,0,LARGEUR/9,HAUTEUR); Rectangle haut = new Rectangle(0,0,LARGEUR,HAUTEUR/9); Rectangle bas = new Rectangle(0,(HAUTEUR/9)*8,LARGEUR,HAUTEUR/9); Rectangle centre = new Rectangle((int)((LARGEUR/9) *2.5),(int)((HAUTEUR/9)*2.5), (int)((LARGEUR/9)*5),(HAUTEUR/9)*4); //obstacles pour rendre la navigation plus difficile Rectangle obstacle = new Rectangle(LARGEUR/2,(int)((HAUTEUR/9)*7), LARGEUR/10,HAUTEUR/9); Rectangle obstacle2 = new Rectangle(LARGEUR/3,(int)((HAUTEUR/9)*5), LARGEUR/10,HAUTEUR/4); Rectangle obstacle3 = new Rectangle(2*(LARGEUR/3),(int)((HAUTEUR/9)*5), LARGEUR/10,HAUTEUR/4); Rectangle obstacle4 = new Rectangle(LARGEUR/3,HAUTEUR/9,LARGEUR/30,HAUTEUR/9); Rectangle obstacle5 = new Rectangle(LARGEUR/2,(int)((HAUTEUR/9)*1.5), LARGEUR/30,HAUTEUR/4); //rectangle pour la ligne darrive pour les deux joueurs Rectangle arrivee = new Rectangle(LARGEUR/9,(HAUTEUR/2)-HAUTEUR/9, (int)((LARGEUR/9)*1.5),HAUTEUR/70); //rectangle pour la voiture du joueur 1 Rectangle j1 = new Rectangle(LARGEUR/9,HAUTEUR/2, LARGEUR/30,LARGEUR/30); //rectangle pour la voiture du joueur 2 Rectangle j2 = new Rectangle(((LARGEUR/9)+ ((int)((LARGEUR/9)*1.5)/2)), (HAUTEUR/2)+(HAUTEUR/10),LARGEUR/30,LARGEUR/30); //constructeur public Course() { //ce code cre le JFrame super("La Course du courage"); setSize(LARGEUR,HAUTEUR); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true);

56

Devenez un petit gnie des jeux vido

//dmarre la classe interne (qui fonctionne indpendamment puisquil sagit dun Thread) Mouvement1 m1 = new Mouvement1(); Mouvement2 m2 = new Mouvement2(); m1.start(); m2.start(); } //dessine les voitures et la piste public void paint(Graphics g) { super.paint(g); //fond de la piste g.setColor(Color.DARK_GRAY); g.fillRect(0,0,LARGEUR,HAUTEUR); //les bordures du dessin sont vertes g.setColor(Color.GREEN); //ligne de dpart pour le premier joueur Rectangle ligne1 = new Rectangle(LARGEUR/9,HAUTEUR/2,(int)((LARGEUR/9)*1.5) /2,HAUTEUR/140); //ligne de dpart pour le deuxime joueur Rectangle ligne2 = new Rectangle(((LARGEUR/9)+((int)((LARGEUR/9)*1.5)/2)), (HAUTEUR/2)+(HAUTEUR/10), (int) ((LARGEUR/9)*1.5)/2,HAUTEUR/140); //on dessine la piste g.fillRect(gauche.x,gauche.y,gauche.width,gauche.height); g.fillRect(droite.x,droite.y,droite.width,droite.height); g.fillRect(haut.x,haut.y,haut.width,haut.height); g.fillRect(bas.x,bas.y,bas.width,bas.height); g.fillRect(centre.x,centre.y,centre.width,centre.height); g.fillRect(obstacle.x,obstacle.y,obstacle.width,obstacle.height); g.fillRect(obstacle2.x,obstacle2.y,obstacle2.width,obstacle2.height); g.fillRect(obstacle3.x,obstacle3.y,obstacle3.width,obstacle3.height); g.fillRect(obstacle4.x,obstacle4.y,obstacle3.width,obstacle4.height); g.fillRect(obstacle5.x,obstacle5.y,obstacle5.width,obstacle5.height); //la ligne de dpart est en blanc g.setColor(Color.WHITE); //on dessine la ligne de dpart g.fillRect(ligne1.x,ligne1.y,ligne1.width,ligne1.height); g.fillRect(ligne2.x,ligne2.y,ligne2.width,ligne2.height); //la ligne darrive est en jaune g.setColor(Color.YELLOW); //on dessine la ligne darrive g.fillRect(arrivee.x,arrivee.y,arrivee.width,arrivee.height); //le joueur 1 est en bleu g.setColor(Color.BLUE); //dessin du joueur g.fill3DRect(j1.x,j1.y,j1.width,j1.height,true); //le joueur 2 est en rouge g.setColor(Color.RED); //dessin du joueur g.fill3DRect(j2.x,j2.y,j2.width,j2.height,true); }

Chapitre 2

Jeux de course

57

private class Mouvement1 extends Thread implements KeyListener { public void run() { //active le KeyListener addKeyListener(this); //boucle infinie pour pouvoir rpter le processus while(true) { //le code est encapsul dans un bloc try pour larrter en cas derreur try { //rafrachit lcran repaint(); //si la voiture tape dans un mur extrieur, sa vitesse passe -4 if(j1.intersects(gauche) || j1.intersects(droite) || j1.intersects(haut) || j1.intersects(bas) || j1.intersects(obstacle) || j1.intersects(obstacle2)|| j1.intersects(j2) || j1.intersects(obstacle3) || j1.intersects(obstacle4) || j1.intersects(obstacle5)) { vitesseJ1 = -4; } //si la voiture tape dans le centre, sa vitesse passe -2.5 if(j1.intersects(centre)) { vitesseJ1 = -2.5; } //augmentation de la vitesse if(vitesseJ1<=5) vitesseJ1+=.2; //dplacement du joueur en fonction de sa direction if(directionJ1==HAUT) { j1.y-=(int)vitesseJ1; } if(directionJ1==BAS) { j1.y+=(int)vitesseJ1; } if(directionJ1==GAUCHE) { j1.x-=(int)vitesseJ1; } if(directionJ1==DROITE) { j1.x+=(int)vitesseJ1; } //diminue le taux de rafrachissement Thread.sleep(75); } catch(Exception e) { //sil y a une exception (une erreur) on sort de la boucle break; } } } //ncessaire pour le KeyListener public void keyPressed(KeyEvent event) { }

58

Devenez un petit gnie des jeux vido

//ncessaire pour le KeyListener public void keyReleased(KeyEvent event) { } //ncessaire pour le KeyListener public void keyTyped(KeyEvent event) { if(event.getKeyChar()==q) { directionJ1 = GAUCHE; } if(event.getKeyChar()==s) { directionJ1 = BAS; } if(event.getKeyChar()==d) { directionJ1 = DROITE; } if(event.getKeyChar()==z) { directionJ1 = HAUT; } } } private class Mouvement2 extends Thread implements KeyListener { public void run() { //active le KeyListener addKeyListener(this); //boucle infinie pour pouvoir rpter le processus while(true) { //le code est encapsul dans un bloc try pour larrter en cas derreur try { //rafrachit lcran repaint(); //si la voiture tape dans un mur extrieur, sa vitesse passe -4 if(j2.intersects(gauche) || j2.intersects(droite) || j2.intersects(haut) || j2.intersects(bas) || j2.intersects(obstacle) || j2.intersects(obstacle2) || j1.intersects(j2)) { vitesseJ2 = -4; } //si la voiture tape dans le centre, sa vitesse passe -2.5 if(j2.intersects(centre)) { vitesseJ2 = -2.5; } //augmentation de la vitesse if(vitesseJ2<=5) vitesseJ2+=.2; //dplace le joueur en fonction de sa direction if(directionJ2==HAUT) { j2.y-=(int)vitesseJ2; }

Chapitre 2

Jeux de course

59

if(directionJ2==BAS) { j2.y+=(int)vitesseJ2; } if(directionJ2==GAUCHE) { j2.x-=(int)vitesseJ2; } if(directionJ2==DROITE) { j2.x+=(int)vitesseJ2; } //diminue le taux de rafrachissement Thread.sleep(75); } catch(Exception e) { //sil y a une exception (une erreur) on sort de la boucle break; } } } //ncessaire pour le KeyListener public void keyPressed(KeyEvent event) { } //ncessaire pour le KeyListener public void keyReleased(KeyEvent event) { } //ncessaire pour le KeyListener public void keyTyped(KeyEvent event) { if(event.getKeyChar()== j) { directionJ2 = GAUCHE; } if(event.getKeyChar()==k) { directionJ2 = BAS; } if(event.getKeyChar()==l) { directionJ2 = DROITE; } if(event.getKeyChar()==i) { directionJ2 = HAUT; } } } //dmarre le programme en appelant le constructeur public static void main(String[] args) { new Course(); } }

La Figure 8.2 illustre les vhicules sur la piste.

60

Devenez un petit gnie des jeux vido

Figure 8.2 Les voitures tournent et se promnent sur la piste

Chapitre 2

Jeux de course

61

Projet 9 : La course du courage Personnalisation


Projet Ajoutez des modications au jeu : ajoutez-y des images et des sons. Ajoutez un cran de bienvenue. Ajoutez un compteur de tours indiquant le gagnant aprs trois tours de piste. Images, sons.

Briques

Images
Envie davoir des images dans votre jeu ? Ce nest pas difcile. Vous pouvez transformer votre voiture de course en vaisseau spatial, en bateau, en avion, en gupard ou en tracteur... Laissez libre cours votre imagination ! Vous devez dabord dessiner une image ou en trouver une sur Internet. Une fois votre moyen de transport choisi, sauvegardez-le dans le rpertoire dans lequel se trouve le chier .class compil (habituellement, <rpertoire de votre projet>/build/classes/ <nom du package>). Les Figures 9.1 9.3 illustrent quelques possibilits de dcor pour votre jeu.
Figure 9.1 Voiture de course

Figure 9.2 Bateau

62

Devenez un petit gnie des jeux vido

Figure 9.3 Avion

Ajoutez ces lignes avant de dessiner limage :


Image img = null; try { URL url = this.getClass().getResource("nom"); img = Toolkit.getDefaultToolkit().getImage(url); } catch(Exception e){}

nom doit tre remplac par le nom de limage utiliser (y compris son extension).
Ensuite, remplacez le code qui dessine les rectangles par cette ligne :
g.drawImage(img, x, y, this)

o x et y sont les x et y du rectangle. De plus, il faut importer, en dbut de chier, java.io.* et java.net.*. Toutes les images utilises dans les jeux de cet ouvrage sont disponibles dans le rpertoire Projets, sur le site web de Pearson, www.pearson.fr, la page ddie cet ouvrage.

Sons
Pour ajouter rapidement des effets sonores vos jeux, utilisez ces lignes :
URL moteur = this.getClass().getResource("moteur.wav"); AudioClip son = JApplet.newAudioClip(moteur); son.loop();

moteur.wav est le nom du chier son. snd.loop() joue le son en boucle. Si vous prfrez ne le jouer quune fois, vous pouvez remplacer cette ligne par :
snd.play();

Noubliez pas dimporter java.applet.AudioClip. Tous les sons utiliss dans les jeux de cet ouvrage sont disponibles dans le rpertoire de Projets, sur le site web de Pearson, www.pearson.fr, la page ddie cet ouvrage.

Chapitre 2

Jeux de course

63

Crer le jeu
Ajoutez un cran de bienvenue grce JOptionPane. Vous pouvez aussi programmer le dcompte du nombre de tours en comptant les collisions avec la ligne darrive. Remplacez les voitures rectangulaires par des images. Noubliez pas dorienter les images dans le sens dans lequel le vhicule se dplace (lorsquil va vers la droite, limage devrait pointer vers la droite). Voici le code complet :
//on importe ce quil faut: import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; import java.applet.AudioClip; //cre une nouvelle classe et le JFrame public class Course extends JFrame { //variables pour les images URL url1 = null, url2 = null, url3 = null, url4 = null, url5 = null, url6 = null, url7 = null, url8 = null, urlT = null; Image img1,img2,img3,img4, img5,img6,img7,img8, titre; //constante pour la taille de lcran final int LARGEUR = 900, HAUTEUR = 650; //a la valeur true si quelquun a gagn boolean gagnantOK = false; //vitesse des joueurs double vitesseJ1 =.5, vitesseJ2 =.5; //nombre de tous des joueurs int toursJ1 = 0, toursJ2 = 0; //constantes pour les directions final int HAUT = 0, DROITE = 1, BAS = 2, GAUCHE = 3; //directions des joueurs (par dfaut vers le haut) int directionJ1 = HAUT; int directionJ2 = HAUT; //cre des rectangles pour les parties haute, basse, gauche, droite et centre de lcran Rectangle gauche = new Rectangle(0,0,LARGEUR/9,HAUTEUR); Rectangle droite = new Rectangle((LARGEUR/9)*8,0,LARGEUR/9,HAUTEUR); Rectangle haut = new Rectangle(0,0,LARGEUR,HAUTEUR/9); Rectangle bas = new Rectangle(0,(HAUTEUR/9)*8,LARGEUR,HAUTEUR/9); Rectangle centre = new Rectangle((int)((LARGEUR/9)*2.5), (int)((HAUTEUR/9)*2.5), (int)((LARGEUR/9)*5),(HAUTEUR/9)*4); //obstacles pour rendre la course plus difficile Rectangle obstacle = new Rectangle(LARGEUR/2,(int)((HAUTEUR/9)*7), LARGEUR/10,HAUTEUR/9);

64

Devenez un petit gnie des jeux vido

Rectangle obstacle2 = new Rectangle(LARGEUR/3,(int)((HAUTEUR/9)*5), LARGEUR/10,HAUTEUR/4); Rectangle obstacle3 = new Rectangle(2*(LARGEUR/3),(int)((HAUTEUR/9)*5), LARGEUR/10,HAUTEUR/4); Rectangle obstacle4 = new Rectangle(LARGEUR/3,HAUTEUR/9,LARGEUR/30,HAUTEUR/9); Rectangle obstacle5 = new Rectangle(LARGEUR/2,(int)((HAUTEUR/9)*1.5), LARGEUR/30,HAUTEUR/4); //ligne darrive pour les deux joueurs Rectangle arrivee = new Rectangle(LARGEUR/9,(HAUTEUR/2)-HAUTEUR/9, (int)((LARGEUR/9)*1.5), HAUTEUR/70); //rectangle pour la voiture du joueur 1 Rectangle j1 = new Rectangle(LARGEUR/9,HAUTEUR/2,LARGEUR/30,LARGEUR/30); //rectangle pour la voiture du joueur2 Rectangle j2 = new Rectangle(((LARGEUR/9)+((int)((LARGEUR/9)*1.5)/2)), (HAUTEUR/2)+(HAUTEUR/10),LARGEUR/30,LARGEUR/30); //constructeur public Course() { //on cre le JFrame super("La Course du courage"); setSize(LARGEUR,HAUTEUR); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); //on charge les adresses try { url1 = this.getClass().getResource("course1.jpg"); url2 = this.getClass().getResource("course2.jpg"); url3 = this.getClass().getResource("course3.jpg"); url4 = this.getClass().getResource("course4.jpg"); url5 = this.getClass().getResource("course5.jpg"); url6 = this.getClass().getResource("course6.jpg"); url7 = this.getClass().getResource("course7.jpg"); url8 = this.getClass().getResource("course8.jpg"); urlT = this.getClass().getResource("titre.png"); } catch(Exception e){} //on rcupre les images pointes par les URL img1 = Toolkit.getDefaultToolkit().getImage(url1); img2 = Toolkit.getDefaultToolkit().getImage(url2); img3 = Toolkit.getDefaultToolkit().getImage(url3); img4 = Toolkit.getDefaultToolkit().getImage(url4); img5 = Toolkit.getDefaultToolkit().getImage(url5); img6 = Toolkit.getDefaultToolkit().getImage(url6); img7 = Toolkit.getDefaultToolkit().getImage(url7); img8 = Toolkit.getDefaultToolkit().getImage(url8); titre = Toolkit.getDefaultToolkit().getImage(urlT); //affichage dun cran de bienvenue avec les rgles JOptionPane.showMessageDialog(null, "Bienvenue la Course du Courage!\n\n"+ "Le jeu: deux joueurs font la course.\n"+ "Le but: terminer trois tours avant votre adversaire!\n"+ "Contrles:\n"+ "Joueur 1 (voiture bleue):\n"+ "directions ZQSD, la vitesse est gre automatiquement.\n"+

Chapitre 2

Jeux de course

65

"Joueur 2 (voiture rouge):\n"+ "directions IJKL, la vitesse est gre automatiquement.\n"+ "Attention lherbe verte, elle peut vous faire draper!\n"+ "Cliquez sur OK pour dmarrer"); //dmarre les classes internes (indpendantes, puisquil sagit de Thread) Mouvement1 m1 = new Mouvement1(); Mouvement2 m2 = new Mouvement2(); m1.start(); m2.start(); //joue le son try { URL moteur = this.getClass().getResource("moteur.wav"); AudioClip son = JApplet.newAudioClip(moteur); son.loop(); } catch(Exception e){} } //dessine les voitures et la piste public void paint(Graphics g) { super.paint(g); //fond de la piste g.setColor(Color.DARK_GRAY); g.fillRect(0,0,LARGEUR,HAUTEUR); //la bordure est verte g.setColor(Color.GREEN); //ligne de dpart pour le joueur 1 Rectangle ligne1 = new Rectangle(LARGEUR/9, HAUTEUR/2,(int) ((LARGEUR/9)*1.5)/2,HAUTEUR/140); //ligne de dpart pour le joueur 2 Rectangle ligne2 = new Rectangle(((LARGEUR/9)+ ((int)((LARGEUR/9)*1.5)/2)),(HAUTEUR/2)+(HAUTEUR/10),(int) ((LARGEUR/9)*1.5)/2, HAUTEUR/140); //on dessine la piste g.fillRect(gauche.x,gauche.y,gauche.width,gauche.height); g.fillRect(droite.x,droite.y,droite.width,droite.height); g.fillRect(haut.x,haut.y,haut.width,haut.height); g.fillRect(bas.x,bas.y,bas.width, bas.height); g.fillRect(centre.x,centre.y,centre.width,centre.height); g.fillRect(obstacle.x,obstacle.y,obstacle.width,obstacle.height); g.fillRect(obstacle2.x,obstacle2.y,obstacle2.width,obstacle2.height); g.fillRect(obstacle3.x,obstacle3.y,obstacle3.width,obstacle3.height); g.fillRect(obstacle4.x,obstacle4.y,obstacle3.width,obstacle4.height); g.fillRect(obstacle5.x,obstacle5.y,obstacle5.width,obstacle5.height); //les lignes de dpart sont blanches g.setColor(Color.WHITE); //on dessine les lignes de dpart g.fillRect(ligne1.x,ligne1.y,ligne1.width,ligne1.height); g.fillRect(ligne2.x,ligne2.y,ligne2.width,ligne2.height); //la ligne darrive est jaune g.setColor(Color.YELLOW);

66

Devenez un petit gnie des jeux vido

//on dessine la ligne darrive g.fillRect(arrivee.x,arrivee.y,arrivee.width,arrivee.height); //image de titre au milieur de lcran g.drawImage(titre,centre.x+10,centre.y+80,this); //dessine le joueur 1 if(directionJ1==HAUT) g.drawImage(img5,j1.x,j1.y,this); if(directionJ1==GAUCHE) g.drawImage(img8,j1.x,j1.y,this); if(directionJ1==BAS) g.drawImage(img7,j1.x,j1.y,this); if(directionJ1==DROITE) g.drawImage(img6,j1.x,j1.y,this); //draw the images for p2 if(directionJ2==HAUT) g.drawImage(img1,j2.x,j2.y,this); if(directionJ2==GAUCHE) g.drawImage(img4,j2.x,j2.y,this); if(directionJ2==BAS) g.drawImage(img3,j2.x,j2.y,this); if(directionJ2==DROITE) g.drawImage(img2,j2.x,j2.y,this); } private class Mouvement1 extends Thread implements KeyListener { public void run() { //"rveille" le KeyListener addKeyListener(this); //tout ceci est dans une boucle infinie pour pouvoir rpter le processus while(true) { //tout le code est dans un bloc try pour sortir en cas derreur try { //rafrachit lcran repaint(); //gestion des collisions avec les murs extrieurs et lautre joueur //la vitesse est alors diminue -4 if(j1.intersects(gauche) || j1.intersects(droite) || j1.intersects(haut) || j1.intersects(bas) || j1.intersects(obstacle) || j1.intersects(obstacle2)|| j1.intersects(j2) || j1.intersects(obstacle3) || j1.intersects(obstacle4) || j1.intersects(obstacle5)) { vitesseJ1 = -4; } //si la voiture touche le centre, on diminue sa vitesse -2.5 if(j1.intersects(centre)) { vitesseJ1 = -2.5; } //nombre de tours: if(j1.intersects(arrivee)&&directionJ1==HAUT) { toursJ1++; }

Chapitre 2

Jeux de course

67

//3 tours complets correspondent un compte de tours denviron 24. //on utiliser un bloc if pour compter et lindiquer lutilisateur //si gagnantOK est false, le joueur a gagn, sinon il a perdu if(toursJ1>=24) { if(!gagnantOK) { gagnantOK = true; JOptionPane.showMessageDialog(null, "Le joueur 1 (bleu) a gagn!!!"); break; } else { JOptionPane.showMessageDialog(null, "Joueur 1: (bleu): PERDU! \n Joueur 2 (rouge): GAGN!"); break; } } //augmente la vitesse if(vitesseJ1<=5) vitesseJ1+=.2; //dplace le joueur en fonction de la direction if(directionJ1==HAUT) { j1.y-=(int)vitesseJ1; } if(directionJ1==BAS) { j1.y+=(int)vitesseJ1; } if(directionJ1==GAUCHE) { j1.x-=(int)vitesseJ1; } if(directionJ1==DROITE) { j1.x+=(int)vitesseJ1; } //diminue le taux de rafrachissement Thread.sleep(75); } catch(Exception e) { //sil y a une exception on sort de la boucle break; } } } //ncessaire pour le KeyListener public void keyPressed(KeyEvent event) { } //ncessaire pour le KeyListener public void keyReleased(KeyEvent event) { } //ncessaire pour le KeyListener public void keyTyped(KeyEvent event) { if(event.getKeyChar()==q) { directionJ1 = GAUCHE; }

68

Devenez un petit gnie des jeux vido

if(event.getKeyChar()==s) { directionJ1 = BAS; } if(event.getKeyChar()==d) { directionJ1 = DROITE; } if(event.getKeyChar()==z) { directionJ1 = HAUT; } } } private class Mouvement2 extends Thread implements KeyListener { public void run() { //"rveille" le KeyListener addKeyListener(this); //tout ceci est dans une boucle infinie pour pouvoir rpter le processus while(true) { //tout le code est dans un bloc try pour sortir en cas derreur try { //rafrachit lcran repaint(); //gestion des collisions avec les murs extrieurs et lautre joueur if(j2.intersects(gauche) || j2.intersects(droite) || j2.intersects(haut) || j2.intersects(bas) || j2.intersects(obstacle) ||j2.intersects(obstacle2) || j1.intersects(j2) || j1.intersects(obstacle3) || j1.intersects(obstacle4) || j1.intersects(obstacle5)) { vitesseJ2 = -4; } //si la voiture touche le centre, on diminue sa vitesse -2.5 if(j2.intersects(centre)) { vitesseJ2 = -2.5; } //nombre de tours if(j2.intersects(arrivee)&&directionJ2==HAUT) { toursJ2++; } //3 tours complets correspondent un compte de tours denviron 24. //on utiliser un bloc if pour compter et lindiquer lutilisateur //si gagnantOK est false, le joueur a gagn, sinon il a perdu if(toursJ2>=24) { if(!gagnantOK) { gagnantOK = true; JOptionPane.showMessageDialog(null, "Le joueur 2 (rouge) a gagn!!!"); break; } else { JOptionPane.showMessageDialog(null, "Joueur 1: (bleu): GAGN! \n Joueur 2 (rouge): PERDU!"); break; }

Chapitre 2

Jeux de course

69

} //augmente la vitesse if(vitesseJ2<=5) vitesseJ2+=.2; //dplace le joueur en fonction de la direction if(directionJ2==HAUT) { j2.y-=(int)vitesseJ2; } if(directionJ2==BAS) { j2.y+=(int)vitesseJ2; } if(directionJ2==GAUCHE) { j2.x-=(int)vitesseJ2; } if(directionJ2==DROITE) { j2.x+=(int)vitesseJ2; } //diminue le taux de rafrachissement Thread.sleep(75); } catch(Exception e) { //sil y a une exception on sort de la boucle break; } } } //ncessaire pour le KeyListener public void keyPressed(KeyEvent event) { } //ncessaire pour le KeyListener public void keyReleased(KeyEvent event) { } //ncessaire pour le KeyListener public void keyTyped(KeyEvent event) { if(event.getKeyChar()==j) { directionJ2 = GAUCHE; } if(event.getKeyChar()==k) { directionJ2 = BAS; } if(event.getKeyChar()==l) { directionJ2 = DROITE; } if(event.getKeyChar()==i) { directionJ2 = HAUT; } } } //dmarre le programme en appelant le constructeur public static void main(String[] args) { new Course(); } }

70

Devenez un petit gnie des jeux vido

Figure 9.4 cran de bienvenue

Figure 9.5 Les voitures sont sur le dpart !

Chapitre 2

Jeux de course

71

Figure 9.6 La voiture bleue a gagn !

72

Devenez un petit gnie des jeux vido

Projet 10 : Le skieur La piste


Le skieur La pente est glissante et vous avez quinze secondes pour descendre la montagne sur une piste que vous crez vous-mme. Si vous chouez, vous mourrez, mais si vous russissez, vous la gloire !
Projet Dans ce projet, vous allez crer un environnement de dessins de piste : la piste est-elle une pente douce, un -pic ou un terrain plein de bosses, de rochers et darbres ? Cest vous qui dcidez ! MouseListener, classes prfabriques.

Nouvelles briques

MouseListener
Nous avons dj vu comment programmer lordinateur pour quil rponde des saisies clavier de lutilisateur. Nous allons maintenant tudier comment voir o lutilisateur clique. Dans un KeyListener, il fallait ajouter trois mthodes, quelles soient utilises ou non. Le MouseListener rpond aux mmes principes, mais il y a cinq mthodes :
public public public public public void void void void void mouseClicked(MouseEvent e){} mouseEntered(MouseEvent e){} mouseExited(MouseEvent e){} mousePressed(MouseEvent e){} mouseReleased(MouseEvent e){}

Le skieur nutilise que les deux dernires mthodes. mousePressed indique o lutilisateur a appuy sur le bouton de la souris (le premier point de la piste). mouseReleased est utilis pour savoir o lutilisateur a relch le bouton, cest--dire o la piste sarrte. Ces mthodes ne servent certes pas grand-chose si vous ne savez pas rcuprer les coordonnes partir des clics des utilisateurs. Pour rcuprer la coordonne en X, on utilise :
e.getX();

On accde la coordonne Y avec :


e.getY();

Chapitre 2

Jeux de course

73

Classes prfabriques
Java fournit de nombreuses classes prfabriques que vous pouvez utiliser. LAPI Java est la liste complte des classes et leur description. On la trouve ladresse http:// java.sun.com/j2se/1.5.0/docs/api/ (cette documentation est en anglais). Nous allons utiliser deux classes prfabriques dans le skieur : Line2D.Double, contenant les informations relatives une ligne, et Point2D.Double, contenant les informations relatives un point (qui est la premire partie de la ligne). LAPI vous indique ce quil faut importer. La table "Constructor Summary" indique de plus comment crer la classe. Pour initialiser un Point2D.Double, il faut passer deux variables de type double au constructeur : les coordonnes x et y. La mthode mousePressed permet donc de crer le premier point de la ligne en crant un Point2D.Double. Il est alors possible de dnir une ligne grce la mthode mouseReleased en utilisant le point prcdent et le point o lutilisateur relche la souris. La ligne peut tre ajoute un ArrayList. Pour savoir quelles mthodes peuvent tre utilises avec une classe, crez une nouvelle instance de cette classe dans NetBeans. Si on prend pour exemple la classe Point2D.Double, faites cela ainsi :
Point2D.Double pnt = new Point2D.Double(23.5, 563.0).

Figure 10.1 Pop-up dans NetBeans

74

Devenez un petit gnie des jeux vido

Puis, tapez ceci :


pnt.

Lorsque vous tapez le point, NetBeans cre une liste de toutes les mthodes utilisables. La plupart sont claires, mais NetBeans offre une description pour les plus complexes. Cette description safche sous la forme dun pop-up, comme le montre la Figure 10.1.

Crer le jeu
Il est temps de crer la premire partie du skieur : lenvironnement de dessin de piste. Utilisez MouseListener et les classes Point2D.Double et Line2D.Double pour dessiner la piste de ski. Enregistrez les lignes dans un ArrayList et utilisez une boucle for pour afcher toutes les lignes de l ArrayList avec la mthode paint.
//importe ce quil faut import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.util.*; //la classe public class Skieur extends JFrame implements MouseListener { //enregistre les lignes ArrayList lignes = new ArrayList(); //enregistre le premier point de la ligne Point2D.Double point; //constructeur public Skieur() { //titre super("Le Skieur"); setSize(700,700); setVisible(true); setDefaultCloseOperation(JFrame. EXIT_ON_CLOSE); addMouseListener(this); } public void paint(Graphics g) { super.paint(g); //les lignes sont dessines en noir g.setColor(Color.black); //parcourt lArrayList et dessine toutes les lignes for(int i = 0; i <lignes.size(); i++)

Chapitre 2

Jeux de course

75

{ //rcupre la ligne Line2D.Double temp = (Line2D.Double) lignes.get(i); //rcupre les coordonnes int x1 = Integer.parseInt(""+Math.round (temp.getX1())); int y1 = Integer.parseInt(""+Math.round (temp.getY1())); int x2 = Integer.parseInt(""+Math.round (temp.getX2())); int y2 = Integer.parseInt(""+Math.round (temp.getY2())); g.drawLine(x1,y1,x2,y2); } } //mthode ncessaire MouseListener public void mouseClicked(MouseEvent e){} //mthode ncessaire MouseListener public void mouseEntered(MouseEvent e){} //mthode ncessaire MouseListener public void mouseExited(MouseEvent e){} //mthode ncessaire MouseListener public void mousePressed(MouseEvent e) { //excut lorsquon appuie sur le bouton de la souris //rcupre le premier point de la ligne point = new Point2D.Double(e.getX(),e.getY()); } //mthode ncessaire MouseListener public void mouseReleased(MouseEvent e) { //excut lorsquon relche le bouton de la souris //termine la ligne et lajoute lArrayList Point2D.Double fin = new Point2D.Double(e.getX(),e.getY()); lignes.add(new Line2D.Double(point,fin)); //rafrachit lcran pour dessiner la ligne repaint(); } public static void main (String[] args) { //lance le programme new Skieur(); } }

La Figure 10.2 illustre le dessin de plusieurs lignes dans linterface du skieur. Nhsitez pas faire preuve dimagination. Dans le chapitre suivant, nous allons crer un skieur pour dvaler les pentes que vous dessinez.

76

Devenez un petit gnie des jeux vido

Figure 10.2 Des lignes connectes pour crer la piste

Chapitre 2

Jeux de course

77

Projet 11 : Le skieur Piste verte


Projet Crez une silhouette pour skier le long de la piste dessine par le joueur.

Crer le jeu
Gnrez dabord limage et le Rectangle reprsentant le skieur. Pour que celui-ci descende le long de la piste, initialisez un Thread pour contrler le mouvement du joueur. Dans le Thread, crez une mthode qui dnit la position initiale du skieur (au-dessus et lgrement la droite du premier point de la premire ligne) comme le montre la Figure 11.1.
Figure 11.1 Point de dpart

Appelez cette mthode dans run avant la boucle while. Crez aussi une autre mthode dont largument est un boolen qui peut arrter la boucle while. Dans la boucle while, vriez si le Rectangle du skieur touche une des lignes (grce la mthode intersects). Pour contrler les mouvements x et y du skieur, crez deux variables globales de type double, vitesse et gravite. Si le skieur nest pas sur la ligne, augmentez la variable gravite. Sil est sur la ligne, calculez la diffrence entre les deux points de la ligne et divisez par 50 sur laxe y et par 100 sur laxe x. Ajoutez ces valeurs, respectivement aux variables gravite et vitesse. Noubliez pas de rafrachir lcran et dajouter un petit dlai avant de repasser dans la boucle. lextrieur du Thread, utilisez KeyListener pour dtecter des appuis sur l (lancer) ou sur q (quitter). Si lutilisateur appuie sur l, lancez la boucle. Si lutilisateur appuie sur q, terminez la boucle.

78

Devenez un petit gnie des jeux vido

//on importe le ncessaire import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.util.*; import java.io.*; import java.net.*; //la classe public class Skieur extends JFrame implements MouseListener, KeyListener { //lignes de la piste ArrayList lignes = new ArrayList(); //premier point de la ligne Point2D.Double point; //fil dexecution Mouvement mouvement; //informations gomtriques sur le skieur Rectangle skieur = null; //dessin ou non du skieur boolean dessineSkieur = false; //constructeur public Skieur() { //titre super("Le Skieur"); setSize(700,700); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); addMouseListener(this); addKeyListener(this); } public void paint(Graphics g) { super.paint(g); //les lignes sont dessines en noir g.setColor(Color.black); //boucle dans toutes les lignes de lArrayList et les dessine for(int i = 0; i <lignes.size(); i++) { //rcupre la ligne dans lArrayList Line2D.Double temp = (Line2D.Double) lignes.get(i); //rcupre les coordonnes int x1 = Integer.parseInt(""+Math.round(temp.getX1())); int y1 = Integer.parseInt(""+Math.round(temp.getY1())); int x2 = Integer.parseInt(""+Math.round(temp.getX2())); int y2 = Integer.parseInt(""+Math.round(temp.getY2())); g.drawLine(x1,y1,x2,y2); } if(dessineSkieur) { try { //dessine le skieur URL url = this.getClass().getResource("skieur.png");

Chapitre 2

Jeux de course

79

Image img = Toolkit.getDefaultToolkit().getImage(url); g.drawImage(img, skieur.x, skieur.y, this); } catch(Exception e){} } } //mthode ncessaire MouseListener public void mouseClicked(MouseEvent e){} //mthode ncessaire MouseListener public void mouseEntered(MouseEvent e){} //mthode ncessaire MouseListener public void mouseExited(MouseEvent e){} //mthode ncessaire MouseListener public void mousePressed(MouseEvent e) { //excut lorsquon appuie sur le bouton de la souris //indique le premier point de la ligne point = new Point2D.Double(e.getX(),e.getY()); } //mthode ncessaire MouseListener public void mouseReleased(MouseEvent e) { //excut lorsquon relche le bouton de la souris //termine la ligne et lajoute lArrayList Point2D.Double fin = new Point2D.Double(e.getX(),e.getY()); lignes.add(new Line2D.Double(point, fin)); //rafrachit lcran pour dessiner la ligne repaint(); } //mthode ncessaire KeyListener public void keyPressed(KeyEvent e){} //mthode ncessaire KeyListener public void keyReleased(KeyEvent e){} //mthode ncessaire KeyListener public void keyTyped(KeyEvent e) { //si lutilisateur appuie sur "l" ou sur "L", dmarre le Thread if(e.getKeyChar()==l || e.getKeyChar()==L) { //initialisation du Thread mouvement = new Mouvement(); mouvement.start(); mouvement.action(true); } //si lutilisateur appuie sur "q" ou sur "Q", arrte le Thread if(e.getKeyChar()==q || e.getKeyChar()==Q) { mouvement.action(false); dessineSkieur = false; mouvement = null; } } //fil dexcution du mouvement du joueur private class Mouvement extends Thread { //vitesse et gravit du joueur double vitesse; double gravite;

80

Devenez un petit gnie des jeux vido

//dmarre et arrte le fil dexcution boolean go = false; public void run() { if(go) { initSkieur(); vitesse = 0; gravite = 1; } while(go) { try { //ligne sur laquelle se trouve le skieur (ou null si aucune ligne) Line2D.Double ligneSkieur = null; //skieur sur la ligne ou non boolean surLigne = false; //il faut rinitialiser la gravit lorsque le skieur atterit sur la ligne //contient cette information et le numro de la ligne int numeroLigne = -1; //vrifie si le skieur est sur une ligne for(int i = lignes.size()-1; i>=0; i--) { //rcupre la ligne Line2D.Double temp = (Line2D.Double) lignes.get(i); if(temp.intersects(skieur.x,skieur.y,30,30)) { ligneSkieur = temp; surLigne = true; if(numeroLigne!=i) { numeroLigne = i; gravite = 0; } break; } } //si le skieur est sur une ligne if(surLigne) { //rcupre la nouvelle gravit en soustrayant les y et en divisant par 50 double mGrav = (ligneSkieur.y2-ligneSkieur.y1)/50; //rcupre la nouvelle vitesse en soustrayant les x et en divisant par 100 double mVit = (ligneSkieur.x2-ligneSkieur.x1)/100; //gestion des valeurs maximales if(vitesse<5) vitesse+=mVit; if(gravite<2.5) gravite+=mGrav; } else { gravite+=.2; } //modifie le mouvement du skieur skieur.x += vitesse; skieur.y += gravite; //ralentit le taux de rafrachissement Thread.sleep(75); //rafrachit repaint();

Chapitre 2

Jeux de course

81

} catch(Exception e){ break; } } } public void action(boolean a) { //arrte le fil dexcution go = a; } public void initSkieur() { /* * dfinit la position de dpart du skieur */ //rcupre la premire ligne Line2D.Double premiereLigne = (Line2D.Double) lignes.get(0); //rcupre le x et le y du premier point de cette ligne int x = Integer.parseInt(""+Math.round(premiereLigne.x1)); int y = Integer.parseInt(""+Math.round(premiereLigne.y1)); skieur = new Rectangle(x+30,y-20,30,30); dessineSkieur = true; } } public static void main(String[] args) { //lance le programme new Skieur(); } }

Les Figures 11.2 11.4 reprsentent la progression du skieur sur la piste dessine.
Figure 11.2 Dpart du skieur

82

Devenez un petit gnie des jeux vido

Figure 11.3 Le skieur est sur la piste

Figure 11.4 Le skieur est tomb !

Chapitre 2

Jeux de course

83

Projet 12 : Le skieur La comptition


Projet Modiez le but du jeu : faire en sorte que le skieur termine sa descente en exactement quinze secondes. Ajoutez aussi des effets sonores pour que le skieur hurle lorsquil chute.

Crer le jeu
Crez dabord un compteur pour chronomtrer la course du skieur grce une variable chrono. Puis, initialisez un nouveau l dexcution (Thread) nomm Chrono. Dans la mthode run, ajoutez une boucle while. Dans cette boucle, passez une pause dune seconde et incrmentez chrono de 1. La Figure 12.1 illustre une manire amusante dafcher le chronomtre.
Figure 12.1 Afchage du chronomtre

Le chronomtre ne doit tre lanc que lorsque le skieur est en mouvement. Il faut donc ajouter, dans les KeyListener qui dmarrent et qui arrtent la course du skieur, du code pour dmarrer ou arrter la boucle while du compteur en modiant un boolen du Thread. Pour dessiner du texte, on utilise la mthode g.drawString("texte", x, y).

84

Devenez un petit gnie des jeux vido

On peut aussi dnir la police du texte au pralable avec la mthode g.setFont(new Font()). Pour indiquer la police, reportez-vous aux constructeurs de la classe Font de lAPI. Pour vrier si un joueur a pass la ligne darrive, crez un boolen nomm vivant. Dans le l dexcution contrlant le mouvement, vriez si la coordonne y est suprieure 600 (une centaine de pixels avant le bord de la fentre). Si cest le cas, il sest cras. Vous pouvez si vous le dsirez modier licne et ajouter des effets sonores (enregistrez vos propres hurlements !). Lorsque le joueur scrase, appelez une mthode pour comparer le temps quinze secondes. Vivant ou mort, si la descente de la piste est termine en exactement quinze secondes, le joueur gagne. Noubliez pas darrter le chronomtre et dafcher le temps nal la n de la course. Pour cela, crez une variable appele tempsFinal.
//on importe le ncessaire import java.applet.AudioClip; import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.util.*; import java.io.*; import java.net.*; //la classe public class Skieur extends JFrame implements MouseListener, KeyListener { //lignes de la piste ArrayList lignes = new ArrayList(); //premier point de la ligne Point2D.Double point; //fils dexcution Mouvement mouvement; Compteur compt; //informations gomtriques sur le skieur Rectangle skieur = null; //dessin ou non du skieur boolean dessineSkieur = false; //compteur int compteur; //le son a-t-il t jou? boolean sonJoue = false; //temps final int tempsFinal = 0;

Chapitre 2

Jeux de course

85

//utiliser la valeur retenue boolean utiliseTemps = false; //si le skieur arrive en bas, on change son icne boolean vivant = true; //constructeur public Skieur() { //titre super("Le Skieur"); setSize(700,700); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); addMouseListener(this); addKeyListener(this); compt = new Compteur(); compt.parti = false; compt.run(); } public void paint(Graphics g) { super.paint(g); //les lignes sont dessines en noir g.setColor(Color.black); //boucle dans toutes les lignes de lArrayList et les dessine for(int i = 0; i <lignes.size(); i++) { //rcupre la ligne dans lArrayList Line2D.Double temp = (Line2D.Double) lignes.get(i); //rcupre les coordonnes int x1 = Integer.parseInt(""+Math.round(temp.getX1())); int y1 = Integer.parseInt(""+Math.round(temp.getY1())); int x2 = Integer.parseInt(""+Math.round(temp.getX2())); int y2 = Integer.parseInt(""+Math.round(temp.getY2())); g.drawLine(x1,y1,x2,y2); } if(dessineSkieur) { try { //draw the time: g.setFont(new Font("times new roman", Font.BOLD, 16)); URL urlTemps = this.getClass().getResource("temps.png"); Image imgT = Toolkit.getDefaultToolkit(). getImage(urlTemps); g.drawImage(imgT, -35, 10, this); if(!utiliseTemps) g.drawString("Chrono courant: "+compteur+" "+skieur.x, 50, 50); else g.drawString("Chrono courant: "+tempsFinal, 50, 50); //draw the guy: if(vivant) { URL url = this.getClass().getResource("skieur.png"); Image img = Toolkit.getDefaultToolkit(). getImage(url); g.drawImage(img, skieur.x, skieur.y, this); } else { URL url = this.getClass().getResource("skieurMort.png"); Image img = Toolkit.getDefaultToolkit().getImage(url);

86

Devenez un petit gnie des jeux vido

g.drawImage(img, skieur.x, skieur.y, this); //si le son na pas encore t jou, on le joueif the snd hasnt been played, play it! if(!sonJoue) { //temps final tempsFinal = compteur; utiliseTemps = true; //joue le son URL son = this.getClass().getResource("hurlement.wav"); AudioClip hurlement = JApplet.newAudioClip(son); hurlement.play(); sonJoue = true; //regarde si le joueur a gagn verifieVictoire(); } } } catch(Exception e){} } } //mthode ncessaire MouseListener public void mouseClicked(MouseEvent e){} //mthode ncessaire MouseListener public void mouseEntered(MouseEvent e){} //mthode ncessaire MouseListener public void mouseExited(MouseEvent e){} //mthode ncessaire MouseListener public void mousePressed(MouseEvent e) { //excut lorsquon appuie sur le bouton de la souris //indique le premier point de la ligne point = new Point2D.Double(e.getX(),e.getY()); } //mthode ncessaire MouseListener public void mouseReleased(MouseEvent e) { //excut lorsquon relche le bouton de la souris //termine la ligne et lajoute lArrayList Point2D.Double fin = new Point2D.Double(e.getX(),e.getY()); lignes.add(new Line2D.Double(point, fin)); //rafrachit lcran pour dessiner la ligne repaint(); } //mthode ncessaire KeyListener public void keyPressed(KeyEvent e){} //mthode ncessaire KeyListener public void keyReleased(KeyEvent e){} //mthode ncessaire KeyListener public void keyTyped(KeyEvent e) { //si lutilisateur appuie sur "l" ou sur "L", dmarre le Thread if(e.getKeyChar()==l || e.getKeyChar()==L) { //initialisation du Thread mouvement = new Mouvement(); mouvement.start(); mouvement.action(true);

Chapitre 2

Jeux de course

87

compt.parti = true; vivant = true; compteur = 0; utiliseTemps = false; sonJoue = false; } //si lutilisateur appuie sur "q" ou sur "Q", arrte le Thread if(e.getKeyChar()==q || e.getKeyChar()==Q) { mouvement.action(false); dessineSkieur = false; mouvement = null; compt.parti = false; } } //fil dexcution du mouvement du joueur private class Mouvement extends Thread { //vitesse et gravit du joueur double vitesse; double gravite; //dmarre et arrte le fil dexcution boolean go = false; public void run() { if(go) { initSkieur(); vitesse = 0; gravite = 1; } while(go) { try { //ligne sur laquelle se trouve le skieur (ou null si aucune ligne) Line2D.Double ligneSkieur = null; //skieur sur la ligne ou non boolean surLigne = false; //il faut rinitialiser la gravit lorsque le skieur atterrit sur la ligne //contient cette information et le numro de la ligne int numeroLigne = -1; //vrifie si le skieur est sur une ligne for(int i = lignes.size()-1; i>=0; i--) { //rcupre la ligne Line2D.Double temp = (Line2D.Double) lignes.get(i); if(temp.intersects(skieur.x,skieur.y,30,30)) { ligneSkieur = temp; surLigne = true; if(numeroLigne!=i) { numeroLigne = i; gravite = 0; } break; } }

88

Devenez un petit gnie des jeux vido

//si le skieur est sur une ligne if(surLigne) { //rcupre la nouvelle gravit en soustrayant les y et en divisant par 50 double mGrav = (ligneSkieur.y2-ligneSkieur.y1)/50; //rcupre la nouvelle vitesse en soustrayant les x et en divisant par 100 double mVit = (ligneSkieur.x2-ligneSkieur.x1)/100; //gestion des valeurs maximales if(vitesse<5) vitesse+=mVit; if(gravite<2.5) gravite+=mGrav; } else { gravite+=.2; } //modifie le mouvement du skieur skieur.x += vitesse; skieur.y += gravite; //regarde si le skieur est encore vivant if(skieur.y > 650){ vivant = false; } //ralentit le taux de rafrachissement Thread.sleep(75); //rafrachit repaint(); } catch(Exception e){ break; } } } public void action(boolean a) { //arrte le fil dexcution go = a; } public void initSkieur() { /* * dfinit la position de dpart du skieur */ //rcupre la premire ligne Line2D.Double premiereLigne = (Line2D.Double) lignes.get(0); //rcupre le x et le y du premier point de cette ligne int x = Integer.parseInt(""+Math.round(premiereLigne.x1)); int y = Integer.parseInt(""+Math.round(premiereLigne.y1)); skieur = new Rectangle(x+30,y-20,30,30); dessineSkieur = true; } } private class Compteur extends Thread { public boolean parti = true; public void run() { try { while(true) {

Chapitre 2

Jeux de course

89

if(parti) { Thread.sleep(1000); compteur++; } } } catch(Exception e){} } } //regarde si le but est atteint public void verifieVictoire() { if(tempsFinal==15) { JOptionPane.showMessageDialog(null, "Flicitations!\n\n" + "MISSION ACCOMPLIE!"); } }

public static void main(String[] args) { //lance le programme new Skieur(); } }

La Figure 12.2 illustre la n du jeu.


Figure 12.2 Fin du jeu

3
Jeux de plateau
Au sommaire de ce chapitre :

La chasse aux mauvais gnies


Projet 13 : Le laboratoire Projet 14 : Attrapez-les vite ! Projet 15 : Plus intelligent...

Le morpion boxeur

Projet 16 : Le ring Projet 17 : Combat ! Projet 18 : K.-O. !

92

Devenez un petit gnie des jeux vido

Projet 13 : La chasse aux mauvais gnies Le laboratoire


La chasse aux mauvais gnies Un mauvais gnie se cache dans son laboratoire avant de semer la panique sur le monde. Comme il craint le soleil et lair frais, il ne sort que brivement. Lorsquil sort, vous devez le frapper avec un clic de souris pour quil rentre dans son laboratoire souterrain. Le problme ? Il narrte pas de se cloner.
Projet Nouvelles briques Crez dabord le laboratoire. Composants, JButton, JLabel.

Composants
Un composant est un lment qui peut tre ajout tout programme Java pour augmenter ses fonctionnalits. Les composants classiques incluent des boutons, des champs de texte et des libells. Cependant, avant dajouter des composants, vous aurez besoin dun endroit pour les y mettre. Cet endroit sappelle un Container (conteneur). Pour crer un conteneur, ajoutez la ligne suivante dans votre constructeur aprs avoir cr un JFrame :
Container <nomVariable> = getContentPane();

<nomVariable> est une variable et son nom est arbitraire.


Aprs cette ligne, vous devez indiquer comment ajouter les composants. Il y a de nombreuses manires de les disposer : en grille, sur les cts, lun aprs lautre, etc. Dans ce livre, nous nous focaliserons sur une disposition de type FlowLayout (disposition en ux) qui place les composants les uns aprs les autres. Cette disposition est la plus simple coder et la plus simple comprendre. Pour que votre conteneur ait une disposition en ux, utilisez cette ligne :
cont.setLayout(new FlowLayout());

Avant de commencer crer des composants, il reste une dernire chose faire : la dernire ligne du constructeur doit contenir ceci :
setContentPane(cont);

Chapitre 3

Jeux de plateau

93

cont doit tre remplac par le nom de votre conteneur. Cette ligne sassure que le JFrame afche tous les composants que vous avez ajouts.

JButton
Un bouton est une zone sur laquelle on peut cliquer. En Java, les boutons sont appels JButton. Un bouton simple est illustr la Figure 13.1.
Figure 13.1 Un JButton

Lorsque vous crez des JButton, il vaut mieux les crer de manire globale (en dehors du constructeur, mais dans la classe). Ainsi, il est plus simple de modier leur texte nimporte o dans le programme. Pour crer un JButton, utilisez la ligne suivante :
JButton <nomVariable> = new JButton("Texte");

<nomDeVariable> est arbitraire, il sagit dune variable. "Texte" est le texte afch dans le JButton. Pour afcher une image la place dun texte, utilisez le code suivant :
ImageIcon <nomImage> = new ImageIcon("chemin avec extension"); JButton <nomVariable> = new JButton(<nomImage>);

<nomImage> et <varName> sont des noms de variables et sont donc arbitraires. "chemin avec extension" est le chemin du chier. Celui-ci est relatif au rpertoire dans lequel se trouve le projet Java et non, comme prcdemment, la classe compile. La Figure 13.2 illustre un bouton avec une image.
Pour ajouter un JButton au conteneur (en supposant que le nom du conteneur soit cont et que celui du bouton soit bouton), ajoutez cette ligne :
cont.add(bouton);

94

Devenez un petit gnie des jeux vido

Figure 13.2 Un JButton avec un ImageIcon

Les objets de type JButton ont, entre autres, de nombreuses mthodes pour dsactiver, activer et modier leurs icnes. Une liste de ces mthodes est fournie dans lAPI. Pour ce jeu, nous devons parler de la mthode setEnabled(). Celle-ci prend en argument un boolen. Si le bouton sappelle bouton, le code suivant le dsactive :
bouton.setEnabled(false);

Et le code suivant lactive :


bouton.setEnabled(true);

JLabel
Un JLabel est un composant dun autre type. Il permet dafcher du texte dans un JFrame. La Figure 13.3 illustre un JLabel.
Figure 13.3 Un JLabel

On cre un JLabel avec cette ligne :


JLabel <nomVariable> = new JLabel("texte");

Chapitre 3

Jeux de plateau

95

Comme les JButton, les JLabel peuvent tre ajouts un JFrame avec une ligne de ce type (si le conteneur sappelle cont) :
cont.add(<nomVariable>);

Les JLabel peuvent galement, comme les JButton, contenir une image. Le code utilis est presque identique :
ImageIcon image = new ImageIcon("chemin avec extension"); JLabel libelle = new JLabel(image);

Lorsquon utilise des JLabels, il est souvent pratique de pouvoir modier leur texte. On peut modier le texte grce la mthode setText(), prenant un String en argument. Par exemple, si votre JLabel sappelle libelle :
libelle.setText("Ceci est le nouveau texte.");

Crer le jeu
Crez un JFrame. Ajoutez-y un conteneur. Puis, crez un tableau 5 5 de JButton, utilisez des boucles for pour initialiser les JButton du tableau et ajoutez-les au conteneur. Ajoutez des images dun mauvais gnie aux boutons et dsactivez tous les boutons. Pour nir, crez et ajoutez un JLabel pour le score (pour linstant, il afchera juste "SCORE :").
import import import import javax.swing.event.*; javax.swing.*; java.awt.*; java.awt.event.*;

public class ChasseAuxGenies extends JFrame { //ce tableau contient les 25 JButton JButton[][] boutons = new JButton[5][5]; //icone affiche lorsque le mauvais gnie sort de son laboratoire ImageIcon vivant = new ImageIcon("vivant.gif"); //JLabel du score JLabel score = new JLabel("SCORE : "); //constructeur public ChasseAuxGenies(){ //cre le JFrame super("Chasse aux mauvais gnies"); setSize(350,325); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //contient les boutons et libells

96

Devenez un petit gnie des jeux vido

Container cont = getContentPane(); cont.setLayout(new FlowLayout()); //prpare laffichage des boutons for(int i = 0; i < boutons.length; i++ ) { for(int j = 0; j < boutons[0].length; j++ ) { //cre le JButton System.out.println(vivant); boutons[i][j] = new JButton(vivant); //ajoute le bouton au JFrame cont.add(boutons[i][j]); //dsactive le bouton boutons[i][j].setEnabled(false); } } //affichage du score score.setText("SCORE : "); cont.add(score); setContentPane(cont); } public static void main (String[] args) { //dmarre le jeu new ChasseAuxGenies(); } }

Figure 13.4 Le jeu cette tape du dveloppement

La Figure 13.4 illustre la premire partie du dveloppement de la chasse aux mauvais gnies. Dans le prochain projet, nous verrons comment rendre le jeu oprationnel en dterminant si le joueur a appuy sur un JButton.

Chapitre 3

Jeux de plateau

97

Projet 14 : La chasse aux mauvais gnies Attrapez-les vite !


Projet Le jeu prend forme. Le visage du mauvais gnie apparat. Mais ne craignez rien, vous allez pouvoir le renvoyer dans sa tanire en ajoutant des interactions avec lutilisateur. ActionListener .

Nouvelles briques

ActionListener
Un ActionListener ragit aux actions. Dans notre cas, une action est un clic dun joueur sur un bouton. Il faut ajouter un ActionListener tous les boutons que vous dsirez surveiller. Dans la chasse aux mauvais gnies, il faut que tous les boutons aient un ActionListener. Pour cela, si votre JButton sappelle bouton, il faut utiliser la ligne suivante :
button.addActionListener(this);

Lorsque vous utilisez des ActionListener, il faut ajouter implements ActionListener la dclaration de la classe. Si vous implmentez dj KeyListener ou MouseListener, vous pouvez implmenter les deux interfaces en les sparant par des virgules. Un KeyListener a de nombreuses mthodes obligatoires. Un ActionListener nen na quune. Lorsquon appuie sur un bouton, Java va dans cette mthode. Voici comment elle doit tre dclare :
public void actionPerformed (ActionEvent event) { }

Pour savoir quel bouton a t actionn, il suft de placer la condition suivante dans une instruction if :
event.getSource() == <nom du bouton>

Je vous avais suggr dutiliser des variables globales pour vos boutons, en voil la raison. Vous devez vous rfrer au nom du bouton pour savoir sur lequel lutilisateur a cliqu.

Crer le jeu
Ajoutez dabord des ActionListener tous les boutons du tableau. Puis, implmentez ActionListener et ajoutez la mthode obligatoire.

98

Devenez un petit gnie des jeux vido

Crez alors un nouveau l dexcution (Thread). Dans sa boucle while innie, faites attendre le programme pendant une dure alatoire (entre 0 et 1 500 millisecondes). Faites apparatre un mauvais gnie (en activant son bouton). Attendez 1 000 millisecondes et dsactivez le bouton. Dans la mthode actionPerformed, lorsque le joueur clique sur un bouton, incrmentez le compteur qui garde en mmoire le score et mettez les deux ls dexcution en pause pour un quart de seconde (pour laisser au joueur le temps de reprendre son soufe). Vous pouvez ensuite afcher le score dans le JLabel.
import javax.swing.event.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class ChasseAuxGenies extends JFrame implements ActionListener { //ce tableau contient les 25 mauvais gnies JButton[][] boutons = new JButton[5][5]; //affiche le score JLabel lblScore = new JLabel(); //le score double score = 0; //icone du mauvais gnie ImageIcon vivant = new ImageIcon("vivant.gif"); //fil dexcution du jeu T jeu = null; //constructeur public ChasseAuxGenies() { //Cre le JFrame super("Chasse aux mauvais gnies"); setSize(350,325); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //contient les boutons et libells Container cont = getContentPane(); cont.setLayout(new FlowLayout()); //prpare les boutons afficher for(int i = 0; i < boutons.length; i++ ) { for(int j = 0; j < boutons[0].length; j++ ) { //cre le JButton boutons[i][j] = new JButton(vivant); //ajoute le bouton au JFrame cont.add(boutons[i][j]); //dsactive le bouton boutons[i][j].setEnabled(false); //le bouton rpond aux clics boutons[i][j].addActionListener(this); } }

Chapitre 3

Jeux de plateau

99

cont.add(lblScore); setContentPane(cont); //dmarre le fil dexcution jeu = new T(); jeu.start(); setContentPane(cont); } //fil dexcution private class T extends Thread { public void run() { //boucle infinie while(true) { //cre une dure alatoire entre 0 et 1.5 secondes int pause = (int)(Math.random()*1500); try { //pause de la dure alatoire Thread.sleep(pause); } catch(Exception e) { } //un gnie alatoire apparat int genie = (int)(Math.random()*5); int genie2 = (int)(Math.random()*5); //fait sortir le gnie en activant le bouton boutons[genie][genie2].setEnabled(true); try { //pause pour laisser le temps au joueur dattraper le gnie Thread.sleep(1000); } catch(Exception e) { } //fait disparatre le gnie boutons[genie][genie2].setEnabled(false); //affiche le score lblScore.setText("SCORE: "+score); } } } //surveille les clics sur les boutons public void actionPerformed(ActionEvent e) { //augmente le score score++ ; //met le jeu en pause pour une demi-seconde try { jeu.sleep(500); Thread.sleep(500); } catch(Exception ex) { } }

100

Devenez un petit gnie des jeux vido

public static void main(String[ ] args) { //dmarre le jeu new ChasseAuxGenies(); } }

La Figure 14.1 illustre la chasse aux mauvais gnies.


Figure 14.1 Vite, attrapez-le !

Continuez votre lecture pour savoir comment augmenter le niveau de difcult au fur et mesure que le joueur touche des mauvais gnies. Attention, les gnies peuvent devenir difciles attraper, ils apprennent de leurs erreurs... Aprs tout, ce sont des mauvais gnies !

Chapitre 3

Jeux de plateau

101

Projet 15 : La chasse aux mauvais gnies Plus intelligent...


Projet Dans ce projet, la tension augmente, le mauvais gnie apparat de plus en plus vite... Tourmentez vos joueurs et apprenez contrler les niveaux de difcult.

Crer le jeu
Lorsque la difcult des jeux naugmente pas, ceux-ci deviennent vite ennuyeux. Pour linstant, la chasse aux mauvais gnies est congure un niveau moyen. Pour rgler ce problme, demandez dabord au joueur combien de chances il dsire avoir pour attraper le mauvais gnie. Puis, crez une variable pour compter les tentatives. Au dbut de la boucle while du l dexcution, incrmentez le compteur. Afchez un message contenant le nombre de coups russis, multipli par 10 000 et divis par le nombre de chances. Ce message termine le jeu. La Figure 15.3 illustre un exemple de bote de dialogue. Ensuite, ajoutez un entier nomm maxPause. Lorsquun mauvais gnie est attrap, soustrayez 100 cette valeur. Puis, crez un entier alatoire sur la base de ce nombre :
int apparition = (int) (Math.random() * maxPause);

Utilisez ce nouveau nombre comme temps pendant lequel le mauvais gnie apparat. Ainsi, plus vous vous amliorez, plus le jeu devient difcile.
import javax.swing.event.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class ChasseAuxGenies extends JFrame implements ActionListener { //ce tableau contient les 25 mauvais gnies JButton[][] boutons = new JButton[5][5]; //affiche ltat du jeu JLabel score = new JLabel(); //variables pour garder trace du score int maxPause = 1000; double coups = 0; double tours = 0; double toursMax = 0; //icone qui apparat lorsque le gnie sort de son laboratoire ImageIcon vivant = new ImageIcon("vivant.gif"); //fil dexcution T jeu = null;

102

Devenez un petit gnie des jeux vido

//constructeur public ChasseAuxGenies() { //cre le JFrame super("Chasse aux mauvais gnies"); setSize(350,325); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //contient le nombre de tours que lutilisateur joue toursMax = Double.parseDouble (JOptionPane.showInputDialog ("Combien de chances voulez-vous avoir dattraper un mauvais gnie ?")); //contient les boutons et libells Container cont = getContentPane(); cont.setLayout(new FlowLayout()); //prpare les boutons afficher for(int i = 0; i < boutons.length; i ++ ) { for(int j = 0; j < boutons[0].length; j++ ) { //cre le JButton boutons[i][j] = new JButton(vivant); //lajoute au JFrame cont.add(boutons[i][j]); //dsactive le bouton boutons[i][j].setEnabled(false); //le bouton rpond aux clics boutons[i][j].addActionListener(this); } } //le JLabel affiche le score score.setText("Tour "+tours+"/"+toursMax+". Score actuel :"+ ((int)((coups/toursMax)*100))); cont.add(score); setContentPane(cont); //dmarre le fil dexcution jeu = new T(); jeu.start(); } //fil dexcution private class T extends Thread { public void run() { //boucle infinie while(true) { //regarde si le jeu est termin if(tours>=toursMax) { //si le jeu est termin, affiche le score JOptionPane.showMessageDialog(null, "Le jeu est termin.\n\n"+"Vous avez attrap "+ coups+" mauvais gnies en "+tours+" tours.\n"+"Votre score est "+ ((int)(((coups*10000)/tours))), "Fin du jeu", JOptionPane.INFORMATION_MESSAGE); break; }

Chapitre 3

Jeux de plateau

103

//compte le nombre de tours tours++; //cre une dure alatoire entre 0 et 1.5 secondes int pause = (int)(Math.random()*1500); try { //pause de la dure alatoire Thread.sleep(pause); } catch(Exception e) { } //fait apparatre un gnie alatoire int genie = (int)(Math.random()*5); int genie2 = (int)(Math.random()*5); //fait sortir le gnie en activant le bouton boutons[genie][genie2].setEnabled(true); int apparition = (int) (Math.random() * maxPause); try { //pause pour laisser au joueur le temps dattraper le gnie Thread.sleep(apparition); } catch(Exception e) { } //fait disparatre le gnie boutons[genie][genie2].setEnabled(false); //affiche les statistiques score.setText("Tour "+tours+"/"+toursMax+ ". Score actuel : "+ ((int)(((coups*10000)/toursMax)))); } } } //surveille les clics de boutons public void actionPerformed(ActionEvent e) { //si un gnie a t attrap //diminue le temps daffichage des gnies //pour rendre le jeu plus difficile maxPause-=100; //augmente le score coups++ ; //met le jeu en pause pour une demi-seconde try { jeu.sleep(500); Thread.sleep(500); } catch(Exception ex) { } } public static void main(String[ ] args) { //dmarre le jeu new ChasseAuxGenies(); } }

104

Devenez un petit gnie des jeux vido

Les Figures 15.1 15.3 illustrent le jeu la chasse aux mauvais gnies.
Figure 15.1 Choisissez le nombre de tours

Figure 15.2 Attrapez-les !

Figure 15.3 Le jeu est termin, le score est afch.

Pour aller plus loin...


Ajoutez de la musique, des applaudissements, des cris de dception, du tonnerre, des explosions ou tout son pouvant augmenter lintensit du jeu. Vous pouvez aussi ajouter des images supplmentaires, modier la taille de la grille ou crer une liste de records de scores. Vous pouvez aussi faire apparatre de temps autre un personnage innocent si vous le frappez, vous avez perdu !

Chapitre 3

Jeux de plateau

105

Projet 16 : Le morpion boxeur Le ring


Le morpion boxeur Le jeu classique du morpion est transform en un match de boxe dans lequel chaque combattant est reprsent par une image diffrente de gants de boxe. Ajoutez des sons de coups, des gmissements ou des railleries pour der vos adversaires (ou lordinateur) et gagner, perdre ou faire match nul.
Projet Nouvelles briques Dessinez dabord le ring avant de pouvoir enler vos gants et commencer vous battre ! NullLayout.

NullLayout
Plutt que dutiliser une disposition de type FlowLayout, qui place les composants lun aprs lautre, vous pouvez utiliser une disposition vide ( null) qui vous permet dindiquer lemplacement des composants en coordonnes de pixels. Pour cela, modiez la ligne setLayout :
cont.setLayout(null);

Vous pouvez ajouter des composants de la mme manire quavec la disposition de type FlowLayout. Pour indiquer lemplacement dun composant, utilisez cette ligne :
<composant>.setBounds(<x>, <y>, <largeur>, <hauteur>);

<composant> est la variable reprsentant le composant. <x> et <y> sont les coordonnes du point suprieur gauche du composant. <largeur> et <hauteur> sont les dimensions souhaites du composant.
Avant que vous ne commenciez crer des jeux et ajouter des composants en vous basant sur leur emplacement en pixels, je prfre vous avertir : la disposition vide nest pas des plus ables. Il se peut que votre cran ne se rafrachisse pas et que vos modications ne soient pas prises en compte. Cependant, ne vous inquitez pas : il existe une manire simple de rafrachir lcran de manire ce que vos modications soient systmatiquement prises en compte. Une fois que vous avez ajout tous les composants dsirs au conteneur, ajoutez simplement la ligne :
cont.repaint();

106

Devenez un petit gnie des jeux vido

Crer le jeu
Dclarez dabord un tableau de neuf lments JButton pour contenir le plateau de jeu. Ajoutez les boutons du tableau au conteneur dans une boucle. Les boutons seront ajouts en fonction dun emplacement en pixels. Vous devez donc concevoir un algorithme simple pour espacer les morceaux du ring correctement. Voici une suggestion : toutes les images du jeu mesurent 100 100 pixels ; les botes doivent donc tre espaces de 100 pixels. Crez de plus deux variables de valeur 0 en dehors de la loupe. chaque itration, incrmentez une des variables de 1. Puis, multipliez cette valeur par 100 pour obtenir lespacement correct en x. Ajoutez une instruction if dans la boucle for. Si le compteur est un multiple de 3 (le plateau est large de trois morceaux), incrmentez la seconde variable pour passer la ligne suivante. Tout ceci peut sembler confus, mais lorsque vous verrez le code, tout semblera plus clair.
int nouvelleLigne = 0; int compteurLigne = 0; for(int i = 0; i < boutons.length; i++) { //initialisation avec une image vide boutons[i] = new JButton(blank); //regarde sil faut utiliser une nouvelle ligne if(i==3 || i ==6) { nouvelleLigne++; compteurLigne = 0; } //dfinit la position du bouton boutons[i].setBounds(compteurLigne*100,nouvelleLigne* 100,100,100); //lajoute au conteneur container.add(boutons[i]); //ajoute lActionListener boutons[i].addActionListener(this); compteurLigne++; }

Maintenant que le plateau est complet, crez une variable appele tour. Chaque fois que la mthode actionPerformed est excute, tour doit tre incrment de 1. Vous pourrez ainsi vrier de quel joueur cest le tour sur la base de la parit de tour. Dans actionPerformed, si tour est impair, cest le tour du joueur O. Sil est impair, cest le tour du joueur X. En fonction du joueur qui est en train de jouer, modiez licne pour afcher la bonne image. Lorsque vous avez modi licne, pensez supprimer lActionListener pour quun joueur ne puisse pas voler la position de son adversaire !

Chapitre 3

Jeux de plateau

107

import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; //classe avec un JFrame et un ActionListener public class MorpionBoxeur extends JFrame implements ActionListener { //tableau de boutons. Nous utilisons un tableau et non un ArrayList //car le nombre de boutons est constant. JButton boutons[] = new JButton[9]; //garde le dcompte des tours. le joueur 1 est pair, le joueur 2 impair //on utilise le modulo (%) pour diffrencier les valeurs int tour = 1; //reprsentent les adversaires ImageIcon rouge = new ImageIcon("rouge.png"); ImageIcon bleu = new ImageIcon("bleu.png"); ImageIcon blanc = new ImageIcon("blanc.png"); //constructeur public MorpionBoxeur() { super("Morpion Boxeur"); setSize(330,350); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //contient les boutons Container cont = getContentPane(); //disposition des boutons cont.setLayout(null); int nouvelleLigne = 0; int compteurLigne = 0; for(int i = 0; i < boutons.length; i++) { //initialise le bouton avec une image vide boutons[i] = new JButton(blanc); //faut-il utiliser une nouvelle ligne? if(i==3 || i ==6) { nouvelleLigne++; compteurLigne = 0; } //position du bouton boutons[i].setBounds(compteurLigne*100,nouvelleLigne*100,100,100); //ajoute le bouton au conteneur cont.add(boutons[i]); //ajoute lActionListener boutons[i].addActionListener(this); compteurLigne++; } } //mthode obligatoire public void actionPerformed(ActionEvent e) { //regarde quel bouton a t cliqu

108

Devenez un petit gnie des jeux vido

for(int i = 0; i < boutons.length; i++) { if(e.getSource()==boutons[i]) { //vrifie le tour if(tour%2==0) { //si pair, tour du joueur 1 (X) boutons[i].setIcon(rouge); } else { //si impair, tour du joueur 2 (0) boutons[i].setIcon(bleu); } //dsactive le bouton pour quil ne puisse pas tre modifi une fois cliqu boutons[i].removeActionListener(this); } } tour++; } //mthode de dmarrage (main) public static void main(String[ ] args) { MorpionBoxeur mp = new MorpionBoxeur(); } }

Les Figures 16.1 16.4 illustrent le droulement du jeu.


Figure 16.1 Dmarrage du jeu

Chapitre 3

Jeux de plateau

109

Figure 16.2 Le joueur 1 attaque

Figure 16.3 Le joueur 2 contre-attaque

Figure 16.4 Le joueur 1 ("O") gagne... mais lordinateur ne peutpas encore dtecter le rsultat

110

Devenez un petit gnie des jeux vido

Projet 17 : Le morpion boxeur Combat !


Projet Bienvenue au camp dentranement. Cest ici que vous allez permettre deux joueurs de saffronter sur le ring. Ajoutez une image de titre pour les chauffer et programmez votre ordinateur pour dterminer qui est le champion et qui doit sincliner.

Crer le jeu
Commencez par lobjectif le plus simple : ajouter limage de titre. Pour cela, crez une image de titre dans un logiciel graphique quelconque. Puis, crez un JLabel pour afcher cette image. Ajoutez ce JLabel au-dessus des boutons ( lemplacement 0,0), Noubliez pas de modier la boucle qui ajoute les boutons pour que ceux-ci ne soient pas couverts par limage du titre. Il suft pour cela dajouter la hauteur de limage aux valeurs en y de la position de vos boutons. Vous pouvez aussi ajouter un nombre la valeur en x de la position des boutons pour quils soient centrs comme le montre la Figure 17.1.
Figure 17.1 Limage de titre et les boutons sont centrs

Ensuite, apprenez lordinateur comment dtecter les K.-O. Crez une mthode appele verifieVictoire. la n de chaque appel de la mthode actionPerformed, appelez

Chapitre 3

Jeux de plateau

111

verifieVictoire. Il existe deux techniques pour vrier une victoire. La premire implique une srie dinstructions if qui nest pas vraiment amusante. La seconde technique demande moins de code. Comme le plateau de morpion boxeur est un carr, il est plus simple de placer ces instructions if dans des boucles. Ceci supprime presque les deux tiers du code crire. Comme la Figure 17.2 lillustre, une boucle unique peut vrier six cas diffrents.
Figure 17.2 Une seule boucle permet de grer 6 cas

Voici maintenant la partie dlicate : crire cette boucle for. Pour cela, crez une boucle for allant de 0 2 (3 itrations). Dans la boucle, ajoutez 4 instructions if : une pour une victoire X en vertical, une pour une victoire O en vertical, une pour une victoire X en horizontal et une pour une victoire O en horizontal. Chaque itration de la boucle dtermine si les icnes des boutons dans une position donne sont toutes de la mme couleur. Le code des instructions if est indiqu ci-aprs :
//cherche une victoire X en vertical if(boutons[i].getIcon().equals(rouge) && boutons[i+3].getIcon().equals(rouge) && boutons[i+6].getIcon().equals(rouge)) JOptionPane.showMessageDialog(null,X gagne); //cherche une victoire O en vertical if(boutons[i].getIcon().equals(bleu) && boutons[i+3].getIcon().equals(bleu) && boutons[i+6].getIcon().equals(bleu)) JOptionPane.showMessageDialog(null,O gagne); //cherche une victoire X en horizontal if(boutons[i*3].getIcon().equals(rouge) && boutons[(i*3)+1].getIcon().equals(rouge) && boutons[(i*3)+2].getIcon().equals(rouge)) JOptionPane.showMessageDialog(null,X gagne);

112

Devenez un petit gnie des jeux vido

//cherche une victoire O en horizontal if(boutons[i*3].getIcon().equals(bleu) && boutons[(i*3)+1].getIcon().equals(bleu) && boutons[(i*3)+2].getIcon().equals(bleu)) JOptionPane.showMessageDialog(null,O gagne);

Vous y tes presque ! Il suft dajouter une seconde boucle pour les victoires diagonales. On procde de la mme manire que pour les lignes horizontales et verticales, ceci prs quil ny a que deux itrations la boucle. La boucle est indique ci-aprs :
//cherche une victoire en diagonal for(int i = 0; i <= 2; i+=2) { //cherche une victoire X en diagonal if(boutons[i].getIcon().equals(rouge) && boutons[4].getIcon().equals(rouge) && boutons[8_i].getIcon().equals(rouge)) JOptionPane.showMessageDialog(null, X gagne); //cherche une victoire O en diagonal if(boutons[i].getIcon().equals(bleu) && boutons[4].getIcon().equals(bleu) && boutons[8_i].getIcon().equals(bleu)) JOptionPane.showMessageDialog(null, O gagne); }

Vous disposez maintenant de tout le code ncessaire pour vrier les victoires. Le code complet est reproduit ci-aprs :
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; //classe avec un JFrame et un ActionListener public class MorpionBoxeur extends JFrame implements ActionListener { //tableau de boutons. On utilise un tableau et non un arrayList //car le nombre de boutons est constant. JButton boutons[] = new JButton[9]; //garde le dcompte des tours. le joueur 1 est pair, le joueur 2 impair //on utilise le modulo (%) pour diffrencier les valeurs int tour = 1; //reprsentent les adversaires ImageIcon rouge = new ImageIcon("rouge.png"); ImageIcon bleu = new ImageIcon("bleu.png"); ImageIcon blanc = new ImageIcon("blanc.png"); //image de titre JLabel titre = new JLabel(new ImageIcon("titre.png"));

Chapitre 3

Jeux de plateau

113

//constructeur public MorpionBoxeur() { super("Morpion Boxeur"); setSize(350,625); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //contient les boutons Container cont = getContentPane(); //disposition des boutons cont.setLayout(null); cont.add(titre); titre.setBounds(0,0,350,288); int nouvelleLigne = 0; int compteurLigne = 0; for(int i = 0; i < boutons.length; i++) { //initialisation avec une image vide boutons[i] = new JButton(blanc); //faut-il utiliser une nouvelle ligne? if(i==3 || i==6) { nouvelleLigne++; compteurLigne = 0; } //position du bouton boutons[i].setBounds(15+(compteurLigne*100),288+ (nouvelleLigne*100),100,100); //ajout du bouton au conteneur cont.add(boutons[i]); //ajoute lActionListener boutons[i].addActionListener(this); compteurLigne++; } //rafrachit lcran cont.repaint(); } //mthode obligatoire public void actionPerformed(ActionEvent e) { //surveille les clics sur les boutons for(int i = 0; i < boutons.length; i++) { if(e.getSource()==boutons[i]) { //calcule de quel joueur cest le tour if(tour%2==0) { //si le tour est pair, cest le tour du joueur 1 (X) boutons[i].setIcon(rouge); } else

114

Devenez un petit gnie des jeux vido

{ //si le tour est impair, cest le tour du joueur 2 (0) boutons[i].setIcon(bleu); } //dsactive le bouton pour quon ne puisse plus re-cliquer dessus boutons[i].removeActionListener(this); } } tour++; //avant que lautre joueur ne joue, on regarde si quelquun a gagn verifieVictoire(); } public void verifieVictoire() { //trois itrations de la boucle pour vrifier les victoires horizontales //et verticale avec peu de code for(int i = 0; i < 3; i++) { //cherche une victoire X en vertical if(boutons[i].getIcon().equals(rouge) && boutons[i+3].getIcon().equals(rouge) && boutons[i+6].getIcon().equals(rouge)) JOptionPane.showMessageDialog(null,"X gagne"); //cherche une victoire O en vertical if(boutons[i].getIcon().equals(bleu) && boutons[i+3].getIcon().equals(bleu) && boutons[i+6].getIcon().equals(bleu)) JOptionPane.showMessageDialog(null,"O gagne"); //cherche une victoire X en horizontal if(boutons[i*3].getIcon().equals(rouge) && boutons[(i*3)+1].getIcon().equals(rouge) && boutons[(i*3)+2].getIcon().equals(rouge)) JOptionPane.showMessageDialog(null,"X gagne"); //cherche une victoire O en horizontal if(boutons[i*3].getIcon().equals(bleu) && boutons[(i*3)+1].getIcon().equals(bleu) && boutons[(i*3)+2].getIcon().equals(bleu)) JOptionPane.showMessageDialog(null,"O gagne"); } //cette boucle cherche les victoires en diagonal for(int i = 0; i <= 2; i+=2) { //cherche une victoire X en diagonal if(boutons[i].getIcon().equals(rouge) && boutons[4].getIcon().equals(rouge) && boutons[8-i].getIcon().equals(rouge)) JOptionPane.showMessageDialog(null,"X gagne"); //cherche une victoire 0 en diagonal if(boutons[i].getIcon().equals(bleu) && boutons[4].getIcon().equals(bleu) && boutons[8-i].getIcon().equals(bleu)) JOptionPane.showMessageDialog(null,"O gagne");

Chapitre 3

Jeux de plateau

115

} } //mthode de dmarrage (main) public static void main(String[] args) { MorpionBoxeur mp = new MorpionBoxeur(); } }

Les Figures 17.3 et 17.4 illustrent la nouvelle image de titre du morpion boxeur et la vrication des victoires. Ali, Tyson, Foreman : dans le prochain projet, vous apprendrez comment programmer le boxeur ultime en ajoutant de lintelligence articielle.
Figure 17.3 Le joueur 1 (O) va gagner !

Figure 17.4 Lordinateur reconnat la victoire du joueur 1 (O).

116

Devenez un petit gnie des jeux vido

Projet 18 : Le morpion boxeur K.-O. !


Projet Oubliez les beaux jeux de jambes, les directs rapides et les coups de poing foudroyants. Lintelligence articielle est la force la plus puissante sur un ring de boxe. Ce projet va vous expliquer comment crer une intelligence articielle pour crer un adversaire votre hauteur et celle de vos amis.

Crer le jeu
Pour crer une intelligence articielle (IA), vous naurez pas besoin dapprendre de nouveau concept ni de nouvelle syntaxe. En revanche, une quantit non ngligeable de mathmatiques sont en jeu. Cela nest pas un problme. Penser la manire dont on joue avant de programmer lIA rend le processus bien plus simple. Lorsque vous crez une IA, vous devez analyser la manire avec laquelle la plupart des gens jouent au morpion. Gnralement, on choisit comme premier coup un coin ou le milieu du plateau pour prendre lavantage. Puis, on analyse le plateau pour en dduire la victoire la plus rapide. Si la victoire nest qu une case, il suft de prendre cette case pour assurer la dfaite de ladversaire. Si la victoire est plus lointaine, il faut penser dfensif pour bloquer lopposant. Une fois pris en considration le processus de pense dun humain pour arriver la victoire, vous pouvez commencer programmer lIA ! Tout dabord, au lieu de changer les icnes dans la mthode actionPerformed, il suft que celle-ci afche licne X. Puis, la n de actionPerformed, appelez une mthode nomme ia. Dans la mthode ia, commencez par examiner le compteur de tours. Sil sagit du premier tour de lordinateur, choisissez le centre ou la case en haut gauche. Puis, tapez linstruction return pour terminer la mthode et laissez le joueur grer son tour. Sil ne sagit pas du premier tour de lordinateur, regardez sil existe deux O aligns. Si cest le cas, agissez de manire offensive et prenez la case, comme lillustre la Figure 18.1. Lordinateur met alors le joueur K.-O. ! Sil nexiste pas de ligne contenant deux O, jouez de manire dfensive et cherchez deux X aligns. Bloquez alors le troisime emplacement pour que ladversaire ne puisse pas gagner, comme lillustre la Figure 18.2. Pour cela, crez une mthode dont largument est un objet de type Icon. Elle cherchera les alignements de deux de ces icnes avec des boucles for. Si un alignement est trouv, placez-vous sur la troisime case et excutez return, ce qui termine la mthode et vite que lordinateur ne joue deux fois en un tour.

Chapitre 3

Jeux de plateau

117

Figure 18.1 Agissez de manire offensive et jouez pour gagner

Figure 18.2 Jouez de manire dfensive et empchez votre adversaire de gagner

Et voil ! Dmarrez le premier round. Le code complet se trouve ci-aprs :


import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; //classe avec un JFrame et un ActionListener public class MorpionBoxeur extends JFrame implements ActionListener { //tableau de boutons. Nous utilisons un tableau et non un ArrayList car //le nombre de boutons est constant. JButton boutons[] = new JButton[9]; //garde trace des tours: les tours pairs sont ceux du joueur 1, les tours //impairs ceux du joueur 2. On les diffrencie avec loprateur modulo (%) int tour = 1; //images pour reprsenter les camps ImageIcon rouge = new ImageIcon("rouge.png"); ImageIcon bleu = new ImageIcon("bleu.png"); ImageIcon blanc = new ImageIcon("blanc.png"); //image de titre JLabel titre = new JLabel(new ImageIcon("titre.png"));

118

Devenez un petit gnie des jeux vido

//constructeur public MorpionBoxeur() { super("Morpion Boxeur"); setSize(350,625); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //contiendra les boutons Container cont = getContentPane(); //indique la disposition des boutons cont.setLayout(null); cont.add(titre); titre.setBounds(0,0,350,288); int nouvelleLigne = 0; int compteurLigne = 0; for(int i = 0; i < boutons.length; i++) { //initialisation avec une image vide boutons[i] = new JButton(blanc); //regarde sil faut crer une ligne if(i==3 || i ==6) { nouvelleLigne++; compteurLigne = 0; } //dfinit la position du bouton boutons[i].setBounds(15+(compteurLigne*100),288+ (nouvelleLigne*100),100,100); //ajoute le bouton au conteneur cont.add(boutons[i]); //ajoute lActionListener boutons[i].addActionListener(this); compteurLigne++; } //rafrachit lcran cont.repaint(); } //mthode obligatoire public void actionPerformed(ActionEvent e) { //regarde sur quel bouton on a appuy for(int i = 0; i < boutons.length; i++) { if(e.getSource()==boutons[i]) { //le bouton passe X boutons[i].setIcon(rouge); //dsactive le bouton pour quil ne puisse pas tre rejou boutons[i].removeActionListener(this); } } tour++; //avant de laisser lordinateur jouer, regarde si quelquun a gagn verifieVictoire(); //lordinateur joue ia(); }

Chapitre 3

Jeux de plateau

119

public void verifieVictoire() { //on commence par trois itrations pour chercher des victoires //en vertical ou en horizontal sans crire trop de code for(int i = 0; i < 3; i++) { //cherche une victoire X en vertical if(boutons[i].getIcon().equals(rouge) && boutons[i+3].getIcon().equals(rouge) && boutons[i+6].getIcon().equals(rouge)) { JOptionPane.showMessageDialog(null,"Vous avez gagn!"); return; } //cherche une vitoire O en vertical if(boutons[i].getIcon().equals(bleu) && boutons[i+3].getIcon().equals(bleu) && boutons[i+6].getIcon().equals(bleu)) { JOptionPane.showMessageDialog(null,"Vous avez perdu!"); return; } //cherche une victoire X en horizontal if(boutons[i*3].getIcon().equals(rouge) && boutons[(i*3)+1].getIcon().equals(rouge) && boutons[(i*3)+2].getIcon().equals(rouge)) { JOptionPane.showMessageDialog(null,"Vous avez gagn!"); return; } //cherche une victoire O en horizontal if(boutons[i*3].getIcon().equals(bleu) && boutons[(i*3)+1].getIcon().equals(bleu) && boutons[(i*3)+2].getIcon().equals(bleu)) { JOptionPane.showMessageDialog(null,"Vous avez perdu!"); return; } } //cette boucle cherche les victoires en diagonal for(int i = 0; i <= 2; i+=2) { //cherche une victoire X en diagonal if(boutons[i].getIcon().equals(rouge) && boutons[4].getIcon().equals(rouge) && boutons[8-i].getIcon().equals(rouge)) { JOptionPane.showMessageDialog(null,"Vous avez gagn!"); return; } //cherche un victoire O en diagonal if(boutons[i].getIcon().equals(bleu) && boutons[4].getIcon().equals(bleu) && boutons[8-i].getIcon().equals(bleu)) { JOptionPane.showMessageDialog(null,"Vous avez perdu!"); return; } } }

120

Devenez un petit gnie des jeux vido

public void ia() { boolean mouvementFait; //si cest le premier tour de lordinateur, essaie de prendre la case en //haut gauche. Si elle est dj prise, prend la case du milieu. if(tour == 2) { //si la case en haut gauche est prise, prend celle du milieu if(boutons[0].getIcon().equals(rouge)) { boutons[4].setIcon(bleu); boutons[4].removeActionListener(this); mouvementFait = true; } //sinon, prend celle en haut gauche else { boutons[0].setIcon(bleu); boutons[0].removeActionListener(this); mouvementFait = true; } } //si ce nest pas le premier tour, cherche les lignes o deux cases sont prises //sil nen existe pas, prend la premire case disponible else { //appel de la mthode pour vrifier deux cases de la couleur passe en argument //la mthode prend alors la case mouvementFait = deuxAlignes(bleu); //si lordinateur na pas trouv de case offensive, trouve une case dfensive if(!mouvementFait) { mouvementFait = deuxAlignes(rouge); //sil ny a pas de mouvement dfensif faire, prend la premire case //quil trouve if(!mouvementFait) { //trouve la premire case disponible for(int i = 0; i < boutons.length; i++) { //si elle est vide, prendre la case if(boutons[i].getIcon().equals(blanc)) { boutons[i].setIcon(bleu); boutons[i].removeActionListener(this); mouvementFait = true; break; } } } } } tour++; System.out.println(tour); verifieVictoire(); if(!mouvementFait) { //si aucune case na t prise, match nul JOptionPane.showMessageDialog(null,"Match nul!!!"); } }

Chapitre 3

Jeux de plateau

121

public boolean deuxAlignes(Icon a) { for(int i = 0; i < 3; i++) { //cherche les colonnes avec deux lments identiques en haut if(boutons[i].getIcon().equals(a) && boutons[i+3].getIcon().equals(a) && boutons[i+6].getIcon().equals(blanc)) { boutons[i+6].setIcon(bleu); boutons[i+6].removeActionListener(this); return true; } //cherche les colonnes du type "un lment, un trou, un lment" if(boutons[i].getIcon().equals(a) && boutons[i+6].getIcon().equals(a) && boutons[i+3].getIcon().equals(blanc)) { boutons[i+3].setIcon(bleu); boutons[i+3].removeActionListener(this); return true; } //cherche les colonnes avec deux lments identiques en bas if(boutons[i+6].getIcon().equals(a) && boutons[i+3].getIcon().equals(a) && boutons[i].getIcon().equals(blanc)) { boutons[i].setIcon(bleu); boutons[i].removeActionListener(this); return true; } //cherche les lignes avec deux lments identiques gauche if(boutons[i*3].getIcon().equals(a) && boutons[(i*3)+1].getIcon().equals(a) && boutons[(i*3)+2].getIcon().equals(blanc)) { boutons[(i*3)+2].setIcon(bleu); boutons[(i*3)+2].removeActionListener(this); return true; } //chercje les lignes du type "un lment, un trou, un lment" if(boutons[i*3].getIcon().equals(a) && boutons[(i*3)+2].getIcon().equals(a) && boutons[(i*3)+1].getIcon().equals(blanc)) { boutons[(i*3)+1].setIcon(bleu); boutons[(i*3)+1].removeActionListener(this); return true; } //cherche les lignes avec deux lments identiques droite if(boutons[(i*3)+2].getIcon().equals(a) && boutons[(i*3)+1].getIcon().equals(a) && boutons[i*3].getIcon().equals(blanc)) { boutons[i*3].setIcon(bleu); boutons[i*3].removeActionListener(this); return true; } //cherche les diagonales avec deux lments identiques contigus for(int j = 0; j <= 2; j+=2) {

122

Devenez un petit gnie des jeux vido

if(boutons[j].getIcon()==a && boutons[4].getIcon()==a && boutons[8-j].getIcon().equals(blanc)) { boutons[8-j].setIcon(bleu); boutons[8-j].removeActionListener(this); return true; } //cherche les diagonales du type "un lment, un trou, un lment" if(boutons[j].getIcon()==a && boutons[8-j].getIcon()==a && boutons[4].getIcon().equals(blanc)) { boutons[4].setIcon(bleu); boutons[4].removeActionListener(this); return true; } if(boutons[8-j].getIcon()==a && boutons[4].getIcon()==a && boutons[j].getIcon().equals(blanc)) { boutons[j].setIcon(bleu); boutons[j].removeActionListener(this); return true; } } } return false; } //mthode de dmarrage public static void main(String[] args) { MorpionBoxeur mp = new MorpionBoxeur(); } }

Les Figures 18.3 et 18.4 illustrent la victoire de lordinateur et le match nul.


Figure 18.3 Lordinateur a gagn

Figure 18.4 Match nul !

Chapitre 3

Jeux de plateau

123

Pour aller plus loin...


Vous pouvez ajouter des sons pour quun public encourage les adversaires ou ajouter des images pour amliorer les messages de n de jeu indiquant quel joueur a gagn. Vous pouvez aussi modier le ring de boxe pour que celui-ci contienne 16 cases (4 4) et non 9. Pour encore plus de challenge, vous pouvez passer le ring en trois dimensions et faire jouer plusieurs joueurs. Vous pouvez aussi grer plusieurs niveaux de difcult et faire progresser lordinateur aprs chaque round.

4
Jeux de tir
Au sommaire de ce chapitre :

Destructeurs de lespace

Projet 19 : Le paysage Projet 20 : Lasers Projet 21 : La vengeance

126

Devenez un petit gnie des jeux vido

Projet 19 : Destructeurs de lespace Le paysage


Destructeurs de lespace La plante Terre est envahie. Vous allez concevoir et commander un vaisseau militaire pour dtruire les aliens. Votre arsenal contient des mitraillettes plasma, des bonus de vie et des rayons recteurs. Sauvez notre plante !
Projet Nouvelles briques Crez le paysage et le vaisseau. MouseMotionListener.

MouseMotionListener
Un MouseMotionListener dtecte les mouvements de la souris. Comme le KeyListener et lActionListener, le MouseMotionListener a deux mthodes obligatoires :
public void mouseMoved (MouseEvent event)

et
public void mouseDragged(MouseEvent event)

Pour obtenir la position en X et en Y du curseur, utilisez les mthodes :


event.getX(); event.getY();

Crer le jeu
Commencez par crer un JFrame de 500 par 700 pixels. Son arrire-fond doit tre noir. Pour les vaisseaux militaires, crez deux objets de type ImageIcon : un pour le vaisseau de base et un pour le vaisseau lorsquil est endommag. Puis, crez un JLabel et attribuez-lui lImageIcon. Ajoutez un MouseMotionListener la classe. Dans la mthode mouseMoved, utilisez la mthode setBounds du vaisseau pour le dplacer en suivant le curseur.
import import import import import javax.swing.*; javax.swing.event.*; java.awt.*; java.awt.event.*; java.util.*;

Chapitre 4

Jeux de tir

127

public class DestructeursEspace extends JFrame implements MouseMotionListener { //contient les composants Container cont; //images du vaisseau ImageIcon imageVaisseau = new ImageIcon("vaisseau.png"); ImageIcon vaisseauEndommage = new ImageIcon("vaisseauTouche.png"); //vaisseau du joueur JLabel vaisseau = new JLabel(imageVaisseau); public DestructeursEspace() { super("Destructeurs de lEspace"); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(500,700); cont = getContentPane(); cont.setLayout(null); //dfinit la couleur de larrire-fond cont.setBackground(Color.BLACK); cont.add(vaisseau); vaisseau.setBounds(225, 550,50,50); addMouseMotionListener(this); setContentPane(cont); } public void mouseMoved(MouseEvent event) { vaisseau.setBounds(event.getX()-25,event.getY()-40,50,50); } public void mouseDragged(MouseEvent event){ } public static void main (String[] args) { new DestructeursEspace(); } }

La Figure 19.1 illustre le vaisseau suivant le curseur. Dans la suite, nous verrons comment ajouter des armes votre vaisseau. Mais quoi servent des armes si vous navez pas de cible ? Nous crerons donc aussi des aliens menaants.

128

Devenez un petit gnie des jeux vido

Figure 19.1 Le vaisseau est prt pour laction !

Chapitre 4

Jeux de tir

129

Projet 20 : Destructeurs de lespace Lasers


Projet Vous tes maintenant prt crer des aliens diaboliques ! Mais avant tout, ajoutez des lasers votre vaisseau pour donner une chance lhumanit de pouvoir se battre.

Crer le jeu
Crez un ImageIcon et un JLabel pour les lasers du vaisseau. Crez un ArrayList pour contenir tous les lasers tirs par le vaisseau. Cet ArrayList contiendra les JLabel euxmmes. Lorsque lArrayList est prt, ajoutez un KeyListener pour dterminer quand faire feu avec les lasers. Lorsque le joueur appuie sur la barre espace, ajoutez le laser au tableau de jeu et lArrayList. Aprs avoir cr un l dexcution et une boucle innie, utilisez une boucle for et la mthode setBounds pour que les lasers tirent vers le haut. Il est maintenant temps de crer les aliens. Crez deux ImageIcon : un dun alien normal (voir la Figure 20.1) et un dun alien touch (voir la Figure 20.2).
Figure 20.1 Alien normal

Figure 20.2 Alien endommag

Ajoutez limage de lalien normal un JLabel. Puis, crez deux variables : niveau et nbEnnemis. Le nombre dennemis correspond au carr de chaque numro de niveau : ainsi, le deuxime niveau a 22 = 4 ennemis, le troisime, 3 2 = 9 ennemis. Dans le constructeur, utilisez une boucle pour initialiser les ennemis. Dans la boucle innie, dplacez les aliens vers le bas. Crez galement un ArrayList pour contenir les aliens. Une instruction if vriera le nombre dennemis encore en vie. Si ce nombre est 0, incrmentez la variable niveau de 1 et ajoutez les aliens correspondants lcran et lArrayList. Pour vous faciliter la vie, vous pouvez crer une mthode pour peupler lArrayList. Lorsque les aliens arrivent en bas de lcran et disparaissent, faites-les rapparatre en haut de lcran.

130

Devenez un petit gnie des jeux vido

Il faut galement dtecter les collisions entre les lasers du vaisseau et les aliens dans la boucle innie. Si un alien et un laser entrent en collision, il faut les retirer. Et noubliez pas de passer licne de lalien celle de lalien touch avant de le supprimer.
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.util.*; public class DestructeursEspace extends JFrame implements KeyListener,MouseMotionListener { //contient les composants Container cont; //niveau courant int niveau = 1; //nombre dennemis int nbEnnemis = 1; //image du laser ImageIcon laserVaisseau = new ImageIcon("laserVaisseau.png"); //lasers du joueur ArrayList lasersJoueur = new ArrayList(); //ennemis ArrayList ennemis = new ArrayList(); //images du vaisseau ImageIcon imgVaisseau = new ImageIcon("vaisseau.png"); ImageIcon vaisseauEndommage = new ImageIcon("vaisseauTouche.png"); //images des ennemis ImageIcon imgEnnemi = new ImageIcon("ennemi.png"); ImageIcon ennemiEndommage = new ImageIcon("ennemiTouche.png"); //vaisseau du joueur JLabel vaisseau = new JLabel(imgVaisseau); public DestructeursEspace() { super("Destructeurs de lEspace"); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(500,700); cont = getContentPane(); cont.setLayout(null); //couleur de larrire fond cont.setBackground(Color.BLACK); cont.add(vaisseau); vaisseau.setBounds(225, 550,50,50); addKeyListener(this); addMouseMotionListener(this); peupleEnnemis(); Jeu jeu= new Jeu(); jeu.start(); setContentPane(cont); }

Chapitre 4

Jeux de tir

131

public void peupleEnnemis() { for(int i = 0; i < nbEnnemis; i++) { JLabel tmpEnnemi = new JLabel(imgEnnemi); int emplAleatoire = (int)(Math.random()*500); ennemis.add(tmpEnnemi); cont.add((JLabel)(ennemis.get(i))); tmpEnnemi.setBounds(emplAleatoire,10,30,30); cont.setComponentZOrder(((JLabel)(ennemis.get(i))),0); } } public class Jeu extends Thread { public void run() { while(true) { try { for(int i = 0; i < ennemis.size(); i++) { JLabel tmpEnnemi = (JLabel)(ennemis.get(i)); int distance = (int)(Math.random()*2); tmpEnnemi.setBounds(tmpEnnemi.getX(),tmpEnnemi.getY()+ distance,30,30); if(tmpEnnemi.getBounds().intersects(vaisseau.getBounds())) { cont.remove(tmpEnnemi); } if(tmpEnnemi.getY()>550)tmpEnnemi.setBounds(tmpEnnemi.getX(), 10, 30, 30); } //regarde si les lasers du joueur touchent les aliens boolean recommence = false; for(int i = 0; i < lasersJoueur.size(); i++) { JLabel temp = ((JLabel)(lasersJoueur.get(i))); temp.setBounds(temp.getX(),temp.getY()-8,10,20); if(temp.getY()<0) { cont.remove(temp); lasersJoueur.remove(i); i--; } for(int j = 0; j < ennemis.size(); j++) { JLabel tmpEnnemi = (JLabel)(ennemis.get(j)); if(temp.getBounds().intersects(tmpEnnemi.getBounds())) { tmpEnnemi.setIcon(ennemiEndommage); Thread.sleep(100); ennemis.remove(j); cont.remove(tmpEnnemi); nbEnnemis--; if(nbEnnemis<=0) { niveau++; nbEnnemis = niveau * niveau; peupleEnnemis(); recommence = true; break; } } }

132

Devenez un petit gnie des jeux vido

if(recommence) break; } cont.repaint(); Thread.sleep(10); } catch(Exception e){ } } } } public void mouseMoved(MouseEvent event) { vaisseau.setBounds(event.getX()-25,event.getY()-40,50,50); } public void mouseDragged(MouseEvent event){ } public void keyPressed(KeyEvent event) { if(event.getKeyChar()== ) { JLabel tmpLaser = new JLabel(laserVaisseau); tmpLaser.setBounds(vaisseau.getX()+20,vaisseau.getY()-20,10,20); lasersJoueur.add(tmpLaser); cont.add((JLabel)(lasersJoueur.get(lasersJoueur.size()-1))); cont.setComponentZOrder((JLabel)(lasersJoueur.get(lasersJoueur.size() -1)),0); } } public void keyReleased(KeyEvent event) { } public void keyTyped(KeyEvent event) { } public static void main(String[] args) { new DestructeursEspace(); } }

Les Figures 20.3 20.5 montrent le joueur dfendant la plante face linvasion. Les aliens arrivent dsormais par salves. Mais la bataille ne sera quun faible d moins que les aliens naient galement de la puissance de feu. Cest ce que permet de faire le projet suivant.

Chapitre 4

Jeux de tir

133

Figure 20.3 Arrive des aliens

Figure 20.4 Ouverture du feu

134

Devenez un petit gnie des jeux vido

Figure 20.5 Oh oh, ils se reproduisent !

Chapitre 4

Jeux de tir

135

Projet 21 : Destructeurs de lespace La vengeance


Projet Le combat sintensie ! Offrez de la puissance de feu aux aliens et crez des bonus apparaissant certains niveaux.

Crer le jeu
Pour armer les aliens, crez une variable alatoire entre 0 et 2 500. Si la valeur de cette variable est infrieure ou gale 1, lalien tire un laser. Crez un ArrayList et utilisez le mme code que celui servant aux tirs du vaisseau. Dans la boucle innie, cherchez les collisions entre les lasers aliens et le vaisseau. Sils entrent en collision, modiez licne du vaisseau pour afcher celle du vaisseau endommag. Puis, crez deux variables : lune delles reprsente le score et la seconde reprsente le niveau de vie du vaisseau. Lorsque le vaisseau est attaqu, diminuez le niveau de vie ; lorsquun alien est dtruit, augmentez le score. En ce qui concerne les bonus, il en existe de deux types : des rayons recteurs et des bonus de vie. Les rayons recteurs mlangent les particules des aliens et les font disparatre temporairement. Les bonus de vie ajoutent de lnergie au vaisseau. Tous les trois niveaux, un decteur de rayons apparat. Tous les cinq niveaux, un bonus de vie apparat. Aux niveaux correspondants, ajoutez le bonus en haut de lcran et faitesle tomber pour que le vaisseau puisse le capturer. Lorsque le vaisseau attrape un bonus de vie, supprimez-le et augmentez le niveau de vie du vaisseau. Lorsque le vaisseau attrape un rayon recteur, supprimez licne et ajoutez un JLabel couvrant la largeur de lcran. Dplacez ce rayon vers le haut grce la mthode setBounds. Si le rayon entre en collision avec un alien, supprimez lalien et ajoutez des points au score du joueur. Ajoutez en bas de lcran un JLabel contenant les statistiques du joueur (niveau, points, vie). Noubliez pas den modier la valeur aprs chaque itration de la boucle innie.
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.util.*; public class DestructeursEspace extends JFrame implements KeyListener,MouseMotionListener { //contient les composants Container cont; //niveau courant int niveau = 1;

136

Devenez un petit gnie des jeux vido

//nombre dennemis int nbEnnemis = 1; //images des lasers ImageIcon laserVaisseau = new ImageIcon("laserVaisseau.png"); ImageIcon laserEnnemi = new ImageIcon("laserEnnemi.png"); //contient les lasers du joueur ArrayList lasersJoueur = new ArrayList(); //contient les ennemis ArrayList ennemis = new ArrayList(); //contient les lasers des ennemis ArrayList lasersEnnemis = new ArrayList(); //images du vaisseau ImageIcon imgVaisseau = new ImageIcon("vaisseau.png"); ImageIcon vaisseauEndommage = new ImageIcon("vaisseauTouche.png"); //images des ennemisthese are the images of the enemies ImageIcon imgEnnemi = new ImageIcon("ennemi.png"); ImageIcon ennemiEndommage = new ImageIcon("ennemiTouche.png"); //bonus: rflecteur JLabel reflecteur = new JLabel(new ImageIcon("reflecteur.png")); //vaisseau du joueur JLabel vaisseau = new JLabel(imgVaisseau); //attaque du rflecteur JLabel attaqueReflecteur = new JLabel(new ImageIcon("attaqueReflecteur.png")); //indique si le rflecteur est utilis boolean utiliseReflecteur = false; //bonus de vie JLabel bonusVie = new JLabel(new ImageIcon("vie.png")); //score int score = 0; //vie int vie = 500; //score final int scoreFinal = 0; JLabel scoreLbl = new JLabel("Niveau : "+niveau+" Score : "+score+ " Vie : "+vie); public DestructeursEspace() { super("Destructeurs de lEspace"); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(500,700); cont = getContentPane(); cont.setLayout(null); //couleur de larrire fond cont.setBackground(Color.BLACK); scoreLbl.setFont(new Font("Times New Roman", Font.BOLD, 20)); scoreLbl.setForeground(Color.WHITE); cont.add(scoreLbl); scoreLbl.setBounds(20,600,400,50); cont.add(vaisseau); vaisseau.setBounds(225, 550,50,50);

Chapitre 4

Jeux de tir

137

addKeyListener(this); addMouseMotionListener(this); peupleEnnemis(); Jeu jeu= new Jeu(); jeu.start(); setContentPane(cont); } public void peupleEnnemis() { for(int i = 0; i < nbEnnemis; i++) { JLabel tmpEnnemi = new JLabel(imgEnnemi); int emplAleatoire = (int)(Math.random()*500); ennemis.add(tmpEnnemi); cont.add((JLabel)(ennemis.get(i))); tmpEnnemi.setBounds(emplAleatoire,10,30,30); cont.setComponentZOrder(((JLabel)(ennemis.get(i))),0); } } public class Jeu extends Thread { public void run() { while(true) { try { for(int i = 0; i < ennemis.size(); i++) { JLabel tmpEnnemi = (JLabel)(ennemis.get(i)); int distance = (int)(Math.random()*2); tmpEnnemi.setBounds(tmpEnnemi.getX(), tmpEnnemi.getY()+distance,30,30); //le rayon rflecteur touche-t-il des aliens? if(utiliseReflecteur) { if(attaqueReflecteur.getBounds().intersects(tmpEnnemi.getBounds())) { cont.remove(tmpEnnemi); i--; nbEnnemis--; score +=15; } } if(tmpEnnemi.getBounds().intersects(vaisseau.getBounds())) { vie--; cont.remove(tmpEnnemi); } if(tmpEnnemi.getY()>550)tmpEnnemi.setBounds(tmpEnnemi.getX(), 10, 30, 30); int feu = (int)(Math.random()*2500); if(feu<=1) { JLabel tmpLaser = new JLabel(laserEnnemi); tmpLaser.setBounds(tmpEnnemi.getX()+5,tmpEnnemi.getY()+30,10,20); lasersEnnemis.add(tmpLaser); cont.add((JLabel)(lasersEnnemis.get(lasersEnnemis.size()-1))); cont.setComponentZOrder((JLabel)(lasersEnnemis.get (lasersEnnemis.size()-1)),0); } } //regarde si les lasers du joueur touchent des aliens boolean recommence = false;

138

Devenez un petit gnie des jeux vido

for(int i = 0; i <lasersJoueur.size(); i++) { JLabel temp = ((JLabel)(lasersJoueur.get(i))); temp.setBounds(temp.getX(),temp.getY()-8,10,20); if(temp.getY()<0) { cont.remove(temp); lasersJoueur.remove(i); i--; } for(int j = 0; j < ennemis.size(); j++) { JLabel tmpEnnemi = (JLabel)(ennemis.get(j)); if(temp.getBounds().intersects(tmpEnnemi.getBounds())) { score+=1000; tmpEnnemi.setIcon(ennemiEndommage); Thread.sleep(100); ennemis.remove(j); cont.remove(tmpEnnemi); nbEnnemis--; if(nbEnnemis<=0) { niveau++; if(niveau%3 == 0) { cont.add(reflecteur); int emplAleatoire = (int)(Math.random()*450); reflecteur.setBounds(emplAleatoire,0,30,30); } if(niveau%5==0) { cont.add(bonusVie); int emplAleatoire = (int)(Math.random()*450); bonusVie.setBounds(emplAleatoire,0,30,30); } nbEnnemis = niveau * niveau; peupleEnnemis(); recommence = true; break; } } } if(recommence)break; } //dplace le rayon rflecteur if(utiliseReflecteur) { attaqueReflecteur.setBounds(0,attaqueReflecteur.getY()-1,500,10); if(attaqueReflecteur.getY()<0) { cont.remove(attaqueReflecteur); utiliseReflecteur = false; niveau++; nbEnnemis = niveau * niveau; peupleEnnemis(); } } //si le niveau est multiple de 3, on ajoute un rflecteur if(niveau%3==0) { reflecteur.setBounds(reflecteur.getX(),reflecteur.getY()+1,30,30);

Chapitre 4

Jeux de tir

139

if(reflecteur.getBounds().intersects(vaisseau.getBounds())) { utiliseReflecteur = true; cont.add(attaqueReflecteur); attaqueReflecteur.setBounds(0,vaisseau.getY(),500,10); cont.remove(reflecteur); reflecteur.setBounds(-200,-200,30,30); } } if(niveau%5==0) { bonusVie.setBounds(bonusVie.getX(),bonusVie.getY()+1,30,30); if(bonusVie.getBounds().intersects(vaisseau.getBounds())) { vie+=50; score+=100; cont.remove(bonusVie); bonusVie.setBounds(-100,-100,30,30); } } //regarde si les lasers des aliens touchent le joueur recommence = false; for(int i = 0; i <lasersEnnemis.size(); i++) { JLabel temp = ((JLabel)(lasersEnnemis. get(i))); temp.setBounds(temp.getX(),temp.getY()+2,10,20); if(temp.getY()>550) { cont.remove(temp); lasersEnnemis.remove(i); i--; } if(vaisseau.getBounds().intersects(temp.getBounds())) { vaisseau.setIcon(vaisseauEndommage); Thread.sleep(100); vaisseau.setIcon(imgVaisseau); score-=100; vie-=50; cont.remove(temp); lasersEnnemis.remove(i); nbEnnemis--; if(nbEnnemis<=0) { niveau++; nbEnnemis = niveau * niveau; peupleEnnemis(); recommence = true; break; } } if(recommence) break; } cont.repaint(); Thread.sleep(10); scoreLbl.setText("Niveau : "+niveau+" Score : "+score+" Vie : "+vie); } catch(Exception e){ } }

140

Devenez un petit gnie des jeux vido

} } public void mouseMoved(MouseEvent event) { vaisseau.setBounds(event.getX()-25,event.getY()-40,50,50); } public void mouseDragged(MouseEvent event){ } public void keyPressed(KeyEvent event) { if(event.getKeyChar()== ) { JLabel tmpLaser = new JLabel(laserVaisseau); tmpLaser.setBounds(vaisseau.getX()+20,vaisseau.getY()-20,10,20); lasersJoueur.add(tmpLaser); cont.add((JLabel)(lasersJoueur.get(lasersJoueur.size()-1))); cont.setComponentZOrder((JLabel)(lasersJoueur.get( lasersJoueur.size()-1)),0); score-=2; } } public void keyReleased(KeyEvent event) { } public void keyTyped(KeyEvent event) { } public static void main(String[] args) { new DestructeursEspace(); } }

Les Figures 21.1 21.3 montrent la terrible bataille pour la Terre.


Figure 21.1 Apparition dun bonus de rayons recteurs

Chapitre 4

Jeux de tir

141

Figure 21.2 Le rayon recteur

Figure 21.3 Apparition dun bonus de vie

142

Devenez un petit gnie des jeux vido

Pour aller plus loin...


Modiez le niveau de vie initial du vaisseau pour rendre le jeu plus ou moins difcile. Ajoutez de nouveaux bonus, comme des rayons laser plus larges pouvant dtruire plusieurs aliens la fois. Utilisez plusieurs vaisseaux : faites jouer plusieurs personnes en mme temps ! Attribuez diffrents pouvoirs aux aliens : certains tirent des lasers, dautres des anneaux dclairs. Modiez le nombre de lasers tirs par le vaisseau. Ajoutez une bombe fragmentation aux armes spciales et limites du vaisseau. Ajoutez des points de vie aux ennemis et permettez-leur de survivre une premire attaque.

5
Jeux de stratgie
Au sommaire de ce chapitre :

Dmineurs

Projet 22 : Le petit nouveau de lquipe Projet 23 : Dmineur expert Projet 24 : BOUM ! Projet 25 : Promotions

Piges

Projet 26 : Dplacements Projet 27 : Mise en place des piges Projet 28 : Pig ! Projet 29 : Le spectacle

144

Devenez un petit gnie des jeux vido

Projet 22 : Dmineurs Le petit nouveau de lquipe


Dmineurs En tant que nouveau membre de lquipe de dmineurs, votre mission est daller risquer votre vie sur le terrain en dsamorant des engins explosifs amorcs. Vos meilleures armes ? Une excellente coordination vue/action, une rexion rapide... et un peu de chance.
Projet Apprenons les bases des explosifs en crant une bombe inerte.

Crer le jeu
Crez dabord un JFrame, de taille 500 par 500 et darrire-fond gris. Puis, dessinez limage de la bombe et du dtonateur. Pour cela, ouvrez Microsoft Paint (ou tout autre diteur dimages) et indiquez la taille de limage avec Image, Attributs comme le montre la Figure 22.1.
Figure 22.1 Taille de limage

Chapitre 5

Jeux de stratgie

145

Choisissez un fond gris clair pour la bombe et le dtonateur de manire vous fondre dans larrire-fond du JFrame. Ainsi, si le jeu est redimensionn, la diffrence entre limage et le fond sera moins visible. Limage est compose de deux parties : la bombe et le dtonateur. Dessinez dabord la bombe en haut de lcran. Utilisez les outils Rectangle et Crayon pour vous faciliter la tche. Noubliez pas le cble du dtonateur et le texte TNT ! Ltape suivante consiste ajouter le dtonateur en bas de lcran. Crez dabord un rectangle gris. Donnez-lui lillusion dun volume 3D en crant des lignes de perspective. Ajoutez des emplacements pour les indices, le temps restant et le code de dsamorage. Vous ajouterez ensuite des composants ces endroits. Une fois que vous avez ni de dessiner limage de la bombe, ajoutez-la au JFrame la position 0,0. Les Figures 22.2 et 22.3 illustrent le dessin de la bombe.
Figure 22.2 Dessin de la bombe

import import import import public {

java.awt.*; java.awt.event.*; javax.swing.*; javax.swing.event.*; class Demineurs extends JFrame

146

Devenez un petit gnie des jeux vido

Figure 22.3 Bombe avant son insertion dans le JFrame

//le JLabel de la bombe JLabel bombe = new JLabel(new ImageIcon("bombe.png")); //le conteneur des composants Container cont; public Demineurs() { super("Dmineurs"); setSize(500,550); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cont = getContentPane(); cont.setLayout(null); cont.setBackground(Color.gray); //Ajoute le fond de limage cont.add(bombe); bombe.setBounds(0,0,500,500); setContentPane(cont); } public static void main (String[ ] args) { new Demineurs(); } }

La Figure 22.4 illustre la bombe acheve. Vous voil diplm... Passons aux choses srieuses et dsamorons des bombes susceptibles dexploser tout moment !

Chapitre 5

Jeux de stratgie

147

Figure 22.4 Bombe afche dans le JFrame

148

Devenez un petit gnie des jeux vido

Projet 23 : Dmineurs Dmineur expert


Projet Vous allez maintenant mettre vos comptences rude preuve pour viter la dtonation.

Crer le jeu
La premire partie de ce projet consiste ajouter quatre composants limage de fond de la bombe : le temps, les indices, le bouton de dsarmement et une zone de saisie de texte. Commencez par initialiser ces quatre composants. Crez la zone de saisie avec un composant TextField, de la mme manire que vous crez un JButton ou un JLabel. Le texte saisi peut tre obtenu avec la commande :
field.getText();

Puis, utilisez la mthode setBounds pour placer les composants. Pour connatre leur position, ouvrez limage dans Microsoft Paint et passez la souris au-dessus de la zone cible. Les coordonnes sont afches en bas droite du programme, comme lillustre la Figure 23.1.
Figure 23.1 Afchage des coordonnes

Chapitre 5

Jeux de stratgie

149

Aprs avoir ajout les composants, crez une variable pour reprsenter le temps restant. Utilisez un l dexcution (Thread) pour diminuer cette variable de 1 toutes les secondes et noubliez pas de rinitialiser le JLabel avec la nouvelle valeur. Il faut maintenant crer le processus de dsamorage de la bombe. Crez dabord une mthode initialisant le code un nombre alatoire. Puis, si le joueur clique sur le JButton, modiez le JLabel reprsentant lindice pour indiquer si la proposition du joueur est trop leve ou trop basse.
import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; public class Demineurs extends JFrame implements ActionListener { //temps restant avant la dtonation int tempsRestant = 12; //JLabel affichant le temps destant JLabel temps = new JLabel(tempsRestant+""); //JLabel de la bombe JLabel bombe = new JLabel(new ImageIcon("bombe.png")); //indice JLabel indice = new JLabel(); //code: int code = 0; //champ de code de dsamorage TextField essai = new TextField(20); //bouton de dsamorage JButton desamorcage = new JButton("DSAMORCER"); //conteneur pour les composants Container cont; //fil dexcution Compteur compteur; public Demineurs() { super("Dmineurs"); setSize(500,550); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cont = getContentPane(); cont.setLayout(null); cont.setBackground(Color.gray); //ajoute limage de fond cont.add(bombe); bombe.setBounds(0,0,500,500); //police du JLabel temps.setFont(new Font("Courier", Font.BOLD, 20)); //ajoute le JLabel de temps restant cont.add(temps); //dfinit la position temps.setBounds(250,371,150,18);

150

Devenez un petit gnie des jeux vido

//place le JLabel au-dessus du fond cont.setComponentZOrder(temps,0); //ajoute le bouton de dsamorage cont.add(desamorcage); desamorcage.setBounds(200,456,150,30); desamorcage.addActionListener(this); cont.setComponentZOrder(desamorcage,0); indice.setText("Un nombre entre 0 et "+20); cont.add(indice); indice.setBounds(167,435,250,20); //place le JLabel au-dessus du fond cont.setComponentZOrder(indice,0); //ajoute le champs de texte cont.add(essai); essai.setBounds(271,404,150,25); //valide tous les composants cont.validate(); setContentPane(cont); setCode(); compteur = new Compteur(); compteur.start(); } public void setCode() { code = (int)(Math.random()*20); } //fil dexcution du dcompte public class Compteur extends Thread { public void run() { while(true) { try { tempsRestant--; temps.setText(tempsRestant+""); Thread.sleep(1000); } catch(Exception e){ } } } } public void actionPerformed(ActionEvent event) { if(Integer.parseInt(essai.getText())>code) { indice.setText("ATTENTION: le code saisi est TROP GRAND"); } if(Integer.parseInt(essai.getText())<code) { indice.setText("ATTENTION: le code saisi est TROP PETIT"); } if(essai.getText().equals(""+code)) { //rien ne se passe pour linstant } } public static void main(String[ ] args) { new Demineurs(); } }

Chapitre 5

Jeux de stratgie

151

Les Figures 23.2 23.5 illustrent le processus de dsamorage. Le projet suivant vous expliquera comment ajouter des images dexplosion.
Figure 23.2 Dcompte du dtonateur

Figure 23.3 Lessai tape trop haut

152

Devenez un petit gnie des jeux vido

Figure 23.4 Lessai tape trop bas

Figure 23.5 La bombe devrait exploser... mais ne le fait pas encore

Chapitre 5

Jeux de stratgie

153

Projet 24 : Dmineurs BOUM !


Projet Faites exploser la bombe. Attention ! Couvrez-vous ! Courez !

Crer le jeu
Pour ajouter des explosions amboyantes, vous devez crer deux images : une premire reprsentant une explosion (voir Figure 24.1) et une seconde, identique la premire, mais dont les couleurs sont inverses et dont la position est modie (voir Figure 24.2). Crez des JLabel pour chaque image. Puis, dans le l dexcution du dcompte, vriez si le temps coul est infrieur ou gal 0. Si cest le cas, appelez une mthode pour afcher les JLabel. Cette mthode supprime tous les composants du conteneur. Il reste seulement les deux images alternes. Pour les faire alterner, utilisez la mthode setBounds.
Figure 24.1 Premire explosion

import import import import

java.awt.*; java.awt.event.*; javax.swing.*; javax.swing.event.*;

154

Devenez un petit gnie des jeux vido

Figure 24.2 Seconde explosion

public class Demineurs extends JFrame implements ActionListener { //temps restant avant la dtonation int tempsRestant = 12; //JLabel affichant le temps destant JLabel temps = new JLabel(tempsRestant+""); //JLabel de la bombe JLabel bombe = new JLabel(new ImageIcon("bombe.png")); //indice JLabel indice = new JLabel(); //la bombe explose JLabel explosion = new JLabel(new ImageIcon("explosion1.png")); JLabel explosion2 = new JLabel(new ImageIcon("explosion2.png")); //code: int code = 0; //champ de code de dsamorage TextField essai = new TextField(20); //bouton de dsamorage JButton desamorcage = new JButton("DSAMORCER"); //conteneur pour les composants Container cont; //fil dexcution Compteur compteur; public Demineurs() { super("Dmineurs"); setSize(500,550); setVisible(true);

Chapitre 5

Jeux de stratgie

155

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cont = getContentPane(); cont.setLayout(null); cont.setBackground(Color.gray); //ajoute limage de fond cont.add(bombe); bombe.setBounds(0,0,500,500); //police du JLabel temps.setFont(new Font("Courier", Font.BOLD, 20)); //ajoute le JLabel de temps restant cont.add(temps); //dfinit la position temps.setBounds(250,371,150,18); //place le JLabel au-dessus du fond cont.setComponentZOrder(temps,0); //ajoute le bouton de dsamorage cont.add(desamorcage); desamorcage.setBounds(200,456,150,30); desamorcage.addActionListener(this); cont.setComponentZOrder(desamorcage,0); indice.setText("Un nombre entre 0 et "+20); cont.add(indice); indice.setBounds(167,435,250,20); //place le JLabel au-dessus du fond cont.setComponentZOrder(indice,0); //ajoute le champs de texte cont.add(essai); essai.setBounds(271,404,150,25); //ajoute lexplosion en dehors de lcran cont.add(explosion); explosion.setBounds(-1000,-1000,500,550); cont.setComponentZOrder(explosion,0); cont.add(explosion2); explosion2.setBounds(-1000,-1000,500,550); cont.setComponentZOrder(explosion2,0); //valide tous les composants cont.validate(); setContentPane(cont); setCode(); compteur = new Compteur(); compteur.start(); } public void setCode() { code = (int)(Math.random()*20); } //fil dexcution du dcompte public class Compteur extends Thread { public void run() { while(true) { try { if(tempsRestant>0) { tempsRestant--;

156

Devenez un petit gnie des jeux vido

temps.setText(tempsRestant+""); } else { break; } Thread.sleep(1000); } catch(Exception e){ } } //appelle la mthode qui affiche lexplosion explode(); } public void explode() { //supprime tous les autres lments cont.remove(temps); cont.remove(bombe); cont.remove(indice); cont.remove(essai); cont.remove(desamorcage); //dplace les images de lexplosion leur emplacement correct explosion.setBounds(0,0,500,550); explosion.setBounds(0,0,500,550); while(true) { try { explosion.setBounds(0,0,500,550); explosion2.setBounds(-1000,-1000,500,550); Thread.sleep(100); explosion2.setBounds(0,0,500,550); explosion.setBounds(-1000,-1000,500,550); Thread.sleep(100); } catch(Exception e){ } } }

} public void actionPerformed(ActionEvent event) { if(Integer.parseInt(essai.getText())>code) { indice.setText("ATTENTION: le code saisi est TROP GRAND"); } if(Integer.parseInt(essai.getText())<code) { indice.setText("ATTENTION: le code saisi est TROP PETIT"); } if(essai.getText().equals(""+code)) { //ce code sera ajout plus tard } } public static void main(String[ ] args) { new Demineurs(); } }

Chapitre 5

Jeux de stratgie

157

Les Figures 24.3 24.5 illustrent lexplosion de la bombe.


Figure 24.3 Dcompte du dtonateur

Figure 24.4 Explosion amboyante

158

Devenez un petit gnie des jeux vido

Figure 24.5 Image alterne de la bombe qui explose

Prt pour plus daction ? Dans le projet suivant, nous ajouterons des niveaux au jeu. Au fur et mesure que vous gagnerez de lexprience, les codes deviendront de plus en plus difciles.

Chapitre 5

Jeux de stratgie

159

Projet 25 : Dmineurs Promotions


Projet Ajoutez des niveaux au jeu. Les premiers ds sont plutt tranquilles... mais ne faites pas trop le malin, les codes vont devenir de plus en plus complexes !

Crer le jeu
Crez dabord un panneau indiquant lutilisateur quil a dsarm une bombe. Pour cela, crez une image qui flicite le joueur comme celle de la Figure 25.1. Afchez cette image dans linstruction if comparant la saisie de lutilisateur et le code alatoire. Puis, rinitialisez le code avec un nombre plus grand. Vous pouvez faire cela en calculant le code sur la base dun nombre maximal plus grand. Augmentez ce maximum chaque tour. Comme les niveaux deviennent plus difciles, il faut donner plus de temps au joueur pour deviner le code de dsamorage. Pour cela, crez un multiplicande qui augmente le temps allou chaque tour. Essayez de jouer. Lorsque vous terminez un niveau, le dtonateur fait toujours exploser la bombe ! Pourquoi ? Vous navez pas encore mis le jeu en pause.
Figure 25.1 Flicitations au joueur

Voici comment procder : dclarez un boolen qui arrte le compteur lorsque sa valeur est true. Puis, vous devez crer un bouton pour que le joueur indique quil est prt dmarrer un nouveau niveau. Lastuce est de ne pas ajouter de nouveau bouton mais dutiliser le bouton de dsamorage. Il ny a plus quun lment ajouter : un score. Crez un JLabel qui afche le score et incrmentez celui-ci du temps restant lorsque la bombe est dsamorce. Noubliez pas de rinitialiser le texte dans le JLabel.
import import import import java.awt.*; java.awt.event.*; javax.swing.*; javax.swing.event.*;

160

Devenez un petit gnie des jeux vido

public class Demineurs extends JFrame implements ActionListener { //score du joueur int score = 0; //temps restant avant la dtonation int tempsRestant = 12; //affichage du temps restant JLabel temps = new JLabel(tempsRestant+""); //JLabel de la bombe JLabel bombe = new JLabel(new ImageIcon("bombe.png")); //indice JLabel indice = new JLabel(); //affichage du score JLabel affScore = new JLabel("Votre taux de succs: "+score); //explosion JLabel explosion = new JLabel(new ImageIcon("explosion.png")); JLabel explosion2 = new JLabel(new ImageIcon("explosion2.png")); //attend que le bouton soit nouveau press boolean attente = false; //affich aprs le dsamorage de la bombe JLabel promotion = new JLabel(new ImageIcon("promotion.png")); //variables pour le niveau de difficult //multiplicande pour le nombre de chiffres int multiplicande = 1; int nombreMax = 10; //code int code = 0; //champ de texte pour le code de dsamorage TextField essai = new TextField(20); //bouton de dsamorage JButton desamorcage = new JButton("DSAMORAGE"); //conteneur des composants Container cont; //fil dexcution Compteur compteur; public Demineurs() { super("Demineurs"); setSize(500,550); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cont = getContentPane(); cont.setLayout(null); cont.setBackground(Color.gray); //ajoute limage de fond cont.add(bombe); bombe.setBounds(0,0,500,500); //police du JLabel temps.setFont(new Font("Courier", Font.BOLD, 20)); //affiche letemps restant cont.add(temps);

Chapitre 5

Jeux de stratgie

161

//position temps.setBounds(250,371,150,18); //place le JLabel au-dessus du fond cont.setComponentZOrder(temps,0); //place le libell de promotion en-dehors de lcran cont.add(promotion); promotion.setBounds(-300,-300,276,122); cont.setComponentZOrder(promotion,0); //ajoute le score lcran cont.add(affScore); affScore.setBounds(5,480,500,30); affScore.setForeground(Color.white); affScore.setFont(new Font("Courier",Font.BOLD,19)); cont.setComponentZOrder(affScore,0); //ajoute le bouton de dsamorage cont.add(desamorcage); desamorcage.setBounds(200,456,150,30); desamorcage.addActionListener(this); cont.setComponentZOrder(desamorcage,0); indice.setText("A number between 0 and "+nombreMax); cont.add(indice); indice.setBounds(167,435,250,20); //place le JLabel au-dessus du fond cont.setComponentZOrder(indice,0); //ajoute le champ texte cont.add(essai); essai.setBounds(271,404,150,25); //ajoute lexplosion en-dehors de lcran cont.add(explosion); explosion.setBounds(-1000,-1000,500,550); cont.setComponentZOrder(explosion,0); cont.add(explosion2); explosion2.setBounds(-1000,-1000,500,550); cont.setComponentZOrder(explosion2,0); //valide les composants cont.validate(); setContentPane(cont); setCode(); compteur = new Compteur(); compteur.start(); } public void setCode() { code = (int)(Math.random()*nombreMax); } //fil dexcution du compteur public class Compteur extends Thread { public void run() { while(true) {

162

Devenez un petit gnie des jeux vido

try { if(!attente) { if(tempsRestant>0) { tempsRestant--; temps.setText(tempsRestant+""); } else { break; } } Thread.sleep(1000); } catch(Exception e){ } } //appelle la mthode qui affiche lexplosion explosion(); } public void explosion() { //supprime tous les composants cont.remove(temps); cont.remove(bombe); cont.remove(indice); cont.remove(affScore); cont.remove(promotion); cont.remove(essai); cont.remove(desamorcage); //dplace les images au bon endroit explosion.setBounds(0,0,500,550); explosion2.setBounds(0,0,500,550); while(true) { try { explosion.setBounds(0,0,500,550); explosion2.setBounds(-1000,-1000,500,550); Thread.sleep(100); explosion2.setBounds(0,0,500,550); explosion.setBounds(-1000,-1000,500,550); Thread.sleep(100); } catch(Exception e){ } } } } public void actionPerformed(ActionEvent event) { if(attente) { promotion.setBounds(-300,-300,276,122); setCode(); indice.setText("Un nombre entre 0 et "+nombreMax); tempsRestant = 15*multiplicande; attente = false; } else { if(Integer.parseInt(essai.getText())>code) { indice.setText("ATTENTION: le code saisi est TROP GRAND"); }

Chapitre 5

Jeux de stratgie

163

if(Integer.parseInt(essai.getText())<code) { indice.setText("ATTENTION: le code saisi est TROP PETIT"); } if(essai.getText().equals(""+code)) { score+=tempsRestant; affScore.setText("Votre taux de russite: "+score); promotion.setBounds(150,100,276,122); attente = true; multiplicande++; nombreMax*=5; } } } public static void main(String[ ] args) { new Demineurs(); } }

Figure 25.2 Dcompte du dtonateur

Les Figures 25.2 25.4 illustrent le stress li au dsamorage.

164

Devenez un petit gnie des jeux vido

Figure 25.3 Bombe dsamorce avec succs

Figure 25.4 BOUM ! Rat !

Chapitre 5

Jeux de stratgie

165

Pour aller plus loin...


Placez deux bombes sur lcran en mme temps. Modiez la difcult du jeu en modiant le temps allou au dsamorage. Ajoutez des lettres ou des symboles au code. Faites travailler le joueur : donnez des quations mathmatiques comme indice. Pour augmenter le niveau de stress, faites en sorte que le chronomtre afche aussi les millisecondes. Ne donnez au joueur quun nombre limit de tentatives. Sil dpasse ce nombre, BOUM ! La bombe explose.

166

Devenez un petit gnie des jeux vido

Projet 26 : Piges Dplacements


Piges Dans ce jeu de stratgie multijoueurs, combattez les autres en les pigeant dans la trace que vous avez laisse derrire. Ne traversez ni le chemin de votre adversaire ni votre propre trace, vous seriez pig !
Projet Construisez deux personnages pouvant se dplacer, contrls par les deux adversaires.

Crer le jeu
Crez dabord un JFrame de taille 500 500 pixels. Puis, crez des images de taille 10 10 pour les deux joueurs. Crez un JLabel pour chaque image. Utilisez la mthode setBounds pour positionner les JLabel de chaque ct du plateau. Crez deux nouveaux ls dexcution pour contrler chacune des directions des deux joueurs. Comme la direction des joueurs est contrle par le clavier, chaque objet Thread doit implmenter KeyListener. Ajoutez les mthodes du KeyListener dans les deux classes. Dans les mthodes, vriez ltat des touches Q, S, D et Z pour le joueur 1 et J, K, L et I pour le joueur 2. Pour garder trace de la direction du joueur, utilisez la mme technique que dans la course du courage : des variables entires reprsentent les diffrentes directions. Une fois ces variables cres, modiezles pour modier la direction dans la mthode keyPressed. Lorsque les directions des joueurs sont tablies, il faut les faire bouger dans larne. Dans la boucle innie de chaque l dexcution, faites bouger les joueurs grce la mthode setBounds.
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; public class Pieges extends JFrame { //les deux joueurs JLabel j1 = new JLabel(new ImageIcon("j1.png")); JLabel j2 = new JLabel(new ImageIcon("j2.png")); boolean continueJeu = true; //les directions int HAUT = 1, DROITE = 2, BAS = 3, GAUCHE = 4;

Chapitre 5

Jeux de stratgie

167

int j1Direction = DROITE; int j2Direction = GAUCHE; Container cont; public Pieges() { super("Piges"); setSize(500,500); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); cont = getContentPane(); cont.setLayout(null); cont.add(j1); cont.setComponentZOrder(j1,0); j1.setBounds(20,245,10,10); cont.add(j2); cont.setComponentZOrder(j2,0); j2.setBounds(455,245,10,10); MouvementJ1 filJ1 = new MouvementJ1(); filJ1.start(); MouvementJ2 filJ2 = new MouvementJ2(); filJ2.start(); setContentPane(cont); } public class MouvementJ1 extends Thread implements KeyListener { public void run() { addKeyListener(this); while(continueJeu) { try { if(j1Direction==HAUT) j1.setBounds(j1.getX(),j1.getY()-5,10,10); if(j1Direction==BAS) j1.setBounds(j1.getX(),j1.getY()+5,10,10); if(j1Direction==DROITE) j1.setBounds(j1.getX()+5,j1.getY(),10,10); if(j1Direction==GAUCHE) j1.setBounds(j1.getX()-5,j1.getY(),10,10); cont.validate(); Thread.sleep(75); } catch(Exception e){ } } } public void keyPressed(KeyEvent e) { if(e.getKeyChar()==q) j1Direction = GAUCHE; if(e.getKeyChar()==s) j1Direction = BAS;

168

Devenez un petit gnie des jeux vido

if(e.getKeyChar()==d) j1Direction = DROITE; if(e.getKeyChar()==z) j1Direction = HAUT; } public void keyTyped(KeyEvent e){ } public void keyReleased(KeyEvent e){ } } public class MouvementJ2 extends Thread implements KeyListener { public void run() { addKeyListener(this); while(continueJeu) { try { if(j2Direction==HAUT) j2.setBounds(j2.getX(),j2.getY()-5,10,10); if(j2Direction==BAS) j2.setBounds(j2.getX(),j2.getY()+5,10,10); if(j2Direction==DROITE) j2.setBounds(j2.getX()+5,j2.getY(),10,10); if(j2Direction==GAUCHE) j2.setBounds(j2.getX()-5,j2.getY(),10,10); cont.validate(); Thread.sleep(75); } catch(Exception e){ } } } public void keyPressed(KeyEvent e) { if(e.getKeyChar()==j) j2Direction = GAUCHE; if(e.getKeyChar()==k) j2Direction = BAS; if(e.getKeyChar()==l) j2Direction = DROITE; if(e.getKeyChar()==i) j2Direction = HAUT; } public void keyTyped(KeyEvent e){ } public void keyReleased(KeyEvent e){ } } public static void main (String[] args) { new Pieges(); } }

Chapitre 5

Jeux de stratgie

169

Les Figures 26.1 et 26.2 illustrent le mouvement des personnages. Le projet suivant vous expliquera comment ajouter les traces que laissent les personnages derrire eux lorsquils bougent. Il est temps de commencer les piger !
Figure 26.1 Larne

Figure 26.2 Les personnages se dplacent

170

Devenez un petit gnie des jeux vido

Projet 27 : Piges Mise en place des piges


Projet Vous pouvez ajouter des traces pour afcher le mouvement des personnages. Ces traces sont au cur du jeu. Ne vous laissez pas piger... et ne laissez pas votre adversaire schapper !

Crer le jeu
La trace des joueurs est une ligne progressive dimages 10 10. Utilisez un segment noir pour reprsenter la trace du joueur 1 et un segment bleu pour le joueur 2. Pour enregistrer toutes les images, utilisez un ArrayList. Cette fonctionnalit sera ensuite utilise pour dtecter les collisions. Dans chaque boucle innie, crez un JLabel temporaire pour garder limage du segment de trace. Ajoutez ce JLabel temporaire lArrayList et au conteneur. setBounds permettra de dnir la position de limage en fonction de la position du joueur. Noubliez pas dutiliser la mthode setComponentZOrder pour garder la piste en position "1" an que limage du joueur soit toujours afche.
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.util.*; public class Pieges extends JFrame { //les joueurs JLabel j1 = new JLabel(new ImageIcon("j1.png")); JLabel p2 = new JLabel(new ImageIcon("j2.png")); //dfinition des directions int HAUT = 1, DROITE = 2, BAS = 3, GAUCHE = 4; int j1Direction = DROITE; int j2Direction = GAUCHE; //trace des joueurs ArrayList traces = new ArrayList(); Container cont; public Pieges() { super("Pieges"); setSize(500,500); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); cont = getContentPane(); cont.setLayout(null); cont.add(j1); cont.setComponentZOrder(j1,0); j1.setBounds(20,245,20,20);

Chapitre 5

Jeux de stratgie

171

cont.add(p2); cont.setComponentZOrder(p2,0); p2.setBounds(455,245,20,20); MouvementJ1 filJ1 = new MouvementJ1(); filJ1.start(); MouvementJ2 filJ2 = new MouvementJ2(); filJ2.start(); setContentPane(cont); } public class MouvementJ1 extends Thread implements KeyListener { public void run() { addKeyListener(this); while(true) { try { //ajoute la trace JLabel temp = new JLabel(new ImageIcon("traceJ1.png"));; traces.add(temp); cont.add(temp); cont.setComponentZOrder(temp,1); temp.setBounds(j1.getX(),j1.getY(),10,10); if(j1Direction==HAUT) j1.setBounds(j1.getX(),j1.getY()-5,20,20); if(j1Direction==BAS) j1.setBounds(j1.getX(),j1.getY()+5,20,20); if(j1Direction==DROITE) j1.setBounds(j1.getX()+5,j1.getY(),20,20); if(j1Direction==GAUCHE) j1.setBounds(j1.getX()-5,j1.getY(),20,20); cont.validate(); Thread.sleep(75); } catch(Exception e){ } } } public void keyPressed(KeyEvent e) { if(e.getKeyChar()==q) j1Direction = GAUCHE; if(e.getKeyChar()==s) j1Direction = BAS; if(e.getKeyChar()==d) j1Direction = DROITE; if(e.getKeyChar()==z) j1Direction = HAUT; } public void keyTyped(KeyEvent e){ } public void keyReleased(KeyEvent e){ } } public class MouvementJ2 extends Thread implements KeyListener { public void run() { addKeyListener(this); while(true) {

172

Devenez un petit gnie des jeux vido

try { //ajoute la trace JLabel temp = new JLabel(new ImageIcon("traceJ2.png"));; traces.add(temp); cont.add(temp); cont.setComponentZOrder(temp,1); temp.setBounds(p2.getX(),p2.getY(),10,10); if(j2Direction==HAUT) p2.setBounds(p2.getX(),p2.getY()-5,20,20); if(j2Direction==BAS) p2.setBounds(p2.getX(),p2.getY()+5,20,20); if(j2Direction==DROITE) p2.setBounds(p2.getX()+5,p2.getY(),20,20); if(j2Direction==GAUCHE) p2.setBounds(p2.getX()-5,p2.getY(),20,20); cont.validate(); Thread.sleep(75); } catch(Exception e){ } } } public void keyPressed(KeyEvent e) { if(e.getKeyChar()==j) j2Direction = GAUCHE; if(e.getKeyChar()==k) j2Direction = BAS; if(e.getKeyChar()==l) j2Direction = DROITE; if(e.getKeyChar()==i) j2Direction = HAUT; } public void keyTyped(KeyEvent e){ } public void keyReleased(KeyEvent e){ } } public static void main(String[] args) { new Pieges(); } }

Les Figures 27.1 27.3 montrent les traces laisses par chaque joueur. Dans le projet suivant, nous verrons comment ajouter la dtection des collisions.

Chapitre 5

Jeux de stratgie

173

Figure 27.1 Les joueurs commencent bouger

Figure 27.2 Les joueurs laissent une trace

174

Devenez un petit gnie des jeux vido

Figure 27.3 Le joueur 1 gagne... mais la victoire est peu probante puisque nous navons pas encore ajout de dtection de collisions.

Chapitre 5

Jeux de stratgie

175

Projet 28 : Piges Pig !


Projet Ajoutez la dtection des collisions. Attention !

Crer le jeu
La dtection de collisions cherche deux vnements : un joueur quittant la zone de jeu et un joueur entrant en collision avec une trace. Pour savoir si un joueur quitte la zone de jeu, utilisez une instruction if dans chaque boucle innie et vriez si les valeurs x et y du joueur sont comprises entre 0 et 500. Si ce nest pas le cas, utilisez un JOptionPane pour indiquer le gagnant. Pour dtecter une collision avec une des traces, utilisez une boucle for pour vrier tous les JLabel ( lexception des dix derniers) de lArrayList. Il ne faut pas vrier les dix derniers segments car ils ont toujours une intersection avec le joueur. Sil existe une collision, utilisez un JOptionPane pour indiquer le gagnant. Si vous excutez le programme, vous remarquerez que le message safche en continu car les ls dexcution ne sont pas arrts. Pour arrter lafchage, utilisez un boolen pour contrler la boucle innie. Une valeur false pour ce boolen arrtera les ls dexcution.
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.util.*; public class Pieges extends JFrame { //les deux joueurs JLabel j1 = new JLabel(new ImageIcon("j1.png")); JLabel j2 = new JLabel(new ImageIcon("j2.png")); boolean continueJeu = true; //les directions int HAUT = 1, DROITE = 2, BAS = 3, GAUCHE = 4; int p1Direction = DROITE; int p2Direction = GAUCHE; //traces des joueurs ArrayList traces = new ArrayList(); Container cont; public Pieges() { super("Piges"); setSize(500,500); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

176

Devenez un petit gnie des jeux vido

setVisible(true); cont = getContentPane(); cont.setLayout(null); cont.add(j1); cont.setComponentZOrder(j1,0); j1.setBounds(20,245,10,10); cont.add(j2); cont.setComponentZOrder(j2,0); j2.setBounds(455,245,10,10); MouvementJ1 filJ1 = new MouvementJ1(); filJ1.start(); MouvementJ2 filJ2 = new MouvementJ2(); filJ2.start(); setContentPane(cont); } public class MouvementJ1 extends Thread implements KeyListener { public void run() { addKeyListener(this); while(continueJeu) { try { //regarde si le joueur 1 tape dans les murs if(j1.getX()>500 || j1.getX()<0 || j1.getY()>500 || j1.getY()<0) { j1Perd(); } //regarde si le joueur 1 tape dans les traces for(int i = 0; i < traces.size()-10; i++) { JLabel tmpTrace = (JLabel) traces.get(i); if(j1.getBounds().intersects(tmpTrace.getBounds())) { j1Perd(); } } //ajoute la trace JLabel temp = new JLabel(new ImageIcon("traceJ1.png"));; traces.add(temp); cont.add(temp); cont.setComponentZOrder(temp,1); temp.setBounds(j1.getX(),j1.getY(),10,10); if(p1Direction==HAUT) j1.setBounds(j1.getX(),j1.getY()-5,10,10); if(p1Direction==BAS) j1.setBounds(j1.getX(),j1.getY()+5,10,10); if(p1Direction==DROITE) j1.setBounds(j1.getX()+5,j1.getY(),10,10);

Chapitre 5

Jeux de stratgie

177

if(p1Direction==GAUCHE) j1.setBounds(j1.getX()-5,j1.getY(),10,10); cont.validate(); Thread.sleep(75); } catch(Exception e){ } } } public void j1Perd() { continueJeu = false; JOptionPane.showMessageDialog(null,"Le joueur 2 a gagn!"); } public void keyPressed(KeyEvent e) { if(e.getKeyChar()==q) p1Direction = GAUCHE; if(e.getKeyChar()==s) p1Direction = BAS; if(e.getKeyChar()==d) p1Direction = DROITE; if(e.getKeyChar()==z) p1Direction = HAUT; } public void keyTyped(KeyEvent e){ } public void keyReleased(KeyEvent e){ } } public class MouvementJ2 extends Thread implements KeyListener { public void run() { addKeyListener(this); while(continueJeu) { try { //regarde si le joueur 1 tape dans les murs if(j2.getX()>500 || j2.getX()<0 || j2.getY()>500 || j2.getY()<0) { j2Perd(); } //regarde si le joueur 2 tape dans les traces for(int i = 0; i < traces.size()-10; i++) { JLabel tmpTrace = (JLabel) traces.get(i); if(j2.getBounds().intersects(tmpTrace.getBounds())) { j2Perd(); } }

178

Devenez un petit gnie des jeux vido

//ajoute la trace JLabel temp = new JLabel(new ImageIcon("traceJ2.png"));; traces.add(temp); cont.add(temp); cont.setComponentZOrder(temp,1); temp.setBounds(j2.getX(),j2.getY(),10,10); if(p2Direction==HAUT) j2.setBounds(j2.getX(),j2.getY()-5,10,10); if(p2Direction==BAS) j2.setBounds(j2.getX(),j2.getY()+5,10,10); if(p2Direction==DROITE) j2.setBounds(j2.getX()+5,j2.getY(),10,10); if(p2Direction==GAUCHE) j2.setBounds(j2.getX()-5,j2.getY(),10,10); cont.validate(); Thread.sleep(75); } catch(Exception e){ } } } public void j2Perd() { continueJeu = false; JOptionPane.showMessageDialog(null,"Le joueur 1 a gagn!!!"); } public void keyPressed(KeyEvent e) { if(e.getKeyChar()==j) p2Direction = GAUCHE; if(e.getKeyChar()==k) p2Direction = BAS; if(e.getKeyChar()==l) p2Direction = DROITE; if(e.getKeyChar()==i) p2Direction = HAUT; } public void keyTyped(KeyEvent e){ } public void keyReleased(KeyEvent e){ } } public static void main (String[] args) { new Pieges(); } }

Les Figures 28.1 et 28.2 illustrent le jeu. Le projet suivant vous permettra dajouter un fond et dafcher les gagnants et perdants en un peu plus gros.

Chapitre 5

Jeux de stratgie

179

Figure 28.1 Les joueurs combattent

Figure 28.2 Le joueur 1 a pig le joueur 2

180

Devenez un petit gnie des jeux vido

Projet 29 : Piges Le spectacle


Projet Ajoutez une image de fond et des graphismes blouissants pour indiquer le gagnant.

Crer le jeu
Laissez libre cours votre imagination. Dessinez une image de taille 500 500 pixels. Crez un JLabel pour linsrer et utilisez la mthode setBounds pour la centrer. Noubliez pas dutiliser la mthode setComponentZOrder pour que limage de fond se trouve effectivement derrire les autres icnes. Dessinez ensuite une image (celle que vous voulez) pour indiquer le gagnant. Afchez cette image la place du JOptionPane lorsquun joueur gagne. Lorsquun joueur a gagn, ajoutez un "rembobinage" du jeu. Vous pouvez dfaire les mouvements des joueurs avec une boucle for en supprimant les segments de trace. Pour cela, crez une boucle for qui part du nombre de composants dans le conteneur moins quatre, de manire ne compter ni le fond ni les images des joueurs. Pour connatre le nombre de composants du conteneur, on utilise :
cont.getComponentCount()

Noubliez pas de rafrachir le conteneur aprs avoir supprim chaque morceau de trace. Crez aussi un JLabel contenant le mme texte que le JOptionPane du projet prcdent.
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.util.*; public class Pieges extends JFrame { //les joueurs JLabel j1 = new JLabel(new ImageIcon("j1.png")); JLabel j2 = new JLabel(new ImageIcon("j2.png")); boolean continueJeu = true; //directions int HAUT = 1, DROITE = 2, BAS = 3, GAUCHE = 4; int directionJ1 = DROITE; int directionJ2 = GAUCHE; //traces des joueurs ArrayList traces = new ArrayList(); Container cont; public Pieges() {

Chapitre 5

Jeux de stratgie

181

super("Trapper"); setSize(500,500); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); cont = getContentPane(); cont.setLayout(null); //JLabel du fond JLabel fond = new JLabel(new ImageIcon("fond.png")); cont.add(fond); fond.setBounds(0,0,500,500); cont.add(j1); cont.setComponentZOrder(j1,0); j1.setBounds(20,245,10,10); cont.add(j2); cont.setComponentZOrder(j2,0); j2.setBounds(455,245,10,10); MouvementJ1 filJ1 = new MouvementJ1(); filJ1.start(); MouvementJ2 filJ2 = new MouvementJ2(); filJ2.start(); setContentPane(cont); } public class MouvementJ1 extends Thread implements KeyListener { public void run() { addKeyListener(this); while(continueJeu) { try { //regarde si le joueur 1 tape dans les murs if(j1.getX()>500 || j1.getX()<0 || j1.getY()>500 || j1.getY()<0) { p1Perd(); } //regarde si le joueur 1 tape dans les traces for(int i = 0; i < traces.size()-10; i++) { JLabel tempTrail = (JLabel) traces.get(i); if(j1.getBounds().intersects(tempTrail.getBounds())) { p1Perd(); } } //ajoute la trace JLabel temp = new JLabel(new ImageIcon("traceJ1.png")); traces.add(temp); cont.add(temp); cont.setComponentZOrder(temp,1); temp.setBounds(j1.getX(),j1.getY(),10,10); if(directionJ1==HAUT) j1.setBounds(j1.getX(),j1.getY()-5,10,10); if(directionJ1==BAS) j1.setBounds(j1.getX(),j1.getY()+5,10,10); if(directionJ1==DROITE) j1.setBounds(j1.getX()+5,j1.getY(),10,10); if(directionJ1==GAUCHE) j1.setBounds(j1.getX()-5,j1.getY(),10,10);

182

Devenez un petit gnie des jeux vido

cont.validate(); Thread.sleep(75); } catch(Exception e){ } } } public void p1Perd() { try { continueJeu = false; JLabel gagnant = new JLabel("Le joueur 2 (bleu) a gagn!"); cont.add(gagnant); cont.setComponentZOrder(gagnant,0); gagnant.setFont(new Font("arial",Font.BOLD,30)); gagnant.setBounds(75,50,400,100); for(int i = cont.getComponentCount()-4; i > 0; i--) { cont.remove(i); cont.repaint(); Thread.sleep(25); } } catch(Exception e){ } } public void keyPressed(KeyEvent e) { if(e.getKeyChar()==q) directionJ1 = GAUCHE; if(e.getKeyChar()==s) directionJ1 = BAS; if(e.getKeyChar()==d) directionJ1 = DROITE; if(e.getKeyChar()==z) directionJ1 = HAUT; } public void keyTyped(KeyEvent e){ } public void keyReleased(KeyEvent e){ } } public class MouvementJ2 extends Thread implements KeyListener { public void run() { addKeyListener(this); while(continueJeu) { try { //regarde si le joueur 2 tape dans les murs if(j2.getX()>500 || j2.getX()<0 || j2.getY()>500 || j2.getY()<0) { j2Perd(); } //regarde si le joueur 1 tape dans les traces for(int i = 0; i < traces.size()-10; i++) { JLabel tempTrail = (JLabel) traces.get(i); if(j2.getBounds().intersects(tempTrail.getBounds())) { j2Perd(); } } //ajoute la trace JLabel temp = new JLabel(new ImageIcon("traceJ2.png"));

Chapitre 5

Jeux de stratgie

183

traces.add(temp); cont.add(temp); cont.setComponentZOrder(temp,1); temp.setBounds(j2.getX(),j2.getY(),10,10); if(directionJ2==HAUT) j2.setBounds(j2.getX(),j2.getY()-5,10,10); if(directionJ2==BAS) j2.setBounds(j2.getX(),j2.getY()+5,10,10); if(directionJ2==DROITE) j2.setBounds(j2.getX()+5,j2.getY(),10,10); if(directionJ2==GAUCHE) j2.setBounds(j2.getX()-5,j2.getY(),10,10); cont.validate(); Thread.sleep(75); } catch(Exception e){ } } } public void j2Perd() { try { continueJeu = false; JLabel winner = new JLabel("Le joueur 1 (noir) a gagn!"); cont.add(winner); cont.setComponentZOrder(winner,0); winner.setFont(new Font("arial",Font.BOLD,30)); winner.setBounds(75,50,400,100); for(int i = cont.getComponentCount()-4; i > 0; i--) { cont.remove(i); cont.repaint(); Thread.sleep(25); } } catch(Exception e){ } } public void keyPressed(KeyEvent e) { if(e.getKeyChar()==j) directionJ2 = GAUCHE; if(e.getKeyChar()==k) directionJ2 = BAS; if(e.getKeyChar()==l) directionJ2 = DROITE; if(e.getKeyChar()==i) directionJ2 = HAUT; } public void keyTyped(KeyEvent e){ } public void keyReleased(KeyEvent e){ } } public static void main(String[] args) { new Pieges(); } }

Les Figures 29.1 et 29.2 illustrent le jeu Piges dnitif.

184

Devenez un petit gnie des jeux vido

Figure 29.1 Limage de fond est en place pendant que les joueurs combattent

Figure 29.2 Le joueur 2 gagne, la trace commence disparatre

Chapitre 5

Jeux de stratgie

185

Pour aller plus loin...


Augmentez la vitesse dun des joueurs tout en diminuant la vitesse de lautre. Chaque vitesse a ses avantages et ses inconvnients. Modiez la taille des joueurs : trs grands ou trs petits ! Crez des niveaux : le meilleur joueur sur trois, cinq ou mme onze tours gagne la partie. Ajoutez deux personnages pour faire jouer quatre joueurs simultanment. Si vous tes seul jouer, vous pouvez crer une intelligence articielle pour vous battre contre lordinateur. Construisez le jeu de manire ce que les joueurs ne puissent tourner que dans un sens. Modiez les touches de manire alatoire au milieu du jeu. Les joueurs nauront aucune ide du sens dans lequel limage tournera !

6
Anciens jeux... revisits
Au sommaire de ce chapitre :

Oiram

Projet 30 : La plate-forme Projet 31 : Allez Oiram ! Projet 32 : Les mchants Projet 33 : Un monde compliqu

Javaman

Projet 34 : Lunivers de Javaman Projet 35 : Javaman vit ! Projet 36 : Lattaque du C++

188

Devenez un petit gnie des jeux vido

Projet 30 : Oiram La plate-forme


Oiram Aidez Oiram capturer les toiles et sauter sur ses ennemis en sautant de plate-forme en plate-forme ! Attention cependant, ce jeu contient plusieurs niveaux. Au fur et mesure quOiram bat ses ennemis, de nouveaux ennemis attendent le niveau suivant pour apparatre !
Projet Nouvelles briques Commencez par crer la plate-forme dans laquelle Oiram se bat. Tableaux deux dimensions.

Tableaux deux dimensions


Les tableaux deux dimensions fonctionnent comme les tableaux habituels, ceci prs quils ont des informations supplmentaires dans une autre dimension. La Figure 30.1 explique les ressemblances et les diffrences.
Figure 30.1 Deux types de tableaux

Pour crer un tableau deux dimensions, crez un tableau standard avec une seconde paire de crochets :
int tableau2D [][] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

Accder un lment se fait de la mme manire que pour les tableaux une dimension :
int element = tableau2D[ligne][colonne];

Chapitre 6

Anciens jeux... revisits

189

Le code suivant permet de connatre le nombre de lignes et de colonnes dun tableau deux dimensions :
int lignes = tableau2D.length; int colonnes = tableau2D[0].length;

Crer le jeu
Le plateau de jeu est divis en trois lments : la terre, lair et les chelles. Chacune de ces zones occupe un carr de 50 pixels de ct sur le plateau. Pour garder la trace de ces carrs, utilisez un tableau deux dimensions contenant des caractres # pour la terre, | pour les chelles et une espace pour lair. Vous devez dessiner les images avant dajouter les zones aux JFrame. Chaque image doit tre de taille 50 50 pixels. Les Figures 30.2 30.4 reprsentent les trois zones diffrentes.
Figure 30.2 Terre

Figure 30.3 Air

Figure 30.4 chelle

Pour afcher le plateau dans un JFrame, itrez sur le tableau grce deux boucles for. chaque itration, utilisez des instructions if pour vrier si la zone courante contient de lair, de la terre ou une chelle. Utilisez la mthode setBounds pour afcher la bonne image.
import import import import import javax.swing.*; javax.swing.event.*; java.awt.*; java.awt.event.*; java.util.*;

190

Devenez un petit gnie des jeux vido

import java.awt.geom.*; public class Oiram extends JFrame { Container cont; //le tableau deux dimensions String arene[][] = {{" "," "," "," "," "," "," "," "," "," "}, {" "," "," "," "," "," "," "," "," "," "}, {" "," "," "," "," "," ","|","#","#"," "}, {" ","#","#","#"," "," ","|","#"," "," "}, {" "," "," "," "," "," ","|","#"," "," "}, {" ","#","#","#","#","#","#","#","#"," "}, {" "," "," "," "," "," "," "," "," "," "}, {"#","#","#","#"," "," ","#","#","#","#"}, {" "," "," "," "," "," "," "," "," "," "}, {"#","#","#","#","#","#","#","#","#","#"}}; public Oiram() { super("Oiram"); setSize(500,500); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cont = getContentPane(); cont.setLayout(null); cont.setBackground(Color.BLACK); //gnre le tableau for(int i = 0; i < arene.length; i++) { for(int j = 0; j < arene[0].length; j++) { JLabel lbl = null; if(arene[j][i].equals("#")) { lbl = new JLabel(new ImageIcon("terre.png")); } else if(arene[j][i].equals(" ")) { lbl = new JLabel(new ImageIcon("air.png")); } else if(arene[j][i].equals("|")) { lbl = new JLabel(new ImageIcon("echelle.png")); } cont.add(lbl); lbl.setBounds(i*50,j*50,50,50); } } repaint(); cont.validate(); setContentPane(cont); } public static void main(String[ ] args) { new Oiram(); } }

Chapitre 6

Anciens jeux... revisits

191

La Figure 30.5 montre le monde de Oiram : la plate-forme.


Figure 30.5 Plate-forme

Dans la projet suivant, librez Oiram et donnez-lui des toiles rcuprer !

192

Devenez un petit gnie des jeux vido

Projet 31 : Oiram Allez Oiram !


Projet Mettez Oiram dans sa maison et permettez-lui de se dplacer. Ajoutez des toiles pour quil puisse les chasser et les capturer.

Crer le jeu
Crez Oiram. Crez pour cela une image de taille 50 50 pixels. Utilisez un JLabel et la mthode setBounds pour placer Oiram dans le coin en bas gauche. La Figure 31.1 montre Oiram son emplacement de dpart.
Figure 31.1 Emplacement de dpart dOiram

Dans le jeu, Oiram se dplace sur le sol, saute dans les airs et escalade des chelles. Crez des boolens pour reprsenter le saut et lescalade. Puis, ajoutez un KeyListener. Dans la mthode keyTyped, regardez si le joueur appuie sur les touches Q, Z et D pour dterminer le mouvement dOiram. Lorsque le joueur appuie sur Q, Oiram bouge vers la gauche. Examinez le boolen indiquant si Oiram est en train descalader. Si oui, positionnez le boolen false. Si non, dplacez-le de 50 pixels vers la gauche. Lorsque le joueur appuie sur Z, Oiram saute ou, sil est sur une chelle, escalade. Si Oiram se trouve dj dans les airs (cest--dire sil est dj en train de sauter ou de tomber), il ne doit pas pouvoir sauter. Si Oiram nest pas sur une chelle et si le carr au-dessus de lui est de lair, dterminez si Oiram est dj en train de sauter ou si le carr sous lui est de lair (et sil doit par consquent tomber). Si Oiram est effectivement sur le sol et sil nest pas dj en train de sauter, dplacez-le vers le haut de 50 pixels. Sil est sur une chelle, dplacez-le de 50 pixels vers le haut et regardez sil se trouve sur un carr dair. Si cest le cas, dplacez-le de 50 pixels vers la droite et positionnez la variable descalade false car il est arriv en haut de lchelle. Lorsque le joueur appuie sur D, Oiram se dplace vers la droite. Vriez dabord quOiram se trouve dans larne. Si oui, vriez si lespace la droite dOiram est de

Chapitre 6

Anciens jeux... revisits

193

lair. Si oui, dplacez Oiram de 50 pixels vers la droite. Si lemplacement sa droite est une chelle, dplacez Oiram de 50 pixels vers la droite et positionnez la variable descalade true. Dmarrez maintenant le jeu. LorsquOiram monte sur une chelle, laspect de lensemble est bizarre, comme le montre la Figure 31.2.
Figure 31.2 Oiram escalade, mais il a lair bizarre

Pour corriger cela, crez une nouvelle image de taille 50 50 pixels reprsentant Oiram escaladant lchelle. Ne lafchez que lorsque la variable descalade est true. La Figure 31.3 illustre la nouvelle image amliore.
Figure 31.3 Oiram escalade ; il na plus lair bizarre

Oiram peut maintenant se dplacer. Il faut donc ajouter des toiles pour quil puisse les attraper. Pour cela, crez une mthode qui gnre alatoirement la position des toiles. Utilisez deux boucles for pour itrer dans le tableau du jeu. Si lemplacement du plateau contient de lair, utilisez un nombre alatoire entre 0 et 9 pour donner une chance sur 10 une toile dapparatre. Si le nombre gnr est 0, crez une toile lemplacement en question. Noubliez pas de lajouter un ArrayList. Cette mthode doit tre appele partir du constructeur. Il ne reste que deux choses faire : faire tomber Oiram et lui permettre de rcuprer les toiles. Pour cela, crez un l dexcution appel Course. Dans la boucle innie, itrez dans lArrayList dtoiles. Si Oiram entre en collision avec une toile, retirez ltoile du conteneur et de l ArrayList. Puis, ajoutez une instruction if pour savoir si Oiram est en train de sauter. Si cest le cas, dplacez Oiram de 50 pixels vers le haut et terminez son saut en donnant la valeur false au boolen. Si Oiram nest pas en train de sauter, vriez si le carr sous lui est compos dair. Si oui, descendez Oiram de 50 pixels. Noubliez pas dajouter la mthode Thread.sleep votre boucle innie.

194

Devenez un petit gnie des jeux vido

import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.awt.geom.*; public class Oiram extends JFrame implements KeyListener { Container cont; //tableau deux dimensions String arene[ ][ ] = {{" "," "," "," "," "," "," "," "," "," "}, {" "," "," "," "," "," "," "," "," "," "}, {" "," "," "," "," "," ","|","#","#"," "}, {" ","#","#","#"," "," ","|","#"," "," "}, {" "," "," "," "," "," ","|","#"," "," "}, {" ","#","#","#","#","#","#","#","#"," "}, {" "," "," "," "," "," "," "," "," "," "}, {"#","#","#","#"," "," ","#","#","#","#"}, {" "," "," "," "," "," "," "," "," "," "}, {"#","#","#","#","#","#","#","#","#","#"}}; ArrayList etoiles = new ArrayList(); JLabel personnage = new JLabel(new ImageIcon("oiram.png")); boolean saut = false; boolean escalade = false; Jeu jeu; public Oiram() { super("Oiram"); setSize(500,500); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cont = getContentPane(); cont.setLayout(null); addKeyListener(this); cont.setBackground(Color.BLACK); cont.add(personnage); personnage.setBounds(0,400,50,50); genereEtoiles(); //genere le tableau for(int i = 0; i < arene.length; i++) { for(int j = 0; j < arene[0].length; j++) { JLabel lbl = null; if(arene[j][i].equals("#")) { lbl = new JLabel(new ImageIcon("terre.png")); } else if(arene[j][i].equals(" ")) { lbl = new JLabel(new ImageIcon("air.png")); } else if(arene[j][i].equals("|")) { lbl = new JLabel(new ImageIcon("echelle.png")); } cont.add(lbl); lbl.setBounds(i*50,j*50,50,50); } }

Chapitre 6

Anciens jeux... revisits

195

repaint(); cont.validate(); jeu = new Jeu(); jeu.start(); setContentPane(cont); } //ajoute les toiles public void genereEtoiles() { for(int i = 1; i < arene.length; i++) { for(int j = 0; j < arene[0].length; j++) { //regarde si lemplacement est de lair if(arene[i][j].equals(" ")) { //une chance sur 10 quune toile apparaisse int placeEtoile = (int)(Math.random()*10); if(placeEtoile==0) { JLabel etoile = new JLabel(new ImageIcon("etoile.png")); cont.add(etoile); etoile.setBounds(j*50,i*50,50,50); cont.setComponentZOrder(etoile,0); cont.setComponentZOrder(personnage,0); etoiles.add(etoile); } } } } } public class Jeu extends Thread { public void run() { while(true) { try { //si Oiram touche une toile, on lenlve for(int i = 0; i < etoiles.size(); i++) { JLabel star = (JLabel) etoiles.get(i); if(star.getBounds().intersects(personnage.getBounds())) { cont.remove(star); etoiles.remove(star); } } //fait tomber Oiram if(!saut) { if(arene[(personnage.getY()/50)+1][personnage.getX()/50].equals(" ")) { personnage.setBounds(personnage.getX(),personnage.getY()+50,50,50); } } else { //termine le saut dOiram litration suivante saut = false; //fait bouger Oiram vers le haut if(arene[(personnage.getY()/50)-1][personnage.getX()/50].equals(" ")) { personnage.setBounds(personnage.getX(),personnage.getY()-50,50,50); } } Thread.sleep(250); } catch(Exception e){ }

196

Devenez un petit gnie des jeux vido

} } } public void keyPressed(KeyEvent e){ } public void keyReleased(KeyEvent e){ } public void keyTyped(KeyEvent e) { //dplacement gauche if(e.getKeyChar()==q) { if(escalade) { escalade = false; personnage.setIcon(new ImageIcon("oiram.png")); } if(personnage.getX()>=50 && arene[personnage.getY()/50][(personnage.getX()/50)-1].equals(" ")) { personnage.setBounds(personnage.getX()-50,personnage.getY(),50,50); } } //dplacement droite if(e.getKeyChar()==d) { if(personnage.getX()<=400 && arene [personnage.getY()/50][(personnage.getX()/50)+1].equals(" ")) { personnage.setBounds(personnage.getX()+50,personnage.getY(),50,50); } if(arene[personnage.getY()/50][(personnage.getX()/50)+1].equals("|")) { personnage.setBounds(personnage.getX()+50,personnage.getY(),50,50); escalade = true; personnage.setIcon(new ImageIcon("surechelle.png")); } } //dplacement vers le haut if(e.getKeyChar()==z) { if(!escalade) { if(arene[(personnage.getY()/50)-1][personnage.getX()/50].equals(" ")) { if(!saut &&!arene[(personnage.getY()/50)+1][personnage.getX() /50].equals(" ")) { saut = true; personnage.setBounds(personnage.getX(),personnage.getY()-50,50,50); } } } else { personnage.setBounds(personnage.getX(), personnage.getY()-50,50,50); if(arene[personnage.getY()/50][personnage.getX()/50].equals(" ")) { personnage.setBounds(personnage.getX()+50,personnage.getY(),50,50); escalade = false; personnage.setIcon(new ImageIcon("oiram.png")); } } } } public static void main(String[ ] args) { new Oiram(); } }

Chapitre 6

Anciens jeux... revisits

197

Les Figures 31.4 et 31.5 montrent Oiram en action. Tout petit gnie des jeux vido sait quun jeu nest pas complet sans adversaire affronter. Le projet suivant explique comment rendre la vie dOiram bien plus difcile.
Figure 31.4 La plate-forme

Figure 31.5 Collecte dtoiles

198

Devenez un petit gnie des jeux vido

Projet 32 : Oiram Les mchants


Projet La chasse est ouverte ! Dessinez les ennemis dOiram. Ils sont rapides, acharns... et redoutables.

Crer le jeu
Dessinez dabord une image de 50 50 pixels dun ennemi dOiram, comme celui de la Figure 32.1.
Figure 32.1 Ennemi dOiram

Puis, crez une mthode pour ajouter les ennemis la plate-forme. Utilisez une boucle pour crer deux ennemis. Placez-les tout en haut de lcran et donnez-leur une coordonne X alatoire. Ajoutez aussi les enemis un ArrayList pour pouvoir y accder facilement ultrieurement. Les ennemis dOiram sont contrls trs simplement : sil y a de lair sous eux, ils tombent. Sinon, ils se dplacent vers la droite ou vers la gauche. Dans la boucle du l dexcution, utilisez une boucle for pour examiner la position de tous les ennemis de lArrayList. Une instruction if permet de dterminer si lennemi se trouve au-dessus dune zone dair. Si cest le cas, descendez lennemi de 50 pixels. Puis, gnrez un nombre alatoire (0 ou 1) en multipliant le rsultat de la mthode Math.random par deux. Si le nombre est 0, vriez si le carr droite de lennemi est de lair. Si oui, dplacez lennemi de 50 pixels vers la droite. Si le nombre alatoire vaut 1, vriez si le carr gauche de lennemi est de lair. Si oui, dplacez lennemi de 50 pixels vers la gauche. Maintenant que les ennemis se dplacent, il faut donner Oiram une chance de se battre. Sil saute sur un ennemi, lennemi meurt. Utilisez une instruction if pour comparer lemplacement dOiram et de son adversaire. Si Oiram est 50 pixels audessus de lennemi, supprimez lennemi du conteneur. Si Oiram occupe le mme carr que son adversaire, supprimez Oiram : lennemi a gagn.

Chapitre 6

Anciens jeux... revisits

199

import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.awt.geom.*; public class Oiram extends JFrame implements KeyListener { //conteneur Container cont; //tableau deux dimensions String arene[][] = {{" "," "," "," "," "," "," "," "," "," "}, {" "," "," "," "," "," "," "," "," "," "}, {" "," "," "," "," "," ","|","#","#"," "}, {" ","#","#","#"," "," ","|","#"," "," "}, {" "," "," "," "," "," ","|","#"," "," "}, {" ","#","#","#","#","#","#","#","#"," "}, {" "," "," "," "," "," "," "," "," "," "}, {"#","#","#","#"," "," ","#","#","#","#"}, {" "," "," "," "," "," "," "," "," "," "}, {"#","#","#","#","#","#","#","#","#","#"}}; //contient les toiles ArrayList etoiles = new ArrayList(); //Oiram JLabel personnage = new JLabel(new ImageIcon("oiram.png")); //Oiram est-il en train de sauter ou descalader? boolean saut = false; boolean escalade = false; //fil dexcution Jeu jeu; //contient les ennemis ArrayList ennemis = new ArrayList(); public Oiram() { super("Oiram"); setSize(500,500); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cont = getContentPane(); cont.setLayout(null); addKeyListener(this); cont.setBackground(Color.BLACK); //ajoute Oiram cont.add(personnage); personnage.setBounds(0,400,50,50); //cre les toiles et les ennemis genereEtoiles(); genereEnnemis(); //gnre le tableau for(int i = 0; i < arene.length; i++) {

200

Devenez un petit gnie des jeux vido

for(int j = 0; j < arene[0].length; j++) { JLabel lbl = null; if(arene[j][i].equals("#")) { lbl = new JLabel(new ImageIcon("terre.png")); } else if(arene[j][i].equals(" ")) { lbl = new JLabel(new ImageIcon("air.png")); } else if(arene[j][i].equals("|")) { lbl = new JLabel(new ImageIcon("echelle.png")); } cont.add(lbl); lbl.setBounds(i*50,j*50,50,50); } } repaint(); cont.validate(); //dmarre le fil dexcution jeu = new Jeu(); jeu.start(); setContentPane(cont); } public void genereEtoiles() { //boucle dans le tableau deux dimensions for(int i = 1; i < arene.length; i++) { for(int j = 0; j < arene[0].length; j++) { if(arene[i][j].equals(" ")) { //probabilit de placer une toile: 1/10 int placeEtoile = (int)(Math.random()*10); if(placeEtoile==0) { //ajoute ltoile JLabel etoile = new JLabel(new ImageIcon("etoile.png")); cont.add(etoile); etoile.setBounds(j*50,i*50,50,50); cont.setComponentZOrder(etoile,0); cont.setComponentZOrder(personnage,0); etoiles.add(etoile); } } } } } public void genereEnnemis() { //ajoute les ennemis for(int i = 0; i < 2; i++) { JLabel ennemi = new JLabel(new ImageIcon("ennemi.png")); cont.add(ennemi); int emplX = (int)(Math.random()*8); ennemi.setBounds(emplX*50,0,50,50); cont.setComponentZOrder(ennemi,0); ennemis.add(ennemi); } }

Chapitre 6

Anciens jeux... revisits

201

public class Jeu extends Thread { public void run() { while(true) { try { //vrifie ce qui suit sur tous les ennemis for(int i = 0; i < ennemis.size(); i++) { JLabel ennemi = (JLabel) ennemis.get(i); //napplique ce qui suit quaux ennemis sur lcran if(ennemi.getY()<=450 && ennemi.getX()<=450) { //descent lennemi, si possible if(arene[(ennemi.getY()/50)+1][ennemi.getX()/50].equals(" ")) { ennemi.setBounds(ennemi.getX(),ennemi.getY()+50,50,50); } //dplace lennemi vers la droite ou la gauche int direction = (int)(Math.random()*2); if(direction==0) { if(arene[ennemi.getY()/50][(ennemi.getX()/50)+1].equals(" ")) { ennemi.setBounds(ennemi.getX()+50,ennemi.getY(),50,50); } } else { if(arene[ennemi.getY()/50][(ennemi.getX()/50)-1].equals(" ")) { ennemi.setBounds(ennemi.getX()-50,ennemi.getY(),50,50); } } //si Oiram saute sur un ennemi, supprime lennemi if(ennemi.getY()-50==personnage.getY() && ennemi.getX() ==personnage.getX()) { ennemi.setBounds(1000,1000,50,50); cont.remove(ennemi); } //si un ennemi mange Oiram, affiche limage de dfaite if(ennemi.getY()==personnage.getY() && ennemi.getX() ==personnage.getX()) { cont.remove(personnage); } } } //vrifie ce qui suit sur toutes les toiles for(int i = 0; i < etoiles.size(); i++) { JLabel star = (JLabel) etoiles.get(i); //si Oiram capture une toile, on la supprime if(star.getBounds().intersects(personnage.getBounds())) { cont.remove(star); etoiles.remove(star); } } //Oiram tombe if(!saut) { if(arene[(personnage.getY()/50)+1][personnage.getX()/50].equals(" ")) { personnage.setBounds(personnage.getX(),personnage.getY()+50,50,50); } }

202

Devenez un petit gnie des jeux vido

//Oiram saute else { saut = false; if(arene[(personnage.getY()/50)-1][personnage.getX()/50] .equals(" ")) { personnage.setBounds(personnage.getX(),personnage.getY()-50,50,50); } } //temporisation Thread.sleep(250); } catch(Exception e){ } } } } public void keyPressed(KeyEvent e){ } public void keyReleased(KeyEvent e){ } public void keyTyped(KeyEvent e) { //dplacement vers la gaucuhe if(e.getKeyChar()==q) { //si Oiram escalade, on arrte lescalade if(escalade) { escalade = false; personnage.setIcon(new ImageIcon("oiram.png")); } //dplacement vers la gauche sil est possible if(personnage.getX()>=50 && arene[personnage.getY()/ 50][(personnage.getX()/50)1].equals(" ")) { personnage.setBounds(personnage.getX()-50,personnage.getY(),50,50); } } //dplacement vers la droite if(e.getKeyChar()==d) { //ne pas permettre Oiram de sortir de lcran if(personnage.getX()<=400 && arene[personnage.getY()/50][(personnage.getX()/50)+1].equals(" ")) { personnage.setBounds(personnage.getX()+50,personnage.getY(),50,50); } //si Oiram touche une chelle, commencer escalader if(arene[personnage.getY()/50][(personnage.getX()/50)+1].equals("|")) { personnage.setBounds(personnage.getX()+50,personnage.getY(),50,50); escalade = true; personnage.setIcon(new ImageIcon("surechelle.png")); } } //saute/escalade if(e.getKeyChar()==z) { //si Oiram nest pas surune chelle, saute if(!escalade) { if(arene[(personnage.getY()/50)-1][personnage.getX()/50].equals(" ")) {

Chapitre 6

Anciens jeux... revisits

203

if(!saut &&!arene[(personnage.getY()/50)+1][personnage.getX() /50].equals(" ")) { saut = true; personnage.setBounds(personnage.getX(),personnage.getY()-50,50,50); } } } //dplace Oiram sur lchelle else { personnage.setBounds(personnage.getX(), personnage.getY()-50,50,50); //Oiram arrive en haut de lchelle. Modifie son icne et le dplace if(arene[personnage.getY()/50][personnage.getX()/50].equals(" ")) { personnage.setBounds(personnage.getX()+50,personnage.getY(),50,50); escalade = false; personnage.setIcon(new ImageIcon("oiram.png")); } } } } public static void main(String[ ] args) { new Oiram(); } }

Les Figures 32.2 32.4 illustrent laction de lennemi. Mais ce nest pas termin pour Oiram ! Continuez pour apprendre comment ajouter des niveaux supplmentaires de difcult.
Figure 32.2 Les ennemis sont vivants !

204

Devenez un petit gnie des jeux vido

Figure 32.3 Un ennemi mort

Figure 32.4 Le dernier ennemi tue Oiram

Chapitre 6

Anciens jeux... revisits

205

Projet 33 : Oiram Un monde compliqu


Projet Ajoutez des niveaux de difcult et des images de victoire ou de dfaite.

Crer le jeu
Oiram va se battre dans cinq niveaux : chaque niveau ajoute des ennemis supplmentaires. Pour augmenter le nombre dennemis, modiez lgrement la mthode qui les dessine. Crez une variable globale pour garder trace du niveau de jeu. Dclarez une autre variable dans la mthode pour contenir un nombre alatoire (1 ou 2). Ajoutez ce nombre alatoire au numro du niveau : cela dterminera le nombre dennemis. Un nouveau niveau commence lorsquOiram supprime tous ses adversaires et lorsquil rcupre toutes les toiles. Pour commencer un nouveau niveau, initialisez deux variables : une qui garde trace des ennemis et une qui garde trace du nombre dtoiles. Chaque fois quOiram rcupre une toile ou bat un ennemi, dcrmentez de 1 la variable approprie. Dans la boucle innie, vriez les valeurs des deux variables. Lorsquelles sont toutes les deux 0, incrmentez le numro du niveau de 1. Appelez les mthodes gnrant les toiles et les ennemis. Ajoutez aussi un JLabel pour afcher le niveau courant. Noubliez pas de rafrachir le JLabel quand le niveau change. Pour donner un score Oiram, crez une variable. Incrmentez-la de 100 chaque fois quOiram capture une toile. Incrmentez-la de 200 lorsquOiram bat un adversaire. Afchez le score dans un JLabel. Vous pouvez aussi ajouter une image de titre amusante. Dessinez Oiram dans une image de 500 50 et afchez un JLabel contenant cette image en haut de la plateforme. Pour ajouter des images de victoire ou de dfaite, crez deux images de 500 500. Afchez-les dabord en dehors de lcran. Si Oiram meurt ou gagne en passant le niveau 5, dplacez la bonne image au centre de larne. Noubliez pas de supprimer toutes les autres images.
import import import import import import public javax.swing.*; javax.swing.event.*; java.awt.*; java.awt.event.*; java.util.*; java.awt.geom.*; class Oiram extends JFrame implements KeyListener {

206

Devenez un petit gnie des jeux vido

//le conteneur Container cont; //tableau deux dimensions String arene[][] = {{" "," "," "," "," "," "," "," "," "," "}, {" "," "," "," "," "," "," "," "," "," "}, {" "," "," "," "," "," ","|","#","#"," "}, {" ","#","#","#"," "," ","|","#"," "," "}, {" "," "," "," "," "," ","|","#"," "," "}, {" ","#","#","#","#","#","#","#","#"," "}, {" "," "," "," "," "," "," "," "," "," "}, {"#","#","#","#"," "," ","#","#","#","#"}, {" "," "," "," "," "," "," "," "," "," "}, {"#","#","#","#","#","#","#","#","#","#"}}; //contient les toiles ArrayList stars = new ArrayList(); //Oiram JLabel character = new JLabel(new ImageIcon("oiram.png")); //Oiram est-il en train descalader ou de sauter? boolean saut = false; boolean escalade = false; //fil dexcution Jeu jeu; //score int score = 0; //nombre dtoiles restantes int etoilesRestantes; //contient les ennemis ArrayList ennemis = new ArrayList(); //images pour la victoire ou la dfaite JLabel victoire = new JLabel(new ImageIcon("victoire.png")); JLabel defaite = new JLabel(new ImageIcon("defaite.png")); //image de titre JLabel titre = new JLabel(new ImageIcon("titre.png")); //niveau courant int niveau = 1; //nombre dennemis int nbEnnemis = 1; //affiche le niveau et le score JLabel lblNiveau = new JLabel("Niveau "+niveau+"/5"); JLabel lblScore = new JLabel("Score "+score); public Oiram() { super("Oiram"); setSize(500,500); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cont = getContentPane(); cont.setLayout(null); addKeyListener(this); cont.setBackground(Color.BLACK);

Chapitre 6

Anciens jeux... revisits

207

//ajoute les images de dfaite et de victoire en dehors de lcran cont.add(victoire); victoire.setBounds(500,500,500,500); cont.add(defaite); defaite.setBounds(500,500,500,500); //affiche le niveau cont.add(lblNiveau); lblNiveau.setFont(new Font("arial",Font.BOLD,20)); lblNiveau.setBounds(375,5,150,50); //affiche le score cont.add(lblScore); lblScore.setFont(new Font("arial",Font.BOLD,20)); lblScore.setBounds(20,5,150,50); //ajoute limage de titre cont.add(titre); titre.setBounds(0,0,500,50); //ajoute Oiram cont.add(character); character.setBounds(0,400,50,50); //cre les toiles et les ennemis genereEtoiles(); genereEnnemis(); //gnre le tableau for(int i = 0; i < arene.length; i++) { for(int j = 0; j < arene[0].length; j++) { JLabel lbl = null; if(arene[j][i].equals("#")) { lbl = new JLabel(new ImageIcon("terre.png")); } else if(arene[j][i].equals(" ")) { lbl = new JLabel(new ImageIcon("air.png")); } else if(arene[j][i].equals("|")) { lbl = new JLabel(new ImageIcon("echelle.png")); } cont.add(lbl); lbl.setBounds(i*50,j*50,50,50); } } repaint(); cont.validate(); //dmarre le fil dexcution jeu = new Jeu(); jeu.start(); setContentPane(cont); } public void genereEtoiles() { //boucle dans le tableau deux dimensions for(int i = 1; i < arene.length; i++) { for(int j = 0; j < arene[0].length; j++) { if(arene[i][j].equals(" ")) {

208

Devenez un petit gnie des jeux vido

//une chance sur 10 de placer une toile int placeEtoile = (int)(Math.random()*10); if(placeEtoile==0) { //ajoute ltoile JLabel star = new JLabel(new ImageIcon("etoile.png")); cont.add(star); star.setBounds(j*50,i*50,50,50); cont.setComponentZOrder(star,0); cont.setComponentZOrder(character,0); stars.add(star); etoilesRestantes++; } } } } } public void genereEnnemis() { //ajoute un nombre alatoire dennemis int augmenterDe = (int)(Math.random()*2)+1; nbEnnemis = niveau+augmenterDe; //ajoute les nouveaux ennemis for(int i = 0; i < nbEnnemis; i++) { JLabel ennemi = new JLabel(new ImageIcon("ennemi.png")); cont.add(ennemi); int emplX = (int)(Math.random()*8); ennemi.setBounds(emplX*50,0,50,50); cont.setComponentZOrder(ennemi,0); ennemis.add(ennemi); } } public class Jeu extends Thread { public void run() { while(true) { try { //score courant lblScore.setText("Score "+score); //vrifie ce qui suit pour tous les ennemis for(int i = 0; i < ennemis.size(); i++) { JLabel enemy = (JLabel) ennemis.get(i); //napplique ce qui suit quaux ennemis sur lcran if(enemy.getY()<=450 && enemy.getX()<=450) { //descend lennemi si cest possible if(arene[(enemy.getY()/50)+1] [enemy.getX()/50].equals(" ")) { enemy.setBounds(enemy.getX(), enemy.getY()+50,50,50); } //dplace lennemi vers la gauche ou la droite int direction = (int)(Math.random()*2); if(direction==0) { if(arene[enemy.getY()/50][(enemy.getX()/50)+1].equals(" ")) { enemy.setBounds(enemy.getX()+50,enemy.getY(),50,50); }

Chapitre 6

Anciens jeux... revisits

209

} else { if(arene[enemy.getY()/50][(enemy.getX()/50)-1].equals(" ")) { enemy.setBounds(enemy.getX()-50,enemy.getY(),50,50); } } //si Oiram saute sur un ennemi, supprime lennemi if(enemy.getY()-50==character.getY() && enemy.getX() ==character.getX()) { enemy.setBounds(1000,1000,50,50); cont.remove(enemy); nbEnnemis--; score+=200; } //si un ennemi mange Oiram, affiche limage de dfaite if(enemy.getY()==character.getY() &&enemy.getX()==character.getX()) { defaite.setBounds(0,0,500,500); cont.setComponentZOrder(defaite,0); for(int j=2; j < cont.getComponentCount(); j++) { cont.remove(j); } cont.validate(); } } } //allez au niveau 5 pour gagner! if(niveau>=5) { victoire.setBounds(0,0,500,500); cont.setComponentZOrder(victoire,0); for(int i = 2; i < cont.getComponentCount(); i++) { cont.remove(i); } cont.validate(); } //niveau suivant if(nbEnnemis<=0 && etoilesRestantes<=0) { niveau++; genereEtoiles(); genereEnnemis(); lblNiveau.setText("Niveau "+niveau+"/5"); } //vrifie ce qui suit pour toutes les toiles for(int i = 0; i < stars.size(); i++) { JLabel star = (JLabel) stars.get(i); //si Oiram capture une toile, on la supprime if(star.getBounds().intersects(character.getBounds())) { score+=100; cont.remove(star); stars.remove(star); etoilesRestantes--; } }

210

Devenez un petit gnie des jeux vido

//Oiram tombe if(!saut) { if(arene[(character.getY()/50)+1][character.getX()/50].equals(" ")) { character.setBounds(character.getX(),character.getY()+50,50,50); } } //Oiram saute else { saut = false; if(arene[(character.getY()/50)-1][character.getX()/50].equals(" ")) { character.setBounds(character.getX(),character.getY()-50,50,50); } } //temporisation Thread.sleep(250); } catch(Exception e){ } } } } public void keyPressed(KeyEvent e){ } public void keyReleased(KeyEvent e){ } public void keyTyped(KeyEvent e) { //dplacement vers la gauche if(e.getKeyChar()==q) { //si Oiram escalade, termine lescalade if(escalade) { escalade = false; character.setIcon(new ImageIcon("oiram.png")); } //dplace Oiram vers la gauche si possible if(character.getX()>=50 && arene[character.getY()/50][(character.getX()/50)-1] .equals(" ")) { character.setBounds(character.getX()-50,character.getY(),50,50); } } //dplacement vers la droite if(e.getKeyChar()==d) { //empche Oiram de sortir de lcran if(character.getX()<=400 && arene[character.getY()/50][(character.getX()/50)+1].equals(" ")) { character.setBounds(character.getX()+50,character.getY(),50,50); } //si Oiram touche une chelle, commence escalader if(arene[character.getY()/50][(character.getX()/50)+1].equals("|")) { character.setBounds(character.getX()+50,character.getY(),50,50); escalade = true; character.setIcon(new ImageIcon("surechelle.png")); } } //saute/escalade if(e.getKeyChar()==z) {

Chapitre 6

Anciens jeux... revisits

211

//if Oiram is not climbing, then jump up! if(!escalade) { if(arene[(character.getY()/50)-1][character.getX()/50].equals(" ")) { if(!saut &&!arene[(character.getY()/50)+1][character.getX() /50].equals(" ")) { saut = true; character.setBounds(character.getX(),character.getY()-50,50,50); } } } //dplace Oiram sur lchelle else { character.setBounds(character.getX(),character.getY()-50,50,50); //Oiram a atteint le haut de lchelle, change son icne et le dplace if(arene[character.getY()/50][character.getX()/50].equals(" ")) { character.setBounds(character.getX()+50,character.getY(),50,50); escalade = false; character.setIcon(new ImageIcon("oiram.png")); } } } } public static void main(String[] args) { new Oiram(); } }

Les Figures 33.1 33.3 illustrent la vie et la mort dOiram.


Figure 33.1 Afchage du niveau et du score

212

Devenez un petit gnie des jeux vido

Figure 33.2 Oiram a perdu

Figure 33.3 Oiram a gagn

Chapitre 6

Anciens jeux... revisits

213

Pour aller plus loin...


Modiez la disposition de larne. Ajoutez plus de plates-formes, plus dchelles, etc. Modiez licne dOiram en un ballon dirigeable lui permettant de faire tomber des bombes sur ses ennemis. Ajoutez des effets sonores lorsquOiram rcupre une toile ou tue un ennemi. Programmez des applaudissements pour les victoires et des hues pour les dfaites. Ajoutez des super-toiles permettant Oiram de voler temporairement. Augmentez la taille du tableau en rtrcissant les zones des tailles de 10 10 pixels. Clonez Oiram an quil y en ait deux ou trois dans larne. Ajoutez un ennemi invisible. Lorsquil se rapproche, programmez un "tremblement" de lcran pour alerter Oiram de la prsence de son ennemi.

214

Devenez un petit gnie des jeux vido

Projet 34 : Javaman Lunivers de Javaman


Javaman Java et C++, les deux plus grands langages de programmation, entrent en guerre ! Manuvrez Javaman pour quil rcupre tous les points sur le champ avant que C++ ne lassche.
Projet Crez lunivers de Javaman : le plateau de jeu.

Crer le jeu
Pour crer le plateau, utilisez un tableau deux dimensions dobjets String. Les "#" reprsentent les murs et les espaces reprsentent les zones vides. On reprsentera donc une bote vide sous cette forme :
#### # # # # ####

Le plateau de Javaman peut tre cr de la mme manire :


########## # # # # ## # # # ## # # # # ## # # ## # # # # ## # # # ## # # # # ##########

Dans le constructeur, une boucle permet dexaminer tous les lments du tableau. La position des lments dans le tableau deux dimensions doit correspondre leur emplacement dans le JFrame. Dessinez des images de 50 50 pixels de blocs jaunes solides et des images de 50 50 pixels reprsentant des carrs noirs avec un cercle blanc lintrieur. Les blocs jaunes sont utiliss pour les carrs de type "#" et les blocs noirs pour les espaces vides. Utiliser des tableaux facilite la modication de la disposition du plateau.

Chapitre 6

Anciens jeux... revisits

215

import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.awt.geom.*; public class Javaman extends JFrame { Container cont; //tableau deux dimensions String arene[][] = {{"#","#","#","#","#","#","#","#","#","#"}, {"#"," "," "," ","#"," "," "," "," ","#"}, {"#"," ","#"," ","#"," "," ","#"," ","#"}, {"#"," ","#"," ","#"," ","#","#"," ","#"}, {"#"," ","#"," "," "," "," ","#"," ","#"}, {"#"," ","#","#"," "," "," ","#"," ","#"}, {"#"," ","#"," "," ","#"," ","#"," ","#"}, {"#"," ","#"," "," ","#"," ","#"," ","#"}, {"#"," "," "," "," ","#"," "," "," ","#"}, {"#","#","#","#","#","#","#","#","#","#"}}; public Javaman() { super("Javaman"); setSize(500,500); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cont = getContentPane(); cont.setLayout(null); cont.setBackground(Color.BLACK); //cre le plateau for(int i = 0; i < arene.length; i++) { for(int j = 0; j < arene[0].length; j++) { JLabel lbl = null; if(arene[i][j].equals("#")) { lbl = new JLabel(new ImageIcon("mur.png")); } else { lbl = new JLabel(new ImageIcon("pastille.png")); } cont.add(lbl); lbl.setBounds(i*50,j*50,50,50); } } repaint(); cont.validate(); setContentPane(cont); }

216

Devenez un petit gnie des jeux vido

public static void main (String[] args) { new Javaman(); } }

La Figure 34.1 illustre lunivers de Javaman. Dans le projet suivant, nous insuferons la vie Javaman. Prparez-le se battre pour sa vie en le rendant mobile.
Figure 34.1 Plateau de Javaman

Chapitre 6

Anciens jeux... revisits

217

Projet 35 : Javaman Javaman vit !


Projet Placez Javaman sur le plateau de jeu. Puis, offrez-lui la vie en ajoutant des contrles au clavier pour modier sa direction.

Crer le jeu
Le plateau de jeu est en place ; on peut ajouter Javaman. Crez une image 50 50 dune tasse de caf. Dans le constructeur, ajoutez cette image avant dajouter le plateau. Placez-le dans le coin en haut droite, en position (50, 50), comme le montre la Figure 35.1. Offrez le mouvement Javaman. Commencez par ajouter un KeyListener la classe. Noubliez pas dajouter les trois mthodes obligatoires. Comme dans le jeu la course du courage, utilisez des variables pour garder trace de lorientation de Javaman (1 vers le haut, 2 vers le bas, 3 vers la droite et 4 vers la gauche). Dans la mthode keyPressed, changez alors la direction de Javaman. Ensuite, crez un l dexcution pour faire avancer JavaMan en ajoutant ou en soustrayant 50 ses coordonnes x et y. Pour viter que Javaman ne passe travers les murs, vriez la valeur de llment correspondant sa position dans le tableau deux dimensions. Si llment est #, redplacez Javaman sa position prcdente.
Figure 35.1 Javaman : position de dpart

import import import import import import

javax.swing.*; javax.swing.event.*; java.awt.*; java.awt.event.*; java.util.*; java.awt.geom.*;

218

Devenez un petit gnie des jeux vido

public class Javaman extends JFrame implements KeyListener { Container cont; int HAUT = 0, BAS = 1, DROITE = 2, GAUCHE = 3; int direction = DROITE; int positionX = 1, positionY = 1; String arene[][] = {{"#","#","#","#","#","#","#","#","#","#"}, {"#"," "," "," ","#"," "," "," "," ","#"}, {"#"," ","#"," ","#"," "," ","#"," ","#"}, {"#"," ","#"," ","#"," ","#","#"," ","#"}, {"#"," ","#"," "," "," "," ","#"," ","#"}, {"#"," ","#","#"," "," "," ","#"," ","#"}, {"#"," ","#"," "," ","#"," ","#"," ","#"}, {"#"," ","#"," "," ","#"," ","#"," ","#"}, {"#"," "," "," "," ","#"," "," "," ","#"}, {"#","#","#","#","#","#","#","#","#","#"}}; JLabel javaMan = new JLabel(new ImageIcon("javaman.png")); public Javaman() { super("JavaMan"); setSize(500,500); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cont = getContentPane(); cont.setLayout(null); addKeyListener(this); cont.setBackground(Color.BLACK); //ajoute Javaman cont.add(javaMan); javaMan.setBounds(50,50,50,50); for(int i = 0; i < arene.length; i++) { for(int j = 0; j < arene[0].length; j++) { JLabel lbl = null; if(arene[i][j].equals("#")) { lbl = new JLabel(new ImageIcon("mur.png")); } else { lbl = new JLabel(new ImageIcon("pastille.png")); } cont.add(lbl); lbl.setBounds(i*50,j*50,50,50); System.out.println("X: "+i*50+" -- Y: "+j*50); } }

Chapitre 6

Anciens jeux... revisits

219

repaint(); cont.validate(); Jeu jeu = new Jeu(); jeu.start(); setContentPane(cont); } public class Jeu extends Thread { public void run() { while(true) { try { if(direction == DROITE) { javaMan.setBounds(javaMan.getX()+50,javaMan.getY(),50,50); positionX++; if(arene[positionX][positionY].equals("#")) { javaMan.setBounds(javaMan.getX()-50,javaMan.getY(),50,50); positionX--; } cont.setComponentZOrder(javaMan,1); } if(direction == GAUCHE) { javaMan.setBounds(javaMan.getX()-50,javaMan.getY(),50,50); positionX--; if(arene[positionX][positionY].equals("#")) { javaMan.setBounds(javaMan.getX()+50,javaMan.getY(),50,50); positionX++; } cont.setComponentZOrder(javaMan,1); } if(direction == HAUT) { javaMan.setBounds(javaMan.getX(),javaMan.getY()-50,50,50); positionY--; if(arene[positionX][positionY].equals("#")) { javaMan.setBounds(javaMan.getX(),javaMan.getY()+50,50,50); positionY++; } cont.setComponentZOrder(javaMan,1); }

220

Devenez un petit gnie des jeux vido

if(direction == BAS) { javaMan.setBounds(javaMan.getX(),javaMan.getY()+50,50,50); positionY++; if(arene[positionX][positionY].equals("#")) { javaMan.setBounds(javaMan.getX(),javaMan.getY()-50,50,50); positionY--; } cont.setComponentZOrder(javaMan,1); } cont.validate(); Thread.sleep(500); } catch(Exception e){ } } } } public void keyTyped(KeyEvent e) { if(e.getKeyChar()==z) direction = HAUT; if(e.getKeyChar()==q) direction = GAUCHE; if(e.getKeyChar()==s) direction = BAS; if(e.getKeyChar()==d) direction = DROITE; } public void keyPressed(KeyEvent e){ } public void keyReleased(KeyEvent e){ } public static void main (String[] args) { new Javaman(); } }

Les Figures 35.2 et 35.3 illustrent les dplacements de Javaman. Lentranement de Javaman est termin... Il est temps dajouter des C++ ennemis !

Chapitre 6

Anciens jeux... revisits

221

Figure 35.2 Javaman est vivant

Figure 35.3 Javaman se dplace

222

Devenez un petit gnie des jeux vido

Projet 36 : Javaman Lattaque du C++


Projet Crez et relchez des ennemis. Les C++ ennemis se dplacent en aveugle, mais ils sont rapides et acharns.

Crer le jeu
Dessinez dabord une image de 50 50 pixels du criminel C++. Pour garder trace de ses clones, crez un tableau de trois lments. Chaque lment sera un ennemi occupant un coin du plateau. Noubliez pas que les mouvements des C++ clons sont alatoires. Pour crer le mouvement, crez un autre tableau de trois lments dans le l dexcution. Chacun de ces lments contient lorientation de chaque lment C++ grce des nombres alatoires entre 1 et 4. Puis, dplacez chaque ennemi dans la direction indique par le nombre alatoire (1 vers le haut, 2 vers le bas, 3 vers la gauche, 4 vers la droite). Pour viter que les ennemis nentrent dans les murs, utilisez la mme technique que celle que vous avez utilise dans le projet prcdent. Ensuite, ajoutez une instruction if dans la boucle. Comparez la position des C++ avec la position de Javaman. Si elles sont identiques, Javaman perd. Afchez alors un JOptionPane pour annoncer la triste nouvelle au joueur. Javaman vite les C++ mais il essaie aussi de dvorer les cercles sur le plateau. Lorsque Javaman passe sur un cercle, remplacez la tuile correspondante par une image de 50 50 pixels noire. Dcrmentez aussi la variable qui garde trace du nombre de cercles restants. Une instruction if permet de dtecter la victoire. Si Javaman gagne, ajoutez un JOptionPane pour indiquer au joueur sa victoire.
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.awt.geom.*; public class Javaman extends JFrame implements KeyListener { Container cont; //direction int HAUT = 0, BAS = 1, DROITE = 2, GAUCHE = 3; int direction = DROITE; int score = 0; int positionX = 1, positionY = 1; //tableau deux dimensions

Chapitre 6

Anciens jeux... revisits

223

String arene[][] = {{"#","#","#","#","#","#","#","#","#","#"}, {"#"," "," "," ","#"," "," "," "," ","#"}, {"#"," ","#"," ","#"," "," ","#"," ","#"}, {"#"," ","#"," ","#"," ","#","#"," ","#"}, {"#"," ","#"," "," "," "," ","#"," ","#"}, {"#"," ","#","#"," "," "," ","#"," ","#"}, {"#"," ","#"," "," ","#"," ","#"," ","#"}, {"#"," ","#"," "," ","#"," ","#"," ","#"}, {"#"," "," "," "," ","#"," "," "," ","#"}, {"#","#","#","#","#","#","#","#","#","#"}}; //icnes JLabel javaMan = new JLabel(new ImageIcon("javaman.png")); JLabel ennemis[ ] = {new JLabel(new ImageIcon("monstre.png")),new JLabel (new ImageIcon("monstre.png")),new JLabel(new ImageIcon("monstre.png"))}; int pastillesrestantes = 44; public Javaman() { super("JavaMan"); setSize(500,500); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cont = getContentPane(); cont.setLayout(null); addKeyListener(this); cont.setBackground(Color.BLACK); //ajoute Javaman cont.add(javaMan); javaMan.setBounds(50,50,50,50); //ajoute le plateau for(int i = 0; i < arene.length; i++) { for(int j = 0; j < arene[0].length; j++) { JLabel lbl = null; if(arene[i][j].equals("#")) { lbl = new JLabel(new ImageIcon("mur.png")); } else { lbl = new JLabel(new ImageIcon("pastille.png")); } cont.add(lbl); lbl.setBounds(i*50,j*50,50,50); System.out.println("X: "+i*50+" Y: "+j*50); } } //position des ennemis cont.add(ennemis[0]); ennemis[0].setBounds(400,50,50,50); cont.setComponentZOrder(ennemis[0],1); cont.add(ennemis[1]); ennemis[1].setBounds(50,400,50,50); cont.setComponentZOrder(ennemis[1],1); cont.add(ennemis[2]);

224

Devenez un petit gnie des jeux vido

ennemis[2].setBounds(400,400,50,50); cont.setComponentZOrder(ennemis[2],1); repaint(); cont.validate(); Jeu jeu = new Jeu(); jeu.start(); setContentPane(cont); } public class Jeu extends Thread { public void run() { while(true) { try { //cherche une victoire de Javaman if(pastillesrestantes<=0) { JOptionPane.showMessageDialog(null,"Gagn!"); } //boucle de mouvement des ennemis int dir[] = new int[3]; for(int i = 0; i < dir.length; i++) { dir[i] = (int)(Math.random()*4); if(dir[i]==HAUT) { ennemis[i].setBounds(ennemis[i].getX(),ennemis[i].getY()-50,50,50); if(arene[ennemis[i].getX()/50] [ennemis[i].getY()/50].equals("#")) { ennemis[i].setBounds(ennemis[i].getX(), ennemis[i].getY()+50,50,50); } } if(dir[i]==BAS) { ennemis[i].setBounds(ennemis[i].getX(),ennemis[i].getY()+50,50,50); if(arene[ennemis[i].getX()/50] [ennemis[i].getY()/50].equals("#")) { ennemis[i].setBounds(ennemis[i].getX(),ennemis[i].getY()-50,50,50); } } if(dir[i]==GAUCHE) { ennemis[i].setBounds(ennemis[i].getX()-50,ennemis[i].getY(),50,50); if(arene[ennemis[i].getX()/50] [ennemis[i].getY()/50].equals("#")) { ennemis[i].setBounds(ennemis[i].getX()+50, ennemis[i].getY(),50,50); } } if(dir[i]==DROITE) { ennemis[i].setBounds(ennemis[i].getX()+50,ennemis[i].getY(),50,50); if(arene[ennemis[i].getX()/50][ennemis[i].getY()/50].equals("#")) { ennemis[i].setBounds(ennemis[i].getX()-50, ennemis[i].getY(),50,50); } }

Chapitre 6

Anciens jeux... revisits

225

//perdu! if(ennemis[i].getX()/50==positionX && ennemis[i].getY()/50==positionY) { JOptionPane.showMessageDialog(null,"Perdu!"); } cont.setComponentZOrder(ennemis[i],1); } //supprime le cercle if(arene[positionX][positionY].equals(" ")) { arene[positionX][positionY] = "."; pastillesrestantes--; JLabel lbl = new JLabel(new ImageIcon("chemin.png")); cont.add(lbl); lbl.setBounds(positionX*50,positionY*50,50,50); cont.setComponentZOrder(lbl,1); score++; } //dplace Javaman if(direction == DROITE) { javaMan.setBounds(javaMan.getX()+50,javaMan.getY(),50,50); positionX++; if(arene[positionX][positionY].equals("#")) { javaMan.setBounds(javaMan.getX()-50,javaMan.getY(),50,50); positionX--; } cont.setComponentZOrder(javaMan,1); } if(direction == GAUCHE) { javaMan.setBounds(javaMan.getX()-50,javaMan.getY(),50,50); positionX--; if(arene[positionX][positionY].equals("#")) { javaMan.setBounds(javaMan.getX()+50,javaMan.getY(),50,50); positionX++; } cont.setComponentZOrder(javaMan,1); } if(direction == HAUT) { javaMan.setBounds(javaMan.getX(),javaMan.getY()-50,50,50); positionY--; if(arene[positionX][positionY].equals("#")) { javaMan.setBounds(javaMan.getX(),javaMan.getY()+50,50,50); positionY++; } cont.setComponentZOrder(javaMan,1); } if(direction == BAS) { javaMan.setBounds(javaMan.getX(),javaMan.getY()+50,50,50); positionY++; if(arene[positionX][positionY].equals("#")) { javaMan.setBounds(javaMan.getX(),javaMan.getY()-50,50,50); positionY--; }

226

Devenez un petit gnie des jeux vido

cont.setComponentZOrder(javaMan,1); } cont.validate(); Thread.sleep(500); } catch(Exception e){ } } } } public void keyTyped(KeyEvent e) { if(e.getKeyChar()==z) direction = HAUT; if(e.getKeyChar()==q) direction = GAUCHE; if(e.getKeyChar()==s) direction = BAS; if(e.getKeyChar()==d) direction = DROITE; } public void keyPressed(KeyEvent e){ } public void keyReleased(KeyEvent e){ } public static void main(String[] args) { new Javaman(); } }

Les Figures 36.1 et 36.2 illustrent la lutte de Javaman pour sa survie.


Figure 36.1 Javaman mange les points

Chapitre 6

Anciens jeux... revisits

227

Figure 36.2 C++ a gagn...

Pour aller plus loin...


Modiez les panneaux de n de jeu et ajoutez des images lors de la victoire ou de la dfaite. Modiez les chemins du tableau ou faites-en un terrain de jeu ouvert. Ajoutez des ennemis. Modiez les icnes des joueurs : vaisseaux lasers ou formes gomtriques. Acclrez ou ralentissez le jeu... ou encore crez des zones pour les fous de vitesse dans le jeu. Ajoutez des points spciaux pour donner des super-pouvoirs Javaman. Plutt que de dplacer les C++ alatoirement, faites-les chasser Javaman. Ajoutez des sons correspondants la victoire ou la dfaite de Javaman. Ajoutez un trou noir sur le plateau pour aspirer tout ce qui le traverse.

7
Jeux de rexion
Au sommaire de ce chapitre :

Jeu de mmoire

Projet 37 : Dessin de la grille Projet 38 : Correspondances Projet 39 : Battez le chronomtre

Ian a dit

Projet 40 : Jeu de couleurs Projet 41 : Surchauffe de cerveau Projet 42 : Plus de niveaux ! Projet 43 : Accessoires de jeu

230

Devenez un petit gnie des jeux vido

Projet 37 : Jeu de mmoire Dessin de la grille


Jeu de mmoire Mme si les processus biochimiques de la mmoire demeurent un mystre, vous pouvez tester la vtre en jouant ce jeu. Un ensemble dimages safche devant vos yeux. Le d consiste faire correspondre les images identiques avant la n du dcompte du chronomtre.
Projet Concevez et dveloppez la grille de 16 cartes.

Crer le jeu
Le jeu de mmoire est une grille 4 4 contenant huit paires dimages. Crez huit images diffrentes de format 100 100 pixels : dessins, photos, etc. Pour obtenir des photos de la bonne taille, photographiez huit objets quelconques et ouvrez les photos dans Microsoft Paint. Appuyez sur Ctrl+A pour slectionner les images et faites glisser jusqu ce que lindication "100, 100" apparaisse en bas de lcran, comme le montre la Figure 37.1.
Figure 37.1 Cration des images

Chapitre 7

Jeux de rexion

231

Une fois limage aux bonnes dimensions, choisissez Sauvegardez sous... et enregistrez limage. Une fois les images cres, enregistrez-les dans un tableau deux dimensions de JButton de taille 4 4. Dans le constructeur, ajoutez les JButton au JFrame grce deux boucles for. Ny attachez pas encore les images que vous avez cres ; dessinez la place une nouvelle image, comme celle de la Figure 37.2, et associez-la au bouton.
Figure 37.2 Image "Jeu de mmoire"

Programmez ensuite une mthode pour attribuer alatoirement les images aux JButton. Pour cela, faites une pause dune demi-seconde grce la mthode Thread.sleep. Puis, initialisez un tableau dentiers pour enregistrer le nombre de fois que chaque image est utilise. Ceci vitera que les images napparaissent plus de deux fois. Utilisez ensuite deux boucles pour traverser le tableau de JButton. chaque itration, gnrez un nombre alatoire entre 1 et 8 inclus. Le tableau initialis prcdemment vous permettra de vrier si limage correspondant au nombre alatoire a t utilise plus dune fois. Si oui, gnrez un nouveau nombre alatoire. Une fois quun nombre alatoire satisfaisant a t gnr, incrmentez la valeur correspondante dans le tableau. Noubliez pas dattribuer la nouvelle icne au JButton correspondant. Comment garder trace de lemplacement de chaque image ? Il suft de crer un tableau bidimensionnel de huit entiers. Donnez llment adquat la valeur du nombre alatoire. Une fois les images afches, il faut les cacher. La mthode Thread.sleep permet de mettre le jeu en pause pendant trois secondes pour donner aux joueurs le temps de mmoriser les images. Puis, dans un nouveau nid de deux boucles for, replacez les icnes du jeu (le dos des cartes).
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; public class Memoire extends JFrame { //limage vide ImageIcon vide = new ImageIcon("vide.png");

232

Devenez un petit gnie des jeux vido

//les boutons JButton boutons[][] = {{new JButton(vide),new JButton(vide), new JButton(vide),new JButton(vide)}, {new JButton(vide),new JButton(vide), new JButton(vide),new JButton(vide)}, {new JButton(vide),new JButton(vide), new JButton(vide),new JButton(vide)}, {new JButton(vide),new JButton(vide), new JButton(vide),new JButton(vide)}}; //emplacement des boutons int emplacements[][] = {{0,0,0,0},{0,0,0,0},{0,0,0,0}, {0,0,0,0}}; Container cont; public Memoire() { super("Jeu de Mmoire"); setSize(415,500); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cont = getContentPane(); cont.setLayout(null); for(int i = 0; i <boutons[0].length; i++) { for(int j = 0; j <boutons.length; j++) { //ajoute les boutons au plateau cont.add(boutons[i][j]); boutons[i][j].setBounds(i*100,j*100,100,100); } } melange(); } public void melange() { try { //pause Thread.sleep(500); //vite quune image soit utilise plus de deux fois int compteUsage[] = {0,0,0,0,0,0,0,0}; for(int i = 0; i < boutons[0].length; i++) { for(int j = 0; j < boutons.length; j++) { //nombre alatoire int rand = (int)(Math.random()*8)+1; while(compteUsage[rand - 1]>1) { //cherche un meilleur nombre alatoire rand = (int)(Math.random()*8)+1; } //ne pas utiliser une image plus de deux fois compteUsage[rand-1]++; //dfinit limage boutons[i][j].setIcon(new ImageIcon("img"+rand+".png")); //garde trace des images emplacements[i][j] = rand; cont.validate(); } }

Chapitre 7

Jeux de rexion

233

//pause Thread.sleep(3000); //deux boucles for for(int i = 0; i < boutons[0].length; i++) { for(int j = 0; j < boutons.length; j++) { //retourne les cartes boutons[i][j].setIcon(vide); cont.validate(); } } } catch(Exception e){} } public static void main(String[ ] args) { new Memoire(); } }

Les Figures 37.3 et 37.4 illustrent le jeu de mmoire. Dans le projet suivant, nous verrons comment faire pour que les joueurs puissent faire correspondre les images.
Figure 37.3 Afchage des images "Jeu de mmoire"

234

Devenez un petit gnie des jeux vido

Figure 37.4 Images faire correspondre

Chapitre 7

Jeux de rexion

235

Projet 38 : Jeu de mmoire Correspondances


Projet Programmez le code permettant au joueur de tester sa mmoire en faisant correspondre les images.

Crer le jeu
Implmentez dabord linterface ActionListener. Ajoutez-la chaque bouton de la liste. Une proposition est constitue de deux clics : limage de base et la seconde image, pour laquelle on cherche la correspondance. Dclarez deux boolens : le premier pour reprsenter un clic sur la premire image, le second pour reprsenter un clic sur la deuxime image. Dans la mthode actionPerformed, le premier boolen indique sil sagit du premier clic du joueur. Si cest le cas, itrez dans lensemble des boutons grce une boucle for. La mthode e.getSource() permet de vrier si le bouton slectionn est le bouton courant de la boucle. Si cest le cas, enregistrez le numro de limage dans une variable globale. Puis, afchez limage adquate sur le bouton. Noubliez pas de garder trace du numro de ligne et de colonne dans des variables globales et dinitialiser le boolen indiquant quil faut choisir un bouton mettre en correspondance. Lors de cette seconde tape, itrez dans lensemble des boutons grce une boucle for. La mthode e.getSource() permet de vrier si le bouton slectionn est le bouton courant de la boucle. Si cest le cas, modiez licne et placez le bouton et les numros de colonne et de ligne dans des variables globales. Initialisez le boolen indiquant lordinateur sil doit chercher une correspondance true et repassez le boolen indiquant sil sagit de la premire carte retourne true. Crez maintenant un nouveau Thread. Dans la boucle de ce l dexcution, une instruction if dtermine sil faut chercher une ventuelle victoire sur le plateau. Si cest le cas, mettez le jeu en pause pour une demi-seconde. Puis, regardez si les deux images choisies par le joueur sont diffrentes, auquel cas il faut les retourner, cest-dire rtablir limage neutre. Si les deux images sont identiques, les images restent afches.
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; public class Memoire extends JFrame implements ActionListener { //image vide ImageIcon vide = new ImageIcon("vide.png");

236

Devenez un petit gnie des jeux vido

//tableau de boutons JButton boutons[ ][ ] = {{new JButton(vide),new JButton(vide), new JButton(vide),new JButton(vide)}, {new JButton(vide),new JButton(vide), new JButton(vide),new JButton(vide)}, {new JButton(vide),new JButton(vide), new JButton(vide),new JButton(vide)}, {new JButton(vide),new JButton(vide), new JButton(vide),new JButton(vide)}}; //limage de tous les boutons int emplacements[ ][ ] = {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}; Container cont; //le joueur a-t-il dj cliqu boolean dejaClique = false; boolean aVerifier = false; //premire carte retourne int premiereCarte; //position 1 de la premire carte int premiereCartePos1; //position 2 de la premire carte int premiereCartePos2; //deuxime carte retourne int deuxiemeCarte; //position 1 de la deuxime carte int deuxiemeCartePos1; //position 2 de la deuxime carte int deuxiemeCartePos2; public Memoire() { super("Jeu de Mmoire"); setSize(415,500); setVisible(true); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cont = getContentPane(); cont.setLayout(null); //images du jeu for(int i = 0; i <boutons[0].length; i++) { for(int j = 0; j < boutons.length; j ++) { cont.add(boutons[i][j]); boutons[i][j].setBounds(i*100,j*100,100,100); boutons[i][j].addActionListener(this); } } melange(); Verificateur verif = new Verificateur(); verif.start(); } public class Verificateur extends Thread { public void run() { while(true) { if(aVerifier) {

Chapitre 7

Jeux de rexion

237

try { sleep(500); } catch(Exception ex){ } if(premiereCarte!=deuxiemeCarte) { //si les images ne correspondent pas, on re-retourne les images boutons[premiereCartePos1][premiereCartePos2].setIcon(vide); boutons[deuxiemeCartePos1][deuxiemeCartePos2].setIcon(vide); } aVerifier = false; } } } } public void melange() { try { //pause Thread.sleep(500); //vite quune image soit utilise plus de deux fois int compteUsage[ ] = {0,0,0,0,0,0,0,0}; for(int i = 0; i < boutons[0].length; i++) { for(int j = 0; j < boutons.length; j++) { //nombre alatoire int rand = (int)(Math.random()*8)+1; while(compteUsage[rand -1]>1) { //trouve un meilleur nombre alatoire rand = (int)(Math.random()*8)+1; } //ne pas utiliser une image plus de deux fois compteUsage[rand-1]++; //dfinit limage boutons[i][j].setIcon(new ImageIcon("img"+rand+".png")); //keep track of the images emplacements[i][j] = rand; cont.validate(); } } //pause Thread.sleep(3000); //deux boucles for for(int i = 0; i < boutons[0].length; i++) { for(int j = 0; j < boutons.length; j++) { //retourne les cartes boutons[i][j].setIcon(vide); cont.validate(); } } } catch(Exception e){} }

238

Devenez un petit gnie des jeux vido

public void actionPerformed(ActionEvent e) { //sil sagit de la premire carte retourne if(!dejaClique) { for(int i = 0; i < boutons[0].length; i++) { for(int j = 0; j < boutons.length; j++) { if(e.getSource()==boutons[i][j]) { //affiche limage int numImage = emplacements[i][j]; boutons[i][j].setIcon(new ImageIcon("img"+numImage+".png")); premiereCarte = numImage; premiereCartePos1 = i; premiereCartePos2 = j; } } } dejaClique = true; } //sil sagit de la deuxime carte retourne else { for(int i = 0; i < boutons[0].length; i++) { for(int j = 0; j < boutons.length; j++) { if(e.getSource()==boutons[i][j]) { //affiche limage int numImage = emplacements[i][j]; boutons[i][j].setIcon(new ImageIcon("img"+numImage+".png")); deuxiemeCarte = numImage; deuxiemeCartePos1 = i; deuxiemeCartePos2 = j; cont.validate(); } } //le fil dexcution cherche une victoire dejaClique = false; aVerifier = true; } } } public static void main(String[ ] args) { new Memoire(); } }

La Figure 38.1 illustre le jeu de mmoire en cours de jeu. Mais la satisfaction du joueur lorsquil a termin un niveau est de courte dure lorsque lon cre de nouveaux niveaux avec plus de ds...

Chapitre 7

Jeux de rexion

239

Figure 38.1 La victoire est proche

240

Devenez un petit gnie des jeux vido

Projet 39 : Jeu de mmoire Battez le chronomtre


Projet Des complications... et une astuce. Le joueur doit battre son propre score du niveau prcdent. Plus vous tes dou, plus le jeu devient difcile. Ajoutez galement des images pour indiquer au joueur comment il sen sort.

Crer le jeu
Pour ajouter un chronomtre, dclarez deux variables globales. La premire contient le temps allou un niveau et la seconde contient le temps restant pour le niveau. Puis, dans la mthode qui mlange les icnes, incrmentez une nouvelle variable pour le numro de niveau. Le temps maximum est obtenu en soustrayant la valeur de la variable du temps restant celle du temps maximal. Rinitialisez la variable tempsRestant au nouveau temps maximum. Crez un nouveau l dexcution. Dans sa boucle innie, faites une pause dune seconde et diminuez la variable du temps restant de 1. Afchez le temps restant dans un JLabel. Modiez la police de ce libell an quil ressemble celui de la Figure 39.1.
Figure 39.1 Un JLabel afche le temps restant

Dans le l dexcution cr dans le projet prcdent, vriez avec une nouvelle instruction si la tentative du joueur est couronne de succs. Si cest le cas, soustrayez 1 de la variable qui garde trace du nombre de paires restantes. Si ce nombre est 0, on peut commencer un nouveau niveau. Appelez la mthode qui mlange les images. Si le temps restant est infrieur ou gal une seconde, le joueur a perdu. Supprimez tous les composants du conteneur grce une boucle et crez un nouveau JLabel pour afcher le nombre de niveaux termins par le joueur. Ce libell est plac au milieu du JFrame. Vous pouvez alors afcher une image diffrente selon le niveau termin. Si le joueur dpasse le niveau 7, il sagit du rang le plus lev (voir Figure 39.3). Les niveaux 3 6 correspondent un niveau intermdiaire (Figure 39.4). Les niveaux 0 2 reprsentent le rang le plus faible (Figure 39.5). Noubliez pas de placer le JLabel au-dessus de limage grce la mthode setComponentZOrder.

Chapitre 7

Jeux de rexion

241

import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; public class Memoire extends JFrame implements ActionListener { //image vide ImageIcon vide = new ImageIcon("vide.png"); //tableau de boutons JButton boutons[][] = {{new JButton(vide),new JButton(vide), new JButton(vide),new JButton(vide)}, {new JButton(vide),new JButton(vide), new JButton(vide),new JButton(vide)}, {new JButton(vide),new JButton(vide), new JButton(vide),new JButton(vide)}, {new JButton(vide),new JButton(vide), new JButton(vide),new JButton(vide)}}; //limage chaque bouton int emplacement[][] = {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}; Container cont; //le joueur a-t-il dj cliqu boolean dejaClique = false; //le joueur a-t-il dj retourn une carte boolean carteRetournee = false; //premire carte retourne int premiereCarte; //position 1 de la premire carte retourne int premiereCartePos1; //position 2 de la premire carte retourne int premiereCartePos2; //seconde carte retourne int deuxiemeCarte; //position 1 de la deuxime carte retourne int deuxiemeCartePos1; //position 2 de la deuxime carte retourne int deuxiemeCartePos2; //nombre de paires restantes int pairesrestantes = 8; //le fil dexcution doit-il chercher une victoire? boolean aVerifier = false; //temps total int tempsMax = 90; //temps restant int tempsRestant = 0; //niveau actuel int niveau = 0; JLabel temps = new JLabel("Temps restant: " + tempsRestant); public Memoire() { super("Jeu de Mmoire"); setSize(415,500); setVisible(true);

242

Devenez un petit gnie des jeux vido

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cont = getContentPane(); cont.setLayout(null); //images du jeu for(int i = 0; i < boutons[0].length; i++) { for(int j = 0; j <boutons.length; j++) { cont.add(boutons[i][j]); boutons[i][j].setBounds(i*100,j*100,100,100); boutons[i][j].addActionListener(this); } } cont.add(temps); temps.setBounds(130,385,300,100); temps.setFont(new Font("arial", Font.BOLD, 14)); melange(); Verificateur verif = new Verificateur(); verif.start(); Compteur compteur = new Compteur(); compteur.start(); } public class Compteur extends Thread { public void run() { while(true) { //dcompte le temps tempsRestant--; temps.setText("Temps restant: "+tempsRestant); try { Thread.sleep(1000); } catch(Exception e){} } } } public class Verificateur extends Thread { public void run() { while(true) { if(aVerifier) { try { sleep(500); } catch(Exception ex){} //si la paire est correcte, on enlve une paire if(premiereCarte==deuxiemeCarte) { pairesrestantes--; } else { //sinon, on rinitialise les images boutons[premiereCartePos1][premiereCartePos2].setIcon(vide); boutons[deuxiemeCartePos1][deuxiemeCartePos2].setIcon(vide); } aVerifier = false; }

Chapitre 7

Jeux de rexion

243

if(pairesrestantes<=0) { //si lutilisateur gagne, dmarre le niveau suivant melange(); } //sil ny a plus de temps, affiche un message if(tempsRestant<0) { //supprime les autres composants for(int i = 0; i <boutons[0].length; i++) { for(int j = 0; j <boutons.length; j++) { cont.remove(boutons[i][j]); } } cont.remove(temps); JLabel lblNiveau = new JLabel("---Niveaux termins: "+ (niveau-1)+"---"); cont.add(lblNiveau); lblNiveau.setForeground(Color.white); lblNiveau.setFont(new Font("arial narrow", Font.PLAIN, 20)); lblNiveau.setBounds(115,385,300,50); if(niveau>=7) { //niveau: gnie du mal JLabel fin = new JLabel(new ImageIcon("genie.png")); cont.add(fin); fin.setBounds(0,0,415,500); } else if (niveau>=3) { //diabolique, mais pas un gnie JLabel fin = new JLabel(new ImageIcon("pasGenie.png")); cont.add(fin); fin.setBounds(0,0,415,500); } else { //vous avez besoin de pratique JLabel fin = new JLabel(new ImageIcon("aide.png")); cont.add(fin); fin.setBounds(0,0,415,500); } cont.setComponentZOrder(lblNiveau,0); cont.validate(); break; } } } } public void melange() { niveau++; tempsMax = tempsMax-tempsRestant; tempsRestant = tempsMax; pairesrestantes = 8; try { //pause Thread.sleep(500);

244

Devenez un petit gnie des jeux vido

//ceci empche quune image soit utilise plus de deux fois int compteUsage[ ] = {0,0,0,0,0,0,0,0}; for(int i = 0; i < boutons[0].length; i++) { for(int j = 0; j < boutons.length; j++) { //nombre alatoire int rand = (int)(Math.random()*8)+1; while(compteUsage[rand-1]>1) { //trouve un meilleur nombre alatoire rand = (int)(Math.random()*8)+1; } //ne pas utiliser une image plus de deux fois compteUsage[rand-1]++; //dfinit limage boutons[i][j].setIcon(new ImageIcon("img"+rand+".png")); //garde trace des images emplacement[i][j] = rand; cont.validate(); } } //pause Thread.sleep(3000); //deux boucles for for(int i = 0; i < boutons[0].length; i++) { for(int j = 0; j < boutons.length; j++) { //retourne les cartes boutons[i][j].setIcon(vide); cont.validate(); } } } catch(Exception e){} } public void actionPerformed(ActionEvent e) { //sil sagit de la premire carte if(!carteRetournee) { for(int i = 0; i < boutons[0].length; i++) { for(int j = 0; j < boutons.length; j++) { if(e.getSource()==boutons[i][j]) { //affiche limage int numImage = emplacement[i][j]; boutons[i][j].setIcon(new ImageIcon("img"+numImage+".png")); premiereCarte = numImage; premiereCartePos1 = i; premiereCartePos2 = j; } } } carteRetournee = true; }

Chapitre 7

Jeux de rexion

245

//sil sagit de la deuxime carte else { for(int i = 0; i < boutons[0].length; i++) { for(int j = 0; j < boutons.length; j++) { if(e.getSource()==boutons[i][j]) { //affiche limage int numImage = emplacement[i][j]; boutons[i][j].setIcon(new ImageIcon("img"+numImage+".png")); deuxiemeCarte = numImage; deuxiemeCartePos1 = i; deuxiemeCartePos2 = j; cont.validate(); } } //le fil dexcution cherche une victoire carteRetournee = false; aVerifier = true; } } } public static void main(String[ ] args) { new Memoire(); } }

Les Figures 39.2 39.5 illustrent le jeu termin.


Figure 39.2 Le chronomtre descend...

246

Devenez un petit gnie des jeux vido

Figure 39.3 Un vrai petit gnie !

Figure 39.4 Rang du milieu

Chapitre 7

Jeux de rexion

247

Figure 39.5 Encore des efforts faire...

Pour aller plus loin...


Utilisez des couleurs alatoires la place des images. Passez dune grille 4 4 de 16 images une grille 10 10 de 100 images. Ajoutez ou retranchez alatoirement du temps. Remlangez les images au milieu du jeu. Changez dimages chaque niveau. Remplacez les images par des sons... bien plus difciles faire correspondre ! Dconcentrez les joueurs avec de la musique, le bruit dun bb qui pleure ou dun chien qui aboie.

248

Devenez un petit gnie des jeux vido

Projet 40 : Ian a dit Jeu de couleurs


Ian a dit Ne clignez pas des yeux : lordinateur montre une srie de couleurs que le joueur doit mmoriser et rpter. Ian a dit devient de plus en plus difcile chaque niveau car les suites de couleurs deviennent de plus en plus longues. Combien de couleurs pouvezvous mmoriser ? Attention, une petite erreur vous fera tout recommencer !
Projet Construisez le plateau de jeu et programmez la squence de couleurs du niveau 1.

Crer le jeu
Le plateau de Ian a dit se compose de quatre carrs de couleurs diffrentes de 200 200 pixels. Crez dabord un JFrame de 400 400 pixels. Puis, programmez une mthode paint, dans laquelle vous dessinerez quatre carrs de 200 200 pixels. Les carrs sont rouge, bleu, vert et jaune. Faites alors une pause dune seconde pour que le joueur puisse se prparer au jeu. Programmez ensuite une mthode choisissant alatoirement une des quatre couleurs. La mthode doit retourner un char reprsentant la couleur choisie. La mthode paint appelle cette nouvelle mthode. Passez le carr choisi dans une couleur plus claire et ajoutez un texte afchant le nom de la couleur (voir Figure 40.1).
Figure 40.1 Bleu apparat sur le carr bleu clair

Mettez le jeu en pause pendant un quart de seconde avant de rtablir les couleurs dorigine sur le tableau. Pour cela, vous devez crer une nouvelle mthode qui rinitialise le plateau de jeu.

Chapitre 7

Jeux de rexion

249

import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; public class IanADit extends JFrame { public IanADit() { super("Ian A Dit"); setSize(400,400); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } public void paint(Graphics g) { super.paint(g); //carr rouge g.setColor(new Color(200,50,50)); g.fillRect(0,0,200,200); //carr bleu g.setColor(new Color(50,50,200)); g.fillRect(200,0,200,200); //carr vert g.setColor(new Color(50,200,50)); g.fillRect(0,200,200,200); //carr jaune g.setColor(new Color(200,200,0)); g.fillRect(200,200,200,200); try { Thread.sleep(1000); } catch(Exception e){} String nouvelleCouleur = nouvelleCouleur(); //dessine la bonne couleur if(nouvelleCouleur.equals("r")) { g.setColor(new Color(255,0,0)); g.fillRect(0,0,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, 40)); g.drawString("Rouge",50,80); } if(nouvelleCouleur.equals("b")) { g.setColor(new Color(0,0,250)); g.fillRect(200,0,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, 40)); g.drawString("Bleu",250,80); } if(nouvelleCouleur.equals("v")) { g.setColor(new Color(0,255,0)); g.fillRect(0,200,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, 40)); g.drawString("Vert",50,280); }

250

Devenez un petit gnie des jeux vido

if(nouvelleCouleur.equals("j")) { g.setColor(new Color(255,255,0)); g.fillRect(200,200,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, 40)); g.drawString("Jaune",250,280); } try { Thread.sleep(250); } catch(Exception e){} reinitialise(g); } //gnre un nouveau nombre alatoire public String nouvelleCouleur() { int rand = (int)(Math.random()*4); if(rand==0) { return "r"; } if(rand==1) { return "b"; } if(rand==2) { return "v"; } if(rand==3) { return "j"; } return " "; } public void reinitialise(Graphics g) { //rinitialise les couleurs g.setColor(new Color(200,50,50)); g.fillRect(0,0,200,200); g.setColor(new Color(50,50,200)); g.fillRect(200,0,200,200); g.setColor(new Color(50,200,50)); g.fillRect(0,200,200,200); g.setColor(new Color(200,200,0)); g.fillRect(200,200,200,200); } public static void main(String[]args) { new IanADit(); } }

Les Figures 40.2 et 40.3 illustrent le droulement de cette premire tape de Ian a dit. La premire partie de la squence de couleurs a t afche. Dans le projet suivant, nous verrons comment tester la mmoire du joueur.

Chapitre 7

Jeux de rexion

251

Figure 40.2 Le plateau de jeu avec des couleurs standard

Figure 40.3 Le carr bleu est clair

252

Devenez un petit gnie des jeux vido

Projet 41 : Ian a dit Surchauffe de cerveau


Projet Cest ici que commence laction. Programmez lordinateur pour savoir si le joueur a saisi la bonne squence de couleurs.

Crer le jeu
An que lutilisateur puisse rpter la squence, implmentez MouseListener. Noubliez pas dajouter les cinq mthodes obligatoires. Dans la mthode mouseClicked, initialisez un boolen, indiquant si lordinateur est en train dafcher la squence, false. Puis, incrmentez la variable reprsentant le nombre dessais du joueur. Vous devez dterminer dans quel carr le joueur clique. Si les positions X et Y du clic sont infrieures 200, le joueur clique en haut gauche. Si X est suprieur 200 et Y infrieur 200, le joueur clique dans le carr en haut droite. Si Y est suprieur 200 et X infrieur 200, le joueur clique dans le carr en bas gauche. Si les deux coordonnes X et Y sont suprieures 200, le joueur clique en bas droite. Donnez la variable dernierClic la valeur du carr dans lequel le joueur a cliqu. Ajoutez aussi la couleur sur laquelle le joueur a cliqu un String reprsentant la tentative du joueur. Appelez la mthode repaint();. Vous devez alors modier la mthode paint. Examinez le boolen indiquant si lordinateur est en train dafcher une squence. Si ce nest pas le cas, claircissez le dernier carr sur lequel le joueur a cliqu grce la variable dernierClic. Dans la mthode mouseClicked, regardez si la squence du joueur correspond celle de lordinateur. Pour cela, extrayez la partie de la squence que lutilisateur a tape et comparez-la la tentative de lutilisateur. Si ces deux chanes sont diffrentes, le joueur sest tromp : afchez un JOptionPane pour annoncer au joueur quil a perdu. Si les chanes sont identiques et si elles sont de la mme taille, le JOptionPane annonce que le joueur a bien termin la squence.
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; public class IanADit extends JFrame implements MouseListener { Container cont; String code = ""; String essai = ""; int nbLettres = 0; String derniereLettre; boolean normal = true;

Chapitre 7

Jeux de rexion

253

public IanADit() { super("Ian A Dit"); setSize(400,400); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); addMouseListener(this); } public void paint(Graphics g) { super.paint(g); if(!normal) { reinitialise(g); String nouvelleCouleur = derniereLettre; //light up the correct square when clicked if(nouvelleCouleur.equals("r")) { g.setColor(new Color(255,0,0)); g.fillRect(0,0,200,200); } if(nouvelleCouleur.equals("b")) { g.setColor(new Color(0,0,250)); g.fillRect(200,0,200,200); } if(nouvelleCouleur.equals("v")) { g.setColor(new Color(0,255,0)); g.fillRect(0,200,200,200); } if(nouvelleCouleur.equals("j")) { g.setColor(new Color(255,255,0)); g.fillRect(200,200,200,200); } try { Thread.sleep(250); } catch(Exception ex){} reinitialise(g); } else { //cre les carrs g.setColor(new Color(200,50,50)); g.fillRect(0,0,200,200); g.setColor(new Color(50,50,200)); g.fillRect(200,0,200,200); g.setColor(new Color(50,200,50)); g.fillRect(0,200,200,200); g.setColor(new Color(200,200,0)); g.fillRect(200,200,200,200); try { Thread.sleep(1000); } catch(Exception e){ } //itre dans le code for(int i = 0; i <code.length(); i++) { try { Thread.sleep(250); } catch(Exception e){ }

254

Devenez un petit gnie des jeux vido

//allume le carr suivant char letter = code.toCharArray()[i]; if(letter==r) { g.setColor(new Color(255,0,0)); g.fillRect(0,0,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, g.drawString("Rouge",50,80); } if(letter==b) { g.setColor(new Color(0,0,250)); g.fillRect(200,0,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, g.drawString("Bleu",250,80); } if(letter==v) { g.setColor(new Color(0,255,0)); g.fillRect(0,200,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, g.drawString("Vert",50,280); } if(letter==j) { g.setColor(new Color(255,255,0)); g.fillRect(200,200,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, g.drawString("Jaune",250,280); } try { Thread.sleep(250); } catch(Exception e){} reinitialise(g);

40));

40));

40));

40));

} try { Thread.sleep(250); } catch(Exception e){ } String nouvelleCouleur = nouvelleCouleur(); //display the appropriate color if(nouvelleCouleur.equals("r")) { g.setColor(new Color(255,0,0)); g.fillRect(0,0,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, 40)); g.drawString("Rouge",50,80); } if(nouvelleCouleur.equals("b")) { g.setColor(new Color(0,0,250)); g.fillRect(200,0,200,200); g.setColor(Color.black);

Chapitre 7

Jeux de rexion

255

g.setFont(new Font("arial", Font.BOLD, 40)); g.drawString("Bleu",250,80); } if(nouvelleCouleur.equals("g")) { g.setColor(new Color(0,255,0)); g.fillRect(0,200,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, 40)); g.drawString("Vert",50,280); } if(nouvelleCouleur.equals("y")) { g.setColor(new Color(255,255,0)); g.fillRect(200,200,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, 40)); g.drawString("Jaune",250,280); } try { Thread.sleep(250); } catch(Exception e){} reinitialise(g); } } public String nouvelleCouleur() { //gnre la couleur alatoire int rand = (int)(Math.random()*4); if(rand==0) { code+="r"; return "r"; } if(rand==1) { code+="b"; return "b"; } if(rand==2) { code+="v"; return "v"; } if(rand==3) { code+="j"; return "j"; } return " "; } public void reinitialise(Graphics g) { //carr rouge g.setColor(new Color(200,50,50)); g.fillRect(0,0,200,200); //carr bleu g.setColor(new Color(50,50,200)); g.fillRect(200,0,200,200);

256

Devenez un petit gnie des jeux vido

//carr vert g.setColor(new Color(50,200,50)); g.fillRect(0,200,200,200); //carr jaune g.setColor(new Color(200,200,0)); g.fillRect(200,200,200,200); } public void mouseExited(MouseEvent e){ } public void mouseEntered(MouseEvent e){ } public void mouseReleased(MouseEvent e){ } public void mousePressed(MouseEvent e){ } public void mouseClicked(MouseEvent e) { normal = false; nbLettres++; //dtecte le carr cliqu par le joueur if(e.getX()<200 && e.getY()<200) { derniereLettre = "r"; essai+="r"; } if(e.getX()>200 && e.getY()<200) { derniereLettre = "b"; essai+="b"; } if(e.getX()<200 && e.getY()>200) { derniereLettre = "v"; essai+="v"; } if(e.getX()>200 && e.getY()>200) { derniereLettre = "j"; essai+="j"; } repaint(); String boutCode = code.substring(0,nbLettres); if(!boutCode.equals(essai)) { //perdu JOptionPane.showMessageDialog(null,"PERDU!"); } else { //le joueur peut continuer if(nbLettres==code.length()) { JOptionPane.showMessageDialog(null,"Correct!"); } } } public static void main(String[] args) { new IanADit(); } }

Les Figures 41.1 41.3 illustrent le droulement du jeu. Jusquici, tout est facile. Mais attention... les choses vont se compliquer trs rapidement.

Chapitre 7

Jeux de rexion

257

Figure 41.1 Squence de lordinateur

Figure 41.2 Rptition correcte

258

Devenez un petit gnie des jeux vido

Figure 41.3 Rptition incorrecte, perdu !

Chapitre 7

Jeux de rexion

259

Projet 42 : Ian a dit Plus de niveaux !


Projet Concevez un nombre inni de niveaux contenant des squences de plus en plus longues mmoriser.

Crer le jeu
Dans la mthode mouseClicked, supprimez le code crant le JOptionPane qui flicite le joueur. Remplacez-le par du code rinitialisant la tentative du joueur et la longueur de la squence. Donnez galement au boolen indiquant si lordinateur est en train dafcher la squence la valeur true. Puis, appelez la mthode repaint. Dans la mthode paint, programmez une boucle for qui itre travers toutes les lettres du code. chaque itration, utilisez cette ligne de code pour dterminer la couleur utiliser :
<code>.toCharArray()[<numro de llment dans le code>];

La mthode ci-dessus retourne un caractre qui peut ensuite tre compar dans une instruction if pour savoir sil contient un "r" (rouge), un "b" (bleu), un "v" (vert) ou un "j" (jaune). clairez le carr correspondant et afchez le texte pour indiquer la couleur. Maintenant que vous disposez de plusieurs niveaux, il faut indiquer au joueur quel niveau il se trouve. Pour cela, crivez une mthode qui dessine un rond blanc entourant du texte noir, comme sur la Figure 42.1.
Figure 42.1 Cercle indiquant le numro du niveau : niveau 6

260

Devenez un petit gnie des jeux vido

Dans la mthode paint, appelez la mthode qui afche le cercle et le numro du niveau avant dexcuter les mthodes Thread.sleep.
import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; public class IanADit extends JFrame implements MouseListener { Container cont; String code = ""; String essai = ""; int lettres = 0; int niveau = 0; String derniereLettre; boolean normal = true; public IanADit() { super("Ian A Dit"); setSize(400,400); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); Container cont = getContentPane(); cont.setLayout(null); addMouseListener(this); } public void paint(Graphics g) { super.paint(g); if(!normal) { reinitialise(g); String nouvelleCouleur = derniereLettre; //allume le carr sur lequel on a cliqu if(nouvelleCouleur.equals("r")) { g.setColor(new Color(255,0,0)); g.fillRect(0,0,200,200); } if(nouvelleCouleur.equals("b")) { g.setColor(new Color(0,0,250)); g.fillRect(200,0,200,200); } if(nouvelleCouleur.equals("v")) { g.setColor(new Color(0,255,0)); g.fillRect(0,200,200,200); } if(nouvelleCouleur.equals("j")) { g.setColor(new Color(255,255,0)); g.fillRect(200,200,200,200); } dessineNiveau(g); try { Thread.sleep(250); } catch(Exception ex){}

Chapitre 7

Jeux de rexion

261

reinitialise(g); } else { niveau++; //affiche les carrs g.setColor(new Color(200,50,50)); g.fillRect(0,0,200,200); g.setColor(new Color(50,50,200)); g.fillRect(200,0,200,200); g.setColor(new Color(50,200,50)); g.fillRect(0,200,200,200); g.setColor(new Color(200,200,0)); g.fillRect(200,200,200,200); dessineNiveau(g); try { Thread.sleep(1000); } catch(Exception e){ } //itre dans le code for(int i = 0; i <code.length(); i++) { try { Thread.sleep(250); } catch(Exception e){} //allume le carr suivant char letter = code.toCharArray()[i]; if(letter==r) { g.setColor(new Color(255,0,0)); g.fillRect(0,0,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, g.drawString("Rouge",50,80); } if(letter==b) { g.setColor(new Color(0,0,250)); g.fillRect(200,0,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, g.drawString("Bleu",250,80); } if(letter==v) { g.setColor(new Color(0,255,0)); g.fillRect(0,200,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, g.drawString("Vert",50,280); } if(letter==j) { g.setColor(new Color(255,255,0)); g.fillRect(200,200,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, g.drawString("Jaune",250,280); }

40));

40));

40));

40));

262

Devenez un petit gnie des jeux vido

dessineNiveau(g); try { Thread.sleep(250); } catch(Exception e){} reinitialise(g); } try { Thread.sleep(250); } catch(Exception e){} String nouvelleCouleur = nouvelleCouleur(); //affiche la bonne couleur if(nouvelleCouleur.equals("r")) { g.setColor(new Color(255,0,0)); g.fillRect(0,0,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, 40)); g.drawString("Rouge",50,80); } if(nouvelleCouleur.equals("b")) { g.setColor(new Color(0,0,250)); g.fillRect(200,0,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, 40)); g.drawString("Bleu",250,80); } if(nouvelleCouleur.equals("v")) { g.setColor(new Color(0,255,0)); g.fillRect(0,200,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, 40)); g.drawString("Vert",50,280); } if(nouvelleCouleur.equals("j")) { g.setColor(new Color(255,255,0)); g.fillRect(200,200,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, 40)); g.drawString("Jaune",250,280); } dessineNiveau(g); try { Thread.sleep(250); } catch(Exception e){} reinitialise(g); } } public void dessineNiveau(Graphics g) { //dessinle le cercle et le texte qui affichent le niveau g.setColor(Color.white); g.fillOval(160,160,80,80); g.setColor(Color.black);

Chapitre 7

Jeux de rexion

263

g.setFont(new Font("arial", Font.BOLD, 15)); g.drawString("Niveau "+niveau,175,205); } public String nouvelleCouleur() { //gnre la couleur alatoire int rand = (int)(Math.random()*4); if(rand==0) { code+="r"; return "r"; } if(rand==1) { code+="b"; return "b"; } if(rand==2) { code+="v"; return "v"; } if(rand==3) { code+="j"; return "j"; } return " "; } public void reinitialise(Graphics g) { //carr rouge g.setColor(new Color(200,50,50)); g.fillRect(0,0,200,200); //carr bleu g.setColor(new Color(50,50,200)); g.fillRect(200,0,200,200); //carr vert g.setColor(new Color(50,200,50)); g.fillRect(0,200,200,200); //carr jaune g.setColor(new Color(200,200,0)); g.fillRect(200,200,200,200); dessineNiveau(g); } public void mouseExited(MouseEvent e){} public void mouseEntered(MouseEvent e){} public void mouseReleased(MouseEvent e){} public void mousePressed(MouseEvent e){} public void mouseClicked(MouseEvent e) { normal = false; lettres++; //dtermine quel carr a t cliqu if(e.getX()<200 && e.getY()<200) { derniereLettre = "r"; essai += "r"; }

264

Devenez un petit gnie des jeux vido

if(e.getX()>200 && e.getY()<200) { derniereLettre = "b"; essai+="b"; } if(e.getX()<200 && e.getY()>200) { derniereLettre = "v"; essai+="v"; } if(e.getX()>200 && e.getY()>200) { derniereLettre = "j"; essai+="j"; } repaint(); String codeSeg = code.substring(0,lettres); if(!codeSeg.equals(essai)) { JOptionPane.showMessageDialog(null,"Perdu!"); } else { //le joueur peut continuer if(lettres==code.length()) { essai = ""; lettres = 0; normal = true; //niveau suivant repaint(); } } } public static void main(String[] args) { new IanADit(); } }

Dans le projet suivant, nous verrons comment ajouter une image de fond et un bouton de dmarrage pour que les joueurs puissent se prparer mentalement affronter Ian a dit.

Chapitre 7

Jeux de rexion

265

Projet 43 : Ian a dit Accessoires de jeu


Projet Construisez une image de dmarrage alertant le joueur du dbut du jeu. Ajoutez galement des images et des messages apparaissant lorsque le joueur termine des niveaux.

Crer le jeu
Dessinez dans un logiciel de dessin une image de dmarrage de 400 400 pixels. Dans le constructeur, ajoutez cette image au JFrame. Ajoutez un JButton en haut de limage, sans oublier son ActionListener, comme reprsent en Figure 43.1
Figure 43.1 Image de dmarrage et son bouton

Dclarez un boolen indiquant si le jeu doit dmarrer et initialisez-le false. Dans la mthode actionPerformed du JButton, donnez au boolen la valeur true et dplacez le bouton en dehors de lcran. Dans la mthode paint, regardez si le boolen a la valeur true. Si oui, commencez le jeu. la n du jeu, remplacez le JOptionPane par du texte. Afchez diffrentes phrases correspondant au niveau que lutilisateur a atteint. Par exemple, si le joueur choue se rappeler la moindre couleur, afchez le texte de la Figure 43.2. Sil se souvient de squences entre une et cinq couleurs, afchez le texte de la Figure 43.3. Sil russit

266

Devenez un petit gnie des jeux vido

mmoriser des squences de taille suprieure cinq couleurs, afchez le texte de la Figure 43.4.
Figure 43.2 Aucune mmoire

Figure 43.3 Bon dpart... mais continuez vous entraner

Chapitre 7

Jeux de rexion

267

Figure 43.4 Une bonne mmoire... indispensable pour un vritable petit gnie des jeux vido

import javax.swing.*; import javax.swing.event.*; import java.awt.*; import java.awt.event.*; public class IanADit extends JFrame implements MouseListener, ActionListener { Container cont; String code = ""; String essai = ""; int lettres = 0; int niveau = 0; String derniereLettre; boolean termine = false; boolean normal = true; boolean debut = false; JButton demarrage = new JButton("Dmarrer"); public IanADit() { super("Ian A Dit"); setSize(400,400); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); Container cont = getContentPane(); cont.setLayout(null); cont.add(demarrage); demarrage.addActionListener(this); demarrage.setFont(new Font("arial",Font.BOLD,20)); demarrage.setBounds(95,250,200,50); JLabel titre = new JLabel(new ImageIcon("titre.png")); cont.add(titre); titre.setBounds(0,0,400,400);

268

Devenez un petit gnie des jeux vido

addMouseListener(this); } public void paint(Graphics g) { super.paint(g); if(!debut) return; if(termine) { //FIN DE JEU reinitialise(g); g.setColor(Color.black); g.setFont(new Font("Arial", Font.BOLD,50)); g.drawString("PERDU!",60,150); g.setFont(new Font("Arial", Font.BOLD,20)); if((niveau-1) ==0) { g.drawString("Vous navez rien mmoris!!",50,285); } else if((niveau-1)<=5) { g.drawString("Vous navez mmoris quune squence de ",15,275); g.drawString((niveau -1)+" couleur(s):(",130,300); } else { g.drawString("Bravo! Vous avez mmoris une",45,275); g.drawString("squence de " +<(niveau-1)+" couleurs alatoires:)",15,300); } } else { if(!normal) { reinitialise(g); String nouvelleCouleur = derniereLettre; //allume le bon carr lorsquon clique dessus if(nouvelleCouleur.equals("r")) { g.setColor(new Color(255,0,0)); g.fillRect(0,0,200,200); } if(nouvelleCouleur.equals("b")) { g.setColor(new Color(0,0,250)); g.fillRect(200,0,200,200); } if(nouvelleCouleur.equals("v")) { g.setColor(new Color(0,255,0)); g.fillRect(0,200,200,200); } if(nouvelleCouleur.equals("j")) { g.setColor(new Color(255,255,0)); g.fillRect(200,200,200,200); } dessineNiveau(g); try { Thread.sleep(250); } catch(Exception ex){} reinitialise(g); } else {

Chapitre 7

Jeux de rexion

269

niveau++; //cre les carrs g.setColor(new Color(200,50,50)); g.fillRect(0,0,200,200); g.setColor(new Color(50,50,200)); g.fillRect(200,0,200,200); g.setColor(new Color(50,200,50)); g.fillRect(0,200,200,200); g.setColor(new Color(200,200,0)); g.fillRect(200,200,200,200); dessineNiveau(g); try { Thread.sleep(1000); } catch(Exception e){} //itre travers le code for(int i = 0; i <code.length(); i++) { try { Thread.sleep(250); } catch(Exception e){ } //allume le carr suivant char letter = code.toCharArray()[i]; if(letter==r) { g.setColor(new Color(255,0,0)); g.fillRect(0,0,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, g.drawString("Rouge",50,80); } if(letter==b) { g.setColor(new Color(0,0,250)); g.fillRect(200,0,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, g.drawString("Bleu",250,80); } if(letter==v) { g.setColor(new Color(0,255,0)); g.fillRect(0,200,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, g.drawString("Vert",50,280); } if(letter==j) { g.setColor(new Color(255,255,0)); g.fillRect(200,200,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, g.drawString("Jaune",250,280); } dessineNiveau(g);

40));

40));

40));

40));

270

Devenez un petit gnie des jeux vido

try { Thread.sleep(250); } catch(Exception e){ } reinitialise(g); } try { Thread.sleep(250); } catch(Exception e){ } String nouvelleCouleur = nouvelleCouleur(); //affiche la bonne couleur if(nouvelleCouleur.equals("r")) { g.setColor(new Color(255,0,0)); g.fillRect(0,0,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, 40)); g.drawString("Rouge",50,80); } if(nouvelleCouleur.equals("b")) { g.setColor(new Color(0,0,250)); g.fillRect(200,0,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, 40)); g.drawString("Bleu",250,80); } if(nouvelleCouleur.equals("g")) { g.setColor(new Color(0,255,0)); g.fillRect(0,200,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, 40)); g.drawString("Vert",50,280); } if(nouvelleCouleur.equals("y")) { g.setColor(new Color(255,255,0)); g.fillRect(200,200,200,200); g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, 40)); g.drawString("Jaune",250,280); } dessineNiveau(g); try { Thread.sleep(250); } catch(Exception e){} reinitialise(g); } } } public void dessineNiveau(Graphics g) { //dessine lovale et le texte qui affichent le niveau g.setColor(Color.white); g.fillOval(160,160,80,80);

Chapitre 7

Jeux de rexion

271

g.setColor(Color.black); g.setFont(new Font("arial", Font.BOLD, 15)); g.drawString("Niveau "+niveau,175,205); } public String nouvelleCouleur() { //gnre une couleur alatoire int rand = (int)(Math.random()*4); if(rand==0) { code+="r"; return "r"; } if(rand==1) { code+="b"; return "b"; } if(rand==2) { code+="v"; return "v"; } if(rand==3) { code+="j"; return "j"; } return " "; } public void reinitialise(Graphics g) { //carr rouge g.setColor(new Color(200,50,50)); g.fillRect(0,0,200,200); //carr bleu g.setColor(new Color(50,50,200)); g.fillRect(200,0,200,200); //carr vert g.setColor(new Color(50,200,50)); g.fillRect(0,200,200,200); //carr jaune g.setColor(new Color(200,200,0)); g.fillRect(200,200,200,200); dessineNiveau(g); } public void actionPerformed(ActionEvent e) { //dmarre le jeu demarrage.setBounds(500,500,50,50); debut = true; repaint(); } public void mouseExited(MouseEvent e){} public void mouseEntered(MouseEvent e){} public void mouseReleased(MouseEvent e){} public void mousePressed(MouseEvent e){}

272

Devenez un petit gnie des jeux vido

public void mouseClicked(MouseEvent e) { normal = false; lettres++; //dtermine sur quel carr le joueur a cliqu if(e.getX()<200 && e.getY()<200) { derniereLettre = "r"; essai+="r"; } if(e.getX()>200 && e.getY()<200) { derniereLettre = "b"; essai+="b"; } if(e.getX()<200 && e.getY()>200) { derniereLettre = "v"; essai+="v"; } if(e.getX()>200 && e.getY()>200) { derniereLettre = "j"; essai+="j"; } repaint(); String boutCode = code.substring(0,lettres); if(!boutCode.equals(essai)) { //game over! termine = true; repaint(); } else { //le joueur peut continuer if(lettres==code.length()) { essai = ""; lettres = 0; normal = true; //niveau suivant repaint(); } } } public static void main(String[ ]args) { new IanADit(); } }

Pour aller plus loin...


Remplacez les couleurs par des indices sonores. Modiez le dessin du jeu pour remplacer les quatre carrs par des touches de piano. Ajoutez des carrs supplmentaires de couleurs diffrentes aprs chaque niveau pass avec succs.

Chapitre 7

Jeux de rexion

273

Ajoutez une limite de temps. Grez un nombre limit de niveaux, mais ajoutez une course contre la montre pour les terminer. Demandez aux joueurs droitiers de jouer de la main gauche et aux gauchers de jouer de la main droite. Forcez les joueurs retarder leur rponse en mettant le jeu en pause pendant plusieurs secondes.
Flicitations ! Vous matrisez maintenant lart de la programmation de jeux vido. Vous tes intelligent, cratif et un magicien de linformatique. Bref, vous tes un vrai petit gnie des jeux vido !

Index

Symboles
- 15 != 16 % 15 * 15 + 15 < 16 <= 16 == 15 > 16 >= 16

API 73 ArrayList 3, 31 accder un lment 31 add 31 ajouter un lment 31 cration 31 exemple 74, 129, 175 get 31 transtypage 32 AudioClip 62 loop 62 play 62

A
Accder un fichier 3 Accolades 11 ActionEvent 97 getSource 97, 235 ActionListener 97 actionPerformed 97 exemple 97, 106, 235 JButton 97 add, ArrayList 31 Afficher un score, JLabel 98

B
Bote de dialogue, saisie 17 Bonus 135 boolean 14 Boucle 24 break 25 do... while 25 exemple 32, 35 fonctionnement 25 exemple 110

276

Devenez un petit gnie des jeux vido

Boucle (suite) for 24 condition 24 exemple 180, 189 fonctionnement 24 format 24 itrateur 24 variable 24 while 24 fonctionnement 25 BoutonVoir JButton 93 break 25 BufferedReader 19

C
Cast Voir Transtypage 17 char 14 Chasse aux mauvais gnies apparition des gnies 97 cration du plateau 92 niveaux de difficult 101 Chronomtre 83, 149 Classe constructeur 40 contenu 11 crer dans NetBeans 7 dlimiter 11 interne 47 crer 47 mthode main 11 nommer 11 Clavier contrler la direction 166 dtecter lappui sur une touche 53 Collisions 53 Color 42 Commentaire 3, 10 Compilateur 5 Compiler un projet 12 Composant 92 dtecter une action 97

Composant graphique 92 bouton 93 disposition 92, 105 JButton 93 JLabel 94 libell 94 placer sur une image 148 setBounds 105 setComponentZOrder 170 TextField 148 Concatnation 15 Condition 15 != 16 < 16 <= 16 == 15 > 16 >= 16 galit 15 de deux String 16 ingalit 16 de deux String 16 infrieur ou gal 16 strictement infrieur 16 strictement suprieur 16 suprieur ou gal 16 Constructeur 40 syntaxe 40 Container 92 add 93 ajouter un composant 93 cration 92 FlowLayout 92 getComponentCount 180 JFrame 92 NullLayout 105 setLayout 92 ConteneurVoir Container 92 Contrle de flux 3, 10 Couleurs 42 disponibles, afficher 42 Course du courage 40 environnement 40 voitures 47 Cration dun fichier 18

Index

277

D
Dclaration 10 Dmineurs affichage des indices 148 cration de la bombe 144 explosion de la bombe 153 niveaux 159 Destructeurs de lespace ajout des aliens et des lasers 129 bonus 135 cration du paysage 126 Dtecter une action sur un composant 97 Dtection de victoire 110 des collisions 53 exemple 54, 130, 175 Directions, grer au clavier 53 Disposition des composants 92, 105 algorithme 106 FlowLayout 92 NullLayout 105 Division par 0 26 do... while Voir Boucle do... while Double 14 drawImage, Graphics 62 drawString, Graphics 83

fillRect, Graphics 42 FlowLayout 92 Flux, contrle 3, 10 Font 84 for Voir Boucle for

G
get, ArrayList 31 getKeyChar, KeyEvent 54 getResource 62 getSource, ActionEvent 235 Graphics 41 couleur 42 drawImage 62 drawString 83 fillRect 42 police 84 setColor 42 setFont 84 Gravit, gestion 77

I
Ian a dit cration du plateau 248 dtection des mouvements du joueur 252 niveaux 259 personnalisation 265 if 3 condition 15 else et else if 16 exemple 35 Image 61, 62 cration 230 de fond 180 placer des composants 148 Toolkit 62 ImageIcon 93 Instruction 3, 10 if 3 int 14 Intelligence artificielle 116, 198

E
cran de bienvenue, JOptionPane 63 lment de tableau, numrotation 30 else 16 Ennemis 198, 222 Excuter un projet 12

F
Fichier accs 3, 19 cration 18 File 18, 19 FileOutputStream 18 FileReader 19

278

Devenez un petit gnie des jeux vido

Interface graphique 40 bouton 93 composant 92 Container 92 disposition des composants 92, 105 JButton 93 JFrame 40 JLabel 94 libell 94 placer des composants sur un fond 148 Intersects, rectangle 53

score 205 setText 95 texte 94 JOptionPane 3, 17, 20 cran de bienvenue 63 exemple 32, 35, 63 saisie de lutilisateur 17

K
KeyEvent 54 getKeyChar 54 KeyListener 53 exemple 54, 77, 129, 166, 192, 217 keyPressed 54 keyReleased 54 keyTyped 54

J
Javaman dplacements 217 ennemis 222 plateau 214 JButton 93 ActionListener 97 activer et dsactiver 94 ajouter au conteneur 93 cration 93 exemple 95, 231 image 93 setEnabled 94 texte 93 Jeu de mmoire ajout des correspondances 235 conception du plateau 230 niveaux 240 JFrame 40 Container 92 cration 40 image de fond 144 paint 41 repaint 43 JLabel 94 affichage dun score 98, 159 de statistiques 135 cration 94 exemple 95 image 95 modifier le texte 95

L
Libell Voir JLabel 94 Line2D.Double 73 exemple 74

M
main, mthode 11 Math.random() 23 Mthode 43 appeler 44 arguments 44 cration 43 main 11 nom 44 syntaxe 43 type de retour 43 Morpion boxeur cration du plateau 105 dtecter les victoires 110 intelligence artificielle 116 MouseEvent 72, 126 getX 72, 126 getY 72, 126

Index

279

MouseListener 72 exemple 74, 252 mouseClicked 72 mouseEntered 72 mouseExited 72 mousePressed 72 mouseReleased 72 MouseMotionListener 126 exemple 126 mouseDragged 126 mouseMoved 126 Murs, gestion 217

N
NetBeans 5 compiler un projet 12 cration dun projet 5 crer une classe 7 excuter un projet 12 Niveaux 101, 159, 205, 240, 259 Nombres alatoires 3, 23 NullLayout 105

Piges ajout des traces 170 dtection des collisions 175 effets graphiques 180 plateau et personnages 166 Plateau de jeu ajout dlments alatoires 193 dfinir dans un tableau deux dimensions 189, 214 Point2D.Double 73 exemple 74 println 11 PrintWriter 18 Projet compiler 12 cration dun projet 5 crer dans NetBeans 5 excuter 12

R
Rafrachissement de lcran 48 random 23 Rectangle 42 dessiner 42 exemple 48, 77 intersects 53 repaint JFrame 43 run Thread 47

O
Oiram ajout des ennemis 198 cration de la plate-forme 188 dplacements et toiles 192 niveaux 205 Oprateurs 15

S
Saisie clavier, KeyListener 53 de lutilisateur 17 Score 205 JLabel 98, 159, 205 setBounds composant graphique 105 exemple 126 setColor, Graphics 42 setComponentZOrder 170 setEnabled, JButton 94

P
paint, JFrame 41 Pause 3, 23 Personnalisation cran de bienvenue 63 exemple 180, 265 images 61 sons 62

280

Devenez un petit gnie des jeux vido

setFont, Graphics 84 setText, JLabel 95 Skieur, cration de la piste 72 sleep 23 Souris dtecter les mouvements 126 dtection des clics 72 Statistiques, affichage dans un JLabel 135 String 14 concatnation 15 galit 16 toCharArray 259 System.out.println 11

Toolkit 62 Transtypage 17 ArrayList 32 dun String en double 17 en int 17 try... catch 48 Types de variables 14

U
URL 62 getResource 62

T
Tableau 3, 30 deux dimensions 188 accder un lment 188 cration 188 exemple 189, 214, 231 taille 189 accs un lment 30 cration 30 dclaration 30 initialisation 30 modifier une valeur 30 TextField 148 Thread 47 appeler 48 chronomtre 83, 149 classe interne 47 crer 47 exemple 48, 77, 98, 149, 166 run 47 Thread.sleep 23 exemple 193 Tir 129

V
Variable 3 boolean 14 char 14 crer 14 dclaration 10, 14 dcrmenter 15 double 14 incrmenter 15 initialisation 14 int 14 modifier la valeur 15 oprateurs 15 String 14 tester 15 types 14 Vitesse, gestion 77

W
while Voir Boucle while

un petit gnie des jeux vido


Devenez
Vous rvez de dvelopper vos propres jeux ? Ce livre est fait pour vous ! Lauteur, lui-mme vritable petit gnie de la programmation, vous explique comment crer un panel de jeux aux variantes illimites : jeux de course, jeux de plateau, jeux de tir, jeux de stratgie, anciens jeux revisits ou jeux de rexion autant de programmes que vous concevrez et contrlerez selon vos rgles. Allant bien au-del des concepts habituellement prsents dans un cours ou un ouvrage de programmation, il vous rvle ici ses astuces pour outrepasser les rgles et construire des jeux drles et impressionnants que vous pourrez modier et personnaliser votre gr. Lapprentissage se fait au l de 43 projets ludiques, de difcult croissante. Des instructions illustres vous guident pas pas dans la programmation en Java, langage universel qui permet de jouer aussi bien sous PC, Mac ou Linux.
propos de lauteur
Ian Cinnamon, certi en Java et en C++, est un phnomne g de 15 ans, qui programme depuis plus de sept ans. Il est actuellement lycen la HarvardWestlake School de Los Angeles, en Californie. Retrouvez-le sur le site compagnon (en anglais) de louvrage www.mhprofessional.com/authors/cinnamon. Vous pourrez y partager et changer des programmes avec dautres dveloppeurs de jeux vido.

Le compilateur Java dans les starting-blocks Jeux de course Jeux de plateau Jeux de tir Jeux de stratgie Anciens jeux revisits Jeux de rexion

Niveau : Tous niveaux Catgorie : Programmation Conguration : Multiplate-forme

Pearson Education France 47 bis, rue des Vinaigriers 75010 Paris Tl. : 01 72 74 90 00 Fax : 01 42 05 22 17 www.pearson.fr

ISBN : 978-2-7440-4090-0

Vous aimerez peut-être aussi