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 # @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')