Javaquarium

4 ans et 3 mois après, il est toujours là, et toujours aussi difficile !

a marqué ce sujet comme résolu.

Du coup, je ne comprends pas l'énoncé quand il est dit "il n'a qu'une seule chance".

Je pense que c'est formulé ainsi parce que quand on tire un poisson au hasard, on a une chance de tomber sur soi-même ou sur un poisson de la même espèce. En gros, ça veut dire, on n'exclut pas les inmangeables du tirage au sort, et si on n'a pas de chance, on ne tire pas un deuxième poisson.

Bon, au passage, je ne me rappelle plus si j'avais déjà posté mon code ou pas. J'ai utilisé une technique un peu bizarre où des parties de comportement sont codées dans des interfaces un peu spéciales. JE sais que c'est une technique assez classique car je n'ai pas la prétention d'inventer une nouvelle construction, mais je ne sais pas trop comment s'appellerait ce design pattern…

+0 -0

Je suis particulièrement d'accord avec informaticienzéro sur le fait que l'ECS convient très bien à un tel problème. en fait dans l'optique de produire un programme en adéquation avec les normes de programmation modernes, l'ECS est le design parfait pour un tel problème, et un arbre d'héritage brut est vachement "moche" ! Pour avoir fait cet exercice il y a environ 3 ans, et l'avoir justement réalisé en c++ avec un arbre d'héritage très laid, je peux vous assurer que si c'était à refaire aujourd'hui, je changerai totalement de design et je déploierai un ECS ;)

Quelqu'un pour expliquer ce qu'est un ECS et/ou pour pointer un bon tutoriel ?

Sinon à part ça, qu'est-ce que vous pensez de mon code ? Je ne poste volontairement que la structure, pas l'implémentation complète. Pour ceux qui la veulent, je la mettrai en téléchargement plus tard mais c'est un peu gros pour poster entièrement ici. Quoi qu'il en soit je pense avoir choisi des noms suffisament évocateurs pour qu'on pige globalement le fonctionnement sans avoir besoin des détails. Excusez-moi d'avance pour le franglais…

Merci.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
public abstract class Animal {
Aquarium aqua;
int pv = 10;
int age = 0;
public Animal (Aquarium ref) ;
public int getPV () ;
public void setPV (int x) ;
public boolean isAlive () ;
public void tick () ;
}

public class Algue extends Animal {
public Algue () ;
public String toString () ;
public void tick () ;
}

public abstract class Poisson extends Animal {
protected interface Eating {
public boolean canEat (Poisson eater, Animal eaten);
public int getPVLost () ;
public int getPVGained ();
public Class<? extends Animal>  getEatingClass ();
}
protected interface Reproduction {
public boolean canReproduce (Poisson a, Poisson b);
public void tick (Poisson p);
}

protected static final Eating
CARNIVORE = new Eating(){ ... },
HERBIVORE = new Eating(){ ... };
protected static final Reproduction
MONOSEXE = new Reproduction(){ ... },
HERMAPHRODITE_AGE = new Reproduction(){ ... },
HERMAPHRODITE_OPPORTUNISTE = new Reproduction(){ ... };

Eating eating;
Reproduction reproduction;
String name;
boolean female;

public Poisson (Aquarium a, String n, boolean f, Eating e, Reproduction r) ;
public abstract Poisson newPoisson (String name, boolean female) ;
public String toString () ;
public boolean isFemale () ;
public String getName () ;
public void eat () ;
public void reproduce () ;
public void tick () ;
public static String generateNameFrom (Poisson p) ;
}

public class Sole/Thon/Merou/Clown/Carpe/Bar extends Poisson {
public Sole/Thon/Merou/Clown/Carpe/Bar (Aquarium a, String name, boolean female) ;
public Poisson newPoisson (String name, boolean female) ;
}

public class Aquarium {
int tick = 0;
Collection<Animal> population ;
Collection<Animal> toAdd ;
Collection<Animal> toRemove ;
Random rand = new Random();

public Aquarium () ;
public void add (Animal a) ;
public void remove (Animal a) ;
public boolean  getRandomBoolean () ;
@SuppressWarnings("unchecked") public <C extends Animal> C getRandom (Class<C> c) ;
public void tick () ;
public String toString () ;
public static void main (String[] args) ;
}
+0 -0

Quelqu'un pour expliquer ce qu'est un ECS et/ou pour pointer un bon tutoriel ?

QuentinC

L'Entity Component System est un pattern très pratique pour la définition d'entité qui vont avoir un (potentiellement grand) nombre de comportements (communs ou non) et interagir ensemble. Pour te faire une idée rapide, tu peux aller voir l'article Wikipedia qui est assez général pour ne pas raconter de bêtises. Ensuite, tu peux jeter un oeil aux liens donnés à la fin qui sont plus poussés.

Pourquoi on le conseille pour cet exercice ? Parce qu'il y a un moment où l'héritage ça commence à bien faire :lol: !

Plus sérieusement, le soucis avec les arbres d'héritages, c'est que quand tu as beaucoup de comportements, si tu veux respecter l'ISP, tu dois définir plein d'interfaces différentes et tes classes vont devoir implémenter un sacré bazar si elles ont accès à pas mal d'entre eux, c'est encore plus relou avec les langages qui ne permettent pas de créer un comportement par défaut parce que tu va sans doute dupliquer plein de code.

L'ECS résout ce problème en proposant plutôt de définir les entités comme une composition de comportements qui sont chacun gérés en ensembles par les Systèmes qui ont pour rôle de répercuter les effets des comportements. Du coup, un autre avantage de l'ECS c'est que les comportements n'ont pas nécessairement besoin d'être fixes ! On peut dynamiquement ajouter et enlever des comportements aux entités.

L'inconvénient de l'ECS c'est que la machinerie sous jacente est beaucoup plus complexe à mettre en oeuvre. Donc il faut qu'elle vaille le coup. Grosso-modo tant que l'on a pas plein de comportements différents et surtout plein de type d'entité utilisant des combinaisons très différentes de comportements, ça ne vaut pas le coût.

Une discussion en rapport sur OC : Structurer jeu C++ (le début est ce qu'il ne faut pas faire, la suite est intéressante).

Quelqu'un pour expliquer ce qu'est un ECS et/ou pour pointer un bon tutoriel ? Source:QuentinC

Tous ces liens viennent de ma page biographie sur PDP.

Et comme tu vas surmener t'en rendre compte, et c'est là que le bât laisse, il est à l'heure actuelle impossible de trouver un tuto ou une ressource complet, fiable et bien écrit qui permette de réaliser un ECS pour un débutant. Malheureusement, tu vas devoir lire un sacré paquet d'articles (dont ceux proposés par informaticienzero) avant d'en savoir assez pour te lancer (un peu à l'aveugle) dedans ! Donc je te souhaite vraiment bon courage !

il est à l'heure actuelle impossible de trouver un tuto ou une ressource complet, fiable et bien écrit qui permette de réaliser un ECS pour un débutant

D'ailleurs si quelqu'un est motivé pour en faire un sur ZdS, il est le bienvenu :-°

SpaceFox

Ce serait effectivement une grosse pluvalue pour le site. J'essayerais bien quand j'en aurais une meilleure compréhension parce que là, effectivement, je suis dans cette phase d'implémentation à l'aveugle.

Et bien sans trop en dévoiler, je sais que GBDivers Valent2000, ZeFresk et moi-même avions envisagé de publier un article avec des bases de code mais le sujet est tellement vaste que le travail est long et fastidieux ! Pour l'instant, c'est loin d'être fini, mais qui sait peut être qu'on arrivera au bout !

Si vous voulez des cobayes pour voir si votre article/tuto explique bien je suis volontaire :D

J'ai pas le temps de faire le Javaquarium, mais je vais le faire dans le cadre d'un projet, au lieu de gerrer tour par tour on va le faire en temps reel avec des algos de genetiques et de l'evolution des pissons (formes, aggressivite etc). Ce serait donc un plus si le tuto/article etait finit ou si je pouvais le tester :p

Quelqu'un pour expliquer ce qu'est un ECS et/ou pour pointer un bon tutoriel ?

QuentinC

Deux liens de plus :

http://gamedevelopment.tutsplus.com/tutorials/create-a-simple-asteroids-game-using-component-based-entities--gamedev-1324

http://gameprogrammingpatterns.com/component.html

La structure ECS m'a emballé. Ce côté "gestion d'inventaire" où l'on plug des composants sur des entités, c'est pratique et très propre. Avec le Javascript, la structure doit pouvoir se faire en deux-deux (étant donné que le langage est peu typé et moins strict que le Java ou le C++).

Merci pour la découverte. :) Je recode mon Javaquarium en ECS.

+0 -0

Je me suis arrêté là en fait. Une algue qui est un animal ?!

Ouais, bon, j'ai pas dit que ma hiérarchie était scientifiquement correcte… Je l'ai fait ainsi parce que ça m'arrangeais bien.

Merci pour vos liens sur les ECS, je m'en vais un peu lire tout ça et je reviendrai avec mes questions, je risque bien d'en avoir avec toute la matière qu'il y a.

En n'ayant encore rien lu pour le moment (même pas wikipédia), il semblerait que ma stratégie ne soit pas si éloignée des ECS que ça en fait, si je m'en remets à votre définition succinte.

Ce qui me fait dire ça c'est que techniquement, dans mon implémentation actuelle, je peux déjà changer le mode de reproduction ou de nourriture d'un poisson donné à la volée si je veux. Les classes spécialisées (Carpe, Sole, Clown, etc.) ne font qu'une dizaine de lignes en fait ! Extrait, ici la classe Thon :

1
2
3
public Thon (Aquarium a, String name, boolean female) {
super(a, name, female, CARNIVORE, MONOSEXE);
}

Où CARNIVORE et MONOSEXE désignent bien des parties de comportements.

Là où je dois m'être éloigné et probablement suivi la mauvaise route, c'est que j'aurais dû faire une Factory au lieu de définir 6 classes distinctes; en fait je me rends compte que ça ne m'apporte pas grand chose d'avoir ces 6 classes, juste une petite facilité pour détecter deux poissons de la même espèce, avec un inconvénient ailleurs quand il s'agit de cloner un poisson nouvau-né.

+0 -0

Bonjour,

je viens de me lancer dans ce projet car je suis une vrai quiche en Java selon moi donc je voudrais m'ameliorer.

Dans ma fonction main je laisse la possibilite a l'utilisateur de rajouter des poissons chaque tour, du coup avant chaque ajout je lui demande le nom du poisson et son sexe mais je ne sais pas comment faire pour que la fonction attende que l'utilisateur ai taper quelque chose avant d'afficher le message suivant … J'ai donc bidouille ce qui suit mais je suis pas sur de la proprete de la chose :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
String inputString2 = new String();
    System.out.println("What name do you want to give to the fish ?");
    do
    {
        inputString = sc.nextLine();
    }while(inputString.isEmpty());
    System.out.println("What sex is it ? M/F");
    inputString2 = sc.nextLine();

    myAquarium.addFish(inputString, inputString2);

en C c'est simple puisque le scanf attend de lui meme que l'utilisateur ai tape quelque chose avant de continuer mais ca n'a pas l'air d'etre le cas en Java …

EDIT : bon apparemment ca marche sans la boucle while maintenant … Mais par contre j'ai lu que pour le sc.nextint() il fallait vider la ligne avec un sc.nextLine() juste derriere sinon ca foutait un peu la merde.

Ha autre question aussi : j'ai cree un classe poisson et 2 classe filles ( carnivore et herbivore) mais en fait je sais pas si dans mon arrayList<Poisson> j'ai moyen d'appeler des methodes des classes filles ? parce que si ce n'est pas possible je vois pas vraiment a quoi ca sert de faire des classes filles. Bref pour l'instant les classes filles ne font qu'appeler le bon constructeur de la classe parent en fonction de si l'espece est carnivore ou non …

EDIT 2 : autre petite question : lors de la reproduction, un poisson n'a le droit de se reproduire qu'une fois par tour s'il n'a pas faim. Du coup si un poisson A va se reproduire avec un poisson B, si le B n'a pas faim non il n'a tout de meme pas le droit de se reproduire avec un poisson C n'est ce pas ? Je me doute un peu de la reponse mais je prefere demander. De plus lorsqu'un poisson A n'a pas faim et donc est en droit de se reproduire, s'il va voir un poisson B qui lui a faim, que se passe-t-il ? Y a-t-il reproduction ou non ?

Et toujours concenant la reproduction, les algues gagnes 1 an avant de se separer en 2 ou apres ? Car ca conditionne le fait qu'une algue se reproduise au tour ou elle passe a 20 ans ou pas. Et elle peut se reproduire le tour ou elle obtient ses 10 pv ou seulement celui d'apres ?

Là où je dois m'être éloigné et probablement suivi la mauvaise route, c'est que j'aurais dû faire une Factory au lieu de définir 6 classes distinctes; en fait je me rends compte que ça ne m'apporte pas grand chose d'avoir ces 6 classes, juste une petite facilité pour détecter deux poissons de la même espèce, avec un inconvénient ailleurs quand il s'agit de cloner un poisson nouvau-né.

QuentinC

L'avantage de cette façon de faire, c'est que tu peux ainsi charger les informations depuis un fichier par exemple (voir ce lien qui montre ici comment créer des personnages différents à partir d'une seule classe en lisant un script Lua), ce qui permet de faciliter des modifications ultérieures (si je veux rajouter une nouvelle race par exemple).

Après avoir lu un peu mais pas encore codé, je comprends un peu mieux de quoi il s'agit mais surtout pourquoi ce serait extrêmement pertinent ici.

J'ai vraiment du mal à comprendre comment tout le bouzin se met en place… mais intuitivement ça a l'air plus facile avec un langage dynamique genre javascript ou lua.

En fait, un tuto présentant pas à pas la mise en place d'un ECS pas trop complexe et allant jusqu'à la résolution d'un relativement petit problème comme notre javaquarium serait une bonne idée; parce que là, je patauge vraiment dans ce truc. Je ne sais pas trop comment commencer.

+0 -0

Malheureusement on ne trouve pas ce genre de tutos actuellement (ou alors je l'aurais raté mais après plusieurs mois de recherche intensive j'ai passé pas mal de ressources au crible donc … ) L'idéal est donc de mettre les mains dans le cambouis et de demander un coup de pouce quand c'est nécessaire ! Je te conseille premièrement d'utiliser un ECS tel qu'artemis qui est dispo dans pas mal de langages afin de comprendre la partie user d'un ECS, savoir comment ça fonctionne et ce que ça doit pouvoir faire. Une fois que tu auras une idée plus précise là dessus, commence par faire un petit cahier des charges et code ^^ je pense qu'il vaut mieux commencer par écrire la classe des entités et des composants, puis implémenter un world, pour finir par les systems et le messaging(qui peut être inclu dans le world) (ce qui est clairement le plus dur)

Mon lien préféré pour le moment c'est celui où le mec explique son truc en C, c'est juste qu'il faut trouver un remplaçant moderne et orienté objet à son système de flags. Très con mais hyper efficace, au demeurant.

Peut-être d'abord commencer par faire la version où la classe entité possède une liste explicite de ses composants et où on exécute update sur tout le monde comme un bourrin, même si c'est déconseillé partout; au moins ça permet de se fixer un peu. La partie qui paraît complètement contre-intuitive, totalement incompréhensible, et qui sera clairement de loin la plus compliquée, c'est celle où on parvient et où on doit se passer de cette liste.

J'aime bien quand même la citation qui dit qu'un jeu c'est juste une base de donnée mise à jour en temps réel ! Du coup il y a peut-être aussi des idées intéressantes à emprunter au monde des SGBDR…

Je regarderai ce que permettent de faire des ECS déjà existants, merci pour les noms; c'est vrai que se poser un moment du côté user permet de se faire une idée plus précise.

+0 -0

Hello, j'ai commence a developper cet exercice mais je suis coince au don de naissance car je me retrouve face a une erreur de null pointer reference que je n'arrive pas a resoudre.

Je dois avouer que je suis plutot mauvais pour trouver mes erreurs … voici mon repertoire github si jamais des gens sont interesses :https://github.com/Zboub/Javaquarium

merci d'avance

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte