mirror of
https://forge.apps.education.fr/blender-edutech/ropy.git
synced 2024-01-27 08:23:20 +01:00
318 lines
13 KiB
Python
318 lines
13 KiB
Python
|
import bge # Bibliothèque Blender Game Engine (BGE)
|
||
|
import math
|
||
|
import time
|
||
|
|
||
|
###############################################################################
|
||
|
# ropy_lib.py
|
||
|
# @title: Bibliothèque du Robot Ropy (rp_*)
|
||
|
# @project: Blender-EduTech
|
||
|
# @lang: fr
|
||
|
# @authors: Philippe Roy <philippe.roy@ac-grenoble.fr>
|
||
|
# @copyright: Copyright (C) 2020-2021 Philippe Roy
|
||
|
# @license: GNU GPL
|
||
|
#
|
||
|
# Bibliothèque des actions du robot
|
||
|
# Bibliothèque pour la construction des murs
|
||
|
#
|
||
|
# Ropy est destiné à la découverte de la programmation procédurale et du language Python.
|
||
|
# A travers plusieurs challenges, donc de manière graduée, les élèves vont apprendre à manipuler les structures algoritmiques de base et à les coder en Python.
|
||
|
#
|
||
|
###############################################################################
|
||
|
|
||
|
# Récupérer l'objet robot
|
||
|
|
||
|
cont = bge.logic.getCurrentController()
|
||
|
obj = cont.owner
|
||
|
scene = bge.logic.getCurrentScene()
|
||
|
nb_objets_fixes = len(scene.objects)
|
||
|
# print ("Nombre d'objets fixes de la scene : ", nb_objets_fixes)
|
||
|
print("Objets de la scene : ", scene.objects)
|
||
|
|
||
|
# Configuration des mouvements
|
||
|
|
||
|
pas=3 # Pas linéaire
|
||
|
pas_rot=math.pi/2 # Pas angulaire
|
||
|
|
||
|
###############################################################################
|
||
|
# Initialisation de la position du robot
|
||
|
###############################################################################
|
||
|
|
||
|
# Position initiale du robot
|
||
|
def rp_init_position():
|
||
|
x = obj['x_init']
|
||
|
y = obj['y_init']
|
||
|
obj.worldPosition.x = -((y-4.5)*3)+3
|
||
|
obj.worldPosition.y = (x-5.5)*3
|
||
|
obj.worldPosition.z = 1.25
|
||
|
print('\x1b[6;30;47m', "Placer le robot case (X,Y) :", x, y, '\x1b[0m')
|
||
|
|
||
|
# Pile des mouvements
|
||
|
# obj['mvts'] = ""
|
||
|
# obj['mvt_i'] = 0
|
||
|
|
||
|
# Répérer le robot détruit
|
||
|
if obj['detruit']:
|
||
|
start = 300
|
||
|
end = start+75
|
||
|
layer = 0
|
||
|
priority = 1
|
||
|
blendin = 1.0
|
||
|
mode = bge.logic.KX_ACTION_MODE_PLAY
|
||
|
layerWeight = 0.0
|
||
|
ipoFlags = 0
|
||
|
speed = 3
|
||
|
scene.objects['Armature'].playAction('ArmatureAction.Saut.001', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
|
||
|
# scene.objects['Body'].playAction('BodyAction.Saut', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
|
||
|
# scene.objects['Eyes_glass'].playAction('Eyes_glassAction.Saut', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
|
||
|
# scene.objects['Mouth'].playAction('MouthAction.Saut', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
|
||
|
# scene.objects['Jetpack'].playAction('JetpackAction.Saut', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
|
||
|
scene.objects['poignee1'].playAction('poignee1Action.Saut', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
|
||
|
scene.objects['poignee2'].playAction('poignee2Action.Saut', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
|
||
|
scene.objects['poignee3'].playAction('poignee3Action.Saut', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
|
||
|
scene.objects['poignee4'].playAction('poignee4Action.Saut', start, end, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
|
||
|
obj['detruit']=False
|
||
|
|
||
|
###############################################################################
|
||
|
# Affichage
|
||
|
###############################################################################
|
||
|
|
||
|
#Afficher position
|
||
|
def rp_print_position():
|
||
|
print('\x1b[6;30;42m', "Position case (X,Y) : ", round(-obj.worldPosition.x/3+5.5), round(obj.worldPosition.y/3+5.5), '\x1b[0m')
|
||
|
|
||
|
###############################################################################
|
||
|
# Moteur physique
|
||
|
# Détection des colisions aves les murs
|
||
|
###############################################################################
|
||
|
|
||
|
# Détection d'une colision
|
||
|
# rpcore_ : fonction bas niveau
|
||
|
def rpcore_detect_mur(debug_flag=False):
|
||
|
|
||
|
# Vecteur du mouvement
|
||
|
init_x = round(obj.worldPosition.y/3+5.5)
|
||
|
init_y = round(-obj.worldPosition.x/3+5.5)
|
||
|
obj.applyMovement((0, -pas, 0), True)
|
||
|
final_x = round(obj.worldPosition.y/3+5.5)
|
||
|
final_y = round(-obj.worldPosition.x/3+5.5)
|
||
|
obj.applyMovement((0, pas, 0), True)
|
||
|
|
||
|
# Calcul du centre du mouvement
|
||
|
mov_xc =init_x + (final_x - init_x)/2-0.5
|
||
|
mov_yc =init_y + (final_y - init_y)/2-0.5
|
||
|
if debug_flag:
|
||
|
print('\x1b[6;30;47m', "Mouvement (X_init,Y_init,X_final,Y_final) : ", init_x,init_y, final_x,final_y, '\x1b[0m')
|
||
|
print('\x1b[6;30;47m', "Mouvement (xc,yc) : ", mov_xc, mov_yc, '\x1b[0m')
|
||
|
|
||
|
# Test sur les murs exterieurs (10x10)
|
||
|
if ((final_x <1) or (final_y <1) or (final_x >10) or (final_y >10)):
|
||
|
if debug_flag:
|
||
|
print ("Détection de mur : mur détecté")
|
||
|
return True
|
||
|
|
||
|
# Test sur les murs intéreurs
|
||
|
else:
|
||
|
i=0
|
||
|
for mur in scene.objects:
|
||
|
i +=1
|
||
|
if mur.name=="Mur":
|
||
|
|
||
|
# Mur en X : calcul du centre du mur
|
||
|
if (round(mur.worldOrientation.to_euler().z,2) == round(math.pi,2)) or (round(mur.worldOrientation.to_euler().z,2) == round(-math.pi,2)):
|
||
|
mur_xc =mur['x1']
|
||
|
mur_yc =mur['y1']+0.5
|
||
|
|
||
|
# Mur en Y : calcul du centre du mur
|
||
|
elif (round(mur.worldOrientation.to_euler().z,2) == round(math.pi/2,2)) or (round(mur.worldOrientation.to_euler().z,2) == round(-math.pi/2,2)):
|
||
|
mur_xc =mur['x1']+0.5
|
||
|
mur_yc =mur['y1']
|
||
|
|
||
|
# Trace de debug
|
||
|
if debug_flag:
|
||
|
print('\x1b[6;30;47m', "Mur",mur['murId'],"X (x1,y1,x2,y2) : ", mur['x1'], mur['y1'], mur['x2'], mur['y2'], '\x1b[0m')
|
||
|
print('\x1b[6;30;47m', "Mur",mur['murId'],"Y (xc,yc) : ", mur_xc, mur_yc, '\x1b[0m')
|
||
|
|
||
|
# Même centre -> mouvement pas possible
|
||
|
if (mov_xc == mur_xc) and(mov_yc == mur_yc):
|
||
|
if debug_flag:
|
||
|
print ("Détection de mur : mur détecté")
|
||
|
return True
|
||
|
|
||
|
# Mouvement possible
|
||
|
if debug_flag:
|
||
|
print ("Détection de mur : pas de mur")
|
||
|
return False
|
||
|
|
||
|
|
||
|
# Fonction pour l'élève
|
||
|
def rp_detect_mur():
|
||
|
if rpcore_detect_mur() == True:
|
||
|
print('\x1b[6;30;45m', "Détection de mur : mur devant ! : Position case (X,Y): ", round(-obj.worldPosition.x/3+5.5), round(obj.worldPosition.y/3+5.5), '\x1b[0m')
|
||
|
return True
|
||
|
else:
|
||
|
print('\x1b[6;30;45m', "Détection de mur : voie libre : Position case (X,Y):", round(-obj.worldPosition.x/3+5.5), round(obj.worldPosition.y/3+5.5), '\x1b[0m')
|
||
|
return False
|
||
|
|
||
|
###############################################################################
|
||
|
# Mouvements
|
||
|
###############################################################################
|
||
|
|
||
|
# Avancer
|
||
|
def rp_avancer(debug_flag=False):
|
||
|
obj.visible=False
|
||
|
if obj['detruit']!=True:
|
||
|
|
||
|
# Vecteur du mouvement
|
||
|
init_x = round(obj.worldPosition.y/3+5.5)
|
||
|
init_y = round(-obj.worldPosition.x/3+5.5)
|
||
|
obj.applyMovement((0, -pas, 0), True)
|
||
|
final_x = round(obj.worldPosition.y/3+5.5)
|
||
|
final_y = round(-obj.worldPosition.x/3+5.5)
|
||
|
obj.applyMovement((0, pas, 0), True)
|
||
|
|
||
|
# Test des murs
|
||
|
if rpcore_detect_mur(debug_flag) == True:
|
||
|
print('\x1b[6;30;41m', "Avancer case (X,Y) -> case (X,Y) :", init_x,",",init_y,"->",final_x,",",final_y, '\x1b[0m')
|
||
|
print('\x1b[6;30;41m', "Bling, blang ... L'aventure de Ropy s'arrête donc ici ...", '\x1b[0m')
|
||
|
obj['mvts'] = obj['mvts']+"c"
|
||
|
obj['detruit']=True
|
||
|
else:
|
||
|
obj.applyMovement((0, -pas, 0), True)
|
||
|
obj['mvts'] = obj['mvts']+"a"
|
||
|
print('\x1b[6;30;42m', "Avancer case (X,Y) -> case (X,Y) :", init_x,",",init_y,"->",final_x,",",final_y, '\x1b[0m')
|
||
|
|
||
|
# Test de l'objectif
|
||
|
i=0
|
||
|
for objectif in scene.objects:
|
||
|
i +=1
|
||
|
if objectif.name=="Objectif":
|
||
|
if objectif['x'] == final_x and objectif['y'] == final_y:
|
||
|
print('\x1b[6;30;42m', "Objectif atteint", '\x1b[0m')
|
||
|
obj['mvts'] = obj['mvts']+"o"
|
||
|
|
||
|
# Tourner à droite
|
||
|
def rp_droite():
|
||
|
# obj.visible=False
|
||
|
if obj['detruit']!=True:
|
||
|
# scene.objects['Robot'].applyRotation((0, 0, -pas_rot), True)
|
||
|
obj.applyRotation((0, 0, -pas_rot), True)
|
||
|
obj['mvts'] = obj['mvts']+"d"
|
||
|
print('\x1b[6;30;42m', "Tourner à droite", '\x1b[0m')
|
||
|
# print("Orientation : ", obj.worldOrientation.to_euler().z)
|
||
|
|
||
|
# Tourner à gauche
|
||
|
def rp_gauche():
|
||
|
# obj.visible=False
|
||
|
if obj['detruit']!=True:
|
||
|
# scene.objects['Robot'].applyRotation((0, 0, pas_rot), True)
|
||
|
obj.applyRotation((0, 0, pas_rot), True)
|
||
|
obj['mvts'] = obj['mvts']+"g"
|
||
|
print('\x1b[6;30;42m', "Tourner à gauche", '\x1b[0m')
|
||
|
# print("Orientation : ", obj.worldOrientation.to_euler().z)
|
||
|
|
||
|
# Orienter
|
||
|
def rp_orientation(orientation):
|
||
|
if orientation=="nord":
|
||
|
obj.applyRotation((0, 0, -obj.worldOrientation.to_euler().z-math.pi/2), True)
|
||
|
if orientation=="sud":
|
||
|
obj.applyRotation((0, 0, -obj.worldOrientation.to_euler().z+math.pi/2), True)
|
||
|
if orientation=="est":
|
||
|
obj.applyRotation((0, 0, -obj.worldOrientation.to_euler().z+math.pi), True)
|
||
|
if orientation=="ouest":
|
||
|
obj.applyRotation((0, 0, -obj.worldOrientation.to_euler().z), True)
|
||
|
# print("Orientation : ", obj.worldOrientation.to_euler().z)
|
||
|
|
||
|
###############################################################################
|
||
|
# Marquage du sol
|
||
|
###############################################################################
|
||
|
|
||
|
# Marquer une case
|
||
|
def rp_marquer():
|
||
|
if obj['detruit']!=True:
|
||
|
obj['mvts'] = obj['mvts']+"m"
|
||
|
if obj['mvts_start'] ==False : # à condition d'avoir terminé le mouvement
|
||
|
marque1= scene.addObject("Marque", obj)
|
||
|
marque1.worldPosition.x = obj.worldPosition.x
|
||
|
marque1.worldPosition.y = obj.worldPosition.y
|
||
|
marque1.worldPosition.z = 0.2
|
||
|
# print('\x1b[6;30;43m', "Marquer case (X,Y) :", round(obj.worldPosition.y/3+5.5),",",round(-obj.worldPosition.x/3+5.5), '\x1b[0m')
|
||
|
|
||
|
# Enlever l'ensemble des murs et des marques
|
||
|
def rp_enlever_marques():
|
||
|
print ("")
|
||
|
print ("Table rase !")
|
||
|
for i in range (nb_objets_fixes, len(scene.objects)):
|
||
|
scene.objects[i].endObject()
|
||
|
|
||
|
###############################################################################
|
||
|
# Construction du niveau
|
||
|
###############################################################################
|
||
|
|
||
|
# Définition du niveau
|
||
|
def rp_niveau (niveau=0):
|
||
|
obj['level'] =niveau
|
||
|
|
||
|
# Construire les murs
|
||
|
# Longueur : fixe d' une case
|
||
|
# Position des murs : liste imbriquée : [[mur1_x1,mur1_y1,mur1_x2,mur1_y2],[mur2_x1,mur2_y1,mur2_x2,mur2_y2], ...]
|
||
|
# FIXME : verifier si les murs sont dans la zone 10x10
|
||
|
# FIXME : intervertir l'ordre des coordonnéees
|
||
|
# FIXME : verifier si le mur est d'une case
|
||
|
def rp_construire_murs (def_murs):
|
||
|
# print("Objets de la scene : ", scene.objects)
|
||
|
i=0
|
||
|
for def_mur in def_murs:
|
||
|
i +=1
|
||
|
# print (def_mur)
|
||
|
|
||
|
# Mur en X
|
||
|
if def_mur[0] == def_mur[2]:
|
||
|
mur1= scene.addObject("Mur", obj)
|
||
|
mur1['murId'] = i
|
||
|
mur1['x1'] = def_mur[0]
|
||
|
mur1['y1'] = def_mur[1]
|
||
|
mur1['x2'] = def_mur[2]
|
||
|
mur1['y2'] = def_mur[3]
|
||
|
# print ("mur ", 0)
|
||
|
# mur1.applyRotation((0, 0, -obj.worldOrientation.to_euler().z), True)
|
||
|
# mur1.applyRotation((0, 0, -math.pi/2), True)
|
||
|
# mur1.applyRotation((0, 0, -obj.worldOrientation.to_euler().z), True)
|
||
|
|
||
|
# mur1.worldOrientation.to_euler().z = 0
|
||
|
mur1.worldPosition.x = -((def_mur[1]-4.5)*3)
|
||
|
mur1.worldPosition.y = ((def_mur[0]-5.5)*3)+1.5
|
||
|
mur1.worldPosition.z = 1.5
|
||
|
print('\x1b[6;30;47m', "Construire mur X",mur1['murId'],"coordonnées (x1,y1,x2,y2) :", def_mur[0], def_mur[1], def_mur[2], def_mur[3], '\x1b[0m')
|
||
|
|
||
|
# Mur en Y
|
||
|
elif def_mur[1] == def_mur[3]:
|
||
|
mur2= scene.addObject("Mur", obj)
|
||
|
mur2['murId'] = i
|
||
|
mur2['x1'] = def_mur[0]
|
||
|
mur2['y1'] = def_mur[1]
|
||
|
mur2['x2'] = def_mur[2]
|
||
|
mur2['y2'] = def_mur[3]
|
||
|
# print ("mur ", -obj.worldOrientation.to_euler().z-math.pi/2)
|
||
|
mur2.applyRotation((0, 0, -obj.worldOrientation.to_euler().z-math.pi/2), True)
|
||
|
# print ("mur ", math.pi/2)
|
||
|
# mur2.applyRotation((0, 0, -math.pi), True)
|
||
|
# mur2.worldOrientation.to_euler().z = math.pi/2
|
||
|
|
||
|
mur2.worldPosition.x = -((def_mur[1]-5.5)*3)-1.5
|
||
|
mur2.worldPosition.y = ((def_mur[0]-4.5)*3)
|
||
|
mur2.worldPosition.z = 1.5
|
||
|
print('\x1b[6;30;47m', "Construire mur Y",mur2['murId'],"coordonnées (x1,y1,x2,y2) :", def_mur[0], def_mur[1], def_mur[2], def_mur[3], '\x1b[0m')
|
||
|
else:
|
||
|
print ('\x1b[6;30;41m', "Mur ni sur X ni sur Y !", '\x1b[0m')
|
||
|
|
||
|
# Marquer l'objectif
|
||
|
def rp_marquer_objectif (x,y):
|
||
|
objectif1= scene.addObject("Objectif", obj)
|
||
|
objectif1.worldPosition.x = -((y-4.5)*3)+3
|
||
|
objectif1.worldPosition.y = (x-5.5)*3
|
||
|
objectif1.worldPosition.z = 0.2
|
||
|
objectif1['x'] = x
|
||
|
objectif1['y'] = y
|
||
|
print('\x1b[6;30;47m', "Marquer l'objectif case (X,Y) :", x,y, '\x1b[0m')
|
||
|
|