2023-05-20 19:49:56 +02:00
import bge # Bibliothèque Blender Game Engine (BGE)
import serial # Liaison série
import labyrinthe_carte # Liaison avec la carte
###############################################################################
# 6-labyrinthe.py
# @title: Module (unique) de la scène 3D du labyrinthe à bille
# @project: Blender-EduTech - Tutoriel 6 : Labyrinthe à bille - Développer le jumeau numérique du labyrinthe
# @lang: fr
# @authors: Philippe Roy <philippe.roy@ac-grenoble.fr>
# @copyright: Copyright (C) 2023 Philippe Roy
# @license: GNU GPL
#
# Commandes déclenchées par UPBGE pour le scène du labyrinthe
#
###############################################################################
# Récupérer la scène 3D
scene = bge . logic . getCurrentScene ( )
# print("Objets de la scene : ", scene.objects) # Lister les objets de la scène
# Constantes
JUST_ACTIVATED = bge . logic . KX_INPUT_JUST_ACTIVATED
JUST_RELEASED = bge . logic . KX_INPUT_JUST_RELEASED
ACTIVATE = bge . logic . KX_INPUT_ACTIVE
# Communication avec la carte Arduino
# serial_baud=115200
# # serial_comm = serial.Serial('COM4',serial_baud, timeout=0.016) # Windows
# serial_comm = serial.Serial('/dev/ttyACM1',serial_baud, timeout=0.016) # GNU/Linux
# print (serial_comm)
# Détection de la carte avec la liaison série
serial_comm = labyrinthe_carte . init_serial ( )
if serial_comm is None :
bge . logic . endGame ( )
###############################################################################
# Gestion de la centrale inertielle (capteur IMU (inertial measurement unit))
# Les valeurs du capteur sont transmises en degré.
# Les valeurs de l'inclinaison du plateau dans UPBGE sont à fournir en radian.
###############################################################################
# Lecture du capteur IMU
def capteur ( cont ) :
obj = cont . owner # obj est l'objet associé au contrôleur donc 'Plateau'
obj_bille = scene . objects [ ' Bille ' ]
ecart = 0.001 # Écart maxi sur la rotation
# Touche ESC -> Quitter
keyboard = bge . logic . keyboard
if keyboard . inputs [ bge . events . ESCKEY ] . status [ 0 ] == ACTIVATE :
serial_comm . close ( )
bge . logic . endGame ( )
# Lecture de la liaison série : programme Arduino : 4-labyrinthe-imu.ino
serial_msg_in = str ( serial_comm . readline ( ) )
2023-10-18 00:09:25 +02:00
# # Mettre la bille à la position de départ avec une vitesse nulle
# if serial_msg_in.find("start")>0:
# if obj_bille['victoire'] or obj_bille['chute']:
# depart()
2023-05-20 19:49:56 +02:00
2023-10-18 00:09:25 +02:00
# Roll et Pitch : copier la position du plateau réel
2023-10-19 06:35:49 +02:00
# FIXME : sensible aux vibrations -> lissage
2023-05-20 19:49:56 +02:00
if serial_msg_in . find ( " , " ) > 0 :
txt = serial_msg_in . split ( ' , ' , 2 )
x_txt = txt [ 0 ] [ 2 : ]
y_txt = txt [ 1 ] [ : - 5 ]
if x_txt != " NAN " and y_txt != " NAN " : # NAN : Not A Number
2023-10-19 06:35:49 +02:00
x = - ( float ( x_txt ) / 57.3 ) # 57,3 = 360 / (2 * pi)
y = ( float ( y_txt ) / 57.3 ) # 57,3 = 360 / (2 * pi)
obj [ ' angle_x ' ] = x * 57.3
obj [ ' angle_y ' ] = y * 57.3
2023-05-20 19:49:56 +02:00
while abs ( x - obj . worldOrientation . to_euler ( ) . x ) > ecart :
obj . applyRotation ( ( x - obj . worldOrientation . to_euler ( ) . x , 0 , - obj . worldOrientation . to_euler ( ) . z ) , False )
while abs ( y - obj . worldOrientation . to_euler ( ) . y ) > ecart :
obj . applyRotation ( ( 0 , y - obj . worldOrientation . to_euler ( ) . y , - obj . worldOrientation . to_euler ( ) . z ) , False )
###############################################################################
# Gameplay
###############################################################################
# Initialisation de la scène
def init ( cont ) :
obj = cont . owner # obj est l'objet associé au contrôleur donc 'Bille'
# Mémorisation de la position de départ de la bille
obj [ ' init_x ' ] = obj . worldPosition . x
obj [ ' init_y ' ] = obj . worldPosition . y
obj [ ' init_z ' ] = obj . worldPosition . z
# Cacher le panneau de la victoire et suspendre la physique du panneau cliquable
scene . objects [ ' Panneau victoire ' ] . setVisible ( False , True )
scene . objects [ ' Panneau victoire - plan ' ] . suspendPhysics ( True )
scene . objects [ ' Bouton fermer ' ] . color = ( 0 , 0 , 0 , 1 ) # Noir
# Cycle (boucle de contrôle de la bille)
def cycle ( cont ) :
obj = cont . owner # obj est l'objet associé au contrôleur donc 'Bille'
obj [ ' z ' ] = obj . worldPosition . z # la propriété z est mis à jour avec la position globale en z de la bille
2023-10-18 00:09:25 +02:00
# # Écriture de la position de la bille sur la liaison série
# if obj['victoire']==False and obj['chute']==False:
# # obj['x'] = obj.worldPosition.x # de -3.5 à 3.5
# # obj['y'] = obj.worldPosition.y # de 3.5 à -3.5
# obj['Lx']=-1*round(obj.worldPosition.x-3.5) # de 7 à 0
# if obj['Lx']<0: obj['Lx']=0
# if obj['Lx']>7: obj['Lx']=7
# obj['Ly']=-1*round(obj.worldPosition.y-3.5) # de 0 à 7
# if obj['Ly']<0: obj['Ly']=0
# if obj['Ly']>7: obj['Ly']=7
# serial_msg_out = str(obj['Lx'])+str(obj['Ly'])+"\n"
# serial_comm.write(serial_msg_out.encode())
2023-10-19 06:35:49 +02:00
# Si l'altitude de bille < -10 et pas de victoire -> chute
if obj [ ' z ' ] < - 10 and obj [ ' victoire ' ] == False :
2023-10-18 00:09:25 +02:00
# # Afficher image de chute sur la matrice de leds
# serial_msg_out = "91\n"
# serial_comm.write(serial_msg_out.encode())
2023-10-19 06:35:49 +02:00
obj [ ' chute ' ] = True
depart ( )
2023-05-20 19:49:56 +02:00
# Départ de la bille
def depart ( ) :
obj_bille = scene . objects [ ' Bille ' ]
obj_plateau = scene . objects [ ' Plateau ' ]
2023-10-18 00:09:25 +02:00
# # Replacement du plateau (tous les angles à 0 en plusieurs fois)
# while obj_plateau.worldOrientation.to_euler().x != 0 and obj_plateau.worldOrientation.to_euler().y !=0 and obj_plateau.worldOrientation.to_euler().z !=0 :
# obj_plateau.applyRotation((-obj_plateau.worldOrientation.to_euler().x, -obj_plateau.worldOrientation.to_euler().y, -obj_plateau.worldOrientation.to_euler().z), False)
2023-05-20 19:49:56 +02:00
# Mettre la bille à la position de départ avec une vitesse nulle
obj_bille . worldLinearVelocity = ( 0 , 0 , 0 )
obj_bille . worldAngularVelocity = ( 0 , 0 , 0 )
obj_bille . worldPosition . x = obj_bille [ ' init_x ' ]
obj_bille . worldPosition . y = obj_bille [ ' init_y ' ]
obj_bille . worldPosition . z = obj_bille [ ' init_z ' ] + 0.5 # On repose la bille
obj_bille [ ' victoire ' ] = False
obj_bille [ ' chute ' ] = False
# Victoire (collision de la bille avec l'arrivée)
def victoire ( cont ) :
2023-10-18 00:09:25 +02:00
# # Afficher image de victoire sur la matrice de leds
# serial_msg_out = "92\n"
# serial_comm.write(serial_msg_out.encode())
# scene.objects['Bille']['victoire']=True
2023-05-20 19:49:56 +02:00
# Animation du Panneau victoire
scene . objects [ ' Panneau victoire ' ] . setVisible ( True , True ) # Afficher le panneau de la victoire
scene . objects [ ' Panneau victoire - plan ' ] . restorePhysics ( ) # Restaurer la physique du panneau cliquable
start = 1
end = 100
layer = 0
priority = 1
blendin = 1.0
mode = bge . logic . KX_ACTION_MODE_PLAY
layerWeight = 0.0
ipoFlags = 0
speed = 1
scene . objects [ ' Panneau victoire ' ] . playAction ( ' Panneau victoireAction ' , start , end , layer , priority , blendin , mode , layerWeight , ipoFlags , speed )
# Highlight du bouton Fermer
def victoire_fermer_hl ( cont ) :
obj = cont . owner
# Activation
if cont . sensors [ ' MO ' ] . status == JUST_ACTIVATED :
obj . color = ( 1 , 1 , 1 , 1 ) # Blanc
# Désactivation
if cont . sensors [ ' MO ' ] . status == JUST_RELEASED :
obj . color = ( 0 , 0 , 0 , 1 ) # Noir
# Fermer le panneau de la victoire (clic)
def victoire_fermer ( cont ) :
if cont . sensors [ ' Click ' ] . status == JUST_ACTIVATED and cont . sensors [ ' MO ' ] . positive :
scene . objects [ ' Panneau victoire ' ] . setVisible ( False , True ) # Cacher le panneau de la victoire
scene . objects [ ' Panneau victoire - plan ' ] . suspendPhysics ( True ) # Suspendre la physique du panneau cliquable
depart ( )