jeu_de_la_vie
Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédenteProchaine révisionLes deux révisions suivantes | ||
jeu_de_la_vie [2019/10/07 08:38] – [Qu'est-ce que le jeu de la vie?] Camille | jeu_de_la_vie [2019/10/18 15:08] – Mushussu | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
- | ====== | + | ====== Documentation du projet "Jeu de la vie" réalisé pour Centre Sciences en 2019 ====== |
===== Introduction: | ===== Introduction: | ||
==== Cadre ==== | ==== Cadre ==== | ||
- | L' | + | L' |
- | ==== Qu' | + | |
- | D' | + | ==== Qu' |
- | //Le jeu de la vie est un automate cellulaire imaginé par John Horton Conway en 1970 et qui est probablement le plus connu de tous les automates cellulaires. | + | D' |
- | Le jeu de la vie n’est pas un jeu, puisqu' | + | |
+ | Le jeu de la vie est un automate cellulaire imaginé par John Horton Conway en 1970 et qui est probablement le plus connu de tous les automates cellulaires. | ||
+ | Le jeu de la vie n’est pas un jeu, puisqu' | ||
Le « jeu » se déroule sur une grille à deux dimensions, théoriquement infinie (mais de longueur et de largeur finies et plus ou moins grandes dans la pratique), dont les cases — qu’on appelle des « cellules », par analogie avec les cellules vivantes — peuvent prendre deux états distincts : « vivante » ou « morte ». | Le « jeu » se déroule sur une grille à deux dimensions, théoriquement infinie (mais de longueur et de largeur finies et plus ou moins grandes dans la pratique), dont les cases — qu’on appelle des « cellules », par analogie avec les cellules vivantes — peuvent prendre deux états distincts : « vivante » ou « morte ». | ||
- | À chaque étape, l’évolution d’une cellule est entièrement déterminée par l’état de ses huit voisines de la façon suivante : | + | **À chaque étape, l’évolution d’une cellule est entièrement déterminée par l’état de ses huit voisines** de la façon suivante : |
+ | |||
+ | * Une cellule morte possédant exactement trois voisines vivantes devient vivante (elle naît). | ||
+ | * Une cellule vivante possédant deux ou trois voisines vivantes le reste, sinon elle meurt. | ||
+ | |||
+ | **La configuration de départ détermine entièrement l' | ||
- | * Une cellule morte possédant exactement trois voisines vivantes devient vivante (elle naît).\\ | ||
- | * | ||
- | * Une cellule vivante possédant deux ou trois voisines vivantes le reste, sinon elle meurt.\\ // | ||
- | * | ||
- | La configuration de départ détermine entièrement l' | ||
=====Cahier des charges===== | =====Cahier des charges===== | ||
- | Dans le cadre d'une exposition, il était nécessaire d' | + | Dans le cadre d'une exposition, il était nécessaire d' |
Le tout devait être assez compact et transportable. | Le tout devait être assez compact et transportable. | ||
+ | |||
=====Réalisation===== | =====Réalisation===== | ||
- | Les choix techniques ont été les suivants: | + | Les choix techniques ont été les suivants:\\ |
- | la contrainte d' | + | la contrainte d' |
- | L' | + | L' |
- | Il était initialement question de pions qui se poseraient dans les trous du plateau de jeu. Le choix s'est porté sur des capteurs de pression (Force Sensing Resistance). Ce choix s'est avéré peu judicieux par la suite, | + | Il était initialement question de pions qui se poseraient dans les trous du plateau de jeu. Le choix s'est porté sur des capteurs de pression (Force Sensing Resistance) |
- | Un bouton pour amorcer le jeu et le faire et évoluer et un bouton pour revenir à la configuration initiale ont été ajoutés sur les GPIO de la Raspberry. | + | Un bouton pour amorcer le jeu et le faire et évoluer et un bouton pour revenir à la configuration initiale ont été ajoutés sur les GPIO du micro-iordinateur. \\ |
- | Enfin, un bouton marche/ | + | Enfin, un bouton marche/ |
Montage des capteurs dans le plateau de jeu: | Montage des capteurs dans le plateau de jeu: | ||
Ligne 42: | Ligne 45: | ||
{{: | {{: | ||
+ | |||
=====Matériel===== | =====Matériel===== | ||
- | Un plateau de jeu dont un carré de 4x4 trous sont évidés de façon à laisser s' | + | Un plateau de jeu dont un carré de 4x4 trous sont évidés de façon à laisser s' |
- | 16 capteurs FSR pour la détection des billes | + | 16 capteurs FSR pour la détection des billes: Fournisseur Pololu, dimensions 0,2 pouces de diamètre (ce qui correspond à 0,5 cm de diamètre)\\ |
- | Fournisseur Pololu, dimensions 0,2 pouces de diamètre (ce qui correspond à 0,5 cm de diamètre) | + | Deux boutons d' |
- | Deux boutons d' | + | |
+ | Un bouton marche/ | ||
+ | Une RaspberryPi pour la gestion des événements et l' | ||
+ | Un écran Waveshare 1920x1080 pixels | ||
- | Un bouton marche/ | ||
- | Une RaspberryPi pour la gestion des événements et l' | ||
- | Un écran | ||
=====Logiciel===== | =====Logiciel===== | ||
Un code python pour la prise en compte des billes et l' | Un code python pour la prise en compte des billes et l' | ||
OS Raspbian version Buster (10.4 (?)) | OS Raspbian version Buster (10.4 (?)) | ||
- | Modifications de l' | + | Modifications de l'OS:\\ |
- | -prise en compte du bouton marche/ | + | -prise en compte du bouton marche/ |
- | -lancement du programme Jeu de la vie au démarrage de l'OS | + | -lancement du programme Jeu de la vie au démarrage de l'OS\\ |
- | Sauvegarde du système complet sur une carte SD de secours: procédure | + | Sauvegarde du système complet sur une carte SD de secours: procédure\\ |
- | -copie de la carte SD d' | + | -copie de la carte SD d' |
- | -copie sur une autre carte SD | + | -copie sur une autre carte SD\\ |
- | Liste exhaustive du matériel: | + | Liste exhaustive du matériel:\\ |
- | Photos | + | Photos\\ |
- | Codes | + | Codes\\ |
- | Schéma électrique pour les FSR | + | Le code a été écrit en python et utilise la bibliothèque pygame. Il s'agit de l' |
- | Schéma d' | + | http:// |
- | Schéma de câblage sur la Raspberry | + | |
+ | |||
+ | ======================================================= | ||
+ | |||
+ | <code python> | ||
+ | '' | ||
+ | import pygame, sys\\ | ||
+ | from pygame.locals import *\\ | ||
+ | import random\\ | ||
+ | import RPi.GPIO as GPIO\\ | ||
+ | from time import sleep\\ | ||
+ | '' | ||
+ | '' | ||
+ | GPIOCasesInit = {17:(9,4), 27:(10,4), 22:(11,4), 5:(12,4), 6:(9,5), 13:(10,5), 19:(11,5), 26:(12,5), 18:(9,6), 24:(10,6), 23:(11,6), 25:(12,6), 12:(9,7), 16:(10,7), 20:(11,7), 21: | ||
+ | assert len(GPIOCasesInit)==16\\ | ||
+ | assert len(set(GPIOCasesInit.values()))==16\\ | ||
+ | GPIO.setmode(GPIO.BCM)\\ | ||
+ | '' | ||
+ | '' | ||
+ | for n in GPIOCasesInit: | ||
+ | GPIO.setup(n, | ||
+ | GPIO.setup(14, | ||
+ | GPIO.setup(15, | ||
+ | '' | ||
+ | '' | ||
+ | GPIO.add_event_detect(14, | ||
+ | GPIO.add_event_detect(15, | ||
+ | #Number of frames per second\\ | ||
+ | FPS = 10\\ | ||
+ | |||
+ | ###Sets size of grid\\ | ||
+ | WINDOWWIDTH = 1920\\ | ||
+ | WINDOWHEIGHT = 1080\\ | ||
+ | CELLSIZE = 40\\ | ||
+ | |||
+ | #Check to see if the width and height are multiples of the cell size.\\ | ||
+ | assert WINDOWWIDTH % CELLSIZE == 0, " | ||
+ | assert WINDOWHEIGHT % CELLSIZE == 0, " | ||
+ | |||
+ | #Determine number of cells in horizonatl and vertical plane\\ | ||
+ | CELLWIDTH = WINDOWWIDTH / CELLSIZE # number of cells wide\\ | ||
+ | CELLHEIGHT = WINDOWHEIGHT / CELLSIZE # Number of cells high\\ | ||
+ | |||
+ | # set up the colours\\ | ||
+ | BLACK = (0, 0, 0)\\ | ||
+ | WHITE = (255, | ||
+ | DARKGRAY = (40, 40, 40)\\ | ||
+ | GREEN = (50, | ||
+ | RED = (255, 0, 100)\\ | ||
+ | |||
+ | BoxExample = {1:(3,10), 2:(15,10), 3:(2,11), 4:(4,11), 5:(10,11), 6:(14,11), 7:(16,11), 8:(3,12), 9:(9,12), 10:(10,12), 11:(11,12), 12:(14,12), 13:(16,12), 14:(15,13), 15:(4,16), 16:(9,16), 17:(10,16), 18:(14,16), 19:(16,16), 20:(17,16), 21:(5,17), 22:(8,17), 23:(11,17), 24:(14,17), 25:(15,17), 26:(17,17), 27:(3,18), 28:(4,18), 29:(5,18), 30:(9,18), 31:(11,18), 32:(10,19), 33: | ||
+ | |||
+ | def text_objects(text, | ||
+ | textSurface = font.render(text, | ||
+ | return textSurface, | ||
+ | |||
+ | def afficheInit(text, | ||
+ | largeText = pygame.font.Font(' | ||
+ | TextSurf, TextRect = text_objects(text, | ||
+ | TextRect.center = (x,y)\\ | ||
+ | DISPLAYSURF.blit(TextSurf, | ||
+ | pygame.display.update()\\ | ||
+ | # | ||
+ | |||
+ | #Draws the grid lines\\ | ||
+ | def drawGrid(): | ||
+ | for x in range(0, WINDOWWIDTH, | ||
+ | pygame.draw.line(DISPLAYSURF, | ||
+ | for y in range (0, WINDOWHEIGHT, | ||
+ | pygame.draw.line(DISPLAYSURF, | ||
+ | |||
+ | |||
+ | def drawGridExample(): | ||
+ | for n in BoxExample: | ||
+ | pygame.draw.rect(DISPLAYSURF, | ||
+ | |||
+ | #Colours the cells green for life and white for no life\\ | ||
+ | def colourGrid(item, | ||
+ | x = item[0]\\ | ||
+ | y = item[1]\\ | ||
+ | y = y * CELLSIZE # translates array into grid size\\ | ||
+ | x = x * CELLSIZE # translates array into grid size\\ | ||
+ | if lifeDict[item] == 0:\\ | ||
+ | pygame.draw.rect(DISPLAYSURF, | ||
+ | if lifeDict[item] == 1:\\ | ||
+ | pygame.draw.rect(DISPLAYSURF, | ||
+ | # | ||
+ | return lifeDict[item]\\ | ||
+ | |||
+ | #Creation un dictionnaire de l' | ||
+ | #Toutes les cellules sont " | ||
+ | def blankGrid(): | ||
+ | gridDict = {}\\ | ||
+ | #Creation d un dictionnaire pour toutes les cellules de la grille\\ | ||
+ | for y in range (CELLHEIGHT): | ||
+ | for x in range (CELLWIDTH): | ||
+ | gridDict[x, | ||
+ | return gridDict\\ | ||
+ | |||
+ | def startingGridInit(lifeDict, | ||
+ | for ncapt in GPIOCasesInit: | ||
+ | if(GPIO.input(ncapt)!=0): | ||
+ | lifeDict[GPIOCasesInit[ncapt]] = 1\\ | ||
+ | # | ||
+ | # | ||
+ | return lifeDict\\ | ||
+ | |||
+ | #Determines how many alive neighbours there are around each cell\\ | ||
+ | def getNeighbours(item, | ||
+ | neighbours = 0\\ | ||
+ | for x in range (-1,2):\\ | ||
+ | for y in range (-1,2):\\ | ||
+ | checkCell = (item[0]+x, | ||
+ | if checkCell[0] < CELLWIDTH | ||
+ | if checkCell [1] < CELLHEIGHT and checkCell[1]> | ||
+ | if lifeDict[checkCell] == 1:\\ | ||
+ | if x == 0 and y == 0: # negate the central cell\\ | ||
+ | neighbours += 0\\ | ||
+ | else:\\ | ||
+ | neighbours += 1\\ | ||
+ | return neighbours\\ | ||
+ | |||
+ | #determines the next generation by running a ' | ||
+ | def tick(lifeDict): | ||
+ | newTick = {}\\ | ||
+ | for item in lifeDict: | ||
+ | #get number of neighbours for that item\\ | ||
+ | numberNeighbours = getNeighbours(item, | ||
+ | if lifeDict[item] == 1: # For those cells already alive\\ | ||
+ | if numberNeighbours < 2: # kill under-population\\ | ||
+ | newTick[item] = 0\\ | ||
+ | elif numberNeighbours > 3: #kill over-population\\ | ||
+ | newTick[item] = 0\\ | ||
+ | else:\\ | ||
+ | newTick[item] = 1 # keep status quo (life)\\ | ||
+ | elif lifeDict[item] == 0:\\ | ||
+ | if numberNeighbours == 3: # cell reproduces\\ | ||
+ | newTick[item] = 1\\ | ||
+ | else:\\ | ||
+ | newTick[item] = 0 # keep status quo (death)\\ | ||
+ | return newTick\\ | ||
+ | |||
+ | #main function\\ | ||
+ | def main():\\ | ||
+ | |||
+ | ps14=0\\ | ||
+ | ps15=0\\ | ||
+ | cs14=0\\ | ||
+ | cs15=0\\ | ||
+ | # GPIOCasesInit = {17:(9,4), 27:(10,4), 22:(11,4), 5:(12,4), 6:(9,5), 13:(10,5), 19:(11,5), 26:(12,5), 12:(9,6), 23:(11,6), 25:(12,6), 21:(9,7), 16:(10,7), 20: | ||
+ | etat=0\\ | ||
+ | FLAG_PUSH = 0\\ | ||
+ | pygame.init()\\ | ||
+ | global DISPLAYSURF\\ | ||
+ | FPSCLOCK = pygame.time.Clock()\\ | ||
+ | DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, | ||
+ | pygame.display.set_caption(' | ||
+ | DISPLAYSURF.fill(WHITE)\\ | ||
+ | # GPIOCasesInit=valCaptInit()\\ | ||
+ | lifeDict = blankGrid() #Creation un dictionnaire de cellules, initialisation a zero\\ | ||
+ | #lifeDict = startingGridInit(lifeDict, | ||
+ | #Colours the live cells, blanks the dead\\ | ||
+ | for item in lifeDict: | ||
+ | colourGrid(item, | ||
+ | drawGrid()\\ | ||
+ | pygame.display.update()\\ | ||
+ | while True: #main game loop\\ | ||
+ | for event in pygame.event.get(): | ||
+ | if event.type == QUIT:\\ | ||
+ | pygame.quit()\\ | ||
+ | sys.exit()\\ | ||
+ | if event.type == pygame.KEYUP: | ||
+ | DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, | ||
+ | cs14=GPIO.input(14)\\ | ||
+ | cs15=GPIO.input(15)\\ | ||
+ | if ps14!=cs14: | ||
+ | print(' | ||
+ | print(' | ||
+ | if(etat==0): | ||
+ | afficheInit(' | ||
+ | afficheInit(' | ||
+ | afficheInit(' | ||
+ | drawGridExample()\\ | ||
+ | pygame.display.update()\\ | ||
+ | #passage a etat suivant\\ | ||
+ | # if GPIO.event_detected(14): | ||
+ | if(ps14==1 and cs14==0): | ||
+ | doit_demarrer=False\\ | ||
+ | nb_viv=0\\ | ||
+ | for elem in GPIOCasesInit: | ||
+ | if(GPIO.input(elem)): | ||
+ | doit_demarrer = True\\ | ||
+ | nb_viv+=1\\ | ||
+ | print(GPIOCasesInit[elem])\\ | ||
+ | print(' | ||
+ | if doit_demarrer: | ||
+ | etat=1\\ | ||
+ | lifeDict = startingGridInit(lifeDict, | ||
+ | |||
+ | else:\\ | ||
+ | etat=0\\ | ||
+ | elif(etat==1): | ||
+ | if(ps15==1 and cs15==0): | ||
+ | # if GPIO.event_detected(15): | ||
+ | etat=0 | ||
+ | lifeDict=blankGrid() | ||
+ | if(ps14==1 and cs14==0): | ||
+ | # if GPIO.event_detected(14): | ||
+ | #runs a tick | ||
+ | nb_viv=0 | ||
+ | lifeDict = tick(lifeDict) | ||
+ | print(' | ||
+ | for item in lifeDict: | ||
+ | if(lifeDict[item]): | ||
+ | nb_viv=nb_viv+1 | ||
+ | print(nb_viv) | ||
+ | if(nb_viv==0): | ||
+ | print(' | ||
+ | etat=0 | ||
+ | #Colours the live cells, blanks the dead | ||
+ | for item in lifeDict: | ||
+ | colourGrid(item, | ||
+ | drawGrid() | ||
+ | pygame.display.update() | ||
+ | # | ||
+ | # | ||
+ | ps14=cs14 | ||
+ | ps15=cs15 | ||
+ | sleep(0.1) | ||
+ | # | ||
+ | |||
+ | if __name__==' | ||
+ | main() | ||
+ | |||
+ | |||
+ | '' | ||
+ | </ | ||
+ | ======================================================= | ||
+ | |||
+ | |||
+ | |||
+ | Schéma électrique pour les FSR\\ | ||
+ | Schéma d' | ||
+ | Schéma de câblage sur la Raspberry\\ | ||
=====Retour d' | =====Retour d' | ||
Ligne 84: | Ligne 331: | ||
Le mieux pour simuler la pression du doigt c’est une « goutte d’eau », pieds autocollants antidérapant en forme de demi-hémisphère sur les cylindres | Le mieux pour simuler la pression du doigt c’est une « goutte d’eau », pieds autocollants antidérapant en forme de demi-hémisphère sur les cylindres | ||
- | |||
- | |||
- | > | ||
> Le 19.07.2019 11:01, Guy Antoine a écrit : | > Le 19.07.2019 11:01, Guy Antoine a écrit : | ||
>> Bonjour Camille | >> Bonjour Camille | ||
Ligne 94: | Ligne 338: | ||
>> en plexi mais c'est très " | >> en plexi mais c'est très " | ||
>> Donc on vérifieras au règlage s'il faut les lester. | >> Donc on vérifieras au règlage s'il faut les lester. | ||
- | |||
- | |||
Modifications en vue de la version 2: | Modifications en vue de la version 2: | ||
Il s' | Il s' | ||
jeu_de_la_vie.txt · Dernière modification : 2020/10/29 14:03 de serge