Catégories
Robotique UNIHIKER

Portique de contrôle

Objectif du projet

Créer un portique de chronométrage pour mesurer le temps mis par un robot suiveur de ligne pour parcourir un circuit.
Le portique détecte le passage du robot grâce à des capteurs infrarouges et affiche le temps sur l’écran du microcontrôleur UNIHIKER.

Le robot passe une première fois sous le portique au départ, puis une deuxième fois à l’arrivée.

  • Premier passage : démarrage du chronomètre.
  • Deuxième passage : arrêt du chronomètre.

Les composants du portique

ÉlémentRôleDescription
🧠 Microcontrôleur UNIHIKERLe cerveau du portiqueIl gère les capteurs, mesure le temps et affiche les résultats sur son écran.
👀 Deux capteurs photoréflecteurs IRDétecter le robotPlacés en vis-à-vis de chaque côté du portique, ils détectent quand le robot passe (interruption du faisceau).
💡 LED verteIndiquer que le portique est prêtAllumée : le portique attend le départ du robot.
🔴 LED rougeIndiquer la mesure en coursAllumée : le portique mesure le temps du parcours.
📺 Écran intégré à l’UNIHIKERAffichage du résultatMontre le message “Prêt”, “Course en cours…” et le temps mesuré.

Le portique attend le robot (LED verte).
Le robot passe une première fois → démarrage du chrono.
Le robot passe une deuxième fois → arrêt du chrono et affichage.

Programmation de l’interface

Détail des instructions pour l’affichage du temps :

Programmation de la détection des passages

⚙️ Principe de détection du robot par le portique

🔦 1. Comment le portique détecte le passage du robot

Le portique utilise un photoréflecteur infrarouge.
C’est un petit capteur qui envoie de la lumière invisible (infrarouge) et mesure la lumière qu’il reçoit en retour.

  • Quand rien ne passe, la lumière rebondit normalement :
    👉 le capteur reçoit beaucoup de lumière.
  • Quand le robot passe devant, il bloque ou réfléchit moins la lumière :
    👉 le capteur reçoit moins de lumière.

C’est ce changement de niveau de lumière que le portique utilise pour savoir qu’un robot vient de passer.

🧠 2. La variable mesure_en_cours

Pour que le portique sache s’il doit démarrer ou arrêter le chronomètre, on utilise une variable mémoire qu’on appelle ici :

Cette variable peut prendre deux valeurs :

ValeurSignificationÉtat du portique
0Attente du robot au départPortique prêt, LED verte allumée
1Chronométrage en coursLED rouge allumée, le portique mesure le temps
⏱️ 3. Les deux passages du robot
🟢 Premier passage : le départ
  1. Le portique attend (mesure_en_cours = 0).
  2. Le robot passe → le capteur détecte un changement de lumière.
  3. Le portique :
    • allume la LED rouge,
    • met mesure_en_cours = 1,
    • attente que le véhicule passe.
🔴 Deuxième passage : l’arrivée
  1. Le robot repasse sous le portique.
  2. Le capteur détecte à nouveau un changement de lumière.
  3. Le portique :
    • rallume la LED verte,
    • remet mesure_en_cours = 0 (prêt pour une nouvelle mesure),
    • attente que le véhicule passe.

Le programme avec la détection et le comptage des passages :

Programmation du chronomètre

🟢 Premier passage : le départ

  1. démarre le chronomètre,

⏱️ Affichage du temps

  1. affiche le temps sur l’écran,

Programmation en python

Bibliothèques conseillées

import time
import math
from unihiker import GUI
from pinpong.board import Board,Pin
from pinpong.extension.unihiker import *

Objets à instancier
# Interfaces
u_gui=GUI()
# Micro contrôleur
Board().begin()

# Photo réflecteur IR sur le port P1
p_p1_analog=Pin(Pin.P1, Pin.ANALOG)

# LED rouge
p_p14_out=Pin(Pin.P14, Pin.OUT)

# LED verte
p_p15_out=Pin(Pin.P15, Pin.OUT)

# Lecture du photo réflecteur IR
lumiere = p_p1_analog.read_analog()

# Gestion des LEDs
p_p14_out.write_digital(0)
p_p15_out.write_digital(1)

# Affichage du chronomètre
mm = 0
ss = 0
chrono=u_gui.draw_clock(
h=mm,m=0,s=ss,
x=120,y=200,r=50,
color= »#0000FF »)
text_chrono = u_gui.draw_text(
text= »Temps= »+
str(mm).zfill(2)+ »: »+str(ss).zfill(2), 
x=20,y=260,
font_size=20, color= »#0000FF »)

# Affichage d’un texte
u_gui.draw_text(
text= »texte à afficher »,
x=40,y=25,
font_size=20, color= »#0000FF »)

# Dessin d’une surface rectangle
u_gui.fill_rect(x=5,y=5,w=230,h=90,color= »#CCFFFF »)

# Dessin d’un pourtour d’un rectangle
u_gui.draw_rect(x=0,y=0,w=240,h=100,width=10,color= »#FF0000″)

# Gestion du temps (pour le chrono)
# Récupération du temps

start = time.time()
# Calcul d’une durée en minutes et secondes
duree = int(time.time() – start)
mm = int(duree / 60)
ss = int(duree – (mm * 60))

# Exemple pour l’affichage du temps
chrono.config(h=mm,m=0,s=ss)
text_chrono.config(text= »Temps= »+str(mm).zfill(2)+ »: »+str(ss).zfill(2))

Catégories
Jeu vidéo ROBLOX

ROBLOX Faire bouger des objets


PARTIE 01 : Lancer des balles

LinearVelocity, VectorForce et AssemblyLinearVelocity — servent tous à faire bouger des objets dans Roblox,
mais ils ne fonctionnent pas du tout de la même manière.

LinearVelocity

Ce que ça fait :
➡️ Fait bouger un objet à une vitesse constante dans une direction.
➡️ Roblox s’occupe automatiquement de calculer la force nécessaire pour maintenir cette vitesse.

C’est parfait pour :

  • Faire voler ou propulser un objet
  • Tirer des projectiles
  • Donner un mouvement stable et constant

VectorForce

Ce que ça fait :
➡️ Applique une force brute (comme une poussée de moteur ou la gravité).
➡️ La vitesse dépend de la masse de l’objet et des forces qui s’opposent.

L’objet est poussé mais ralentit ou accélère selon sa masse, sa friction, etc.

C’est parfait pour :

  • Simuler une propulsion physique réaliste
  • Faire un jetpack, un vent, une poussée de moteur
  • Ajouter une force continue (comme la gravité personnalisée)

AssemblyLinearVelocity

Ce que ça fait :
➡️ Change directement la vitesse actuelle du corps rigide complet.
➡️ C’est comme “modifier” la vitesse sans appliquer de vraie force.

L’objet prend instantanément cette vitesse.
Pas de physique calculée, pas de force — juste une vitesse imposée.

📍 C’est parfait pour :

  • Faire bouger instantanément un objet
  • Lancer un objet d’un coup
  • Remettre à zéro sa vitesse facilement

Crée une balle à lancer

Crée une balle à partir de l’onglet Modèle puis Pièce et Sphère :

Renomme le part en « Balle » :

Change les propriétés suivantes du part Balle :

Déplace le part Balle sous ServerStorage :

ServerStorage permet de stocker des objets secrets ou internes au serveur (comme des scripts, modèles ou outils que les joueurs ne doivent pas voir directement). Donc la conséquence immédiate du déplacement de la balle : celle-ci n’est plus visible dans ton jeu, ni dans ton workspace.

Programme un lancer avec linearVelocity :

VectorVelocity fait bouger ta balle à une vitesse constante dans la direction du regard du joueur.

La balle rouge bouge sans la contrainte de la physique du jeu, notamment de la gravité.

Crée un script sous ServerScriptService et lance les balles devant le joueur :

-- je récupère la balle dans le ServerStorage
local ss = game:GetService("ServerStorage")
local balle= ss:WaitForChild("Balle")

-- je récupère la liste des jueurs
local players = game:GetService("Players")

-- je lance la blle avec linearVelocity
local function linearVelocityBall(player)
	
	-- je récupère le corps du joueur
	local char = player.Character or
                     player.CharacterAdded:Wait()
	local hrp = char:WaitForChild("HumanoidRootPart")

	-- Je génère une copie de la balle dans le workspace
	local ball = balle:Clone()
	ball.BrickColor = BrickColor.Red()
	ball.Parent = workspace
	ball.CFrame = hrp.CFrame * CFrame.new(0, 2, -2)

	-- J'applique à la balle une force constante 
	local lv = Instance.new("LinearVelocity")
	lv.MaxForce = math.huge
	lv.VelocityConstraintMode = 
                        Enum.VelocityConstraintMode.Vector
	lv.VectorVelocity = hrp.CFrame.LookVector * 5
	lv.Parent = ball
	
	-- J'attache cette force à la balle
	local attchment = Instance.new("Attachment")
	attchment.Parent = ball
	lv.Attachment0 = attchment
	
	-- Je détruis la balle au bout de 5 secondes
	game.Debris:AddItem(ball, 5)
end

-- Le joueur se connecte
players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function()
		for i = 1, 5 do
			task.wait(1)
			linearVelocityBall(player)		
		end
	end)
end)

VectorVelocity fait bouger ta balle à une vitesse constante dans la direction du regard du joueur.

L’objet bouge sans que tu aies besoin de gérer la physique.

Ton script instancie un Attachment. Un Attachment est un point de repère invisible dans une pièce (Part, MeshPart, etc.)
C’est comme une punaise virtuelle que tu peux placer n’importe où dans la pièce.

🔹 Il sert à :

  • indiquer un point précis où appliquer une force, un effet, ou une jointure,
  • ou relier deux objets ensemble (LinearVelocity, VectorForce).

L’objet bouge sans que tu aies besoin de gérer la physique.

Programme un lancer avec vectorForce:

Applique une force brute (comme une poussée de moteur ).
La vitesse dépend de la masse de l’objet et des forces qui s’opposent. La belle bleue est poussée mais ralentit ou accélère selon sa masse, sa friction et subit la gravité.

Modifie ton script pour le lancer avec une balle bleue :

local function vectorForceBall(player)
	
	-- je récupère le corps du joueur
	local char = player.Character or
                     player.CharacterAdded:Wait()
	local hrp = char:WaitForChild("HumanoidRootPart")

	-- Je génère une copie de la balle dans le workspace
	local ball = balle:Clone()
	ball.BrickColor = BrickColor.Blue()
	ball.Parent = workspace
	ball.CFrame = hrp.CFrame * CFrame.new(0, 2, -2)
	
	-- J'applique à la balle un VectorForce
	local vf = Instance.new("VectorForce")
	vf.RelativeTo = Enum.ActuatorRelativeTo.World
	vf.ApplyAtCenterOfMass = true
	vf.Force = hrp.CFrame.LookVector * ball:GetMass() * 5

	vf.Parent = ball

	-- J'attache cette force à la balle
	local attchment = Instance.new("Attachment")
	attchment.Parent = ball
	vf.Attachment0 = attchment
	
	-- Je détruis la balle au bout de 5 secondes
	game.Debris:AddItem(ball, 5)
end

players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function()
		for i = 1, 5 do
			task.wait(1)
			linearVelocityBall(player)
			task.wait(1)
			vectorForceBall(player)		
		end
	end)
end)

Programme un lancer avec AssemblyLinearVelocity

La balle verte prend instantanément la vitesse appliquée.
Pas de physique calculée, pas de force — juste une vitesse imposée

Modifie ton script :

local function assemblyLinearVelocityBall(player)
	
	-- je récupère le corps du joueur
	local char = player.Character or 
                     player.CharacterAdded:Wait()
	local hrp = char:WaitForChild("HumanoidRootPart")

	-- Je génère une copie de la balle dans le workspace
	local ball = balle:Clone()
	ball.BrickColor = BrickColor.Green()
	ball.Parent = workspace
	ball.CFrame = hrp.CFrame * CFrame.new(0, 2, -2)
	
        -- J'applique une vitesse à l'objet
	ball.AssemblyLinearVelocity = hrp.CFrame.LookVector *
                                      ball:GetMass() * 5
	
	-- Je détruis la balle au bout de 5 secondes
	game.Debris:AddItem(ball, 5)

end

players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function()
		task.wait(5)
		for i = 1, 5 do
			task.wait(1)
			linearVelocityBall(player)
			task.wait(1)
			vectorForceBall(player)
			task.wait(1)
			assemblyLinearVelocityBall(player)			
		end
	end)
end)

PARTIE 02 : Une barrière

Avant de commencer à construire ta barrière, choisis ces options pour ton projet :

Construction d’une barrière

Puis commence à construire ta barrière en créant un bloc :

Renomme le part en Socle :

Modifie les propriétés suivantes :

Puis un deuxième part pour la barrière :

Renomme le part en Barriere :

Avec les propriétés suivantes :

Sous ton workspace crée un Model que tu renommes en Barriere puis range les deux parts précédent sous ce Model :

Installe une charnière pour le mécanisme d’ouverture de la porte :

Avec un premier point d’appui sur la barrière et un deuxième sur le socle :

Tu dois obtenir ce résultat dans explorer :

  • deux points d’attachement un sur le socle et un autre sur la barrière,
  • une charnière HingeConstraint sur la barrière.

Tu peux régler plus précisément le point d’attachement, en sélectionnant celui-ci dans explorer et en utilisant l’outil déplacer :

Modifie les propriétés du HingeConstraint :

Si tu lances ton jeu, tu obtiens ce résultat :

Si tu changes la propriété TargetAngle :

En lançant ton jeu, tu obtiens le résultat suivant :

Automatisation d’ouverture de la barrière

Rajoute une boîte de collision transparente autour de la barrière afin d’automatiser son ouverture :

N’oublie pas d’enlever le CanCollide de la boîte de collision.

Puis crée un script dans ton Model Barriere :

Puis saisie ce script pour ouvrir et fermer automatiquement ta barrière :

-- Récupération de la barrière
local barriere = script.Parent.Barriere
-- Récupération de la boîte de collision
local boiteCollision = script.Parent.BoiteCollision

-- Quand la boîte de collision touche un un personnage
boiteCollision.Touched:Connect(function(hit)
	-- On récupère le modèle parent de la pièce touchée
	local character = hit.Parent
	-- On vérifie si ce modèle a un "Humanoid" (seuls les personnages en ont un)
	local humanoid = character:FindFirstChild("Humanoid")

	if humanoid then
		-- Ouverture de la barrière
		barriere.HingeConstraint.TargetAngle = 90
	end
end)

-- Quand la boîte de collision ne touche plus de personnage
boiteCollision.TouchEnded:Connect(function(hit)
	-- On récupère le modèle parent de la pièce touchée
	local character = hit.Parent
	-- On vérifie si ce modèle a un "Humanoid" (seuls les personnages en ont un)
	local humanoid = character:FindFirstChild("Humanoid")

	if humanoid then
		-- Fermeture de la barrière
		barriere.HingeConstraint.TargetAngle = 0
	end
end)

-- Fermeture de la barrière au début
barriere.HingeConstraint.TargetAngle = 0

Lance ton jeu pour tester ta barrière automatique :

PARTIE 03 : ROULER EN VOITURE

Choisis ces paramètres pour la construction de ton véhicule :

  • Joindre les surfaces
  • 1 pour l’incrémentation pour dimensionner les objets

Choix d’un Bloc pour le châssis de la voiture

Redimensionne le châssis de ta voiture et renomme le part en « Chassis« :

Crée un nouveau bloc pour créer les moyeux des roues de la voiture :

Choisis sa demension :

Duplique en quatre blocs :

Colle les blocs sur le châssis :

Sur les quatre côtés du châssis :

Duplique deux nouveaux blocs pour la direction, modifie la couleur :

Décoche la propriété CanCollide pour ces blocs :

Sous worksapace crée cette structure et range tous les parts de ta voiture :

Par le clic droit de la souris, demande le menu suivant :

Insére l’objet VehicleSeat :

Installe cet objet sur le châssis, cet objet représente le siège du conducteur :

Déplace cet objet sous l’arborescence de ta voiture :

Lance le jeu pour venir t’assoir sur le siège de ton véhicule :

Insère des contraintes entre les pièces de ton véhicule pour transmettre la direction :

Vision de la transmission de direction à droite

Vision de la transmission de direction à gauche

Tu dois obtenir ce résultat dans ton explorer :

Sélectionne les HingeConstraint de tes deux roues de l’avant pour modifier les propriétés suivantes :

Rappel : c’est quoi un HingeConstraint ?

Un HingeConstraint = une charnière virtuelle.
Il permet à un objet de tourner autour d’un axe (comme une porte, une roue, ou un bras robotique).

Mais quand on ajoute un moteur dessus, il peut :

  • tourner jusqu’à un certain angleServo

Quand ActuatorType = Servo

Le Servo agit comme un moteur intelligent :
il regarde la position actuelle de la pièce, puis la fait tourner jusqu’à atteindre l’angle qu’on lui demande.

👉 On lui donne une cible (TargetAngle), et il s’arrête tout seul quand il y arrive.

🔩 3️⃣ Les propriétés importantes

PropriétéRôle
TargetAnglel’angle à atteindre (en degrés)
ServoMaxTorquela force que le moteur peut exercer pour y arriver
AngularSpeedvitesse à laquelle il tourne pour atteindre l’angle
ActuatorTypedoit être mis sur Enum.ActuatorType.Servo

Tu dois obtenir la visualisation du mécanisme de la direction de tes deux roues :

Renomme les parts des roues avant droite et gauche ayant un HingeConstraint en « Direction » :

Rend invisible les deux parts des deux roues avant :

Rajoute un script sous le modèle de ta voiture :

local seat = script.Parent.VehicleSeat

local roueAvantGauche = script.Parent.RoueAvantGauche
local roueAvantDroite = script.Parent.RoueAvantDroite

local steerAngle = 30

seat:GetPropertyChangedSignal("Steer"):Connect(function()
	print("Steer =", seat.Steer)
	roueAvantGauche.Direction.HingeConstraint.TargetAngle = 
                        steerAngle * seat.Steer
	roueAvantDroite.Direction.HingeConstraint.TargetAngle = 
                        steerAngle * seat.Steer
end)

Ce script fait tourner les roues avant d’une voiture quand le joueur tourne à gauche ou à droite avec le clavier (A / D ou Q / D selon ton clavier).

📘 Le code

local seat = script.Parent.VehicleSeat

➡️ On récupère le siège de conduite de la voiture (VehicleSeat).
C’est lui qui détecte quand le joueur tourne à gauche ou à droite.

local roueAvantGauche = script.Parent.RoueAvantGauche
local roueAvantDroite = script.Parent.RoueAvantDroite

➡️ On récupère les deux roues avant du véhicule, pour pouvoir les faire pivoter.

  • RoueAvantGauche = la roue de gauche
  • RoueAvantDroite = la roue de droite

Ces roues ont chacune une charnière (HingeConstraint) qui permet de les faire tourner.

local steerAngle = 30

➡️ C’est l’angle maximum de rotation des roues (en degrés).
Ici : les roues peuvent tourner jusqu’à 30° vers la gauche ou la droite.

🧠 Maintenant, la partie importante :

seat:GetPropertyChangedSignal("Steer"):Connect(function()
	print("Steer =", seat.Steer)
	roueAvantGauche.Direction.HingeConstraint.TargetAngle = steerAngle * seat.Steer
	roueavantDroite.Direction.HingeConstraint.TargetAngle = steerAngle * seat.Steer
end)

1️⃣ seat:GetPropertyChangedSignal("Steer")

➡️ écoute la propriété Steer du siège (objet noir que l’on a inséré au dessus du véhicule).
Cette valeur change quand le joueur appuie sur :

  • Q → tourner à gauche
  • D → tourner à droite
  • Relâcher les touches → revenir droit

2️⃣ seat.Steer

Cette valeur peut être :

  • -1 → le joueur tourne à gauche
  • 0tout droit
  • 1 → le joueur tourne à droite

3️⃣ steerAngle * seat.Steer

➡️ C’est un calcul pour savoir de combien tourner les roues :

SteerCalculRésultat
130 × 1roues tournées à +30° (droite)
030 × 0roues droites
-130 × -1roues tournées à -30° (gauche)

4️⃣ Application de l’angle

roueAvantGauche.Direction.HingeConstraint.TargetAngle = steerAngle * seat.Steer
roueAvantDroite.Direction.HingeConstraint.TargetAngle = steerAngle * seat.Steer

➡️ Le script change l’angle cible (TargetAngle) de la charnière des roues avant.
👉 Résultat : quand le joueur tourne, les roues s’inclinent à gauche ou à droite comme une vraie voiture 🚘

🧠 En résumé

ÉlémentRôle
VehicleSeatdétecte les touches du joueur
Steerindique la direction du volant (-1, 0, 1)
HingeConstraintpermet de faire tourner les roues
TargetAngleangle que doit atteindre la roue
steerAnglelimite maximale de rotation (ici 30°)

🎯 Ce que fait le script

➡️ À chaque fois que le joueur tourne :

  1. Le siège envoie une valeur (Steer)
  2. Le script multiplie cette valeur par 30
  3. Les roues avant tournent de cet angle

💬 En bref :

Quand tu tournes le volant, les roues tournent dans la même direction, comme une vraie voiture

Lance ton jeu pour vérifier le bon fonctionnement de ta direction :

Maintenant nous allons installer les roues.

Crée une roue centrée sur la direction de ta voiture, surélève ton châssis de voiture :

Renomme le part en « roue » :

Duplique en 4 roues :

Place tes 4 roues bien centrées :

Range tes roues dans l’arborescence de ta voiture :

Pour chaque roue positionne une charnière à partir du centre de la roue sur le centre de la direction :

Sélectionne les quatre HingeConstraint des quatre roues et applique ces propriétés :

Qu’est-ce qu’un HingeConstraint ?

Un HingeConstraint (en français : contrainte de charnière) relie deux objets pour qu’ils puissent tourner autour d’un axe, comme une porte sur ses gonds ou une roue sur son axe.

Sans moteur, il laisse juste la pièce tourner librement.
Avec un Motor, il fait tourner activement la pièce tout seul.

Quand ActuatorType = Motor

Alors le HingeConstraint se comporte comme un moteur qui fait tourner la pièce en continu 🌀

Les propriétés les plus importantes sont :

PropriétéRôle
AngularVelocityvitesse de rotation de la pièce (en radians/s)
MotorMaxTorqueforce maximum du moteur (plus elle est grande, plus il peut pousser)
AngularResponsivenessvitesse à laquelle le moteur s’adapte aux changements (réactivité)

Vérifie le sens de rotation :

Tu remarques que le sens gauche est inverse de celui du sens droit.

Vérifie le bon fonctionnement de la direction :

Modifie ton script :

local seat = script.Parent.VehicleSeat

local roueAvantGauche = script.Parent.RoueAvantGauche
local roueAvantDroite = script.Parent.RoueAvantDroite

local roueArriereGauche = script.Parent.RoueArriereGauche
local roueArriereDroite = script.Parent.RoueArriereDroite

local steerAngle = 30
local speed = 60

seat:GetPropertyChangedSignal("Steer"):Connect(function()
	print("Steer =", seat.Steer)
	roueAvantGauche.Direction.HingeConstraint.TargetAngle = 
                        steerAngle * seat.Steer
	roueAvantDroite.Direction.HingeConstraint.TargetAngle =
                        steerAngle * seat.Steer
end)

seat:GetPropertyChangedSignal("Throttle"):Connect(function()
	print("Throttle =", seat.Throttle)
	roueAvantGauche.Roue.HingeConstraint.AngularVelocity =
                        speed * seat.Throttle
	roueAvantDroite.Roue.HingeConstraint.AngularVelocity =
                        speed * -seat.Throttle

	roueArriereGauche.Roue.HingeConstraint.AngularVelocity =
                        speed * seat.Throttle
	roueArriereDroite.Roue.HingeConstraint.AngularVelocity =
                        speed * -seat.Throttle
end)

Ce script permet de faire tourner les roues d’une voiture quand le joueur accélère ou recule avec le clavier (les touches Z / S ou flèche haut / flèche bas).

🧩 Étape 1 : on récupère les objets importants

local seat = script.Parent.VehicleSeat

➡️ On récupère le siège de conduite de la voiture.
C’est lui qui détecte quand le joueur appuie pour avancer ou reculer.

local roueAvantGauche = script.Parent.RoueAvantGauche
local roueAvantDroite = script.Parent.RoueAvantDroite

local roueArriereGauche = script.Parent.RoueArriereGauche
local roueArriereDroite = script.Parent.RoueArriereDroite

➡️ On récupère les 4 roues du véhicule :

  • 2 à l’avant
  • 2 à l’arrière

Chaque roue contient un objet appelé HingeConstraint, une charnière qui permet à la roue de tourner sur elle-même.

🧩 Étape 2 : les réglages de base

local steerAngle = 30
local speed = 60
  • steerAngle : angle pour tourner (pas utilisé ici, mais utile si on veut tourner les roues plus tard).
  • speed : vitesse de rotation des roues (plus la valeur est grande, plus la voiture va vite 🚀).

🧩 Étape 3 : détecter quand le joueur accélère ou recule

seat:GetPropertyChangedSignal("Throttle"):Connect(function()

➡️ Cette ligne écoute la propriété « Throttle » du siège.
Elle change quand le joueur appuie sur :

  • Z / flèche hautThrottle = 1 → avancer 🏎️
  • S / flèche basThrottle = -1 → reculer 🚙
  • Rien → Throttle = 0 → arrêt ⛔

🧩 Étape 4 : faire tourner les roues

roueAvantGauche.Roue.HingeConstraint.AngularVelocity = speed * seat.Throttle
roueAvantDroite.Roue.HingeConstraint.AngularVelocity = speed * -seat.Throttle

🌀 Explication :

Chaque roue tourne grâce à sa vitesse angulaire (AngularVelocity), c’est-à-dire la vitesse à laquelle elle tourne autour de son axe.

Mais pourquoi une roue est multipliée par -seat.Throttle
👉 Parce que les roues droite et gauche sont dans des sens opposés (comme une vraie voiture).
Si elles tournaient dans le même sens, la voiture glisserait sur place au lieu d’avancer 😅.

Donc :

  • les roues de gauche tournent dans un sens,
  • celles de droite tournent dans le sens inverse,
    ➡️ ce qui fait avancer la voiture dans la bonne direction 🚗💨
roueArriereGauche.Roue.HingeConstraint.AngularVelocity = speed * seat.Throttle
roueArriereDroite.Roue.HingeConstraint.AngularVelocity = speed * -seat.Throttle

Même principe pour les roues arrière : elles tournent aussi pour propulser la voiture.

🧠 En résumé

ÉlémentRôle
VehicleSeatdétecte si le joueur accélère ou recule
Throttle-1 (reculer), 0 (ne bouge pas), 1 (avancer)
HingeConstraintfait tourner la roue
AngularVelocityvitesse de rotation de la roue
speeddéfinit la vitesse du véhicule
signe négatif -pour que les roues tournent dans le bon sens

🚗💨 En image (imagine) :

ToucheThrottleEffet
Z / ↑1roues tournent, voiture avance
S / ↓-1roues tournent en sens inverse, voiture recule
(rien)0roues s’arrêtent

Tu peux rouler avec ta voiture !!!!!!!!!!!!!

Catégories
ALGORA Non classé Robotique

Barrière automatique

Construis ce robot barrière automatique avec un servomoteur :

Clique sur le menu Edition en haut de l’écran et choisis Paramètres des ports.

Clique ensuite sur le bouton Tout décocher .

Puis coche D9 pour indiquer l’installation du servomoteur :

Vérifie que l’instruction sur le servomoteur est couleur bleue :

Active le test pour contrôler le servomoteur :

Utilise deux instructions servomoteur pour connaitre la position de la barrière ouverte et celle de la barrière fermée :

En cliquant sur les instructions, tu commande le servomoteur, attention il doit être sous tension.

Si tu veux contrôler la vitesse d’ouverture de la barrière :

Donne un nom à aux deux actions :

Installe un bouton poussoir pour piloter l’ouverture de ta barrière :

Installe le connecteur du bouton poussoir sur A0 et modifie les paramètres des ports :

Vérifie que l’instruction sur le capteur de pression est bien de la couleur bleue :

Programme pour ouvrir la barrière sur l’appui du capteur de pression, puis attendre un certain avant de refermer automatiquement la barrière :

Transfert ton programme et test le bon fonctionnement :

Rajoute une LED rouge pour prévenir que la barrière est fermée :

Installe la LED sur A1 :

Programme pour allumer la LED rouge quand la barrière est fermée.

Introduis la possibilité de deux modes de fonctionnement :

  • un mode avec une ouverture puis une fermeture automatique
  • un mode avec juste une ouverture

Pour distinguer les deux modes, un appui rapide sur le bouton poussoir permet une ouverture puis une fermeture, un appui long permet une ouverture simple :

Transfert ton programme et test le bon fonctionnement :

Catégories
UNIHIKER

UNIHIKER premiers pas

Bonjour et EMOJI

Ce projet utilise la classe GUI de la bibliothèque UNIHIKER et la fonction draw_emoji() pour générer des emojis émotionnels.

Importe les bibliothèques :

from unihiker import GUI
import time 

Crée cet objet pour gérer les interfaces :

gui = GUI()

Instruction pour dessiner un cercle :

circle = gui.draw_circle(x = 120,y = 140,r = 50,width = 3,color = "#FF6666")
  • x et y position du centre du cercle sur l’écran
  • r le rayon du cercle
  • width et color la largeur et la couleur du dessin du cercle

Documentation draw_circle

Instruction pour créer un emoji

emj = gui.draw_emoji(emoji = "Wink", origin = "center", x=120, y=120, duration = 0.2, w=50) 
  • emoji = type d’emoji
  • origin = arrangement de l’emoji par rapport à sa position
  • x, y = positionnement de l’emoji sur l’écran
  • duration = durée de l’animation
  • w = taille de l’emoji

Documentation draw_emoji

Instruction pour l’affichage du text :

Text = gui.draw_text(text='Hello , Patrick !',
                     x=15,y=260,
                     font_size=20)
  • text = texte à afficher
  • x,y = positionnement du texte à l’écran
  • font_size = taille de la police de caractère

Documentation gui.draw_text

from unihiker import GUI
import time 

gui = GUI()

# Dessin d'un cercle pour le visage
circle = gui.draw_circle(x = 120,y = 140,r = 50,width = 3,color = "#FF6666")

# Création de l'emoji 
emj = gui.draw_emoji(emoji = "Wink", origin = "center", x=120, y=120, duration = 0.2, w=50) 

# Affichage du prénom en bas de l'écran
Text = gui.draw_text(text='Hello , Patrick !',x=15,y=260,font_size=20)
Text.config(color='#0000FF')

width = 50
radius = 30
delta_radius = 2.5
delta_width = 5
while True:
    # Animation de l'emoji 
    time.sleep(0.3)
    width += delta_width
    radius += delta_radius
    circle.config(r=radius)
    emj.config(w = width) 
    if not (50 <= width <= 240):
        delta_width = -delta_width
        delta_radius = -delta_radius

Si tu veux une progression plus douce (effet oscillation)
Tu peux remplacer l’incrémentation linéaire par une fonction sinus :

from unihiker import GUI
import time, math

gui = GUI()

# Dessin d'un cercle pour le visage
circle = gui.draw_circle(x = 120,y = 140,r = 50,width = 3,color = "#FF6666")

# Création de l'emoji 
emj = gui.draw_emoji(emoji = "Wink", origin = "center", x=120, y=120, duration = 0.2, w=50) 

# Affichage du prénom en bas de l'écran
Text = gui.draw_text(text='Hello , Patrick !',x=15,y=260,font_size=20)
Text.config(color='#0000FF')

width = 50
radius = 30
delta_radius = 2.5
delta_width = 5

t = 0
while True:
    time.sleep(0.03)
    radius = 80 + 40 * math.sin(t)
    width = 120 + 60 * math.sin(t)
    circle.config(r=int(radius))
    emj.config(w=int(width))
    t += 0.1

Les différentes possibilité des emoji.

  • Angry,
  • Nerve,
  • Peace,
  • Shock,
  • Sleep,
  • Smile,
  • Sweat,
  • Think,
  • Wink

Changement des EMOJI avec les boutons A ou B

from unihiker import GUI
from pinpong.extension.unihiker import *
import time, math

gui = GUI()

# Dessin d'un cercle pour le visage
circle = gui.draw_circle(x = 120,y = 140,r = 50,width = 3,color = "#FF6666")

emoji_table = ["Angry", "Nerve", "Peace", "Shock", "Sleep", "Smile", "Sweat", "Think", "Wink"]
index = 0
# Création de l'emoji 
emj = gui.draw_emoji(emoji = emoji_table[index], origin = "center", x=120, y=120, duration = 0.2, w=50) 

# Affichage du prénom en bas de l'écran
Text = gui.draw_text(text='Hello , Patrick !',x=15,y=260,font_size=20)
Text.config(color='#0000FF')

width = 50
radius = 30
delta_radius = 2.5
delta_width = 5
import time, math

t = 0
while True:
    time.sleep(0.03)
    radius = 80 + 40 * math.sin(t)
    width = 120 + 60 * math.sin(t)
    circle.config(r=int(radius))
    emj.config(w=int(width))
    t += 0.1
    # Changement de l'emoji avec le bouton A ou B
    if (button_a.is_pressed()==True):
        index = index + 1 if index < 8 else 0
        emj.config(emoji = emoji_table[index])
    if (button_b.is_pressed()==True):
        index = index - 1 if index > 0 else 8
        emj.config(emoji = emoji_table[index])

Bouton A ou B lumineux

Les boutons A et B de l’UNIHIKER sont accessibles à l’utilisateur, ce qui permet de créer un projet impliquant une LED contrôlée par des boutons. Ce projet vérifie d’abord si les boutons A et B de l’UNIHIKER ont été enfoncés, puis contrôle l’allumage et l’extinction de la LED bleue située à l’arrière de l’UNIHIKER. La bibliothèque PinPong propose deux façons d’utiliser les boutons : la première consiste à lire directement la requête, la seconde à utiliser les rappels d’événements d’interruption. Voici un exemple de contrôle de l’allumage et de l’extinction de la LED à l’aide des boutons A et B.

Utilise ces librairies :

from pinpong.extension.unihiker import *
from pinpong.board import Board,Pin
from unihiker import GUI

Crée un objet pour les interfaces :

gui=GUI()

Initialise la carte du microcontrôleur :

Board().begin()

Instruction pour dessiner un cercle plein

ledUI = gui.fill_circle(x=120,y=100,r=50,color="#FFFF00")

Documentation fill_circle

Pour tester l’appui sur les boutons A ou B utilise cette instruction

if (button_a.is_pressed()==True):

Documentation sur la gestion des boutons

Test de l’appui de boutons dans le code :

from pinpong.extension.unihiker import *
from pinpong.board import Board,Pin
from unihiker import GUI

# Initialisation de l'interface et de la carte
gui=GUI()
Board().begin()

# Initialisation de la LED
ledUI = gui.fill_circle(x=120,y=100,r=50,color="#FFFF00")
led = Pin(Pin.P25, Pin.OUT)

while True:
    # Bouton A appuyé
    if (button_a.is_pressed()==True):
        led.write_digital(1)
        ledUI.config(color="#0000FF")

    # Bouton B appuyé
    if (button_b.is_pressed()==True):
        led.write_digital(0)
        ledUI.config(color="#FF0000")

Fonctions d’interception de l’événement de l’appui sur le bouton A ou B

from pinpong.extension.unihiker import *
from pinpong.board import Board,Pin
from unihiker import GUI

# Controle de l'appui du bouton A
def on_buttona_click_callback():
    led.write_digital(1)
    ledUI.config(color="#0000FF")

# Controle de l'appui du bouton B
def on_buttonb_click_callback():
    led.write_digital(0)
    ledUI.config(color="#FF0000")

# Initialisation de l'interface et de la carte
gui=GUI()
Board().begin()

ledUI = gui.fill_circle(x=120,y=100,r=50,color="#FFFF00")

# Eteindre la LED
led = Pin(Pin.P25, Pin.OUT)

# Intercpetion des boutons A et B
gui.on_a_click(on_buttona_click_callback)
gui.on_b_click(on_buttonb_click_callback)


while True:
    pass

LED externe sur le port 22

led = Pin(Pin.P22, Pin.OUT)

Détecteur de luminosité

UNIHIKER est équipé d’un capteur de lumière placé au-dessus de l’écran frontal, permettant de détecter l’intensité lumineuse ambiante. Grâce à cette fonctionnalité, un détecteur de luminosité peut être développé. Ce projet consiste à afficher la valeur lumineuse détectée par le capteur sur l’écran.

Documentation sur le dispositif light sensor

from unihiker import GUI
import time

from pinpong.board import Board 
from pinpong.extension.unihiker import *

# # initialization
Board().begin()

# Instantiate a GUI object
gui = GUI()
img = gui.fill_circle(x=120,y=100,r=50,color="#FFFF00")
value = gui.draw_text(x=145, y=28, text='0', font_size=18)

while True :
    # Update the displayed light value
    Light = light.read()
    value.config(text = Light)

    # Light value level
    if Light < 600:
        img.config(color="#FF6600")
    elif 600 <= Light < 1024:
        img.config(color="#FF9900")
    elif 1024 <= Light < 2048:
        img.config(color="#FFCC33")
    elif 2048 <= Light < 3072:
        img.config(color="#FFFF99")
    else:
        img.config(color="#FFFF00")

    time.sleep(1)

Dans cet exemple, UNIHIKER est initialisé avec Board().begin(). Ensuite, un objet GUI est instancié et un objet image et un objet texte sont créés à l’aide des méthodes draw_image() et draw_text(), respectivement. Dans la boucle principale, l’intensité lumineuse ambiante est obtenue grâce à la méthode light.read() de la bibliothèque PinPong, et la valeur lumineuse est affichée à l’écran grâce à la méthode draw_text() de la bibliothèque GUI.

L’intensité lumineuse ambiante est divisée en cinq niveaux en moyenne, et différents niveaux de luminosité sont représentés par des cercles de couleurs différentes, selon les conditions d’éclairage.

Piano musical

L’UNIHIKER est équipé d’un buzzer capable d’émettre différentes tonalités en réglant différentes fréquences. Cette fonctionnalité permet de créer un piano électronique. Ce projet propose une interface utilisateur simple permettant aux utilisateurs de jouer différentes notes en appuyant sur des boutons à l’écran. Voici un exemple de piano électronique :

Documentation pour dessiner les touches du clavier

from pinpong.extension.unihiker import *
from pinpong.board import Board,Pin
from unihiker import GUI
import time

# Gestion des touches du piano
def button_click1():
    buzzer.pitch(262,1)
    text.config(text="C4")
def button_click2():
    buzzer.pitch(294,1)
    text.config(text="D4")
def button_click3():
    buzzer.pitch(330,1)
    text.config(text="E4")
def button_click4():
    buzzer.pitch(349,1)
    text.config(text="F4")
def button_click5():
    buzzer.pitch(392,1)
    text.config(text="G4")
def button_click6():
    buzzer.pitch(440,1)
    text.config(text="A4")
def button_click7():
    buzzer.pitch(494,1)
    text.config(text="B4")
def button_click8():
    buzzer.pitch(277,1)
    text.config(text="C#4")
def button_click9():
    buzzer.pitch(311,1)
    text.config(text="D#4")
def button_click10():
    buzzer.pitch(370,1)
    text.config(text="F#4")
def button_click11():
    buzzer.pitch(415,1)
    text.config(text="G#4")
def button_click12():
    buzzer.pitch(466,1)
    text.config(text="A#4")

# Initialisation de l'interface et de la carte
u_gui=GUI()
Board().begin()
# Affichage du titre
bg=u_gui.fill_rect(x=0,y=0,w=240,h=320,color="#CCCCFF")
text = u_gui.draw_text(x=185,y=160,text="Clavier musical",origin="center",font_size=28,angle=270)

# Zones sensibles du clavier musical (touches blanches)
do=u_gui.fill_rect(x=0,y=3,w=130,h=43,color="#FFFFFF",onclick=button_click1)
re=u_gui.fill_rect(x=0,y=48,w=130,h=43,color="#FFFFFF",onclick=button_click2)
mi=u_gui.fill_rect(x=0,y=93,w=130,h=43,color="#FFFFFF",onclick=button_click3)
fa=u_gui.fill_rect(x=0,y=138,w=130,h=43,color="#FFFFFF",onclick=button_click4)
so=u_gui.fill_rect(x=0,y=183,w=130,h=43,color="#FFFFFF",onclick=button_click5)
la=u_gui.fill_rect(x=0,y=228,w=130,h=43,color="#FFFFFF",onclick=button_click6)
xi=u_gui.fill_rect(x=0,y=273,w=130,h=43,color="#FFFFFF",onclick=button_click7)

# Zones sensibles du clavier musical (touches noires)
bian1=u_gui.fill_rect(x=50,y=32,w=80,h=30,color="#000000",onclick=button_click8)
bian2=u_gui.fill_rect(x=50,y=77,w=80,h=30,color="#000000",onclick=button_click9)
bian3=u_gui.fill_rect(x=50,y=167,w=80,h=30,color="#000000",onclick=button_click10)
bian4=u_gui.fill_rect(x=50,y=212,w=80,h=30,color="#000000",onclick=button_click11)
bian5=u_gui.fill_rect(x=50,y=257,w=80,h=30,color="#000000",onclick=button_click12)

while True:
    time.sleep(0.1)

Dans cet exemple, UNIHIKER est initialisé avec Board().begin().

Ensuite, un objet GUI est instancié, sur un fond bleu plusieurs rectangles noirs et blancs (représentant différentes touches de piano) sont créés à l’aide de la fonction fill_rect().

Ensuite, une série de fonctions d’événements sur le click de chaque touche sont définies, chacune correspondant à une note de musique.

Dans les fonctions appelées par un click sur la touche, le buzzer est contrôlé pour émettre un son d’une fréquence et d’une durée spécifiques à l’aide de la fonction buzzer.pitch (frequency, duration).

Chaque note de musique est liée à une touche de piano, et lorsque la touche est enfoncée, la fonction de rappel correspondante est exécutée et le buzzer joue la note correspondante.

De plus, une zone de texte affiche le nom de la note jouée, permettant ainsi à l’utilisateur d’identifier la note jouée.

Sonde sonore

L’UNIHIKER est également équipé d’un microphone capable de capter l’intensité du bruit ambiant. Cette fonctionnalité permet de créer un dispositif de surveillance du bruit, affichant l’intensité du bruit ambiant à l’écran. De plus, un seuil de bruit peut être défini ; lorsqu’il est dépassé, un signal sonore retentit pour vous avertir. Voici un exemple de dispositif de surveillance du bruit :

Documentation sur la sonde sonore

from pinpong.extension.unihiker import *
from pinpong.board import Board,Pin
from unihiker import Audio
from unihiker import GUI

Board().begin()

# Instantiation des objets audio et interface
audio = Audio()
gui = GUI()
# Titre du dispositif
gui.draw_text(text="Sonde sonore",x=120,y=50,font_size=20, color="#0000FF", origin="center")
# Affichage du niveau sonore
sound_text = gui.draw_text(text="",x=120,y=170,font_size=55, color="#0000FF", origin="center")

while True:
    # Récupération du niveau sonore et son affichage
    sound_value = audio.sound_level()
    sound_text.config(text=sound_value, color="#0000FF")

    # Déctection du niveau sonore
    if (sound_value > 50):
        # Alerte visuelle et sonore
        sound_text.config(color="#FF0000")
        buzzer.pitch(392)
        time.sleep(0.1)
        buzzer.stop()
        # On laisse le niveau sonore retomber avant de le mesurer à nouveau
        time.sleep(1)

Dans cet exemple, l’UNIHIKER est initialisé avec la fonction Board().begin().

Ensuite, un objet Audio et un objet GUI sont instanciés, et deux objets texte sont créés avec la fonction draw_text(). Ces objets texte affichent respectivement la surveillance du bruit et les valeurs de bruit correspondantes.

Dans la boucle principale, la méthode sound_level() de l’objet Audio permet d’obtenir l’intensité sonore ambiante, puis la méthode config() de l’objet texte permet de mettre à jour la valeur de luminosité à l’écran. Parallèlement, l’intensité sonore est vérifiée pour vérifier si elle dépasse le seuil défini. Si tel est le cas, la fonction buzzer.pitch(frequency) émet une alarme sonore, puis la fonction buzzer.stop() désactive le buzzer.

Compteur de sauts

L’UNIHIKER est également équipé d’un accéléromètre et d’un gyroscope 6 axes, capables de lire les valeurs x, y et z de l’accéléromètre et du gyroscope individuellement. Cette fonctionnalité permet de créer un compteur de saut : les valeurs de l’accéléromètre et du gyroscope s’affichent à l’écran, et le nombre de saut est calculé et affiché en fonction de l’intensité de l’accélération.

Documentation sur l’accéléromètre et le gyroscope

from pinpong.extension.unihiker import *
from pinpong.board import Board,Pin
from unihiker import GUI
import time

# Chronomètre du temps du jeu
chrono = 0
# Compteur de sauts
value = 0

# Réinitialisation des compteurs avec le bouton A
def on_buttona_click_callback():
    global chrono
    global value
    chrono = 0
    value = 0

# Initialisation de la carte et de l'interface
Board().begin()
gui = GUI()

# Affichage des données
gui.draw_text(text="Accéléromètre",x=10,y=5,font_size=16, color="#0000FF")
gui.draw_text(text="Gyroscope",x=10,y=105,font_size=16, color="#0000FF")
gui.draw_text(text="Compteur de sauts",x=10,y=210,font_size=16, color="#0000FF")
accelerometer_x = gui.draw_text(text="X:",x=30,y=35,font_size=12, color="#000000")
accelerometer_y = gui.draw_text(text="Y:",x=30,y=60,font_size=12, color="#000000")
accelerometer_z = gui.draw_text(text="Z:",x=30,y=85,font_size=12, color="#000000")
gyroscope_x = gui.draw_text(text="X:",x=30,y=135,font_size=12, color="#000000")
gyroscope_y = gui.draw_text(text="Y:",x=30,y=160,font_size=12, color="#000000")
gyroscope_z = gui.draw_text(text="Z:",x=30,y=185,font_size=12, color="#000000")
pedometer=gui.draw_text(text=value,x=30,y=230,font_size=45, color="#000000")

# Attente appui bouton A pour commmencer
gui.wait_a_click()

# Initialisation pour interception l'appui sur le bouton A
gui.on_a_click(on_buttona_click_callback)

while True:
    # Récupération des mouvements par l'accéléromètre et le gyroscope
    accelerometer_x.config(text=(str("X:") + str(accelerometer.get_x())))
    accelerometer_y.config(text=(str("Y:") + str(accelerometer.get_y())))
    accelerometer_z.config(text=(str("Z:") + str(accelerometer.get_z())))
    gyroscope_x.config(text=(str("X:") + str(gyroscope.get_x())))
    gyroscope_y.config(text=(str("Y:") + str(gyroscope.get_y())))
    gyroscope_z.config(text=(str("Z:") + str(gyroscope.get_z())))

    # Comptage de sauts
    if (accelerometer.get_strength() > 1.5):
        value = (value + 1)
    
    # Affichage des sauts et du chronomètre
    pedometer.config(text=str(value) + "/" + str(int(chrono)))
    time.sleep(0.1)
    chrono +=0.1

Dans cet exemple, l’UNIHIKER est initialisé avec la fonction Board().begin() et un objet GUI est instancié.
Ensuite, grâce à la méthode draw_text(), plusieurs objets texte sont créés pour afficher les valeurs d’accélération, de gyroscope et de nombre de pas, ainsi que leurs valeurs correspondantes.

Le programme principal utilise accelerometer.get_x(), accelerometer.get_y() et accelerometer.get_z() pour obtenir les valeurs x, y et z de l’accélération, et gyroscope.get_x(), gyroscope.get_y() et gyroscope.get_z() pour les valeurs x, y et z du gyroscope. Ces valeurs sont ensuite affichées à l’écran grâce à la méthode config() de l’objet texte.

De plus, le nombre de saut est calculé à l’aide de la fonction accelerometer.get_strength() et incrémenté de 1 lorsque l’intensité d’accélération dépasse 1,5.

Le nombre de sauts est affiché à l’écran avec le chronomètre via la méthode config() de l’objet texte.

Catégories
PAGES MEMBRES

Protégé : ADA LOVELACE

Cette publication est protégée par un mot de passe. Pour la voir, veuillez saisir votre mot de passe ci-dessous :

Catégories
MICRO PYTHON MICRO:BIT

Bataille navale Micro:bit

🚀 Mission : Détruire les navires ennemis et rester le dernier survivant !

Principe du jeu

Votre objectif ? Couler les navires adverses et être le dernier joueur encore en lice ! Chaque micro:bit représente un champ de bataille : à vous de viser juste.

Comment ça marche ?

  • Un navire caché : Dès que vous allumez votre micro:bit, un navire apparaît aléatoirement sur la grille de LEDs (reconnaissable à sa lumière plus faible).
  • Un missile à guider : La LED la plus brillante, c’est votre missile ! Inclinez votre micro:bit (avant/arrière, gauche/droite) pour le déplacer et viser l’ennemi.
  • Prêt à tirer ?
    • Bouton A : Figez la position de votre missile pour ajuster votre tir.
    • Bouton B : FEU ! Envoyez votre missile vers les adversaires.
  • Touché ! Si votre missile atteint un navire, la micro:bit de la victime joue une musique de défaite… mais attention, elle reviendra en jeu après un délai ! À vous de la neutraliser à nouveau.

💻 À vous de coder ! Pour créer ce jeu, voici les fonctionnalités clés à programmer :

  1. Communication radio : Envoyez et recevez les coordonnées (ligne/colonne) des tirs entre toutes les micro:bits du jeu.
  2. Contrôle du missile : Utilisez l’accéléromètre pour déplacer le missile en inclinant la carte.
  3. Gestion des tirs :
    • Bouton A : Verrouillez la position du missile.
    • Bouton B : Lancez le tir et transmettez les coordonnées aux autres joueurs.
  4. Position aléatoire du navire : À chaque début de partie, le navire apparaît à un endroit aléatoire.
  5. Détection de collision : Si un missile touche un navire, affichez une croix et déclenchez une musique de défaite.
  6. Temps de réapparition : Un navire touché réapparaît après quelques secondes : soyez prêt à recommencer !

💡 Pourquoi c’est génial ?

  • Un jeu multijoueur : Affrontez vos amis en temps réel !
  • De la stratégie : Mémorisez les tirs et neutralisez vos adversaires.
  • Un projet complet : Codez la logique, l’affichage des LEDs, les sons et la communication entre cartes.

🛠️ Prêt à relever le défi ? Avec la micro:bit, vous allez apprendre à : ✔ Utiliser des capteurs (accéléromètre, boutons). ✔ Programmer l’affichage des LEDs et des sons. ✔ Faire communiquer plusieurs cartes entre elles.

À vos micro:bits ! Qui sera le dernier survivant ? 🎮💥

Le champ de bataille :

Ton navire : LED reconnaissable à sa lumière plus faible.

Ton missile : la LED la plus brillante

Déplace ton missile penche à droite/gauche

En avant / en arrière

Bouton A : fige le tir

Bouton B : Lance le missile

Touché

Programme en mode bloc

sous vittascience : https://fr.vittascience.com/microbit

Un exemple de programmation pour émettre les coordonnées x, y du missile et les recevoir :

Pour tester si le bouton B est relâché :

Pour gérer le roulis (droite/gauche) :

Pour gérer le tangage (avant/arrière) :

Pour gérer l’affichage de la position du missile :

Pour gérer l’affichage aléatoire du navire :

Puis dans Répéter indéfiniment :

Si touché :

Pour figer la cible avec le bouton A, avec une variable emettre :

  • emettre = 0 : réglage de la cible
  • emettre = 1 : cible figée

Le bouton A fige la position du tir :

Programme en python

Librairie à importer :

from microbit import *
import radio
import random
import math
import music

Pour configurer la radio :

radio.on()
radio.config(channel = 83, power = 6, length = 32, group=5)

Fonction pour émettre les coordonnées pour correspondre au programme en mode bloc :

def radio_sendValue(name, value):
    radio.send("&&&" + "int:" + "[" + name + ";" + str(value) + "]&&&")

Fonction pour recevoir les coordonnées pour correspondre au programme en mode bloc :

def radio_receiveValue():
    data = radio.receive()

    if data:
        print("receive", data)
        parseData = data[8:-4].split(';')
        return parseData[0], int(parseData[1])
    else:
        return None, None

Pour afficher une image de LEDs :

led_image = Image('00000:00000:00000:00000:00000')
display.show(led_image)

Affichage d’une LED :

 display.set_pixel(x, y, 9)
 display.set_pixel(x_cible, y_cible, 4)

pour générer un nombre aléatoire :

x_cible = random.randint(0, 4)
y_cible = random.randint(0, 4)

Affichage d’une croix :

display.show(Image.NO)

Affichage signe envoyé :

display.show(Image.YES)

Gestion des boutons A et B :

if button_a.is_pressed():
    while not (not button_a.is_pressed()):
        pass

Gestion de l’accéléromètre :

if (
   math.atan2(
       accelerometer.get_x(),
       math.sqrt(accelerometer.get_y()**2 + accelerometer.get_z()**2)
       ) * 180.0 / math.pi > 30
   ):
   x = 4
if (
   math.atan2(
       accelerometer.get_y(), -accelerometer.get_z()) *
       180.0 / math.pi > 30
   ):
   y = 4

Lancement de la musique :

music.play(music.JUMP_DOWN, loop=False)
Catégories
PAGES MEMBRES

Protégé : ZAYD NASIRI

Cette publication est protégée par un mot de passe. Pour la voir, veuillez saisir votre mot de passe ci-dessous :

Catégories
PAGES MEMBRES

Protégé : YASSINE BAH

Cette publication est protégée par un mot de passe. Pour la voir, veuillez saisir votre mot de passe ci-dessous :

Catégories
PAGES MEMBRES

Protégé : THOMAS LASSERE

Cette publication est protégée par un mot de passe. Pour la voir, veuillez saisir votre mot de passe ci-dessous :

Catégories
PAGES MEMBRES

Protégé : THIBAUT COMBES

Cette publication est protégée par un mot de passe. Pour la voir, veuillez saisir votre mot de passe ci-dessous :