Ordinateurs

Construire un jeu de désamorçage de la bombe en utilisant Python et Raspberry Pi

J’adore donner des conseils sur la façon de coder et d’utiliser des gadgets pour créer des projets sympas.

créer-un-jeu-de-désamorcer-la-bombe-en-utilisant-python-et-raspberry-pi

Pas votre tutoriel Hello World ordinaire

Je ne sais pas pour vous, mais depuis que j’apprends à programmer, je tombe sur les mêmes types de tutoriels dans toutes les langues : « Hello World » et « Comment créer un carnet d’adresses ». Bien qu’ils soient tous deux parfaits pour apprendre les bases, je n’aime pas les projets arbitraires, même s’ils m’apprennent.

Quand j’ai eu mon Raspberry Pi 2 l’année dernière, j’ai décidé que j’allais apprendre Python avec et je n’allais certainement pas simplement faire des tutoriels « Hello World ». Le résultat de mon projet est un jeu qui prend l’entrée de l’utilisateur à partir des boutons de ma planche à pain en utilisant les broches GPIO. Dans ce didacticiel, nous allons recréer ce jeu et essayer d’apprendre exactement ce que nous faisons avec chaque ligne de code, au lieu de simplement copier et coller et jouer à un jeu simple à la fin.

L’image

Commençons.

Je fais tout cela sur un Raspberry Pi 2 exécutant Raspbian Jessie. Le Pi est connecté à mon réseau local via un câble Ethernet (si vous avez l’adaptateur WI-FI, cela fonctionnera tout aussi bien) et je suis connecté en ssh depuis mon MacBook Pro. Vous pouvez tout faire localement sur le Pi si vous l’avez connecté à un moniteur, un clavier et une souris.

Le tableau de bord

Mettons en place notre tableau de répartition. Si vous ne savez pas, le tableau va de haut en bas sur le long chemin. Chaque ligne horizontale est la même connexion, donc tout ce qui se trouve à côté horizontalement sera alimenté en même temps.

J’ai inclus une image de mon tableau de répartition actuel et une interprétation numérique de l’idée générale. La conception numérique a été réalisée dans le logiciel Fritzing. Ce n’est pas une interprétation parfaite car elle n’offrait pas la possibilité d’inclure le cordonnier, mais elle fait passer le message.

Les LED sont connectées comme suit. Le rouge est connecté au positif à la broche 27 et au négatif au 3V négatif via une résistance de 220 Ω (code de couleur rouge, rouge, marron, or). Assurez-vous d’utiliser une résistance ou vous risquez d’éteindre votre LED. Le vert est connecté positif à la broche 22 et négatif au négatif 3V via une résistance de 220 Ω. Le bouton du haut est connecté positif à 17 et négatif à la masse. Le bouton du bas est connecté positif à 18 et négatif à la masse.

créer-un-jeu-de-désamorcer-la-bombe-en-utilisant-python-et-raspberry-pi
Le fil rouge va à la LED rouge et le fil vert va à la LED verte.  Les fils noirs sont positifs aux boutons et les fils blancs sont les masses.

Le fil rouge va à la LED rouge et le fil vert va à la LED verte. Les fils noirs sont positifs aux boutons et les fils blancs sont les masses.

Le code : vue d’ensemble

Commençons par parler de notre objectif final. Lorsque le jeu est lancé, il affichera un paragraphe sur l’écran du terminal racontant l’histoire de tomber sur une bombe à retardement. En tant que seule personne présente, il appartient au joueur de décider s’il doit couper le fil rouge ou le fil bleu (dans ce cas, les fils sont les boutons du panneau de dérivation). Lorsque l’utilisateur appuie sur un bouton, un voyant rouge ou vert clignote et un message de félicitations ou d’échec s’affiche à l’écran.

Afin de rendre ce jeu vraiment aléatoire, nous utilisons un générateur de nombres aléatoires et quelques mathématiques de base afin de déterminer quel bouton est le bon et lequel entraînera la mort de nombreux passants innocents.

Le Code : Importations

OK, passons aux choses amusantes.

Nous devons d’abord importer les frameworks que nous utiliserons dans ce jeu : random, time et gpio.

#Import frameworks
from random import randint
import RPi.GPIO as GPIO
import time

J’inclus toujours des commentaires pour m’assurer que lorsque je reviendrai plus tard (ou si quelqu’un voit cela), je me souviens de ce que fait chaque bloc.

Faites défiler pour continuer

Afin de limiter la taille et les exigences de calcul, nous n’importons que la partie randint du framework aléatoire. Ce n’est pas si grave dans un programme aussi petit que celui-ci, mais c’est une bonne pratique à adopter.

Pour faciliter l’interaction avec le framework GPIO, nous l’importons en tant que GPIO. GPIO est maintenant une variable qui nous empêche d’écrire RPi.GPIO à chaque fois ; vous pouvez changer le nom de la variable en ce que vous voulez.

A lire aussi :  Guide du débutant sur l'utilisation du terminal

Nous avons besoin de quelques secondes où nous retardons ou attendons pendant ce jeu, nous importons donc du temps.

Le code : Configuration GPIO

Nous devons maintenant dire au Pi quelles broches nous utiliserons pour ce projet. N’oubliez pas que pour ce projet, nous ne nous connectons pas directement aux composants, mais le mappons via une carte de dérivation par un cordonnier en forme de T CanaKit à 40 broches.

#GPIO Setup
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN,pull_up_down=GPIO.PUD_UP) #Top Button
GPIO.setup(18, GPIO.IN,pull_up_down=GPIO.PUD_UP) #Bottom Button
GPIO.setup(27, GPIO.OUT) #Red
GPIO.setup(22, GPIO.OUT) #Green

Tout d’abord, nous désactivons les avertissements GPIO. Le code fonctionnera sans cette ligne, mais vous recevrez un avertissement à chaque fois que vous l’exécuterez, il est donc préférable de l’ignorer.

Maintenant, nous devons indiquer au code que nous le mappons sur la carte de dérivation. Je vais être honnête, je ne comprends pas entièrement cette partie, je n’ai juste pas besoin d’inclure cette ligne de code pour aider nos chiffres à s’aligner.

Les 4 dernières lignes font toutes la même chose, elles indiquent au Pi quelles broches nous utilisons et à quelle heure l’appareil se trouve à l’autre extrémité du circuit de la broche : entrée ou sortie.

Le code : fonction de jeu

Nous arrivons maintenant à créer une fonction. Parlons des fonctions pendant une minute. Les fonctions prennent beaucoup d’instructions et les transforment en une seule « variable » (ce n’est pas la bonne terminologie, mais suivez-moi là-dessus) que vous pouvez appeler plus tard. Dans ce cas, nous disons au programme ce qu’est le jeu, mais nous ne le laissons pas s’exécuter tant que nous ne sommes pas prêts. Cela nous permet également d’arrêter le jeu ou d’ajouter des fonctionnalités supplémentaires si nous le souhaitons plus tard.

Comme cette fonction est très longue, je vais diviser les segments de code en segments plus courts. Rappelez-vous fait partie de la fonction de jeu. J’inclurai le code de fonction complet ainsi que le code de programme complet plus tard. Mais je ne veux pas submerger qui que ce soit avec un tas de code à la fois.

def game():

Nous définissons d’abord notre fonction et lui donnons un nom. J’ai choisi d’être vraiment créatif ici et de le nommer jeu.

	#Random Number
	x = randint(0,9)
	#Determine if number is even or odd
	y = x%2

Maintenant, nous choisissons un nombre. Parce que nous avons utilisé randint, le nombre sera un entier (ce qui signifie pas de décimales pour ceux d’entre vous qui détestent les maths) et entre parenthèses, nous passons 0, 9 comme arguments. Dans ce cas, cela rend la plage d’entiers 0-9. De manière réaliste, nous pourrions faire (1, 2) et limiter l’entier à 1 ou 2, mais nous faisons cela pour augmenter notre apprentissage, alors allons-y avec 0-9.

Maintenant, nous devons le réduire à une option 50/50. J’ai choisi de le faire en déterminant si le nombre était pair ou impair. Pour ce faire, nous utilisons une fonction appelée modulo, représentée par %. Encore une fois, pour vous les non-mathématiques, modulo renvoie le reste d’un problème de division donc 27/5 = 5 reste 3 et 27 % 5 = 3. Cela peut déterminer impair ou pair parce que nous savons que si un nombre pair divisé par 2 a pas de reste, donc tout nombre pair modulo 2 vaut 0.

Dans ce cas, x est notre entier aléatoire, nous allons donc faire de y notre équation pour déterminer l’impair ou le pair. Donc y est x % 2, ce qui signifie que les seuls résultats possibles que y pourrait donner sont 0 ou 1. Nous avons maintenant notre option 50/50.

	#Story
	print "You are casually walking down the street one day when out of nowhere you notice a ticking time bomb, ready to explode. You immediately remember your bomb squad days and rush into action. You have the bomb nearly defused, but you must now choose: red wire or blue wire. You have 10 seconds."
	time.sleep(1)
	print "Choose wisely"

Tout bon jeu a besoin d’une histoire. Ici, nous produisons simplement l’histoire en texte brut dans la fenêtre du terminal. Ensuite, nous attendons 1 seconde, puis disons à l’utilisateur de choisir judicieusement.

	#Button Controls
	while (GPIO.input(17) == True or GPIO.input(18) == True): #Listen for input from buttons
		topButton = GPIO.input(17)
		bottomButton = GPIO.input(18)
		if (topButton == False): #Top Button Pressed
			if (y == 0): #If the number was even and you pushed the top button, you lose
				print("You have failed. Countless people have died due to your incompetence and you have been reduced to nothing but a few subatomic particles that are barely visible to the human eye.")
				GPIO.output(27,GPIO.HIGH)
				time.sleep(.3)
			else: #If the number was odd and you pushed the top button, you win.
				print ("Well done! You have successfully defused the bomb and saved many lives. You are an international hero!")
				GPIO.output(22,GPIO.HIGH)
				time.sleep(.3)

Maintenant, le code pour les boutons. Gardez à l’esprit que lorsqu’un bouton est enfoncé, il renvoie false. Lorsqu’il n’est pas poussé, il est vrai. Pour moi, cela semble un peu en arrière, mais il a été conçu par quelqu’un de plus intelligent que moi.

A lire aussi :  5 outils techniques que chaque écrivain devrait avoir en 2023

Ce jeu fonctionnera dans une boucle while indiquant que tant que l’un des boutons n’est pas enfoncé, le Pi continuera d’attendre une entrée.

Pour faciliter le code, j’ai déclaré chaque entrée de bouton GPIO comme une variable nommée en anglais afin qu’il n’ait pas à se souvenir de quel numéro correspond à quoi. Les variables ‘topbutton’ et ‘bottombutton’ correspondent à leur emplacement sur le breakout board.

Maintenant, nous utilisons une instruction if/elif. Je l’ai divisé entre deux segments ici pour le rendre plus facile à lire. Le bouton du haut gagnera si l’utilisateur appuie dessus et que le nombre aléatoire précédent est impair. S’ils appuient sur le bouton du haut et que le nombre est pair, ils perdent. Nous disons donc que si l’utilisateur touche le bouton du haut, nous vérifions si y est égal à 0 (le nombre aléatoire était pair), puis il imprime le message perdant et allume le voyant rouge. Sinon (donc y est 1 ou le nombre aléatoire était impair), il affiche le message gagnant et allume le feu vert.

C’est la première fois que nous utilisons la fonction GPIO.output. Dans le cas des LED, nous produisons soit HIGH pour on ou LOW pour off. Puisque nous avons configuré GPIO en tant que variable plus tôt, nous pouvons simplement dire GPIO.output (numéro de broche, HIGH ou LOW) pour allumer ou éteindre la lumière.

Le time.sleep(.3) empêche l’ordinateur de remplir votre écran de milliers de messages de victoire ou d’échec. Cela vous donne suffisamment de temps pour retirer votre doigt du bouton.

		elif (bottomButton == False): #Button Button Pressed
                	if (y == 1): #If the number was odd and you pushed the bottom button, you lose.
                        	print("You have failed. Countless people have died due to your incompetence and you have been reduced to nothing but a few subatomic particles that are barely visible to the human eye.")
				GPIO.output(27,GPIO.HIGH)
				time.sleep(.3)
                	else: #If the number was even and you pushed the bottom button, you win.
                        	print ("Well done! You have successfully defused the bomb and saved many lives. You are an international hero!")
				GPIO.output(22,GPIO.HIGH)
				time.sleep(.3)
		time.sleep(.3) #Leave the light on for .3 second
		GPIO.output(22,GPIO.LOW) #Turn off Green
		GPIO.output(27,GPIO.LOW) #Turn off Red

Maintenant, nous faisons le même calcul, sauf pour le bouton du bas. Cette section est ignorée si le bouton du haut est enfoncé et la section précédente est ignorée si le bouton du bas est enfoncé. C’est la beauté des déclarations if.

Remarquez que nous utilisons une instruction elif au lieu de just and else. Sinon accepterait n’importe quelle entrée sauf appuyer sur le bouton du haut, donc il fonctionnerait si rien n’était appuyé. Nous voulons cependant qu’il ne s’exécute que si nous avons appuyé sur un bouton ou sur l’autre, nous utilisons donc elif.

Après les calculs pour déterminer si le joueur a gagné ou perdu et le temps d’attente de 0,3 seconde, le Pi éteindra les deux LED. Il ne devrait y avoir qu’une seule LED allumée, rouge ou verte selon que le jeu est gagné ou perdu, mais cela ne fait pas de mal d’en éteindre une qui est déjà éteinte, le Pi ne fera aucun changement. Cela garantit simplement qu’une lumière ne reste pas allumée après la fin du jeu.

	print "Exiting Game"
	return

Rappelez-vous que j’ai dit que c’était une boucle qui fonctionnait tant qu’au moins 1 bouton n’était pas enfoncé? Eh bien, lorsque vous appuyez sur les deux boutons, cela sortira de la boucle et mettra fin au programme. Ici, nous imprimons dans la fenêtre du terminal que le jeu se ferme. La commande return termine en fait le programme.

La fonction de jeu complète

def game():
	#Random Number
	x = randint(0,9)
	#Determine if number is even or odd
	y = x%2

	#Story
	print "You are casually walking down the street one day when out of nowhere you notice a ticking time bomb, ready to explode. You immediately remember your bomb squad days and rush into action. You have the bomb nearly defused, but you must now choose: red wire or blue wire. You have 10 seconds."
	time.sleep(1)
	print "Choose wisely"

	#Button Controls
	while (GPIO.input(17) == True or GPIO.input(18) == True): #Listen for input from buttons
		topButton = GPIO.input(17)
		bottomButton = GPIO.input(18)
		if (topButton == False): #Top Button Pressed
			if (y == 0): #If the number was even and you pushed the top button, you lose
				print("You have failed. Countless people have died due to your incompetence and you have been reduced to nothing but a few subatomic particles that are barely visible to the human eye.")
				GPIO.output(27,GPIO.HIGH)
				time.sleep(.3)
			else: #If the number was odd and you pushed the bottom button, you win.
				print ("Well done! You have successfully defused the bomb and saved many lives. You are an international hero!")
				GPIO.output(22,GPIO.HIGH)
				time.sleep(.3)
		elif (bottomButton == False): #Button Button Pressed
                	if (y == 1): #If the number was odd and you pushed the bottom button, you lose.
                        	print("You have failed. Countless people have died due to your incompetence and you have been reduced to nothing but a few subatomic particles that are barely visible to the human eye.")
				GPIO.output(27,GPIO.HIGH)
				time.sleep(.3)
                	else: #If the number was even and you pushed the bottom button, you win.
                        	print ("Well done! You have successfully defused the bomb and saved many lives. You are an international hero!")
				GPIO.output(22,GPIO.HIGH)
				time.sleep(.3)
		time.sleep(.3) #Leave the light on for .3 second
		GPIO.output(22,GPIO.LOW) #Turn off Green
		GPIO.output(27,GPIO.LOW) #Turn off Red

	print "Exiting Game"
	return

Le code : appeler la fonction

Maintenant que la fonction est enfin écrite, nous pouvons l’appeler et jouer le jeu. Aucun argument n’est nécessaire pour cette fonction. Nous l’appelons simplement pour que le Pi sache qu’il est temps de jouer.

game()

Le code entier

#Import frameworks
from random import randint
import RPi.GPIO as GPIO
import time

#GPIO Setup
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN,pull_up_down=GPIO.PUD_UP) #Top Button
GPIO.setup(18, GPIO.IN,pull_up_down=GPIO.PUD_UP) #Bottom Button
GPIO.setup(27, GPIO.OUT) #Red
GPIO.setup(22, GPIO.OUT) #Green


def game():
	#Random Number
	x = randint(0,9)
	#print(x)
	#Determine if number is even or odd
	y = x%2

	#Story
	print "You are casually walking down the street one day when out of nowhere you notice a ticking time bomb, ready to explode. You immediately remember your bomb squad days and rush into action. You have the bomb nearly defused, but you must now choose: red wire or blue wire. You have 10 seconds."
	time.sleep(1)
	print "Choose wisely"

	#Button Controls
	while (GPIO.input(17) == True or GPIO.input(18) == True): #Listen for input from buttons
		topButton = GPIO.input(17)
		bottomButton = GPIO.input(18)
		if (topButton == False): #Top Button Pressed
			if (y == 0): #If the number was even and you pushed the top button, you lose
				print("You have failed. Countless people have died due to your incompetence and you have been reduced to nothing but a few subatomic particles that are barely visible to the human eye.")
				GPIO.output(27,GPIO.HIGH)
				time.sleep(.3)
			else: #If the number was odd and you pushed the bottom button, you win.
				print ("Well done! You have successfully defused the bomb and saved many lives. You are an international hero!")
				GPIO.output(22,GPIO.HIGH)
				time.sleep(.3)
		elif (bottomButton == False): #Button Button Pressed
                	if (y == 1): #If the number was odd and you pushed the bottom button, you lose.
                        	print("You have failed. Countless people have died due to your incompetence and you have been reduced to nothing but a few subatomic particles that are barely visible to the human eye.")
				GPIO.output(27,GPIO.HIGH)
				time.sleep(.3)
                	else: #If the number was even and you pushed the bottom button, you win.
                        	print ("Well done! You have successfully defused the bomb and saved many lives. You are an international hero!")
				GPIO.output(22,GPIO.HIGH)
				time.sleep(.3)
		time.sleep(.3) #Leave the light on for .3 second
		GPIO.output(22,GPIO.LOW) #Turn off Green
		GPIO.output(27,GPIO.LOW) #Turn off Red

	print "Exiting Game"
	return
game()

Démonstration vidéo

Ci-dessous, j’ai inclus une vidéo qui montre à la fois l’écran du terminal et les voyants et boutons. Il y a une fonctionnalité supplémentaire à ce sujet qui n’est pas couverte dans notre tutoriel. Il y a une lumière clignotante qui est un compte à rebours limitant le temps dont dispose le joueur pour faire un choix. À un moment donné, je ferai peut-être un tutoriel sur la façon d’ajouter cette fonctionnalité, mais comme cela ne fonctionne pas encore parfaitement, je vais simplement laisser cette partie de côté pour le moment.

A lire aussi :  Un guide du débutant pour Notepad ++

Cet article est exact et fidèle au meilleur de la connaissance de l’auteur. Le contenu est uniquement à des fins d’information ou de divertissement et ne remplace pas un conseil personnel ou un conseil professionnel en matière commerciale, financière, juridique ou technique.

eembee le 19 septembre 2018 :

Même s’il a été créé pour Jessie, le tutoriel fonctionne toujours bien. Je voulais juste dire à quel point c’est utile et amusant. J’ai référé quelqu’un ici la semaine dernière et ils ont adoré. Merci encore Coton !

Bouton retour en haut de la page