Explorer les Livres électroniques
Catégories
Explorer les Livres audio
Catégories
Explorer les Magazines
Catégories
Explorer les Documents
Catégories
des
petit gnie
jeux vido
Dveloppez
facilement
des jeux vidos
multiplates-formes
7
97
e
D
!
ans
Ian Cinnamon
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 afin de vous fournir
une information complte et fiable. 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.
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
91
Introduction ..................................................
Le compilateur .............................................
39
VII
Prface ............................................................
Introduction ....................................................
Remerciements ...........................................
Le compilateur ...............................................
10
91
92
97
101
105
110
116
14
23
30
35
37
39
Destructeurs de lespace
Projet 19 : Le paysage .............................. 126
Projet 20 : Lasers ....................................... 129
Projet 21 : La vengeance ............................ 135
La course du courage
40
47
53
61
Le skieur
Projet 10 : La piste ......................................
72
77
83
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
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++ ......................
Jeu de mmoire
Projet 38 : Correspondances ...................... 235
188
192
198
205
214
217
222
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 dfis.
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 dmystifie 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 certifi en Java et en C++. Il est actuellement lycen la Harvard-Westlake
School de Los Angeles, Californie.
Introduction
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 rflexion, 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 rflexes 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 dfi. Une tte froide et une rflexion 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.
Introduction
Les commentaires. Ils permettent dannoter votre code pour savoir ce que fait
chaque ligne.
Les contrles de flux. 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
afficher 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 artificielle. Pour dplacer un ennemi de manire alatoire, les nombres alatoires sont ce quil vous faut.
Les tableaux et les ArrayList. Ils servent grouper des objets similaires (ennemis,
recharges, etc.) et ainsi gagner du temps.
Les accs aux fichiers (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.
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 officieux 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.
Le compilateur
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
Figure 0.4
Suppression du fichier
Main.java
Figure 0.5
Cration dune nouvelle
classe Java
1
Java dans les
starting-blocks
Au sommaire de ce chapitre :
Projet 1 : Le perroquet
10
Projet 1 : Le perroquet
Projet
Nouvelles briques
Lorsque lon apprend programmer en Java, il faut connatre quatre types de code
essentiels : les commentaires, les instructions, les dclarations et le contrle de flux.
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 modifier le code plus facilement ultrieurement. Lorsquun programme atteint quelques centaines de lignes, il est
difficile 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 afficher quelque chose
lcran. Elles se terminent toujours par un point-virgule.
Les dclarations
Les dclarations sont des instructions qui crent ou modifient 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 flux
Le contrle de flux 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
11
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 flux 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 dafficher
un message lcran :
System.out.println("Ce message entre guillemets est affich.");
Figure 1.1
Ce code affiche du texte lcran
Ce code est une mthode fournie par Java. Il suffit de lui indiquer le texte afficher,
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
Squence dchappement
Rsultat
\n
\t
\"
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 laffichage de votre premier jeu !
Figure 1.2
Compiler le projet
Chapitre 1
13
Figure 1.3
Lancer le projet
Figure 1.4
Affichage 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
Nouvelles briques
lheure actuelle, vous savez crer un programme simple qui affiche 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 :
Comment crer (dclarer et initialiser) une variable ? Les variables de type int, double
ou char se dclarent comme ceci :
int <nom> = <valeur>;
Chapitre 1
15
Vous pouvez aussi crer une variable sans indiquer sa valeur (cela sappelle une dclaration). Il suffit pour cela de terminer la ligne prmaturment avant linitialisation de
la variable grce un point-virgule :
int number;
On peut aussi modifier la valeur dun entier int ou dun flottant double en utilisant les
syntaxes qui suivent. Pour ajouter 1 nombre :
nombre++;
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.".
16
!= teste lingalit.
Lorsque les variables sont de type String, il ne faut pas utiliser ==. Il faut utiliser la
syntaxe suivante :
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)
signifie "si b a la valeur true" (vrai) et if(!b) signifie "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
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 suffit 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
signifie 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 modifier 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);
18
Cette ligne ne fait pour linstant pas grand-chose. Elle se contente dallouer un espace
pour un fichier nomm motdepasse.mdp.
Nous allons maintenant voir comment sauver ce fichier 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);
"Ce texte est crit dans le fichier" est habituellement une variable de type
String.
Une fois le fichier cr, il faut indiquer lordinateur que tout est fini. Utilisez pour
cela les lignes suivantes :
sortie.flush();
sortie.close();
fluxSortie.close();
Chapitre 1
19
Cette fois, la variable de type String (ici, "motdepasse.mdp") est le nom du fichier que
vous allez ouvrir.
Ensuite, crez un objet de type FileReader. La classe FileReader sert ouvrir le fichier
et en prparer la lecture.
FileReader fr = new FileReader(fichier);
Lorsque vous avez termin daccder un fichier, vous devez indiquer lordinateur
que vous avez fini :
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 fichiers.
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 fichier).
20
Chapitre 1
21
Figure 2.3
Saisir le nouveau mot
de passe
Figure 2.4
Deviner le mot de passe
enregistr
22
Figure 2.5
Bonne rponse
Figure 2.6
Mauvaise rponse
Chapitre 1
23
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.
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 fin 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
Boucles
Il est temps dapprendre quelques techniques de contrle de flux. Le contrle de flux
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).
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
25
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
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 :
Chapitre 1
27
28
Figure 3.2
quation, dcompte
et rsultat
Chapitre 1
29
Figure 3.3
Rejouer ?
30
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 difficile 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 dfinir la taille dun tableau, qui dans
notre cas est six.
Pour accder une valeur/un lment dun tableau ou pour la modifier, 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.
Chapitre 1
31
Par exemple, pour modifier le premier lment ( la position 0) du tableau pleinDEntiers et lui donner la valeur 50, on utilisera :
pleinDEntiers[0] = 50;
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 simplifier, 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));
32
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 afficher 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
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 affichage
dun jeu
Figure 4.2
Saisie dun nouveau
nom de jeu
34
Figure 4.3
Continuer le programme
Figure 4.4
Accder un jeu en
indiquant son numro
Figure 4.5
Affichage du jeu demand
Chapitre 1
35
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
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
37
Instructions. Les instructions sont des commandes. Elles sont la base de tout jeu.
Contrle de flux. 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.
JOptionPane. Un JOptionPane permet dobtenir des saisies et dafficher 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.
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 fichiers. Les accs aux fichiers 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 8 : Collisions !
Projet 9 : Personnalisation
Le skieur
Projet 10 : La piste
Projet 12 : La comptition
40
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 fin de la ligne public class... Par
exemple, si votre classe sappelle Jeu, la ligne ressemblerait ceci :
public class Jeu extends JFrame
Modifiez galement la mthode main afin 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();
Chapitre 2
Jeux de course
41
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
42
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 affiche 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
Chapitre 2
Jeux de course
43
Figure 6.3
Un rectangle vert
dans un JFrame
Et, pour redessiner le JFrame, il suffit dutiliser le code suivant dans votre programme :
repaint();
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
<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
46
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();
}
}
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
Nouvelles briques
<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 infinie :
while (true)
{
}
48
Ces quelques lignes permettent de vrifier 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 infinie.
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 finale (ici, 4).
Puis, faites bouger la voiture en modifiant la valeur y de son rectangle en y ajoutant la
valeur de la vitesse de la voiture. Pour finir, 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
50
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();
}
}
52
Figure 7.2
Les voitures acclrent
vers lavant
Chapitre 2
Jeux de course
53
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 vrifier 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
implements KeyListener
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 modifier 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
simplifier, 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 suffit
alors de comparer sa direction avec HAUT plutt quavec 0.
Puis, utilisez un KeyListener pour que le joueur puisse modifier sa direction. Modifiez
la direction en testant la direction actuelle de la voiture et modifiez x si la voiture va
vers la gauche ou vers la droite, y si elle va vers le haut ou vers le bas.
Vrifiez 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
56
Chapitre 2
Jeux de course
57
58
Chapitre 2
Jeux de course
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();
}
}
59
60
Figure 8.2
Les voitures tournent et
se promnent sur la piste
Chapitre 2
Jeux de course
61
Briques
Images
Envie davoir des images dans votre jeu ? Ce nest pas difficile. 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
fichier .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
Figure 9.3
Avion
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)
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();
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
Chapitre 2
Jeux de course
65
66
Chapitre 2
Jeux de course
67
68
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
}
//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();
}
}
69
70
Figure 9.4
cran de
bienvenue
Figure 9.5
Les voitures sont
sur le dpart !
Chapitre 2
Figure 9.6
La voiture bleue
a gagn !
Jeux de course
71
72
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();
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 dfinir 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
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 saffiche 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
afficher 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();
}
}
76
Figure 10.2
Des lignes connectes
pour crer la piste
Chapitre 2
Jeux de course
77
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 dfinit 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,
vrifiez 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
Chapitre 2
Jeux de course
79
80
Chapitre 2
Jeux de course
Les Figures 11.2 11.4 reprsentent la progression du skieur sur la piste dessine.
Figure 11.2
Dpart du skieur
81
82
Figure 11.3
Le skieur est sur la piste
Figure 11.4
Le skieur est tomb !
Chapitre 2
Jeux de course
83
Crer le jeu
Crez dabord un compteur pour chronomtrer la course du skieur grce une variable
chrono. Puis, initialisez un nouveau fil 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
dafficher le chronomtre.
Figure 12.1
Affichage 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 modifiant un boolen du
Thread.
Pour dessiner du texte, on utilise la mthode g.drawString("texte", x, y).
84
Chapitre 2
Jeux de course
85
86
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
Chapitre 2
Jeux de course
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!");
}
}
89
3
Jeux de plateau
Au sommaire de ce chapitre :
Projet 13 : Le laboratoire
Le morpion boxeur
Projet 16 : Le ring
Projet 17 : Combat !
Projet 18 : K.-O. !
92
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();
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 affiche 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 modifier 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 affich dans
le JButton. Pour afficher 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 fichier. 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
Figure 13.2
Un JButton avec un
ImageIcon
Les objets de type JButton ont, entre autres, de nombreuses mthodes pour dsactiver,
activer et modifier 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);
JLabel
Un JLabel est un composant dun autre type. Il permet dafficher du texte dans un
JFrame. La Figure 13.3 illustre un JLabel.
Figure 13.3
Un JLabel
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 modifier leur texte.
On peut modifier 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 finir, crez et ajoutez un JLabel pour le score (pour linstant, il affichera
juste "SCORE :").
import
import
import
import
javax.swing.event.*;
javax.swing.*;
java.awt.*;
java.awt.event.*;
96
Figure 13.4
Le jeu cette tape
du dveloppement
Chapitre 3
Jeux de plateau
97
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);
Pour savoir quel bouton a t actionn, il suffit 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
Crez alors un nouveau fil dexcution (Thread). Dans sa boucle while infinie, 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 fils dexcution en pause
pour un quart de seconde (pour laisser au joueur le temps de reprendre son souffle).
Vous pouvez ensuite afficher 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
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) {
}
}
99
100
Continuez votre lecture pour savoir comment augmenter le niveau de difficult au fur
et mesure que le joueur touche des mauvais gnies.
Attention, les gnies peuvent devenir difficiles attraper, ils apprennent de leurs
erreurs... Aprs tout, ce sont des mauvais gnies !
Chapitre 3
Jeux de plateau
101
Crer le jeu
Lorsque la difficult des jeux naugmente pas, ceux-ci deviennent vite ennuyeux. Pour
linstant, la chasse aux mauvais gnies est configure 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 fil dexcution, incrmentez le compteur. Affichez 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 difficile.
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
//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
104
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 affich.
Chapitre 3
Jeux de plateau
105
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, modifiez la
ligne setLayout :
cont.setLayout(null);
<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 fiables. Il se peut que votre cran ne se rafrachisse pas et que vos
modifications ne soient pas prises en compte. Cependant, ne vous inquitez pas : il
existe une manire simple de rafrachir lcran de manire ce que vos modifications
soient systmatiquement prises en compte. Une fois que vous avez ajout tous les
composants dsirs au conteneur, ajoutez simplement la ligne :
cont.repaint();
106
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 vrifier 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, modifiez
licne pour afficher la bonne image. Lorsque vous avez modifi licne, pensez
supprimer lActionListener pour quun joueur ne puisse pas voler la position de son
adversaire !
Chapitre 3
Jeux de plateau
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
107
108
Chapitre 3
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
Jeux de plateau
109
110
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 afficher cette image. Ajoutez ce JLabel au-dessus des boutons ( lemplacement 0,0),
Noubliez pas de modifier la boucle qui ajoute les boutons pour que ceux-ci ne soient
pas couverts par limage du titre. Il suffit 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 fin de chaque appel de la mthode actionPerformed, appelez
Chapitre 3
Jeux de plateau
111
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
Vous y tes presque ! Il suffit 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 vrifier 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
//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
Jeux de plateau
113
114
{
//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
vrification des victoires. Ali, Tyson, Foreman : dans le prochain projet, vous apprendrez
comment programmer le boxeur ultime en ajoutant de lintelligence artificielle.
Figure 17.3
Le joueur 1 (O) va
gagner !
Figure 17.4
Lordinateur reconnat la
victoire du joueur 1 (O).
116
Oubliez les beaux jeux de jambes, les directs rapides et les coups
de poing foudroyants. Lintelligence artificielle est la force la plus
puissante sur un ring de boxe. Ce projet va vous expliquer comment
crer une intelligence artificielle pour crer un adversaire votre
hauteur et celle de vos amis.
Crer le jeu
Pour crer une intelligence artificielle (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 suffit 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 suffit que celle-ci affiche licne X.
Puis, la fin 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
118
//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
120
Chapitre 3
Jeux de plateau
121
122
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();
}
}
Figure 18.4
Match nul !
Chapitre 3
Jeux de plateau
123
4
Jeux de tir
Au sommaire de ce chapitre :
Destructeurs de lespace
Projet 19 : Le paysage
Projet 20 : Lasers
Projet 21 : La vengeance
126
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)
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
128
Figure 19.1
Le vaisseau est prt
pour laction !
Chapitre 4
Jeux de tir
129
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 fil dexcution et une boucle
infinie, 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 infinie,
dplacez les aliens vers le bas. Crez galement un ArrayList pour contenir les aliens.
Une instruction if vrifiera 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
Il faut galement dtecter les collisions entre les lasers du vaisseau et les aliens dans la
boucle infinie. 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
132
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 dfi
moins que les aliens naient galement de la puissance de feu. Cest ce que permet de
faire le projet suivant.
Chapitre 4
Figure 20.3
Arrive des aliens
Figure 20.4
Ouverture du feu
Jeux de tir
133
134
Figure 20.5
Oh oh, ils se reproduisent !
Chapitre 4
Jeux de tir
135
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 infinie, cherchez
les collisions entre les lasers aliens et le vaisseau. Sils entrent en collision, modifiez
licne du vaisseau pour afficher 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 rflecteurs et des
bonus de vie. Les rayons rflecteurs mlangent les particules des aliens et les font
disparatre temporairement. Les bonus de vie ajoutent de lnergie au vaisseau. Tous
les trois niveaux, un dflecteur 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 rflecteur, 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 modifier la valeur aprs chaque itration de la boucle infinie.
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
//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
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
}
}
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();
}
}
Chapitre 4
Figure 21.2
Le rayon rflecteur
Figure 21.3
Apparition dun bonus
de vie
Jeux de tir
141
142
5
Jeux de stratgie
Au sommaire de ce chapitre :
Dmineurs
Projet 24 : BOUM !
Projet 25 : Promotions
Piges
Projet 26 : Dplacements
Projet 28 : Pig !
Projet 29 : Le spectacle
144
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 fini 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
Figure 22.3
Bombe avant son insertion
dans le JFrame
Chapitre 5
Figure 22.4
Bombe affiche dans
le JFrame
Jeux de stratgie
147
148
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 affiches en bas droite du programme, comme lillustre
la Figure 23.1.
Figure 23.1
Affichage des coordonnes
Chapitre 5
Jeux de stratgie
149
Aprs avoir ajout les composants, crez une variable pour reprsenter le temps
restant. Utilisez un fil 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, modifiez 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
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
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
Crer le jeu
Pour ajouter des explosions flamboyantes, 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 modifie (voir Figure 24.2).
Crez des JLabel pour chaque image. Puis, dans le fil dexcution du dcompte, vrifiez si le temps coul est infrieur ou gal 0. Si cest le cas, appelez une mthode
pour afficher 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
Figure 24.2
Seconde explosion
Chapitre 5
Jeux de stratgie
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--;
155
156
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
Figure 24.4
Explosion flamboyante
Jeux de stratgie
157
158
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 difficiles.
Chapitre 5
Jeux de stratgie
159
Ajoutez des niveaux au jeu. Les premiers dfis 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.
Affichez 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 difficiles, 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 affiche 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
Chapitre 5
Jeux de stratgie
//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) {
161
162
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
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
163
164
Figure 25.3
Bombe dsamorce
avec succs
Figure 25.4
BOUM ! Rat !
Chapitre 5
Jeux de stratgie
165
166
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 fils 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, vrifiez 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, modifiezles pour modifier la direction dans la mthode keyPressed.
Lorsque les directions des joueurs sont tablies, il faut les faire bouger dans larne.
Dans la boucle infinie de chaque fil 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
168
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
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 infinie, crez un JLabel temporaire pour garder limage du
segment de trace. Ajoutez ce JLabel temporaire lArrayList et au conteneur.
setBounds permettra de dfinir la position de limage en fonction de la position du
joueur. Noubliez pas dutiliser la mthode setComponentZOrder pour garder la piste en
position "1" afin que limage du joueur soit toujours affiche.
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
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) {
171
172
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
Figure 27.1
Les joueurs commencent
bouger
Figure 27.2
Les joueurs laissent
une trace
Jeux de stratgie
173
174
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
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 infinie et vrifiez 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 vrifier
tous les JLabel ( lexception des dix derniers) de lArrayList. Il ne faut pas vrifier
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 saffiche en continu
car les fils dexcution ne sont pas arrts. Pour arrter laffichage, utilisez un boolen
pour contrler la boucle infinie. Une valeur false pour ce boolen arrtera les fils
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
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
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();
}
}
177
178
//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();
}
}
Chapitre 5
Figure 28.1
Les joueurs combattent
Figure 28.2
Le joueur 1 a pig
le joueur 2
Jeux de stratgie
179
180
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. Affichez
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()
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
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
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();
}
}
183
184
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
6
Anciens jeux... revisits
Au sommaire de ce chapitre :
Oiram
Projet 30 : La plate-forme
Javaman
188
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
189
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 afficher le plateau dans un JFrame, itrez sur le tableau grce deux boucles for.
chaque itration, utilisez des instructions if pour vrifier si la zone courante
contient de lair, de la terre ou une chelle. Utilisez la mthode setBounds pour afficher
la bonne image.
import
import
import
import
import
javax.swing.*;
javax.swing.event.*;
java.awt.*;
java.awt.event.*;
java.util.*;
190
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
191
192
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. Vrifiez dabord
quOiram se trouve dans larne. Si oui, vrifiez si lespace la droite dOiram est de
Chapitre 6
193
Pour corriger cela, crez une nouvelle image de taille 50 50 pixels reprsentant
Oiram escaladant lchelle. Ne laffichez 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 fil dexcution appel Course. Dans la boucle infinie,
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, vrifiez si le carr sous lui est compos dair. Si oui, descendez Oiram de
50 pixels. Noubliez pas dajouter la mthode Thread.sleep votre boucle infinie.
194
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
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
}
}
}
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
197
Figure 31.5
Collecte dtoiles
198
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 fil
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, vrifiez 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, vrifiez 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
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++) {
199
200
Chapitre 6
201
202
//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
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
difficult.
Figure 32.2
Les ennemis sont vivants !
204
Figure 32.3
Un ennemi mort
Figure 32.4
Le dernier ennemi tue
Oiram
Chapitre 6
205
Crer le jeu
Oiram va se battre dans cinq niveaux : chaque niveau ajoute des ennemis supplmentaires. Pour augmenter le nombre dennemis, modifiez 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 infinie, vrifiez 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 afficher
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.
Affichez le score dans un JLabel.
Vous pouvez aussi ajouter une image de titre amusante. Dessinez Oiram dans une
image de 500 50 et affichez 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.
Affichez-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
//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
207
208
Chapitre 6
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
//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
211
212
Figure 33.2
Oiram a perdu
Figure 33.3
Oiram a gagn
Chapitre 6
213
214
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 :
####
# #
# #
####
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 modification de la disposition du plateau.
Chapitre 6
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);
}
215
216
La Figure 34.1 illustre lunivers de Javaman. Dans le projet suivant, nous insufflerons
la vie Javaman. Prparez-le se battre pour sa vie en le rendant mobile.
Figure 34.1
Plateau de Javaman
Chapitre 6
217
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 fil 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, vrifiez 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
Chapitre 6
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);
}
219
220
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();
}
}
Chapitre 6
Figure 35.2
Javaman est vivant
Figure 35.3
Javaman se dplace
221
222
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 fil
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. Affichez 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
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
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
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
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();
}
}
Chapitre 6
227
Figure 36.2
C++ a gagn...
7
Jeux de rflexion
Au sommaire de ce chapitre :
Jeu de mmoire
Projet 38 : Correspondances
Ian a dit
230
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 rflexion
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 vrifier 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 suffit de crer un tableau bidimensionnel
de huit entiers. Donnez llment adquat la valeur du nombre alatoire.
Une fois les images affiches, 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
//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 rflexion
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
Affichage des images
"Jeu de mmoire"
234
Figure 37.4
Images faire correspondre
Chapitre 7
Jeux de rflexion
235
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 vrifier 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, affichez 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 vrifier si le bouton slectionn est le
bouton courant de la boucle. Si cest le cas, modifiez 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 fil 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
affiches.
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
//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 rflexion
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){}
}
237
238
Chapitre 7
Figure 38.1
La victoire est proche
Jeux de rflexion
239
240
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 fil dexcution. Dans sa boucle infinie, faites une pause dune
seconde et diminuez la variable du temps restant de 1. Affichez le temps restant dans
un JLabel. Modifiez la police de ce libell afin quil ressemble celui de la Figure 39.1.
Figure 39.1
Un JLabel affiche le temps
restant
Dans le fil dexcution cr dans le projet prcdent, vrifiez 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
afficher le nombre de niveaux termins par le joueur. Ce libell est plac au milieu du
JFrame. Vous pouvez alors afficher 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 rflexion
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);
241
242
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 rflexion
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
Chapitre 7
Jeux de rflexion
245
246
Figure 39.3
Un vrai petit gnie !
Figure 39.4
Rang du milieu
Chapitre 7
Jeux de rflexion
247
Figure 39.5
Encore des efforts
faire...
248
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 affichant 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
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);
}
Jeux de rflexion
249
250
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 affiche. Dans le projet suivant,
nous verrons comment tester la mmoire du joueur.
Chapitre 7
Figure 40.2
Le plateau de jeu avec
des couleurs standard
Figure 40.3
Le carr bleu est clair
Jeux de rflexion
251
252
Crer le jeu
Afin 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 dafficher 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 modifier la mthode paint. Examinez le boolen indiquant si lordinateur est en train dafficher 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 : affichez 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
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){ }
Jeux de rflexion
253
254
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 rflexion
255
256
//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();
}
}
Chapitre 7
Figure 41.1
Squence de lordinateur
Figure 41.2
Rptition correcte
Jeux de rflexion
257
258
Figure 41.3
Rptition incorrecte,
perdu !
Chapitre 7
Jeux de rflexion
259
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 dafficher 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 affichez 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
Dans la mthode paint, appelez la mthode qui affiche 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 rflexion
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));
261
262
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 rflexion
263
264
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 rflexion
265
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
266
Figure 43.3
Bon dpart...
mais continuez
vous entraner
Chapitre 7
Jeux de rflexion
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
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 rflexion
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));
269
270
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 rflexion
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){}
271
272
Chapitre 7
Jeux de rflexion
273
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
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
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
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
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
277
278
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
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
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
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
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
O
Oiram
ajout des ennemis 198
cration de la plate-forme 188
dplacements et toiles 192
niveaux 205
Oprateurs 15
P
paint, JFrame 41
Pause 3, 23
Personnalisation
cran de bienvenue 63
exemple 180, 265
images 61
sons 62
279
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
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
280
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
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
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
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
Le compilateur
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
rflexion autant de programmes que vous concevrez et
contrlerez selon vos rgles.
Jeux de course
Jeux de plateau
Jeux de tir
Jeux de stratgie
Anciens jeux revisits
Jeux de rflexion
Lapprentissage se fait au fil de 43 projets ludiques, de difficult 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
ISBN : 978-2-7440-4090-0