voila, je me lance encore un projet de fou ... (un jeu de la vie pour ceux qui connaissent)
pour commencer, je me demande comment gérer en C++ une matrice d'objet (case)
afin de gérer ma grille quoi ...
si j'avais 10 cases ... bon 10 objet en RAM ... c'est pas lourd ... mais si après je veux aller plus loin ... genre un cube de 100 cases de coté (1 Mcase au total) je ne pense pas qu'il soit rigoureux de stocker ça en RAM ...
donc je suis ouvert à tous conseils ... sur la gestion de cette matrice ...
en gros l'objet case aura en attribut sa position dans la grille ... mais je ne sais pas comment gérer cet ensemble de case ...
merci ... et si vous arrivez à me débloquer ce petit problème, je ferais une entrée dans les PdZ ...
Pour faire une grille, je te propose les std::vector (tuto dans ma signature) dans un premier temps.
Une strucutre plus adaptée comme celles de boost seront peut-être plus efficaces mais aussi moins intuitive pour un débutant (je trouve).
Pour ce qui est du stockage, si il y a un grand nombre (>95%) de cases vides, peut-être serait-il intéressant de ne stocker que les cases pleines dans une std::map<> en indiquant à chaque case où elle se situe. Je sais pas si je suis clair.
Moi je pense qu'il y a un probleme en amont. Pourquoi stocker un cube de 100*100*100 ??
Quel "jeu" peut avoir besoin de stocker un cube de "cases", as tu des exemples ? (avec des screenshots)
Ok, quasi tous les jeux 2D stockent des tiles, donc un carré (un matrice de dimension 2)
Mais pourquoi diable stocker un cube de tile ? Ne pense surtout pas que les jeux 3D sont fait comme ça
Je connais mal le jeu de la vie. Mais si je comprends, ce sont des "machins" qui se déplacent dans un plan (ou dans l'espace), et se multiplient.
Est ce que c'est vraiment utile de coder tout l'espace ? Sachant qu'il y aura surement 99% d'espace vide ? (meme s'il y a du monde) Pourquoi ne pas faire un tableau d'objets, avec des coordonnées, ce qui permettrait en outre de ne pas limiter l'espace a un cube ?
Est ce que c'est vraiment utile de coder tout l'espace ? Sachant qu'il y aura surement 99% d'espace vide ? (meme s'il y a du monde) Pourquoi ne pas faire un tableau d'objets, avec des coordonnées, ce qui permettrait en outre de ne pas limiter l'espace a un cube ?
bah en fait, j'ai eu une vision ... (certain voient des buissons enflamé, ou des vierges dans des grottes ... moi j'ai vue une animation)
... (Kane said : one vision, one goal . The peace from the power. spécial dédicasse au fan de c&c)
revenons à nos moutons ... bèèèèèèè
donc je me suis dit ... que le jeu de la vie tel qu'il est implenté n'est qu'un delire matématique et n'a aucun fondement biologique...
donc je compte rajouter au principe du jeux de la vie des notions purement bio tel que la ""portance du milieu"" ou la ""dureté du mileu"" à savoir ...
pour la portance du mileu
je vais essayer de dessiner ... donc voila ...
YYYYYYY
*******
**XXX**
*******
YYYYYYY
les * sont des cellules , X et Y des "cases libres" milieu... pour un biologiste il parait evident que la partie Y du milieu sera plus riche en nutriment que la partie X ...
et donc les cellules vont preferentielement se multiplier vers Y
le milieu Z (clos) sera moins riche (car plus profond) que le milieu X (interieur)lui même moins riche que le milieu Y (exterieur)
cas de la dureté du mileu
là c'est simple assez simple à comprendre ... les cellules les plus exterieures meurent plus vite (et donc se multiplient moins) que celle en profondeur
j'ai pensé que si j'arrivai à implenter c'est dexu truc là ... je pourrais obtenir des "organismes" a peu pres stable ...
alors oui, au début 99% de mon mileu sera du même type ... mais avec le temps, ça vas bouger ...
... enfin ...
je suis encore en train de reflechir à comment j'organise tout ça ... et surtout il vas falloir que je test tout ... mais bon ... avec du temps je devrai y arriver ...
tes "zones" sont grandes : je pense qu'il est toujours inutile de code l'espace.
De la meme façon que tu pourrais mettre tes "individus" dans un tableau de sprites, tu peux aussi ranger tes "zones", dans un tableau. Avec une description simple : une zone cubique est le plus simple.
En classant tes zones via leur bounding box, dans un arbre par exemple, tu peux optimiser la fonction qui te dira, pour une bactérie donnée, dans quelle zone elle est.
Ce sont des optimisation analogues aux algos d'octree ou de BSP tree, qui te permettent, dans un First Person Shooter, de savoir vers quelle zone de triangles tu es, afin de ne tester les collisions que vers eux !
En gros, fait toi un tableau de molécules, et un tableau de "zones"
ainsi qu'une fonction qui, pour une molécule donnée, recherche dans quelle zone tu es.
Ben tu crames pas té mémoire comme ça !! Et tu n'es pas limité dans un cube.
L'astuce est de ne pas surtout pas coder les zones "case par case", mais de trouver une maniere de coder de tres grandes zones en un minimum de données : le cube (pour la zone) se code en 6 float, aussi grand soit il.
le cube (pour la zone) se code en 6 float, aussi grand soit il.
... moij'aurai dit en 8 int ...
Citation : Fvirtman
Et tu n'es pas limité dans un cube.
comment tu simule un espace physique en 3 dimensions facilement autrement qu'avec un cube ?
Citation : Fvirtman
Ben tu crames pas té mémoire comme ça
de toute facon, en gros chaque cellule vas avoir des caractéristiques presque toute différentes ... donc vas bien falloir que je stocke en mémoire toute mes cellules
mais justement, tu es dans un espace réel, tu n'as pas de limite (seulement celle d'un float ou d'un double)
Tu es codes une coordonnées avec 3 flottants (x,y,z), et basta
A partir de la, tu n'as pas besoin de décrire tout l'espace, tu décris uniquement les objets que tu veux placer, avec des coordonnées a 3 flottants (x,y,z)
Penses tu que les jeux 3D de la PS1 par exemple (qui possédait 4 Mo de RAM dont une grosse partie dédiée au son et a l'affichage) étaient des gros cubes ?
Il y avait du FPS avec de grands niveaux sur PS1 !
donc en gros, il faut que j'oublie l'idée de représenter les éléments simplement dans l'espace ... je les placerai dans un espace non defini (juste une origine) 1 à 1 ... et c'est l'ensemble qui me definira mes strucures ....
je sais pas si je suis clair ...
enfin, je ne me pose pas la question si des structures apparaissent ... c'est l'ensemble de mes éléments qui les definironts
Malgré que tu portes le jeu de la vie dans une espace 3D et qui tu modifies les règles, tu comptes toujours garder le principe de règles d'évolutions locales? (L'état d'une case à l'instant T + 1 dépend de l'état de cette case et de ses voisines à l'instant T?)
L'état d'une case à l'instant T + 1 dépend de l'état de cette case et de ses voisines à l'instant T?
bah en fait je ne prend pas le prob comme cela ...
mon point de reference n'est pas l'état d'une case vide en elle même mais plutot l'état d'une cellule ...
un case "cellule" pourra creer une autre case cellule autour d'elle (si plusieurs choix possible ... un "rand") en fonction de ce qui l'entour (la cellule mère) ... mais la case qui vas recevoir une nouvelle cellule sera relativemenet passive ...
mais les cases % vont avoir des caractéristiques différentes des cases *
et donc mon problème est comment reperer qu'un motif comme celui la se forme
pour ceux qui sont arrivé au bout, je vous remercie et m'excuse pour les fautes d'orthographes qui doivent subsister ....
et donc si vous avez des reponces ... ou des remarques ne vous gènez pas ....
merci ...
à bientott etre que des cases vide exterieurs, aucune cellule ne peut y prende place
une cellule est au centre de 8 cases voisine
une cellule possède
1 degré de maturité : jeune / mature
une cellule jeune ne peut pas se diviser même si elle en a la possibilité
une cellule mature peut se diviser si elle en a la possibilité
Pour ce diviser,une cellule doit se trouver à
moins de 1 cellule d'une case intérieur
moins de 2 cellules d'une case exterieur
une nouvelle cellule peut apparaitre
Sur une case vide aléatoire à coté de la cellule mère
Si elle ne risque pas de tuer la cellule mère
Si une cellule peut se diviser mais n'a pas d'emplacement pour, elle redevient jeune
Une cellule meurt, si elle se trouve à plus de
1 cellules d'une case close
2 cellules d'une case interieur
3 cellules d'une case exterieur
condition initiale : (a etudier)
une seule cellule jeune au centre du plateau
enregistrement : a creuser ...
à la fin de chaque itération, on crée des fichiers images X/Y et X/Z
avec un code couleur : vert => cellules jeunes
rouge => cellules matures
blanc => case vide ext
jaune => case vide int
gris => case vide close
Interface utilisateur :
A décider : "JDV -fichier_param" => ouverture fenetre avec 3D
fenetre de saisie des param => fenetre avec 3D
voila ... ensuite j'ai commencer à ecrires des algorithmes ( à la sauce DrDam) ...
donc voila : la boucle principale
algo de la boucle globale du programme (hors init et term)
variables locals
double compt_tour => nombre de cycle que le programme a effectué
cell cell1 =>premiere cellule du programme
cell curent_cell => cellule en cours de "traitement"
int[3] pos => tableau de 3 elements contenant les coordonné dans l'espace
int[*][*][*] monde => espace de jeux =>
valeur => 0 case ext
1 case int
2 case clos
3 case cellule
parametres d'entrés
double tour => nombre de cycle que le programme doit effectuer
int toext => distance neutre par rapport à une case exterieur
int toint => distance neutre par rapport à une case interieur
int toclos => distance neutre par rapport à une case close
neutre : si d < => ok pour multiplication
si d > => ok pour mort
int t_mat =>temps de maturation des cellules en cycles
debut
compt_tour <- 0
TQ ( tour >= compt_tour ) // tant que la simulation n'est pas terminée
Faire
compt_tour <- compt_tour + 1 // compte les tours effectuer
current_cell <- cell1 // on charge la premiere cellule
TQ (curent_cell != null) // tant que l'on est avec des cellules
Faire
current_cell.temp <- current_cell.temp + 1 // la cellule vieilli d'un tour
Si( current_cell.temp%t_mat = 0 et current_cell.maturite = FAUX) // si la cellule peut devenir mature => multiple du temps de maturation
Faire
current_cell.maturite <- VRAI // elle le devient
ctrl = new regles(current_cell) // on genere la series de ctrl pour la cellule en cours
Si( ctrl.death(toext,toint,toclos,monde) ) // la cellule doit elle mourrir
Faire
Si current_cell.precedante = NULL // il s'agit de la premiere cellule
Faire
cell1 <- current_cell.suivante // on place la cellule suivante dans cell1
FinSi
current_cell.mort() // on detruit la cellule courante et on passe à la suivante
sinon //si la cellule ne doit pas mourrir
Si( current_cell.maturite = VRAI ) // est elle mature ?
Faire
Si(ctrl.div(toext,toint,toclos,monde)) // si oui, peut elle se diviser
Faire
Si (pos <- ctrl.pos(monde)) // si oui, où ?
Faire //si il y a un endroit
current_cell.division(pos) // divise toi !
MAJ liste des cases vides int et clos // on met à jour la table du monde
Sinon
current_cell.maturite<-FALSE //si elle ne peut pas se diviser, elle redevient jeune
Sinon
current_cell.maturite<-FALSE //si elle ne peut pas se diviser, elle redevient jeune
fin si
curent_cell<-curent_cell.suivante // on passe à la cellule suivante
fin si
affichage de la position de la cellule
destruct ctrl // on libère les ctrl pour la cellule suivante
Fin TQ
save_affichage ... enfin un truc ...
Fin TQ
et pour le moment, ma classe Cell qui gère les cellules
algo de la classe mère "cellule"
#attributs
public
bool maturite <- FAUX; => FAUX pour jeune
VRAI pour mature
int temp <- 0 => temps de vie d'une cellule... necessaire pour passer du stade jeune à mature
int X => position en X
int Y => position en Y
int Z => position en Z
cell suivante => parametre de liste chainé
cell precedante => parametre de liste chainé
#méthodes
cell construct(x,y,z,suivante,precedente) => crée une nouvelle cell
void division(int[3] new_pos) => demande la creation d'une nouvelle cellule
cell mort() => renvoi la cellule suivante de celle detruite
fin classe
methodes
methode mort()
{
cell_tmp<-self:suivante;
self:suivante.precedente<-self:suivante;
self:precedente.suivante<-cell_tmp.precedante;
destroy_self;
return cell_tmp;
}
cell_construct(x,y,z,suivante,precedente)
{
self.x<-X;
self.y<-Y;
self.z<-Z;
self.suivant<-suivante;
self.precedante<-precedante;
return self;
}
division(new_pos)
{
self:maturit<-0;
self:temp <-0;
new_cell <- new cell (new_pos[0],new_pos[1], new_pos[2], self.suivante, self);
return new_cell;
}
et la classe qui contients mes règles ...
Classe regles...
cette classe contients les controles qui seront effectuer pour l'intégrité des regles
attributs
cell cible => cellule sur qui est effectuer les controles
methodes
int[3] dispo(monde) => cette méthode trouve une case disponible pour une nouvelle cellule
bool div(toext,toint,toclos,monde) => cette méthode controle si la cellule peu se diviser
bool death(toext,toint,toclos,monde) => cette méthode controle si la cellule vas mourrir
int to_case(int type,monde) => cette méthode renvoi la distance de la case "type" la plus proche
type = 0 => exterieur
type = 1 => interieur
type = 2 => clos
fin classe ctrl
bool div(toext,toint,toclos,monde)
{
text <- to_case(0,monde)
tint <- to_case(1,monde)
tclos <- to_case(2,monde)
Si (text < toext ou tint < toint ou tclos < toclos)
Faire
return VRAI
sinon return FAUX
}
bool death(toext,toint,toclos,monde)
{
text <- to_case(0,monde)
tint <- to_case(1,monde)
tclos <- to_case(2,monde)
Si (text > toext et tint > toint et tclos > toclos )
Faire
return Vrai
sinon return FAUX
}
int[3] dispo(monde)
{
current_X = cible.x
current_Y = cible.y
current_Z = cible.z
int[3][26] table // contiendra toutes les cases dispo => voir pour un tableau dynamique
int i = 0
Pour z compris entre current_Z - 1 et current_Z + 1 par pas de 1
faire
Pour y compris entre current_Y - 1 et current_Y + 1 par pas de 1
faire
Pour x compris entre current_X - 1 et current_X + 1 par pas de 1
faire
si monde[x][y][z] != cell
faire
table[0][i] <- x
table[1][i] <- y
table[2][i] <- z
fin pour
fin pour
fin pour
si taille(table)/3 = 1
return table
sinon
i <- rand(taille(table)/3)
return(table[][i])
fin Si
}
int to_case(int type,monde)
{
current_X = cible.x
current_Y = cible.y
current_Z = cible.z
int i <-0
bool ok <- FAUX
TQ ok != VRAI
i <- i + 1
Pour z compris entre current_Z - i et current_Z + i par pas de 1
faire
Pour y compris entre current_Y - i et current_Y + i par pas de 1
faire
Pour x compris entre current_X - i et current_X + i par pas de 1
faire
si monde[x][y][z] = type
faire
ok <- VRAI
fin pour
fin pour
fin pour
Fin TQ
return i
}
bon pour le moment, c'est juste des algos ..
si il y a des choses qui vous choques ... dites les moi ...
par ailleur j'ai des questions qui me trottent dans l'esprits...
Citation : Question N°1
dans ma table monde ...
je doit stocker quoi ?
stocker les objets => dans ce cas quid de difference case_vide VS cell ?
stocker type (1=cell , 2=case_vide (3 sous types) => comment remonter à l'objet
stocker pointeur => comment l'utiliser ?
Citation : question N°2
comment je peut gerer les ensembles imbriqué ...
par exemple: avec X des cellules et * et % des cases du milieu
Bonjour, il y a un moment je me souviens avois créé un jeu de la vie en SDL.
La structure al plus adaptée que j'ai trouvé est un champ de bits étant donné que l'objet cellule a deux états vivant ou mort, c'est juste un booléen.
Les structure "creuses" adaptées aux matrices de 0 ne sont pas toujours optimales pour ce genre de jeu, car souvent l'espace est à 50% plein et 50% vide, mais pas toujours. Du coup la technique de champ de bits est bien adaptée (et facile à programmer en plus).
Sans optimisation, une simple boucle qui applique à chaque case une fonction qui donne son état en fonction de ses voisin marche pour des tailles de plus de 1000 * 1000 assez rapidement sans s'arracher les cheveux.
Si le but est d'avoir un algo optimisé, le plus simple est de regarder le code de LucidLife (que je ne connais pas). sinon voila quelques pistes:
1) séparer le cas creux (quelques cellules vivantes) du cas beaucoup de cellules vivantes.
dans le cas creux on peut utiliser une liste de coordonnées pour les cellules vivantes, ce qui a plusieurs aventages:
- faible consommation mémoire
- on peut résoudre le jeu uniquement à leur voisinage puisque une cellule n'apparaitra jamais dans une zone de vide. --> faible temps de calcul
dans le cas où il y a beaucoup de cellules on se contente de faire une matrice normale et d'itérer sur toutes les cases, comme dans le cas simple.
Voila on implémente tout ca en exploitant la virtualité et ca fait déja un joli programme.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
* Un wrapper C++ pour sqlite * Une alternative a boost units
* Un wrapper C++ pour sqlite * Une alternative a boost units