import bge # Blender Game Engine (UPBGE) import aud # Sounds import threading # Multithreading import trace import sys import time import math import mathutils import random ############################################################################### # rp_lib.py # @title: Bibliothèque du Robot Ropy (rp_*) # @project: Ropy (Blender-EduTech) # @lang: fr # @authors: Philippe Roy # @copyright: Copyright (C) 2020-2022 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 algorithmiques de base et à les coder en Python. # ############################################################################### scene = bge.logic.getCurrentScene() # Colors purple = (0.202, 0.114, 0.521,1) turquoise = (0.051, 0.270, 0.279,1) magenta = (0.799, 0.005, 0.314,1) orange = (0.799, 0.130, 0.063,1) yellow = (0.799, 0.617, 0.021, 1) green = (0.246, 0.687, 0.078, 1) red = (0.799, 0.031, 0.038, 1) blue = (0.127, 0.456, 1.000, 1) black = (0, 0, 0, 1) color_text = (0, 0, 0, 1) # Noir color_text_red = (0.799, 0.031, 0.038, 1) color_text_orange = (0.799, 0.176, 0.054, 1) color_text_yellow = (0.799, 0.617, 0.021, 1) # ray_yellow = (0.799, 0.617, 0.021, 1) # [0.8, 0.619, 0.021]) # ray_blue = (0.127, 0.456, 1.000, 1) # ray_black = (0, 0, 0, 1) color_kaykit_black = (0.019, 0.032, 0.037, 1) # Sounds # audiodev = aud.Device() # snd_build = aud.Sound('asset/sounds/build.wav') # sndbuff_build = aud.Sound.cache(snd_build) # snd_archer = aud.Sound('asset/sounds/archer.wav') # sndbuff_archer = aud.Sound.cache(snd_archer) # snd_mage = aud.Sound('asset/sounds/mage.wav') # sndbuff_mage = aud.Sound.cache(snd_mage) # snd_life = aud.Sound('asset/sounds/life.ogg') # sndbuff_life = aud.Sound.cache(snd_life) threads_cmd=[] debug_thread = scene.objects['Terrain']['debug_thread'] # UPBGE constants JUST_ACTIVATED = bge.logic.KX_INPUT_JUST_ACTIVATED JUST_RELEASED = bge.logic.KX_INPUT_JUST_RELEASED ACTIVATE = bge.logic.KX_INPUT_ACTIVE # JUST_DEACTIVATED = bge.logic.KX_SENSOR_JUST_DEACTIVATED ############################################################################### # Méthode kill pour les tâches (threads) ############################################################################### class thread_with_trace(threading.Thread): def __init__(self, *args, **keywords): threading.Thread.__init__(self, *args, **keywords) self.killed = False def start(self): self.__run_backup = self.run self.run = self.__run threading.Thread.start(self) def __run(self): sys.settrace(self.globaltrace) self.__run_backup() self.run = self.__run_backup def globaltrace(self, frame, event, arg): if event == 'call': return self.localtrace else: return None def localtrace(self, frame, event, arg): if self.killed: if event == 'line': raise SystemExit() return self.localtrace def kill(self): self.killed = True ############################################################################### # Start et stop des tâches (threads) ############################################################################### def thread_start(threads, type_txt, fct): threads.append(thread_with_trace(target = fct)) threads[len(threads)-1].start() if (debug_thread): print ("Thread",type_txt, "#", len(threads)-1, "open.") def thread_stop(threads, type_txt): i=0 zombie_flag=False for t in threads: if not t.is_alive(): if (debug_thread): print ("Thread",type_txt, "#",i,"closed.") else: if (debug_thread): print ("Thread",type_txt, "#",i,"still open ...") t.kill() t.join() if not t.is_alive(): if (debug_thread): print ("Thread",type_txt, "#",i,"killed.") else: if (debug_thread): print ("Thread",type_txt, "#",i,"zombie...") zombie_flag=True i +=1 if zombie_flag==False: if (debug_thread): print ("All threads",type_txt, "are closed.") scene.objects['Terrain']['thread_cmd']=False return True else: if (debug_thread): print ("There are zombies threads",type_txt, ".") return False def thread_cmd_start(fct): thread_start(threads_cmd, "commands", fct) def thread_cmd_stop(): thread_stop(threads_cmd, "commands") def rp_end(): if (debug_thread): print ("Thread commands is arrived.") scene.objects['Terrain']['thread_cmd']=False def rp_fin(): rp_end() def rp_quit(): rp_end() ############################################################################### # Sounds ############################################################################### # FIXME : Sound crash in Windows (very strange : blender, UPBGE, python ?), no music for Bill def sound_play (sound): if scene.objects['Commands']['sound'] and sys.platform!="win32": audiodev.play(sound) ############################################################################### # Rover fonction élèves ############################################################################### ## # Avancer le rover ## def rp_avancer (): print ("rp_avancer()") step =1 obj=scene.objects['Rover'] # print (obj.worldOrientation.to_euler().z) x0 = obj.worldPosition.x y0 = obj.worldPosition.y z0 = obj.worldPosition.z if round(obj.worldOrientation.to_euler().z, 2) == 0.00: # Sud obj.worldPosition=[x0, y0-step, z0] if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi,2) or round(obj.worldOrientation.to_euler().z, 2) == - round(math.pi,2) : # Nord obj.worldPosition=[x0, y0+step, z0] if round(obj.worldOrientation.to_euler().z, 2) == round(math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == -round(3*(math.pi/2),2) : # Est obj.worldPosition=[x0+step, y0, z0] if round(obj.worldOrientation.to_euler().z, 2) == round(-math.pi/2,2) or round(obj.worldOrientation.to_euler().z, 2) == round(3*(math.pi/2),2) : # Ouest obj.worldPosition=[x0-step, y0, z0] rp_tempo (0.1) ## # Tourner à gauche ## def rp_gauche (): print ("rp_gauche()") step=math.pi/2 # Pas angulaire obj=scene.objects['Rover'] obj.applyRotation((0, 0, step), True) rp_tempo (0.1) ## # Tourner à droite ## def rp_droite (): print ("rp_droite()") step=math.pi/2 # Pas angulaire obj=scene.objects['Rover'] obj.applyRotation((0, 0, -step), True) rp_tempo (0.1) ## # Marquer ## def rp_marquer (): rp_tempo (0.1) print ("rp_marquer()") obj=scene.objects['Rover'] x = obj.worldPosition.x y = obj.worldPosition.y z = obj.worldPosition.z # Vérification de l'absence de balise sur la tuile if [x,y] in scene.objects['Terrain']['map_tile_beacon'] : print ("Case déjà marquée !") return False for i in range (100): beacon = scene.objects["Beacon-"+str(i)] if beacon['activated']==False: beacon.worldPosition=[x,y,0.2] beacon['activated']=True beacon.setVisible(True, True) break if i ==99 : print ("Plus de balise disponible !") # beacon= scene.addObject("Beacon", scene.objects['Terrain']) # beacon.worldPosition=[x,y,0.2] scene.objects['Terrain']['map_tile_beacon'].append([x,y]) rp_tempo (0.1) return True ## # Détecter ## def rp_detect (): print ("rp_detect") # FIXME ## # Prendre ## def rover_prendre (): print ("rp_prendre") # FIXME ## # Radar ## def rover_radar (): print ("rp_radar") # FIXME ############################################################################### # Rover ############################################################################### ## # Colision ## def rover_colision (): pass ############################################################################### # Temporisation ############################################################################### def rp_sleep (duration): time.sleep(duration) def rp_tempo (duration): # time.sleep(duration*(1/scene.objects['Commands']['speed'])) scene.objects['Commands']['time']=0 while scene.objects['Commands']['time']