jeux de la vie (les Chmolls)

Programmation d'applications complexes
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

jeux de la vie (les Chmolls)

Message par Backup »

qui ne s'est pas pris pour Dieu a jouer avec son ordinateur a Populous et Sim ou autre Spore,


ce qui m'a d'ailleurs toujours plus ou moins fasciné avec les ordinateur c'était la possibilité de faire naitre des êtres virtuel
a l'époque des TI99/4a et autre Mo5, Atari st..etc , je m'amusais a créer
des "fourmis" en utilisant les "plots"

je leur donnais des règles et je regardais ce qui se passait... :) on s'amuse comme on peut n'est ce pas.... :D

récemment avec Spore (que je n'ai toujours pas acheté d'ailleurs)
m'est apparu le concept de la génétique dans le monde virtuel !!

comment en effet faire en sorte que des être virtuel récupère des caractéristique génétique de leur parents ??...

voila la question que je me suis posé..

je me suis donc mis a cogiter un poil (faut pas déconner non plus :lol:)

j'ai donc cree un univers bizarre et saugrenu (comme souvent les univers virtuel) :D


l'univers est donc l'écran !<-- pas trop dur jusque la :)

des êtres "primitif" apparaissent Les CHMOLs !!
gérés par la variable nombre_de_chmol


ces êtres (primitif) peuvent avoir comme forme soit Rond, soit Carré
il peuvent être de différentes couleurs et être soit Mâle, soit femelle

ils ont un mode de déplacement assez simple!! :
des qu'ils rencontre un autre Chmol par contact , ils rebroussent chemin
s'ils rencontre le bord de l'écran il rebroussent chemin

toutes les 2 secondes le premiers contact entre un mâle et une femelle engendre un BB :) (qu'il est mignon :) )

ce bb récupère une partie des composante de la couleur du père et une partie de la composante de la mère....

et aussi une partie de la forme du père, et une partie de la forme de la mère

ce qui peut donner des bb ayant la forme

demi-rond_demi_rond (si la mère et le père étaient des ronds)
demi-carre_demi-carré (si la mère et le père étaient carre)
demi-rond_demi-carré (si l'un des deux parent avait une forme différente)
demi-carré_demi-rond (si l'un des deux parent avait une forme différente)


bien sur ensuite les enfants qui copulent (je sais c'est pas moral.. :lol:)
qu'ils soient enfants ou parents
les petits enfants récupèrent aussi une partie des caractéristique leur parents


ceci est un petit exemple de ce principe de génétique très très simplifié :)
a noter, je ne gère pas la mortalité, ni le besoin de nourriture
bien que le paramètre vie soit implémenté, ont verra une version futur
on arrive vite a une surpopulation
:lol: :D

il se peut que le prg au debut genere que des male ou que des femelles
bien sur dans se cas relancez le prg !! :)
en utilisant la touche espace , les chmols sont regeneré !!

le mieux étant d'avoir des males et des femelles de différentes couleurs et forme pour voir les effets de la génétique :)

ajout de la gestion des touches [+] e [-] pour ajouter ou diminer les chmols !!

Code : Tout sélectionner

; Version 4
; Code by Dobro
; Purebasic 4.20
Declare create_chmol(id,posx,posy,pasx,pasy,vie,sex,couleur,forme,angle.f) ; procedure qui cree un etre vivant
Declare TimerProc(hwnd.l, uMsg.l, idEvent.l, dwTime.l)

Declare.f RotationX(x, angle.f, dist)
Declare.f RotationY(y, angle.f, dist)

Global nombre_de_chmol=3
Global compteur=nombre_de_chmol
Global effet,effet2

#dobro =1
#Police =1
#sprite=1

Structure etre
      id.l ; identité du chmol
      posx.l ; position x du schmol
      posy.l ; position y du schmol
      pas_x.l ; sens de directio x  du chmol
      pas_y.l; sens de direction y du chmol
      vie.l ; etat de santé du chmol
      sex.b ; sex du chmol
      couleur.l ; couleur du chmol
      forme.b ; forme des etres de base (les primitifs !!) LOL
      angle.f ; l'angle ; la direction du chmol
EndStructure

Global Dim etre.etre(nombre_de_chmol)





InitKeyboard () : ; j'espere qu'il y a un clavier au moins !!
Resultat = InitSprite () :InitSprite3D() ; initialisation de la gestion des  Sprites par Purebasic

; ************** definition des variables ****************
EcranX = 800
EcranY = 600
; ***************************************************


; *********** ouvre une fenetre aucentre de l'ecran sans bordure, mais ayant la petite croix pour fermer *****************
WindowID = OpenWindow (1, 0, 0,EcranX, EcranY, "hello" , #PB_Window_SystemMenu|#PB_Window_BorderLess |#PB_Window_ScreenCentered )
; **************************************************************************************************

;********** placement d'un ecran graphique dans notre fenetre préalablement crée *************************    
Result = OpenWindowedScreen ( WindowID (1),0,0, EcranX,EcranY, 1, 0,0)
; *****************************************************************************************
  
Handle = WindowID(1) 
SetTimer_(Handle, 1, 2000, @TimerProc()) ; envoie un evenement toutes les 2 secondes pour les naissances
SetTimer_(Handle, 2, 3000, @TimerProc()) ; envoie un evenement toutes les 4 secondes pour les morts
SetTimer_(Handle, 3, 200, @TimerProc()) ; envoie un evenement toutes les 3 secondes pour les changements d'angles
For i=1 To nombre_de_chmol
      id=id+1
      posx=Random(800-32)+32
      posy=Random(600-32)+32
      pas_x=Random(2)+1
      pas_y=Random(2)+1
      vie=100
      sex=Random(1)
      couleur=RGB(Random(255),Random(255),Random(255))
      forme= Random(1)
      angle.f=Random(359)+1
      create_chmol(id,posx,posy,pas_x,pas_y,vie,sex,couleur,forme,angle.f)
Next i
    

Repeat  ;*********  debut de boucle principale  ************************** 
      ExamineKeyboard (); on regarde si le clavier a ete touché par l'utilisateur  
      ; ************************ ecriture dans l'ecran *********************
      StartDrawing ( ScreenOutput ()) ; on va ecrire dans le fond de l'ecran
            Resultat = DrawText (50, 10, "nombre de chmol :"+Str(compteur) , RGB (255,255,0), RGB (0,0,0) ) 
      StopDrawing ()
      ; ******************************************************************
      
      If KeyboardPushed(#PB_Key_Space)
            id=0
            For i=1 To nombre_de_chmol
                  id=id+1
                  posx=Random(800-32)+32
                  posy=Random(600-32)+32
                  pas_x=Random(2)+1
                  pas_y=Random(2)+1
                  vie=100
                  sex=Random(1)
                  couleur=RGB(Random(255),Random(255),Random(255))
                  forme= Random(1)
                  angle.f=Random(359)+1
                  create_chmol(id,posx,posy,pas_x,pas_y,vie,sex,couleur,forme,angle.f)
            Next i
      EndIf
      
      If KeyboardPushed(#PB_Key_Add) 
            id=0
            nombre_de_chmol= nombre_de_chmol+1
            compteur= nombre_de_chmol
            Redim etre.etre(nombre_de_chmol)
            For i=1 To nombre_de_chmol
                  id=id+1
                  posx=Random(800-32)+32
                  posy=Random(600-32)+32
                  pas_x=Random(2)+1
                  pas_y=Random(2)+1
                  vie=100
                  sex=Random(1)
                  couleur=RGB(Random(255),Random(255),Random(255))
                  forme= Random(1)
                  angle.f=Random(359)+1
                  create_chmol(id,posx,posy,pas_x,pas_y,vie,sex,couleur,forme,angle.f)
            Next i
      EndIf
      If KeyboardPushed(#PB_Key_Subtract)
            id=0
            nombre_de_chmol= nombre_de_chmol-1
            If nombre_de_chmol<=0
                  nombre_de_chmol=1
            EndIf 
            compteur= nombre_de_chmol
            Redim etre.etre(nombre_de_chmol)
            For i=1 To nombre_de_chmol
                  id=id+1
                  posx=Random(800-32)+32
                  posy=Random(600-32)+32
                  pas_x=Random(2)+1
                  pas_y=Random(2)+1
                  vie=100
                  sex=Random(1)
                  couleur=RGB(Random(255),Random(255),Random(255))
                  forme= Random(1)
                  angle.f=Random(359)+1
                  create_chmol(id,posx,posy,pas_x,pas_y,vie,sex,couleur,forme,angle.f)
            Next i
      EndIf
      
      
      ;-affichage
      ; ***************** affichage *****************************************
      
      For i=1 To nombre_de_chmol  ; pour tout les etre present dans la liste chainée on recupere 
            
            id=etre(i)\id  ; l'identité   
            vie=etre(i)\vie ; son niveau de vie 
            sex=etre(i)\sex ; son sex 
            couleur=etre(i)\couleur   
            ; ici
            
            etre(i)\posx=RotationX(etre(i)\posx, etre(i)\angle.f, etre(i)\pas_x)  
            etre(i)\posy=RotationY(etre(i)\posy, etre(i)\angle.f, etre(i)\pas_y)
            
            ; ********* condition de collision et sortie d'ecran ****************************
            ; sortie d'ecran
            If etre(i)\posx >EcranX
                  etre(i)\posx=1
            EndIf
            If etre(i)\posy >EcranY
                  etre(i)\posy=1
            EndIf
            If etre(i)\posx <=0
                  etre(i)\posx=EcranX-1
            EndIf
            If etre(i)\posy <=0
                  etre(i)\posy=EcranY-1
            EndIf 
            ;************************************************************************
            
            ; *************** regle de collision entre eux ******************************
            flag=0
            For i2=1 To nombre_de_chmol
                  If i2<>etre(i)\id And etre(i)\vie>0  ; on ne test pas le sprite en cours d'observation pour une collision avec lui-meme et qu'il est vivant
                        If SpritePixelCollision(i2, etre(i2)\posx,etre(i2)\posy, etre(i)\id,  etre(i)\posx,etre(i)\posy)  
                              
                              ;******** changement de la direction suivant la collision ***************
                              If etre(i)\posx <etre(i2)\posx
                                    etre(i)\pas_x =-2
                              EndIf
                              If etre(i)\posx >etre(i2)\posx
                                    etre(i)\pas_x =2
                              EndIf
                              If etre(i)\posy <etre(i2)\posy
                                    etre(i)\pas_y =-2
                              EndIf
                              If etre(i)\posy >etre(i2)\posy
                                    etre(i)\pas_y =2
                              EndIf 
                              
                              ; ******* rencontre male+male ou femelle+femelle ***********
                              If etre(i2)\sex=etre(i)\sex And effet2=0
                                    etre(i)\posx=-100 ; pour tuer les chmol on triche
                                    etre(i)\posy=-100 ; on les mets en dehor de l'ecran
                                    etre(i)\pas_x=0 ; et on les exclus des test de collision
                                    etre(i)\pas_y=0 
                                    etre(i2)\posx=-100 
                                    etre(i2)\posy=-100  
                                    etre(i2)\pas_x=0
                                    etre(i2)\pas_y=0 
                                    
                                    etre(i)\vie=0   ; en utilisant cette variable on sait que le chmol vie ou pas
                                    etre(i2)\vie=0   
                                    compteur=compteur-2
                                    effet2 =1
                              EndIf
                              ; ****************************************************
                              
                              
                              
                              ;-Reproduction
                              ; ******************  REPRODUCTION  ************
                              If etre(i2)\sex<>etre(i)\sex And effet=0  ; rencontre male+femele 
                                    
                                    nombre_de_chmol=nombre_de_chmol+1 ; ajout d'un etre vivant
                                    compteur=compteur+1
                                    Redim etre.etre(nombre_de_chmol)
                                    ; recupere les parametres  de ses deux parents !!
                                    ; posx=EcranX/2; les bb naissent au millieu de l'ecran
                                    ; posy=EcranY/2
                                    posx=etre(i)\posx
                                    posy=etre(i2)\posy 
                                    pas_x=etre(i2)\pas_x
                                    pas_y=etre(i)\pas_y
                                    sex=Random(1) ; sex aleatoire
                                    
                                    ; gestion de la future couleur du bb
                                    ; couleur d'un des 2 parents
                                    rouge1=Red(etre(i)\couleur)
                                    vert1=Green(etre(i)\couleur)
                                    bleue1=Blue(etre(i)\couleur)
                                    
                                    ; couleur de l'autre
                                    rouge2=Red(etre(i2)\couleur)
                                    vert2=Green(etre(i2)\couleur)
                                    bleue2=Blue(etre(i2)\couleur)
                                    
                                    ; on mix !! 
                                    couleur=RGB(rouge1,vert1,bleue2)
                                    
                                    ; mixage de la forme 
                                    StartDrawing(SpriteOutput(etre(i)\id)) 
                                          Global  Dim tab(32,32)
                                          For y=1 To 31
                                                For x=1 To 16 
                                                      tab(x,y)=Point(x,y) 
                                                Next x
                                          Next y 
                                    StopDrawing()
                                    StartDrawing(SpriteOutput(etre(i2)\id))
                                          For y=1 To 31
                                                For x=16 To 31 
                                                      tab(x,y)=Point(x,y) 
                                                Next x
                                          Next y 
                                    StopDrawing() 
                                    forme=3
                                    effet =1
                                    effet2 =1 ; empeche la mort de frapper au moment de la naissance
                                    create_chmol(nombre_de_chmol,posx,posy,pas_x,pas_y,vie,sex,couleur,forme,angle) ; creation du BB                                     
                              EndIf 
                        EndIf
                        
                  EndIf
            Next i2 
            ; *********************************************************************
            
            ; ******* affichage du sprite ****************************************
            If etre(i)\vie>0 
                  
                  
                  ;   DisplayTransparentSprite ( id , etre(i)\posx,  etre(i)\posy) ; affiche le sprite au coordonées modifié par les touches 
                  Start3D()
                        RotateSprite3D(id , etre(i)\angle,0)
                        DisplaySprite3D( id , etre(i)\posx,  etre(i)\posy,255)
                  Stop3D()
            EndIf
            
            ; **************************************************************** 
      Next i 
      
      ; *************** affiche l'ecran ********************************
      FlipBuffers (): ; affiche l'ecran
      ; **************************************************************
      ; ***********************************************************************************
      
      ; **** ok on nettoie pour le prochain affichage **********************
      ClearScreen ( RGB (0, 0, 0)) : ;efface l'ecran
      ; ***************************************************************
      
      event= WindowEvent ()
      Delay (2)
Until event= #PB_Event_CloseWindow Or KeyboardPushed ( #PB_Key_Escape ) ; press touche droit 



Procedure create_chmol(id,posx,posy,pas_x,pas_y,vie,sex,couleur,forme,angle.f)
      ;-creation chmol
      ; ******* creation d'un chmol ************ 
      etre(id)\id =id 
      etre(id)\posx =posx 
      etre(id)\posy =posy 
      etre(id)\pas_x =pas_x  
      etre(id)\pas_y =pas_y  
      etre(id)\vie =vie 
      etre(id)\sex.b =sex 
      etre(id)\couleur.l =couleur 
      etre(id)\angle =angle.f 
      If CreateSprite (etre(id)\id,32,32,#PB_Sprite_Texture) ; on creer un sprite vide (une cellule) de 32 par 32 et on lui donne le numero 1
            StartDrawing ( SpriteOutput (etre(id)\id) ) ; on va dessiner dedans ! 
                  If forme=0
                        Circle (16,16,16, etre(id)\couleur.l ) ; on dessine un cercle rouge
                  EndIf
                  If forme=1
                        Box(0,0,32,32,etre(id)\couleur.l )
                  EndIf
                  If forme=3  
                        For y=1 To 31
                              For x=1 To 16
                                    Plot(x,y, tab(x,y))
                              Next x
                        Next y 
                        For y=1 To 31
                              For x=16 To 31
                                    Plot(x,y, tab(x,y))
                              Next x
                        Next y   
                  EndIf 
                  If etre(id)\sex.b=1 
                        DrawText(12, 12, "M",RGB(0,0,0), RGB(255,255,255))
                  Else 
                        DrawText(12, 12, "F",RGB(0,0,0), RGB(255,255,255))
                  EndIf
            StopDrawing ()
      EndIf 
      ; ******************************************
      CreateSprite3D(etre(id)\id, etre(id)\id)
EndProcedure



Procedure TimerProc(hwnd.l, uMsg.l, idEvent.l, dwTime.l)
      Select uMsg
            Case #WM_TIMER
                  Select idEvent
                        Case 1 
                              effet=0  ; permet une reproduction a nouveau toute les 2 secondes
                        Case 2
                              effet2=0 ; permet de faire mourrir 2 male ou 2 femelle qui se collisionnent
                              
                        Case 3
                              For i4=1 To nombre_de_chmol 
                                    etre(Random(nombre_de_chmol))\angle.f=Random(90) 
                              Next i4
                  EndSelect
      EndSelect
EndProcedure

Procedure.f RotationX(x, angle.f, dist)
      ProcedureReturn x + Cos (angle.f* #PI /180)*dist
EndProcedure
    
    
Procedure.f RotationY(y, angle.f, dist)
      ProcedureReturn y + Sin (angle.f* #PI /180)*dist
EndProcedure
Dernière modification par Backup le dim. 05/oct./2008 8:09, modifié 12 fois.
Frenchy Pilou
Messages : 2194
Inscription : jeu. 27/janv./2005 19:07

Message par Frenchy Pilou »

C'est Eddy M qui va être content (Schmoll) :lol:

Rigolo les êtres créés ressemblent à des trognons de pommes :D

Sinon un modèle de programmation lisible, commentée! 8)

Un sitesur ces sujets :)
tmyke
Messages : 1554
Inscription : lun. 24/juil./2006 6:44
Localisation : vosges (France) 47°54'39.06"N 6°20'06.39"E

Message par tmyke »

Cool, comme quoi un bon petit code fait parfois des merveilles.
C'est rigolo, de temps en temps j'en est un ou deux qui pète les plomb dans les coins...
(c'est vraiment pas beau a voir la dégénérescence...)
Force et sagesse...
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

Et la vie fut !

Message par GeBonet »

Génial... Cela me rappelle un des premier jeux publier dans "L'ordinateur Individuel N°1 ou N°2"... (Octobre 1978 ou 30ième anniversaire)... Le "jeux de la vie" qui évaluait la chance de croissance ou non d'une population d'éléments vivant... Seuil critique à atteindre etc... :lol: :lol:
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

bien sur :)

on peut ajouter d'autres regles, pour leur durée de vie parce que là
si on laisse la surpopulation lorsqu'on arrive vers les 400-500 ça rame grave !!

ce qui est normal , puisqu'il faut gérer les collision de chacun de ces chmols :lol:

il faudrait ajouter une règle du type

si 2 males se tamponne (:lol:) l'un des deux meurts , (ou les 2)
pareils pour les femelles :)

prochaine version
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

voila version mis a jour :(premier listing)

ajout d'une gestion de la vie et de la mort
lorsque 2 males ou 2 femelles se rencontre et que cela tombe toute les 5 secondes les premiers a se rencontrer meurent !!

la reproduction a elle lieu toute les 2 secondes

cela equilibre assez bien la tribu.... :D

c'est marrant de voir que juste apres le naissance, certains enfants se tuent mutuellement..
:)
Le Soldat Inconnu
Messages : 4312
Inscription : mer. 28/janv./2004 20:58
Localisation : Clermont ferrand OU Olsztyn
Contact :

Message par Le Soldat Inconnu »

Les enfants ont toujours une tranche en biais :lol:

aucun enfant n'est complet, et ne reste que la diagonale
ou sont les parties inférieures gauche et supérieure droite ?

je ne les vois jamais .... 8O au voleur, on a piqué des demi ... eud, des demi machin
Je ne suis pas à moitié Polonais mais ma moitié est polonaise ... Vous avez suivi ?

[Intel quad core Q9400 2.66mhz, ATI 4870, 4Go Ram, XP (x86) / 7 (x64)]
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

Le Soldat Inconnu a écrit :Les enfants ont toujours une tranche en biais :lol:

aucun enfant n'est complet, et ne reste que la diagonale
ou sont les parties inférieures gauche et supérieure droite ?

je ne les vois jamais .... 8O au voleur, on a piqué des demi ... eud, des demi machin
non ! c'etait fait expres ! :)

j'appellais ça des demi, mais en fait je récupèrais la partie en haut a gauche de l'un de parents , et la partie en bas a droite de l'autre pour faire l'enfant !!

comme ça je pensais qu'on verrai mieux lorsqu'une partie est ronde et l'autre carré !! :D

mais tu as raison j'ai modifier ça :D


je viens de modifier le listing, pour arranger un peu les collisions entre elles , ça fait moins fouillis :)
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Message par Huitbit »

Sympa ce code :D !

Je ne sais pas si pour un écran de veille c'est trop gourmand mais ça pourrait le faire avec des sprites plus travaillés!
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

Huitbit a écrit :Sympa ce code :D !

Je ne sais pas si pour un écran de veille c'est trop gourmand mais ça pourrait le faire avec des sprites plus travaillés!
pas bete du tout tiens :)
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

nouvelle version avec changement du mode de deplacement des Chmols :)

ça les rends plus "vivant" :D
Dernière modification par Backup le sam. 04/oct./2008 12:10, modifié 2 fois.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

ce dernier listing me fait apparaitre un truc marrant

quelques soit les differences "genetique" et donc d'apparence de mes chmols au depart de la sequence
au bout de x generation, les chmols finissent tous par se resembler !!!

un exemple direct de la consanguinité ?? :)
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

ajout d'un numero de version pour le listing
ajout de la gestion des touches [+] e [-] pour ajouter ou diminuer les chmols !!

ajout de la gestion de la touche espace pour regenerer les chmols
pour ajout de diversité ! ... :D
Avatar de l’utilisateur
GeBonet
Messages : 453
Inscription : ven. 29/févr./2008 16:17
Localisation : Belgique

Message par GeBonet »

Reflet de l'humanité... Je reviens de 7 ans de Brésil... Règne de la mixeginétisation... Pays Métisse, préfiguration de l'humanité, tous sont Blancs et noirs, Indiens et noirs = caboclos et tous sont caboclos et blancs, japonais, italiens, bref reflet du monde...
quelques soit les différences "génétique" et donc d'apparence de mes chmols au depart de la séquence
au bout de x génération, les chmols finissent tous par se ressembler !!!
L'évolution de la diversité serait à l'instar de tes "Chmols", l'uniformité ? C'est la démonstration du jeux de la vie... Ou le nombre est suffisant pour atteindre l'évolution la multiplication des gènes renforçant tous les individus et les uniformisant à terme. Ou le nombre est trop faible et là c'est la consanguinité qui conduit à l'extinction... C'est bien là la question, ou se trouve le seuil critique entre l'évolution garantie et l'extinction aussi garantie (si on ne passe pas son temps à s'exterminer de temps en temps) ?
Avatar de l’utilisateur
Huitbit
Messages : 940
Inscription : jeu. 08/déc./2005 5:19
Localisation : Guadeloupe

Laisse pas traîner ton chmol...

Message par Huitbit »

Petite contribution au joyeux bac à sable del profesor Dobro :

Image

Code : Tout sélectionner

; Version 4 
; Code by Dobro 
; Purebasic 4.20 
Declare create_chmol(id,posx,posy,pasx,pasy,vie,sex,couleur,forme,angle.f) ; procedure qui cree un etre vivant 
Declare TimerProc(hwnd.l, uMsg.l, idEvent.l, dwTime.l) 

Declare.f RotationX(x, angle.f, dist) 
Declare.f RotationY(y, angle.f, dist) 

Global nombre_de_chmol=40 
Global compteur=nombre_de_chmol 
Global effet,effet2 

#dobro =1 
#Police =1 
#sprite=1 

Structure etre 
  id.l ; identité du chmol 
  posx.l ; position x du schmol 
  posy.l ; position y du schmol 
  pas_x.l ; sens de directio x  du chmol 
  pas_y.l; sens de direction y du chmol 
  vie.l ; etat de santé du chmol 
  sex.b ; sex du chmol 
  couleur.l ; couleur du chmol 
  forme.b ; forme des etres de base (les primitifs !!) LOL 
  angle.f ; l'angle ; la direction du chmol 
EndStructure 

Global Dim etre.etre(nombre_de_chmol) 
Structure info 
  globale.l 
  male.l 
EndStructure 

NewList population.info() 

InitKeyboard () : ; j'espere qu'il y a un clavier au moins !! 
Resultat = InitSprite () :InitSprite3D() ; initialisation de la gestion des  Sprites par Purebasic 

; ************** definition des variables **************** 
EcranX = 800 
EcranY = 600 
; *************************************************** 


; *********** ouvre une fenetre aucentre de l'ecran sans bordure, mais ayant la petite croix pour fermer ***************** 
WindowID = OpenWindow (1, 0, 0,EcranX, EcranY+168, "Chmols " , #PB_Window_SystemMenu|#PB_Window_BorderLess |#PB_Window_ScreenCentered ) 
; ************************************************************************************************** 

;********** placement d'un ecran graphique dans notre fenetre préalablement crée *************************    
Result = OpenWindowedScreen ( WindowID (1),0,0, EcranX,EcranY, 0, 0,0) 
; ***************************************************************************************** 
  
Handle = WindowID(1) 
SetTimer_(Handle, 1, 2000, @TimerProc()) ; envoie un evenement toutes les 2 secondes pour les naissances 
SetTimer_(Handle, 2, 3000, @TimerProc()) ; envoie un evenement toutes les 4 secondes pour les morts 
SetTimer_(Handle, 3, 200, @TimerProc()) ; envoie un evenement toutes les 3 secondes pour les changements d'angles 
For i=1 To nombre_de_chmol 
  id=id+1 
  posx=Random(800-32)+32 
  posy=Random(600-32)+32 
  pas_x=Random(2)+1 
  pas_y=Random(2)+1 
  vie=100 
  sex=Random(1) 
  couleur=RGB(Random(255),Random(255),Random(255)) 
  forme= Random(1) 
  angle.f=Random(359)+1 
  create_chmol(id,posx,posy,pas_x,pas_y,vie,sex,couleur,forme,angle.f) 
Next i 
    

Repeat  ;*********  debut de boucle principale  ************************** 
  ExamineKeyboard (); on regarde si le clavier a ete touché par l'utilisateur  
  
  If KeyboardPushed(#PB_Key_Space) 
    id=0 
    For i=1 To nombre_de_chmol 
      id=id+1 
      posx=Random(800-32)+32 
      posy=Random(600-32)+32 
      pas_x=Random(2)+1 
      pas_y=Random(2)+1 
      vie=100 
      sex=Random(1) 
      couleur=RGB(Random(255),Random(255),Random(255)) 
      forme= Random(1) 
      angle.f=Random(359)+1 
      create_chmol(id,posx,posy,pas_x,pas_y,vie,sex,couleur,forme,angle.f) 
    Next i 
  EndIf 
  
  If KeyboardPushed(#PB_Key_Add) 
    id=0 
    nombre_de_chmol= nombre_de_chmol+1 
    compteur= nombre_de_chmol 
    ReDim etre.etre(nombre_de_chmol) 
    For i=1 To nombre_de_chmol 
      id=id+1 
      posx=Random(800-32)+32 
      posy=Random(600-32)+32 
      pas_x=Random(2)+1 
      pas_y=Random(2)+1 
      vie=100 
      sex=Random(1) 
      couleur=RGB(Random(255),Random(255),Random(255)) 
      forme= Random(1) 
      angle.f=Random(359)+1 
      create_chmol(id,posx,posy,pas_x,pas_y,vie,sex,couleur,forme,angle.f) 
    Next i 
  EndIf 
  If KeyboardPushed(#PB_Key_Subtract) 
    id=0 
    nombre_de_chmol= nombre_de_chmol-1 
    If nombre_de_chmol<=0 
      nombre_de_chmol=1 
    EndIf 
    compteur= nombre_de_chmol 
    ReDim etre.etre(nombre_de_chmol) 
    For i=1 To nombre_de_chmol 
      id=id+1 
      posx=Random(800-32)+32 
      posy=Random(600-32)+32 
      pas_x=Random(2)+1 
      pas_y=Random(2)+1 
      vie=100 
      sex=Random(1) 
      couleur=RGB(Random(255),Random(255),Random(255)) 
      forme= Random(1) 
      angle.f=Random(359)+1 
      create_chmol(id,posx,posy,pas_x,pas_y,vie,sex,couleur,forme,angle.f) 
    Next i 
  EndIf 
  
  
  ;-affichage 
  ; ***************** affichage ***************************************** 
  
  For i=1 To nombre_de_chmol  ; pour tout les etre present dans la liste chainée on recupere 
    
    id=etre(i)\id  ; l'identité    
    vie=etre(i)\vie ; son niveau de vie 
    sex=etre(i)\sex ; son sex 
    couleur=etre(i)\couleur    
    ; ici 
    
    etre(i)\posx=RotationX(etre(i)\posx, etre(i)\angle.f, etre(i)\pas_x)  
    etre(i)\posy=RotationY(etre(i)\posy, etre(i)\angle.f, etre(i)\pas_y) 
    
    ; ********* condition de collision et sortie d'ecran **************************** 
    ; sortie d'ecran 
    If etre(i)\posx >EcranX 
      etre(i)\posx=1 
    EndIf 
    If etre(i)\posy >EcranY 
      etre(i)\posy=1 
    EndIf 
    If etre(i)\posx <=0 
      etre(i)\posx=EcranX-1 
    EndIf 
    If etre(i)\posy <=0 
      etre(i)\posy=EcranY-1 
    EndIf 
    ;************************************************************************ 
    
    ; *************** regle de collision entre eux ****************************** 
    flag=0 
    For i2=1 To nombre_de_chmol 
      If i2<>etre(i)\id And etre(i)\vie>0  ; on ne test pas le sprite en cours d'observation pour une collision avec lui-meme et qu'il est vivant 
        If SpritePixelCollision(i2, etre(i2)\posx,etre(i2)\posy, etre(i)\id,  etre(i)\posx,etre(i)\posy)  
          
          ;******** changement de la direction suivant la collision *************** 
          If etre(i)\posx <etre(i2)\posx 
            etre(i)\pas_x =-2 
          EndIf 
          If etre(i)\posx >etre(i2)\posx 
            etre(i)\pas_x =2 
          EndIf 
          If etre(i)\posy <etre(i2)\posy 
            etre(i)\pas_y =-2 
          EndIf 
          If etre(i)\posy >etre(i2)\posy 
            etre(i)\pas_y =2 
          EndIf 
          
          ; ******* rencontre male+male ou femelle+femelle *********** 
          If etre(i2)\sex=etre(i)\sex And effet2=0 
            etre(i)\posx=-100 ; pour tuer les chmol on triche 
            etre(i)\posy=-100 ; on les mets en dehor de l'ecran 
            etre(i)\pas_x=0 ; et on les exclus des test de collision 
            etre(i)\pas_y=0 
            etre(i2)\posx=-100 
            etre(i2)\posy=-100  
            etre(i2)\pas_x=0 
            etre(i2)\pas_y=0 
            
            etre(i)\vie=0   ; en utilisant cette variable on sait que le chmol vie ou pas 
            etre(i2)\vie=0    
            compteur=compteur-2 
            effet2 =1 
          EndIf 
          ; **************************************************** 
          
          
          
          ;-Reproduction 
          ; ******************  REPRODUCTION  ************ 
          If etre(i2)\sex<>etre(i)\sex And effet=0  ; rencontre male+femele 
            
            nombre_de_chmol=nombre_de_chmol+1 ; ajout d'un etre vivant 
            compteur=compteur+1 
            ReDim etre.etre(nombre_de_chmol) 
            ; recupere les parametres  de ses deux parents !! 
            ; posx=EcranX/2; les bb naissent au millieu de l'ecran 
            ; posy=EcranY/2 
            posx=etre(i)\posx 
            posy=etre(i2)\posy 
            pas_x=etre(i2)\pas_x 
            pas_y=etre(i)\pas_y 
            sex=Random(1) ; sex aleatoire 
            
            ; gestion de la future couleur du bb 
            ; couleur d'un des 2 parents 
            rouge1=Red(etre(i)\couleur) 
            vert1=Green(etre(i)\couleur) 
            bleue1=Blue(etre(i)\couleur) 
            
            ; couleur de l'autre 
            rouge2=Red(etre(i2)\couleur) 
            vert2=Green(etre(i2)\couleur) 
            bleue2=Blue(etre(i2)\couleur) 
            
            ; on mix !! 
            couleur=RGB(rouge1,vert1,bleue2) 
            
            ; mixage de la forme 
            StartDrawing(SpriteOutput(etre(i)\id)) 
            Global  Dim tab(32,32) 
            For y=1 To 31 
              For x=1 To 16 
                tab(x,y)=Point(x,y) 
              Next x 
            Next y 
            StopDrawing() 
            StartDrawing(SpriteOutput(etre(i2)\id)) 
            For y=1 To 31 
              For x=16 To 31 
                tab(x,y)=Point(x,y) 
              Next x 
            Next y 
            StopDrawing() 
            forme=3 
            effet =1 
            effet2 =1 ; empeche la mort de frapper au moment de la naissance 
            create_chmol(nombre_de_chmol,posx,posy,pas_x,pas_y,vie,sex,couleur,forme,angle) ; creation du BB                                      
          EndIf 
        EndIf 
        
      EndIf 
    Next i2 
    ; ********************************************************************* 
    
    ; ******* affichage du sprite **************************************** 
    If etre(i)\vie>0 
      
      
      ;   DisplayTransparentSprite ( id , etre(i)\posx,  etre(i)\posy) ; affiche le sprite au coordonées modifié par les touches 
      Start3D() 
      RotateSprite3D(id , etre(i)\angle,0) 
      DisplaySprite3D( id , etre(i)\posx,  etre(i)\posy,255) 
      Stop3D() 
    EndIf 
    
    ; **************************************************************** 
  Next i 
  
  ;-graphique 
  
  If ElapsedMilliseconds()-chrono>2000 
    chrono=ElapsedMilliseconds() 
    If compteur_max<compteur 
      compteur_max=compteur 
    EndIf 
    date_en_cours=date_en_cours+2 
    compteur_male=0 
    date=0 
    For i=1 To compteur 
      If etre(i)\sex=1 
        compteur_male=compteur_male+1 
      EndIf 
    Next i 
    
    AddElement(population()) 
    population()\globale=compteur 
    population()\male=compteur_male 
    
    StartDrawing(WindowOutput(1)) 
    Box(0,600,800,168,RGB(0,0,50)) 
    Line(20,610,0,140,RGB(0,0,255)) 
    Line(20,750,750,0,RGB(0,0,255)) 
    DrawText(20,600,"Durée d'observation : "+Str(date_en_cours)+" s    Total (en jaune)="+Str(compteur)+"    Mâles(en bleu)="+Str(compteur_male)+"("+Str(Int(compteur_male/compteur*100))+"%)    Femelles(en rouge)="+Str(compteur-compteur_male)+"("+Str(Int((compteur-compteur_male)/compteur*100))+"%) ") 
    coeff_echelle_t.f=750/date_en_cours 
    coeff_echelle_population.f=130/compteur_max 
    ancienne_population_male=0 
    ancienne_population_globale=0 
    ForEach population() 
      date=date+2 
      LineXY(20+(date-2)*coeff_echelle_t,750-ancienne_population_male*coeff_echelle_population,20+date*coeff_echelle_t,750-population()\male*coeff_echelle_population,RGB(50,50,255)) 
      LineXY(20+(date-2)*coeff_echelle_t,750-(ancienne_population_globale-ancienne_population_male)*coeff_echelle_population,20+date*coeff_echelle_t,750-(population()\globale-population()\male)*coeff_echelle_population,RGB(255,50,00)) 
      LineXY(20+(date-2)*coeff_echelle_t,750-ancienne_population_globale*coeff_echelle_population,20+date*coeff_echelle_t,750-population()\globale*coeff_echelle_population,RGB(255,255,50)) 
      ancienne_population_male=population()\male 
      ancienne_population_globale=population()\globale 
    Next 
    
    StopDrawing() 
    
    
  EndIf 
  
  
  ; *************** affiche l'ecran ******************************** 
  FlipBuffers (): ; affiche l'ecran 
  ; ************************************************************** 
  ; *********************************************************************************** 
  
  ; **** ok on nettoie pour le prochain affichage ********************** 
  ClearScreen ( RGB (0, 0, 0)) : ;efface l'ecran 
  ; *************************************************************** 
  
  event= WindowEvent () 
  Delay (2) 
Until event= #PB_Event_CloseWindow Or KeyboardPushed ( #PB_Key_Escape ) ; press touche droit 



Procedure create_chmol(id,posx,posy,pas_x,pas_y,vie,sex,couleur,forme,angle.f) 
  ;-creation chmol 
  ; ******* creation d'un chmol ************ 
  etre(id)\id =id 
  etre(id)\posx =posx 
  etre(id)\posy =posy 
  etre(id)\pas_x =pas_x  
  etre(id)\pas_y =pas_y  
  etre(id)\vie =vie 
  etre(id)\sex.b =sex 
  etre(id)\couleur.l =couleur 
  etre(id)\angle =angle.f 
  If CreateSprite (etre(id)\id,32,32,#PB_Sprite_Texture) ; on creer un sprite vide (une cellule) de 32 par 32 et on lui donne le numero 1 
    StartDrawing ( SpriteOutput (etre(id)\id) ) ; on va dessiner dedans ! 
    If forme=0 
      Circle (16,16,16, etre(id)\couleur.l ) ; on dessine un cercle rouge 
    EndIf 
    If forme=1 
      Box(0,0,32,32,etre(id)\couleur.l ) 
    EndIf 
    If forme=3  
      For y=1 To 31 
        For x=1 To 16 
          Plot(x,y, tab(x,y)) 
        Next x 
      Next y 
      For y=1 To 31 
        For x=16 To 31 
          Plot(x,y, tab(x,y)) 
        Next x 
      Next y    
    EndIf 
    If etre(id)\sex.b=1 
      DrawText(12, 12, "M",RGB(0,0,0), RGB(255,255,255)) 
    Else 
      DrawText(12, 12, "F",RGB(0,0,0), RGB(255,255,255)) 
    EndIf 
    StopDrawing () 
  EndIf 
  ; ****************************************** 
  CreateSprite3D(etre(id)\id, etre(id)\id) 
EndProcedure 



Procedure TimerProc(hwnd.l, uMsg.l, idEvent.l, dwTime.l) 
  Select uMsg 
    Case #WM_TIMER 
      Select idEvent 
        Case 1 
          effet=0  ; permet une reproduction a nouveau toute les 2 secondes 
        Case 2 
          effet2=0 ; permet de faire mourrir 2 male ou 2 femelle qui se collisionnent 
          
        Case 3 
          For i4=1 To nombre_de_chmol 
            etre(Random(nombre_de_chmol))\angle.f=Random(90) 
          Next i4 
      EndSelect 
  EndSelect 
EndProcedure 

Procedure.f RotationX(x, angle.f, dist) 
  ProcedureReturn x + Cos (angle.f* #PI /180)*dist 
EndProcedure 
    
    
Procedure.f RotationY(y, angle.f, dist) 
  ProcedureReturn y + Sin (angle.f* #PI /180)*dist 
EndProcedure
On s'aperçoit que les nombres de naissances et de décès s'équilibrent malgré l'évolution des gènes.
Il faudrait des évènements (guerres, épidémies...) pour voir un changement significatif du nombre de chmols !

Hasta la vista !
Dernière modification par Huitbit le dim. 05/oct./2008 11:42, modifié 2 fois.
Répondre