Jeux Libres

Plateforme de création de jeux vidéo (Le site est en cours de création / réorganisation)


» Les Tutoriaux » La programmation de jeux avec le langage Java » Le monde de la programmation orientée objet

Le monde de la programmation orientée objet


[b]Voilà alors ici je vais vous expliquez plus en détail comment fonctionnent les classes, les méthodes appelées sur les objets ou les classes.





Chapitre précédent     Sommaire     Chapitre suivant


Qu'est-ce donc la POO ?


Définition



La POO (programmation orientée objet) est une manière simplifiée pour encoder un programme, la POO recherche donc la simplicité de conception et non la performance.

Les langages orienté objets sont donc plus simple à comprendre pour l'homme mais plus long lors de la compilation et comme java interprète du code à l'exécution pour le rendre compréhensible par votre plateforme, il est plus lent à l'exécution, pour cela que la plupart des jeux sont codé en c++.
Mais, java ne vise pas la performance mais la simplicité de conception, et avec les extensions de Java (j3D, jdbc, etc...) et les librairies du c/c++ utlisable maintenant avec Java, ce langage peut égaler le c/c++.
De plus avec la performance des processeurs actuels, la différence ne se voit presque plus.

Hiérarchie aux niveau des langages



Il était une fois...

Le langage machine :


Seul langage assimilable par votre machine. C'est une suite de 0 et de 1 : complexe à comprendre et à déchiffrer pour l'homme.

Le langage assembleur :


Il fut inventé pour permettre de rendre plus simple l'encodage, car le langage machine est trop complexe pour l'homme. Imaginer que vous devez coder par exemple tout une suite de 0 et de 1, vous ne saurez en fin de compte même plus si cela représente une image, un nombre, du texte, ... (enfin en 2 mot c'est tellement compliqué que ça se fait pas, sauf si vous êtes fou (lol)), on a donc inventé ce langage qui contient des instructions du genre charger un registre d'un processeur avec une valeur en mémoire centrale, ou une valeur tapée au clavier, utilisation de structures répétitives et alternatives, ... (enfin bref je ne vous apprendrez pas ce langage, il ne s'utilise plus beaucoup, je n'ai pas beaucoup appris ce langage, et avec les processeurs actuels, on sais quand on commence mais pas quand on fini, ce langage est juste utiliser pour par exemple faire marcher un processeur correctement.
Ce langage fait donc correspondre un symbole à une instruction binaire, le programme chargé de transformer ces symboles en instructions binaire pour le processeur, est appelé un assembleur.

Mais ce langage a beaucoup d'inconvénient, il est de bas niveau.

L'inconvénient majeur de ce langage c'est que chaque processeur à un langage assembleur bien à lui propre, et donc un programme qui est codé pour un processeur intel ne marchera pas sur une machine ayant un processeur AMD.
De plus, il n'intègre pas de fonctions, juste des instructions du genre le if que l'on a vu ou les boucles avec un compteur, mais plus complexe à utiliser que ce que l'on a vu.
On a donc inventé les langages évolués, dis de haut niveaux. (Note qu'il existe des langages encore plus évolués tel que mySQL dit de 4ème génération et le Prolog de 5ème génération)

Les langages évolués


Ensuite après l'assembleur, nous avons les langages de 3ème génération, langages évolués.
Eux ils ont l'avantage de fonctionner avec n'importe quel type de processeur.
C'est votre système d'exploitation qui se chargera de traduire ce langage en langage machine, selon le type de processeur.
Et votre code source, est traduit en langage de bas niveau, grâce à un compilateur.

Il y a notamment les langages procéduraux connus comme le C, le Pascal, le Visual Basic et plein d'autres.
Ceux-ci ont la particularité de décomposer les programmes en fonctions.
Le procédural s'intéresse donc surtout aux grandes fonctionnalités que va devoir gérer votre programme.

Et enfin il y a les langages de POO, eux, ils ne s'intéressent pas uniquement aux grandes fonctionnalités du programme, mais aussi aux différents acteurs de ce programme. (Java, Python, c++, c#, etc...)

Tout ces acteurs sont considéré comme des objets, et chacun possède ses propres caractéristiques et ses propres fonctionnalités.

On fait donc deux découpes dans le code, d'abord on découpe le programme en fonction des grands acteurs de celui-ci et ensuite on découpe le programme en fonction des grandes fonctionnalités que doivent accomplir ces acteurs.

Exemple pour bien comprendre

On doit créer un mmorpg avec des personnages et chaque personnage appartient à une classe bien particulière. (guerrier, magicien, marchand, voleur, ninja, taekwan, fusilleur, chasseur à l'arc, etc...)
Bah on va donc commencer en POO à s'intéresser à coder la classe Personnage qui contiendra des fonctions (méthodes) et caractéristiques (variables) qui seront communes à tout ces personnages.
Ensuite on va s'intéresser aux classes qui auront des fonctions plus spécifique chacune.
Le magicien par exemple pourra lancer des sors avec un bâton.
Le guerrier aura une épée et une cheval par exemple.
Le ninja pourra utiliser des shuriken et des kunaï pour se battre.
Le taekwon attaquera avec ses pieds.
Le marchand lui sont but sera de vendre un max d'objets, il faudra donc qu'il puisse vendre, etc ...
On fait donc 2 découpes :
Quels sont les objets de notre programme et que peuvent ils faire ?
Il y a aussi là une hiérarchie d'objets plus généraux (un personnage) vers des objets plus spécifiques (des magiciens), cela s'appelle l'héritage, je vous en parlerai plus loin dans la POO.

Conséquences de la POO:

Dépendance fonctionnelle : chaque objets devront être modifié avec les méthodes de la classe à laquelle il appartient.

Indépendance de développement : Chaque classe agit indépendamment d'une autre.

Un petit mot sur les autres langages.



Le mySQL : c'est un langage de 4ème génération, là, la différence est que on ne doit plus écrire tout le corps des méthodes, et se préoccuper de l'algorithme, ce langage en effet, comprends une séries d'instructions, telles que des instructions pour faire des recherches dans un tableau de données, trier, faire la moyenne, etc...
Et lorsque vous écrirez vos instructions, celles ci vont être interprétées, et le langage mySQL utilisera donc les bonnes méthodes, et algorithmes en fonction de ce que vous lui avez demander, et va vous renvoyer les résultats.
Là donc, on a plus de fonctions, ni d'objets, le langage les fabriques lui même, à partir de ce qu'on lui demande.

Et pour ce qui est du Prolog, ce langage est utilisé pour produire de nouvelles procédures, à partir d'autres procédures existantes.

Mais on n'utilisera pas ces langages, je ne détaillerai donc pas plus.
Voila vous connaissez l'histoire des langages de programmation maintenant.


Les notions de base


Je vais peut-être me redire mais mieux vaut que je le fasse, surtout sur ces notions fondamentales à absolument maîtriser, si vous ne les maîtrisez pas, pas la peine de commencer à créer des jeux avec le langage Java, vous ne comprendrai rien!

Un objet c'est quoi ?


Bah en fait il n'est pas vraiment possible de définir précisément ce qu'est un objet, ça peut être n'importe quoi, se sera à vous de voir en fonction du jeux que vous voudrez créer, quels seront les objets de votre jeux.
Ces objets seront donc différents pour chaque jeux.

Les deux parties d'un objet



Un objet aura toujours deux parties :

une partie statique :
Ce sont les variables propres à chaque objets. (Ses caractéristiques)

Exemple : sa taille de type entier.

Et une partie dynamique :

Ce sont les méthodes qui permettent de modifier la valeur des variables pour un objet. Ceci définit le comportement de l'objet.

Toutes les variables et méthodes propre à un type d'objet devront se retrouver dans sa classe!!

Une classe d'objets c'est quoi ?


C'est tout simplement un genre de moule qui permet de créer des objets de même type, une classe est une sorte d'usine si vous voulez. (Vous avez une usine qui crée des objet vitre, une autre qui crée des objets voitures, etc...bah les classes c'est pareil!)

Pour chaque objets que vous devrez créer, il faudra donc lui définir une classe avec ses caractéristiques et ses méthodes.

Exemple, on veut créer des objets de type Voiture.

On souhaite lui définir une couleur (un entier) et une marque. (un String)

Ensuite on souhaite pouvoir la faire avancer.
Bah voici ce que ça va donner en java :
Code de la classe voiture :
Code : Java
public class Voiture {
int couleur;
String marque;
int position;
public void move (int depalcement) {
position += deplacement;
}
}

Code de la classe principale contenant le main.
Code : Java
public class TestVoiture {
public static void main (String[] args) {
Voiture v1 = new Voiture ();
v1.couleur = 3;
v1.marque = "Peugeot";
v1.move (50);
System.out.println("Couleur de la voiture : "+v1.couleur+"marque : "+v1.marque +"position : "+v1.position);
}
}

Essayez.

Il y aura donc 2 choses que vous serez amener à faire : utiliser des méthodes de classes d'objets déjà définies et créer vous même vos propres classes.

Pour bien comprendre je vous invite maintenant à ouvrir blue-J.

Manipulations



Maintenant je vais vous faire effectuer quelques manipulations pour vous bien comprendre le rôle des classes et des méthodes sur les objets.^^

Plus tard, nous apprendront à sortir de blue-J et à effectuer toutes les manipulations nécessaire dans un main, mais pour pas tout mélanger, nous allons (contrairement aux exercices précédents ou je vous ai fait tout écrire dans une seule classe, celle du main) ne plus utiliser cette classe avec le main pour l'instant.
Nous nous intéresserons uniquement aux classes, méthodes et objets.^^

En effet, jusqu'ici donc je vous ai fait utiliser que une seule classe dans les exercices, la classe du main, on a donc fait pratiquement que du procédural jusqu'à maintenant.

Bon maintenant je vous invite à cliquer sur project, open project, shapes.
Il est normalement dans le répertoire C:\blueJ\examples

La vous devriez voir apparaitre une séries de rectangles qui sont en faîtes, des classes.

Faîtes clique droit puis compiler pour les compiler.
On ne va s'intéresser que aux classes Triangle, Circle et Square pour le moment, la classe Canvas est trop complexe.
Faîtes un coup un clic droit sur la classe Triangle et après sélectionner new Triangle ().
Laissez triangle1 dans le champ Name Of Instance qui est le nom référençant votre objet.
Puis vous voyez en dessous normalement apparaître un objet triangle1 de type Triangle!!
Comme sur l'image ci dessous :
Image utilisateur
Cliquer dessus (clic droit) et vous voyez toute une série de méthodes!
Un genre à l'image ci dessous : (Ne vous étonnez pas si vous n'avez pas les même méthodes, j'ai prit les images sur des classes que j'ai faîtes)
Image utilisateur
Avec certaines, des arguments entre les ().
Pour voir votre triangle, faîtes makeVisible ()
La on voit un triangle qui s'affiche.
Maintenant vous pouvez modifier sa taille par exemple.
Cliquer sur changeSize et entrer la largeur et la hauteur que vous voulez donnez à votre triangle.
On peut aussi le faire décaler à droite et à gauche, avec les méthode moveRight et moveLeft, etc ...

Si vous voulez consulter la valeur des variables de votre objet, cliquer tout en bas sur inspect et vous avez normalement une fenêtre de ce genre ci :
Image utilisateur

Vous aller maintenant analyser le code de la classe Triangle, pour cela, clic droit sur la classe Triangle puis vous faîtes "open editor".

Cette classe que contient - elle ?

Ouvrez donc l'éditeur de la classe Triangle maintenant.
Vous voyez que on a d'abord importer un répertoire de java qui est awt, je vous expliquerai plus loin ce qu'il contient.
On voit que pour donner un nom à la classe il est écrit :
public class Triangle {

Et en dessous ?

En dessous on a les attributs ou variables du triangle :
sa hauteur (un entier), etc ...

Après la déclaration des variables, on a ce que l'on appelle un constructeur.

C'est quoi ça un constructeur ???


Ce sera l'objet du tutoriel suivant.^^
Et les méthodes

En dessous, enfin on a les méthodes avec leurs corps.
Voila donc le code de base d'une classe en Java qui crée des objets.^^
Maintenant vous pouvez aussi analyser celui de la classe Square et celui de la classe Circle.

Je vous invite à dessiner une maison avec blue-j^^.
Sympa non ?

Remarque : vous remarquerai sans doute (ceux qui font du c++), qu'il n'y à pas d'instruction "delete" dans le code ni de destructeurs, c'est normal car les objets en Java sont virés automatiquement de la mémoire dès qu'ils ne sont plus utilisé dans le programme, il y a en Java ce que l'on appelle le "garbage collector" (collecteur de crasses), qui supprime de la mémoire les objets (qui ne sont plus utilisés dans le programme) automatiquement pour vous.


Le cycle de vie d'un objet est donc :

1) Sa création. (avec le mot clef new = l'instanciation)
2) Une série de modifications. (avec l'appel des méthodes sur lui même)
3) Sa mort (le "garbage collector" s'en charge pour nous)

Vous pouvez créer dans chacune de vos classe une méthode main pour la tester!


A l'exécution, une seule méthode main sera exécutée, même si vous en avez plusieurs dans vos différentes classes.
On verra cela lorsque l'on fera des jar files ou on devra préciser la classe contenant la méthode main qui démarrera notre programme lorsqu'on le lancera.


Code de classes pour ceux qui ont un autre IDE.



Circle :

Code : Java
import java.awt.*;
import java.awt.geom.*;
 
/**
* A circle that can be manipulated and that draws itself on a canvas.
*
* @author Michael Kolling and David J. Barnes
* @version 1.0 (15 July 2000)
*/

 
public class Circle
{
private int diameter;
private int xPosition;
private int yPosition;
private String color;
private boolean isVisible;

/**
* Create a new circle at default position with default color.
*/

public Circle()
{
diameter = 30;
xPosition = 20;
yPosition = 60;
color = "blue";
isVisible = false;
}
/**
* Make this circle visible. If it was already visible, do nothing.
*/

public void makeVisible()
{
isVisible = true;
draw();
}

/**
* Make this circle invisible. If it was already invisible, do nothing.
*/

public void makeInvisible()
{
erase();
isVisible = false;
}

/**
* Move the circle a few pixels to the right.
*/

public void moveRight()
{
moveHorizontal(20);
}
 
/**
* Move the circle a few pixels to the left.
*/

public void moveLeft()
{
moveHorizontal(-20);
}
 
/**
* Move the circle a few pixels up.
*/

public void moveUp()
{
moveVertical(-20);
}
 
/**
* Move the circle a few pixels down.
*/

public void moveDown()
{
moveVertical(20);
}
 
/**
* Move the circle horizontally by 'distance' pixels.
*/

public void moveHorizontal(int distance)
{
erase();
xPosition += distance;
draw();
}
 
/**
* Move the circle vertically by 'distance' pixels.
*/

public void moveVertical(int distance)
{
erase();
yPosition += distance;
draw();
}
 
/**
* Slowly move the circle horizontally by 'distance' pixels.
*/

public void slowMoveHorizontal(int distance)
{
int delta;
 
if(distance < 0)
{
delta = -1;
distance = -distance;
}
else
{
delta = 1;
}
 
for(int i = 0; i < distance; i++)
{
xPosition += delta;
draw();
}
}
 
/**
* Slowly move the circle vertically by 'distance' pixels.
*/

public void slowMoveVertical(int distance)
{
int delta;
 
if(distance < 0)
{
delta = -1;
distance = -distance;
}
else
{
delta = 1;
}
 
for(int i = 0; i < distance; i++)
{
yPosition += delta;
draw();
}
}
 
/**
* Change the size to the new size (in pixels). Size must be >= 0.
*/

public void changeSize(int newDiameter)
{
erase();
diameter = newDiameter;
draw();
}
 
/**
* Change the color. Valid colors are "red", "yellow", "blue", "green",
* "magenta" and "black".
*/

public void changeColor(String newColor)
{
color = newColor;
draw();
}
 
/*
* Draw the circle with current specifications on screen.
*/

private void draw()
{
if(isVisible) {
Canvas canvas = Canvas.getCanvas();
canvas.draw(this, color, new Ellipse2D.Double(xPosition, yPosition,
diameter, diameter));
canvas.wait(10);
}
}
 
/*
* Erase the circle on screen.
*/

private void erase()
{
if(isVisible) {
Canvas canvas = Canvas.getCanvas();
canvas.erase(this);
}
}
}

Triangle :

Code : Java
import java.awt.*;
 
/**
* A triangle that can be manipulated and that draws itself on a canvas.
*
* @author Michael Kolling and David J. Barnes
* @version 1.0 (15 July 2000)
*/

 
public class Triangle
{
private int height;
private int width;
private int xPosition;
private int yPosition;
private String color;
private boolean isVisible;
 
/**
* Create a new triangle at default position with default color.
*/

public Triangle()
{
height = 30;
width = 40;
xPosition = 50;
yPosition = 15;
color = "green";
isVisible = false;
}
/**
* Make this triangle visible. If it was already visible, do nothing.
*/

public void makeVisible()
{
isVisible = true;
draw();
}

/**
* Make this triangle invisible. If it was already invisible, do nothing.
*/

public void makeInvisible()
{
erase();
isVisible = false;
}

/**
* Move the triangle a few pixels to the right.
*/

public void moveRight()
{
moveHorizontal(20);
}
 
/**
* Move the triangle a few pixels to the left.
*/

public void moveLeft()
{
moveHorizontal(-20);
}
 
/**
* Move the triangle a few pixels up.
*/

public void moveUp()
{
moveVertical(-20);
}
 
/**
* Move the triangle a few pixels down.
*/

public void moveDown()
{
moveVertical(20);
}
 
/**
* Move the triangle horizontally by 'distance' pixels.
*/

public void moveHorizontal(int distance)
{
erase();
xPosition += distance;
draw();
}
 
/**
* Move the triangle vertically by 'distance' pixels.
*/

public void moveVertical(int distance)
{
erase();
yPosition += distance;
draw();
}
 
/**
* Slowly move the triangle horizontally by 'distance' pixels.
*/

public void slowMoveHorizontal(int distance)
{
int delta;
 
if(distance < 0)
{
delta = -1;
distance = -distance;
}
else
{
delta = 1;
}
 
for(int i = 0; i < distance; i++)
{
xPosition += delta;
draw();
}
}
 
/**
* Slowly move the triangle vertically by 'distance' pixels.
*/

public void slowMoveVertical(int distance)
{
int delta;
 
if(distance < 0)
{
delta = -1;
distance = -distance;
}
else
{
delta = 1;
}
 
for(int i = 0; i < distance; i++)
{
yPosition += delta;
draw();
}
}
 
/**
* Change the size to the new size (in pixels). Size must be >= 0.
*/

public void changeSize(int newHeight, int newWidth)
{
erase();
height = newHeight;
width = newWidth;
draw();
}
 
/**
* Change the color. Valid colors are "red", "yellow", "blue", "green",
* "magenta" and "black".
*/

public void changeColor(String newColor)
{
color = newColor;
draw();
}
 
/*
* Draw the triangle with current specifications on screen.
*/

private void draw()
{
if(isVisible) {
Canvas canvas = Canvas.getCanvas();
int[] xpoints = { xPosition, xPosition + (width/2), xPosition - (width/2) };
int[] ypoints = { yPosition, yPosition + height, yPosition + height };
canvas.draw(this, color, new Polygon(xpoints, ypoints, 3));
canvas.wait(10);
}
}
 
/*
* Erase the triangle on screen.
*/

private void erase()
{
if(isVisible) {
Canvas canvas = Canvas.getCanvas();
canvas.erase(this);
}
}
}


Square :

Code : Java
import java.awt.*;
 
/**
* A square that can be manipulated and that draws itself on a canvas.
*
* @author Michael Kolling and David J. Barnes
* @version 1.0 (15 July 2000)
*/

 
public class Square
{
private int size;
private int xPosition;
private int yPosition;
private String color;
private boolean isVisible;
 
/**
* Create a new square at default position with default color.
*/

public Square()
{
size = 30;
xPosition = 60;
yPosition = 50;
color = "red";
isVisible = false;
}
/**
* Make this square visible. If it was already visible, do nothing.
*/

public void makeVisible()
{
isVisible = true;
draw();
}

/**
* Make this square invisible. If it was already invisible, do nothing.
*/

public void makeInvisible()
{
erase();
isVisible = false;
}

/**
* Move the square a few pixels to the right.
*/

public void moveRight()
{
moveHorizontal(20);
}
 
/**
* Move the square a few pixels to the left.
*/

public void moveLeft()
{
moveHorizontal(-20);
}
 
/**
* Move the square a few pixels up.
*/

public void moveUp()
{
moveVertical(-20);
}
 
/**
* Move the square a few pixels down.
*/

public void moveDown()
{
moveVertical(20);
}
 
/**
* Move the square horizontally by 'distance' pixels.
*/

public void moveHorizontal(int distance)
{
erase();
xPosition += distance;
draw();
}
 
/**
* Move the square vertically by 'distance' pixels.
*/

public void moveVertical(int distance)
{
erase();
yPosition += distance;
draw();
}
 
/**
* Slowly move the square horizontally by 'distance' pixels.
*/

public void slowMoveHorizontal(int distance)
{
int delta;
 
if(distance < 0)
{
delta = -1;
distance = -distance;
}
else
{
delta = 1;
}
 
for(int i = 0; i < distance; i++)
{
xPosition += delta;
draw();
}
}
 
/**
* Slowly move the square vertically by 'distance' pixels.
*/

public void slowMoveVertical(int distance)
{
int delta;
 
if(distance < 0)
{
delta = -1;
distance = -distance;
}
else
{
delta = 1;
}
 
for(int i = 0; i < distance; i++)
{
yPosition += delta;
draw();
}
}
 
/**
* Change the size to the new size (in pixels). Size must be >= 0.
*/

public void changeSize(int newSize)
{
erase();
size = newSize;
draw();
}
 
/**
* Change the color. Valid colors are "red", "yellow", "blue", "green",
* "magenta" and "black".
*/

public void changeColor(String newColor)
{
color = newColor;
draw();
}
 
/*
* Draw the square with current specifications on screen.
*/

private void draw()
{
if(isVisible) {
Canvas canvas = Canvas.getCanvas();
canvas.draw(this, color,
new Rectangle(xPosition, yPosition, size, size));
canvas.wait(10);
}
}
 
/*
* Erase the square on screen.
*/

private void erase()
{
if(isVisible) {
Canvas canvas = Canvas.getCanvas();
canvas.erase(this);
}
}
}


Et enfin la classe Canvas pour dessiner le tout :
Code : Java
import javax.swing.*;
import java.awt.*;
import java.util.List;
import java.util.*;
 
/**
* Canvas is a class to allow for simple graphical drawing on a canvas.
* This is a modification of the general purpose Canvas, specially made for
* the BlueJ "shapes" example.
*
* @author: Bruce Quig
* @author: Michael Kolling (mik)
*
* @version: 1.6 (shapes)
*/

public class Canvas
{
// Note: The implementation of this class (specifically the handling of
// shape identity and colors) is slightly more complex than necessary. This
// is done on purpose to keep the interface and instance fields of the
// shape objects in this project clean and simple for educational purposes.
 
private static Canvas canvasSingleton;
 
/**
* Factory method to get the canvas singleton object.
*/

public static Canvas getCanvas()
{
if(canvasSingleton == null) {
canvasSingleton = new Canvas("BlueJ Shapes Demo", 300, 300,
Color.white);
}
canvasSingleton.setVisible(true);
return canvasSingleton;
}
 
// ----- instance part -----
 
private JFrame frame;
private CanvasPane canvas;
private Graphics2D graphic;
private Color backgroundColour;
private Image canvasImage;
private List objects;
private HashMap shapes;

/**
* Create a Canvas.
* @param title title to appear in Canvas Frame
* @param width the desired width for the canvas
* @param height the desired height for the canvas
* @param bgClour the desired background colour of the canvas
*/

private Canvas(String title, int width, int height, Color bgColour)
{
frame = new JFrame();
canvas = new CanvasPane();
frame.setContentPane(canvas);
frame.setTitle(title);
canvas.setPreferredSize(new Dimension(width, height));
backgroundColour = bgColour;
frame.pack();
objects = new ArrayList();
shapes = new HashMap();
}
 
/**
* Set the canvas visibility and brings canvas to the front of screen
* when made visible. This method can also be used to bring an already
* visible canvas to the front of other windows.
* @param visible boolean value representing the desired visibility of
* the canvas (true or false)
*/

public void setVisible(boolean visible)
{
if(graphic == null) {
// first time: instantiate the offscreen image and fill it with
// the background colour
Dimension size = canvas.getSize();
canvasImage = canvas.createImage(size.width, size.height);
graphic = (Graphics2D)canvasImage.getGraphics();
graphic.setColor(backgroundColour);
graphic.fillRect(0, 0, size.width, size.height);
graphic.setColor(Color.black);
}
frame.setVisible(visible);
}
 
/**
* Draw a given shape onto the canvas.
* @param referenceObject an object to define identity for this shape
* @param color the color of the shape
* @param shape the shape object to be drawn on the canvas
*/

// Note: this is a slightly backwards way of maintaining the shape
// objects. It is carefully designed to keep the visible shape interfaces
// in this project clean and simple for educational purposes.
public void draw(Object referenceObject, String color, Shape shape)
{
objects.remove(referenceObject); // just in case it was already there
objects.add(referenceObject); // add at the end
shapes.put(referenceObject, new ShapeDescription(shape, color));
redraw();
}
 
/**
* Erase a given shape's from the screen.
* @param referenceObject the shape object to be erased
*/

public void erase(Object referenceObject)
{
objects.remove(referenceObject); // just in case it was already there
shapes.remove(referenceObject);
redraw();
}
 
/**
* Set the foreground colour of the Canvas.
* @param newColour the new colour for the foreground of the Canvas
*/

public void setForegroundColor(String colorString)
{
if(colorString.equals("red"))
graphic.setColor(Color.red);
else if(colorString.equals("black"))
graphic.setColor(Color.black);
else if(colorString.equals("blue"))
graphic.setColor(Color.blue);
else if(colorString.equals("yellow"))
graphic.setColor(Color.yellow);
else if(colorString.equals("green"))
graphic.setColor(Color.green);
else if(colorString.equals("magenta"))
graphic.setColor(Color.magenta);
else if(colorString.equals("white"))
graphic.setColor(Color.white);

else if (colorString.equals("gray"))
graphic.setColor (Color.gray);
else
graphic.setColor(Color.black);
}
 
/**
* Wait for a specified number of milliseconds before finishing.
* This provides an easy way to specify a small delay which can be
* used when producing animations.
* @param milliseconds the number
*/

public void wait(int milliseconds)
{
try
{
Thread.sleep(milliseconds);
}
catch (Exception e)
{
// ignoring exception at the moment
}
}
 
/**
* Redraw ell shapes currently on the Canvas.
*/

private void redraw()
{
erase();
for(Iterator i=objects.iterator(); i.hasNext(); ) {
((ShapeDescription)shapes.get(i.next())).draw(graphic);
}
canvas.repaint();
}

/**
* Erase the whole canvas. (Does not repaint.)
*/

private void erase()
{
Color original = graphic.getColor();
graphic.setColor(backgroundColour);
Dimension size = canvas.getSize();
graphic.fill(new Rectangle(0, 0, size.width, size.height));
graphic.setColor(original);
}
 
 
/************************************************************************
* Inner class CanvasPane - the actual canvas component contained in the
* Canvas frame. This is essentially a JPanel with added capability to
* refresh the image drawn on it.
*/

private class CanvasPane extends JPanel
{
public void paint(Graphics g)
{
g.drawImage(canvasImage, 0, 0, null);
}
}

/************************************************************************
* Inner class CanvasPane - the actual canvas component contained in the
* Canvas frame. This is essentially a JPanel with added capability to
* refresh the image drawn on it.
*/

private class ShapeDescription
{
private Shape shape;
private String colorString;
 
public ShapeDescription(Shape shape, String color)
{
this.shape = shape;
colorString = color;
}
 
public void draw(Graphics2D graphic)
{
setForegroundColor(colorString);
graphic.fill(shape);
}
}
 
}


Le constructeur


C'est quoi un constructeur ?



C'est une méthode particulière qui sert à donner une valeur par défaut aux variables présentes dans votre classe. Donc, on peut, lorsque vous créer un objet avec l'opérateur new, donner une valeur par défaut aux variables de cet objet.

Le constructeur porte le même nom que la classe et n'admet aucun type de retour, même pas void!!

Si vous ne définissez pas de constructeur dans votre classe, un constructeur est automatiquement appelé par défaut et donne une valeur par défaut à toutes les variables de votre classe.


Les valeurs par défault des variables

La valeur par défaut pour les nombres, c'est zéro, et pour les autres variables (variables d'instance), c'est la valeur particulière null. (qui veut dire rien)
Pour les variables de type char c'est le caractère null le '\0'.
Pour les variables de type boolean c'est la valeur false.
Lorsque vous déclarer un objet au début d'une classe, sa valeur vaut null.
Donc si vous ne créer pas de constructeur, et si vous voulez utiliser une méthode qui modifie les valeurs de votre objet qui vaut null, ça ne marchera pas!!


Erreur fréquente en Java.

Créer une classe maison, effacer tout le blalabla qui a entre les crochets qui délimitent la classe, et écriver ceci :
Code : Java
private Triangle toit;
public void moveToit () {
toit.moveDown ();
}

Compiler et faîtes new maison puis faîtes moveToit ()
Là vous avez une belle erreur en exécution car en faîtes, votre objet toit vaut null, en effet, on l'a juste déclaré mais pas créé!
Vous aurez une erreur de type NullPointerException.
Alors il vous faut rajouter un constructeur dans votre classe maison qui s'en chargera.
code Java :
Code : Java
public Maison () {
toit = new Triangle ();
toit.changeColor("black");
toit.makeVisivle ();
}

Et là normalement ça devrait marché.
Voilà donc l'utilité des constructeurs, il est conseiller de toujours en avoir au moins un.
Dans chaque classe que vous créerez à partir de maintenant, vous devrez donc définir au moins un constructeur.


Le nombre d'arguments dans votre constructeur doit correspondre avec le nombre d'arguments dans votre new lorsque vous créez un objet.


La surcharges des méthodes et des constructeurs


La signature des méthodes :



C'est ce qui permet au compilateur Java, lorsque vous invoquer une méthode, de reconnaitre la méthode qu'il doit rechercher en mémoire pour pouvoir ensuite l'exécuter.

Mais sur base de quels critères recherche t - il une méthode ?


Sur base de son nom tout d'abord; mais aussi sur base de la liste des types de ses arguments. (le nom des arguments il s'en moque tout comme le type de retour de la méthode)

Le critère sur lequel se base le compilateur lors des appels de méthodes s'appelle la signature d'une méthode.
Celle-ci caractérise donc une méthode (servent d'identifiant pour une méthode si vous voulez)

La signature d'une méthode c'est quoi donc ?


Le nom de la méthode suivit de la liste des types de ses arguments entre les ().
S'il n'y a pas d'arguments dans la méthode, la signature c'est juste le nom de la méthode alors.

Exemple

La signature de la méthode changeSize de la classe Triangle est donc :
changeSize (int, int)

La surcharge des méthodes :



Ce sont des méthodes dans une même classe, qui portent le même nom, mais dont la liste des types de leurs arguments n'est pas la même.

Donc si je veux surcharger la méthode changeSize, il suffit que j'écrive :


public void changeSize (double weigth, double heigth)
signature : changeSize (double, double)


Vous voyez que j'ai plus mit des int mais des double.

Attention, jamais deux fois la même signature dans une même classe!!!


On peut aussi surcharger les constructeurs?

Bah oui bien sûr, pourquoi on ne pourrait pas.
Cela sert lorsque l'on doit donner des valeurs par défaut différemment aux variables.
En gros lorsque l'on veut pouvoir créer des objets différemment.

Par exemple, il serait mieux dans la classe Triangle, de pouvoir, lors de la création d'un triangle, lui donner soi-même une position initiale.

Je veux dans ma classe maison, positionner le toit dans le coin supérieur gauche de l'écran (coordonnées : (0, 0))
D'où l'utilité de créer une surcharge du constructeur de la classe triangle.
Rajouter en dessous du constructeur de la classe triangle ceci.
Code : Java
public Triangle (int vx, int vy) {
xPosition = vx;
yPosition = vy;
width = 40;
height = 30;
color = "black";
isVisible = false;
}

Faîtes new triangle (int vx, int vy) et donnez lui une position en entrant les deux valeurs dans les champs.

Ensuite dans la classe Maison ajouter (0, 0) après le new Triangle comme ceci :
Code : Java
toit = new Triangle (0, 0);


Voilà, il n'est plus à la même place, vous pouvez faire la même chose avec la variable color, etc...
Mais n'oublier pas d'initialiser toutes les variables de votre classe dans le constructeur sinon ça fait un joli bug.


L'encapsulation


C'est quoi encore de ce truc vous allez me dire.

Bah en fait c'est simple à comprendre.

Encapsulation :

Chaque variable d'instance ou objet, appartient à sa classe et doit se conformer aux méthodes de cette classe, seul les méthodes de cette classe peuvent modifier la valeur des variables membre de ses objets.
Donc les variables sont, comme vous le constater dans la classe Triangle, déclarées private ça veut dire qu'on ne peut pas y accéder directement. (à partir une autre classe)

On ne peut pas écrire dans une autre classe par exemple
triangle.x = 5;

x est privé et n'est pas accessible en dehors de la classe Triangle.

Il faudra utilisé obligatoirement une méthode de la classe Triangle qui va modifier la valeur de x.

Il faudra aussi en créer une pour récupérer la valeur de x.
Ce sont ce qu'on appelle des getters et des setters. (aussi connus sous le nom d'accesseurs et mutateurs)


Les setters :
Code : Java
public void setX (int nvX) {
x = nvX;
}

Les getters :
Code : Java
public int getX () {
return x;
}


Ainsi pour récupérer le contenu de x dans une autre classe, on écrira :
valeur = triangle.getX (); (getX est déclaré public donc pas de problème)

Si vous écrivez "valeur = triangle.x" ça ne marchera pas car x est déclaré private dans la classe Triangle et n'est donc pas accessible en dehors de celle-ci.
Bien sur il y a parfois des exceptions, comme par exemple quand on écrit tableau.length


Mais c'est pas conseillé car ça ne respecte pas le principe d'encapsulation.

Il se peut aussi que des classes ou méthodes soient private, je verrai cela avec vous plus loin mais c'est assez rare.
En général ce sont des méthodes qui sont appelée dans des méthodes publiques pour simplifier le code d'une méthode publique.
Il dernière choses, une méthode récursive est une méthode qui est appelée dans celle-ci.
Exemple :
Code : Java
public void afficher (int nb) {
System.out.println("Méthode appelée.");
nb--;
if (nb != 0)
afficher (nb);
}

La méthode affichée est appelée dans celle-ci même!

A partir de maintenant je vous oblige à déclarer toutes vos variables private et vos méthodes public, et je le ferai aussi.

Si vous ne mettez rien (pas de public, ni de private, ...) alors ce qui suit sera par défaut visible uniquement dans le package ou votre classe se trouve.


Le mot clef this


C'est quoi encore ce mot vous allez me dire ?



Il pointe vers l'objet qui est entrain d'être créé ou modifié lors de l'appel d'un constructeur ou d'une méthode sur lui même.
Le mot clé this pointe donc vers l'objet lui même.

Utilité de this



Dans la classe Triangle par exemple, vous avez du donner un nom différent dans les arguments de votre constructeur :
Code : Java
public Triangle (int vX, int vY) {
x = vX;
y = vY;
}

Sinon le compilateur va confondre les arguments de votre constructeur et vos variables d'instances que vous essayer d'initialiser.
Bah grâce au mot clef this, on peut écrire ceci :
Code : Java
public Triangle (int x, int y) {
this.x = x;
this.y = y;
}

Pratique non ?
this pointe vers l'objet lui même. (Celui que l'on en entrain de créer)
Ainsi le compilateur sais faire la distinction entre vos variables d'instances de l'objet lui même et les arguments de votre constructeur.

Sinon il peut aussi être utilisé lors de la surcharge des constructeurs.
Exemple :
Code : Java
public Triangle (int c, int y) {
this.x = x;
this.y = y;
}
public Triangle () {
this (0, 0);
//etc ...
}

Donc grâce à this, on peut faire appel au premier constructeur dans le second pour éviter de devoir retaper du code.

le "this (0, 0)" doit être la première ligne de votre constructeur!


Sérieusement, moi je trouves ce mot clef vraiment très pratique!


Exercices (Méthodes, classes, objets et constructeurs)


1)
Rajouté une méthode dans les classes Triangles, square et Circle, une méthode moveTo qui permettra de faire bouger une forme à un endroit précis sur l'écran.
2)
Compléter la classe maison afin de créer une maison.
Vous devez mettre dans votre constructeur, un toit, une façade, deux fenêtre et une porte.
Créé une méthode pour déplacer la maison.


Solution des exercices. (classes, objets, méthodes et ....)


1)
Il suffit tout simplement de rajouter une méthode moveTo dans chacune de ces 3 classes qui modifie les coordonnées de l'objet créé.
Elle doit recevoir en argument la nouvelle position en x et en y de l'objet.
Ensuite reste plus qu'à remplacer les positions dans le corps de la méthode ce qui donne :
Code : Java

public void moveTo (int x, int y) {
       xPosition = x;
       yPosition = y;
       draw (); //Pour remettre à jour l'écran.
}
 

Voilà ajouter cette méthode aux classes et ça ira =)

2)
Alors là je vous ai demandé de compléter notre classe maison, il faut d'abord modifier le constructeur. Bon je vais centrer le toit, je vais donc voir dans la classe Canvas quel est la largeur de la fenêtre.

Là, il l'a écrit lors de la création de son Canvas, elle vaut 300, et la hauteur aussi.

Je placerai moi donc le toit au départ aux coordonnées 150, 10.
Je vais lui mettre comme taille, 50 de hauteur et 200 de largeur.
N'oublier pas de le rendre visible!

Ensuite il faut créer un rectangle et le placer juste en dessous du toit.
Bon histoire de pas m'ennuyer de trop, je vais surcharger les constructeurs de la classe Triangle et de la classe Square pour leur donner directement leur positon, taille et couleur quand je les créées dans le constructeur de ma classe Maison.

Ce qui me donne en définitif pour la classe Triangle le constructeur suivant :
Code : Java

public Triangle (int x, int y, int h, int w, String Color) {
         xPosition = x;
         yPosition = y;
         this.color = color;
         height = h;
         width = w;
         isVisible = false;
}
 

Et dans ma classe Square :
Code : Java

public Square (int x, int y, int size, String color) {
        xPosition = x;
        yPosition = y;
        this.size = size;
        this.color = color;
        isVisible = false;
}
 

Je vous conseille de faire la même chose dans la classe Circle car on l'utilisera après.
Code : Java

public Circle (int x, int y, int d, String color) {
        xPosition = x;
        yPosition = y;
        diameter = d;
        this.color = color;
        isVisible = false;
}
 

Nah, maintenant qu'on a nos constructeurs bien définit, on peut créé notre maison. (enfin!)
Je vais donc vous mettre le constructeur de ma classe maison maintenant :
Code : Java

public Maison () {
        toit = new Triangle (150, 10, 50, 150, "black");
        toit.makeVisible ();
        mur = new Square (90, 60, 120, "red");
        mur.makeVisible ();
        fenetreGauche = new Square (100, 70, 40, "blue");
        fenetreGauche.makeVisible ();
        fenetreDroite = new Square (160, 70, 40, "blue");
        fenetreDroite.makeVisible ();
        porte = new Square (130, 140, 40, "black");
        porte.makeVisible ();
}
 

Et maintenant il reste plus qu'à créer une méthode pour la faire bouger.
Allons y. =)
Voici donc ma méthode^^
Code : Java

public void move (int x, int y) {
        toit.moveTo (x, y);
        mur.moveTo (x - 60, y +50);
        fenetreDroite.moveTo (x + 10, y + 60);
        fenetreGauche.moveTo (x - 50, y + 60);
        porte.moveTo (x - 20, y + 130);
}
 

Voilà si vous comprenez ça, nous pouvons passer à la suite. ;)




Nous voyons donc ici que la POO peux s'avérer très pratique. Elle permet de géré la composition des objets grâce aux classes, qui définit les variables et méthodes pour chaque type d'objets, donc pas besoin de redéclarer à chaque fois les variables et méthodes lors de la créations de plusieurs objets de même type grâce aux classes.

Les constructeurs permettent une initialisation par défaut des attributs/variables des objets lors de leurs création.
Pas besoin de delete ni de destructeur, les objets sont automatiquement supprimés lors de leur inutilité grâce au garbage collector!!
Perso je trouves le Java que c'est quand même bien pratique, c++ j'ai du mal à comprendre avec les delete et les pointeurs sur les objets pouwaaa.



Chapitre précédent     Sommaire     Chapitre suivant



Rédigé par Lo



Hébergeur du site : 1and1.fr



Site de création de Jeux Vidéo
Apprenez à créer vos propres Jeux Video

A propos de la construction du site...
515475 pages ont été consultées sur le site !
Dont 335 pages pendant les 24 dernières heures.

Page générée en 1.093 secondes


Nos partenaires
- Otium Production : Aide aux débutants à créer leurs jeux
- Site de dessins d'enfants


  © 2005-2010 www.jeux-libres.com - Toute reproduction totale ou partielle du contenu de ce site est strictement interdite.