mirror of
https://forge.apps.education.fr/blender-edutech/ropy.git
synced 2024-01-27 08:23:20 +01:00
new UI and threading
This commit is contained in:
parent
21f1bcedc5
commit
31197de25f
BIN
ropy-02.blend
Normal file
BIN
ropy-02.blend
Normal file
Binary file not shown.
877
rp.py
Normal file
877
rp.py
Normal file
@ -0,0 +1,877 @@
|
||||
import bge # Blender Game Engine (UPBGE)
|
||||
import bpy # Blender
|
||||
import aud # Sounds
|
||||
import math
|
||||
import mathutils
|
||||
import time
|
||||
import sys
|
||||
import os
|
||||
import webbrowser
|
||||
import threading # Multithreading
|
||||
import xml.etree.ElementTree as ET # Creating/parsing XML file
|
||||
import runpy
|
||||
|
||||
import rp_map1 as rp_map # waves script
|
||||
# import ct_doc # documentation
|
||||
# import ct_cmd # user script (commands)
|
||||
|
||||
###############################################################################
|
||||
# rp.py
|
||||
# @title: Ropy
|
||||
# @project: Ropy (Blender-EduTech)
|
||||
# @lang: fr
|
||||
# @authors: Philippe Roy <philippe.roy@ac-grenoble.fr>
|
||||
# @copyright: Copyright (C) 2020-2022 Philippe Roy
|
||||
# @license: GNU GPL
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Commands trigged by button : cmd_*
|
||||
# Commands trigged by 3D scene objects : scn_*
|
||||
# Commands trigged by user (student or map designer) : rp_*
|
||||
# 3D scene manipulation : manip_*
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
# Debug flag
|
||||
scene = bge.logic.getCurrentScene()
|
||||
scene.objects['Commands']['debug_fps']=False
|
||||
|
||||
# Memory
|
||||
sys.setrecursionlimit(10**5) # Limite sur la récursivité (valeur par défaut : 1000) -> segfault de Blender
|
||||
|
||||
# Dynamic import user file
|
||||
# importlib.invalidate_caches()
|
||||
# ct_map = importlib.import_module('ct_map1') # Waves script
|
||||
# ct_cmd = importlib.import_module('ct_cmd') # User script (commands) -> segfault de Blender
|
||||
|
||||
# UPBGE scene
|
||||
eevee = bpy.context.scene.eevee
|
||||
fps_time=0.0
|
||||
|
||||
# Config file
|
||||
# print (os.getcwd())
|
||||
rp_config = ET.parse('rp_config.xml')
|
||||
rp_config_tree = rp_config.getroot()
|
||||
|
||||
# Colors
|
||||
color_magenta = (0.800, 0.005, 0.315,1)
|
||||
color_orange = (0.799, 0.130, 0.063,1)
|
||||
color_white = (0.8, 0.8, 0.8, 1)
|
||||
color_yellow = (0.8, 0.619, 0.021, 1)
|
||||
color_black = (0, 0, 0, 1)
|
||||
|
||||
color_kaykit_black = (0.019, 0.032, 0.037, 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)
|
||||
|
||||
# Sounds
|
||||
audiodev = aud.Device()
|
||||
snd_click = aud.Sound('asset/sounds/click.ogg')
|
||||
sndbuff_click = aud.Sound.cache(snd_click)
|
||||
|
||||
# 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
|
||||
|
||||
###############################################################################
|
||||
# User interface : texte info et compteurs
|
||||
###############################################################################
|
||||
|
||||
##
|
||||
# Mise à jour de l'affichage des compteurs
|
||||
##
|
||||
|
||||
def points_maj (cont):
|
||||
|
||||
# Texte
|
||||
scene.objects['Points-Step-text']['Text']=str(scene.objects['Points']['step'])
|
||||
scene.objects['Points-Level-text']['Text']=str(scene.objects['Points']['level'])
|
||||
scene.objects['Points-Nbligne-text']['Text']=str(scene.objects['Points']['nbligne'])
|
||||
scene.objects['Points']['tics'] +=1
|
||||
|
||||
# Fin de la mission
|
||||
# FIXME
|
||||
|
||||
###############################################################################
|
||||
# Terrain
|
||||
###############################################################################
|
||||
|
||||
##
|
||||
# Mouse over du terrain
|
||||
##
|
||||
|
||||
def scn_terrain_mo (cont):
|
||||
pass
|
||||
|
||||
##
|
||||
# Initialisation lors du chargement du terrain
|
||||
##
|
||||
|
||||
def terrain_init ():
|
||||
|
||||
# Cacher les fenêtres
|
||||
|
||||
# Ajout du Hud
|
||||
scene.active_camera = scene.objects["Camera"]
|
||||
scene.objects['Sun'].setVisible(True,True)
|
||||
scene.addOverlayCollection(scene.cameras['Camera-Hud'], bpy.data.collections['Hud'])
|
||||
|
||||
# Configuration du moteur de rendu
|
||||
eevee.use_eevee_smaa = True
|
||||
|
||||
# Init de la carte
|
||||
rp_map.map_init()
|
||||
rp_map.map_reset()
|
||||
|
||||
##
|
||||
# Mise en route et pause du cycle
|
||||
##
|
||||
|
||||
def terrain_run ():
|
||||
sound_play (sndbuff_click)
|
||||
|
||||
# Pause
|
||||
# FIXME : HL alors que c'est avec les touches
|
||||
# FIXME : Stopper Ropy
|
||||
if scene.objects['Terrain']['run'] == True:
|
||||
scene.objects['Terrain']['run']=False
|
||||
scene.objects['Pause'].setVisible(False,False)
|
||||
scene.objects['Pause'].suspendPhysics()
|
||||
scene.objects['Pause-Hl'].setVisible(False,False)
|
||||
scene.objects['Run']. restorePhysics()
|
||||
scene.objects['Run-Hl'].setVisible(True,False)
|
||||
scene.objects['Cmd-text']['Text']= "Run (F5)"
|
||||
scene.objects['Cmd-text'].setVisible(True,False) # FIXME : suppresion de du message
|
||||
|
||||
# Run
|
||||
# FIXME : HL alors que c'est avec les touches
|
||||
else :
|
||||
scene.objects['Terrain']['run']=True
|
||||
scene.objects['Run'].setVisible(False,False)
|
||||
scene.objects['Run'].suspendPhysics()
|
||||
scene.objects['Run-Hl'].setVisible(False,False)
|
||||
scene.objects['Pause']. restorePhysics()
|
||||
scene.objects['Pause-Hl'].setVisible(True,False)
|
||||
scene.objects['Cmd-text']['Text']= "Pause (F5)"
|
||||
scene.objects['Cmd-text'].setVisible(True,False)
|
||||
|
||||
# Démarrage de la map
|
||||
if scene.objects['Terrain']['thread_run']==False:
|
||||
scene.objects['Stop'].setVisible(True,False)
|
||||
scene.objects['Stop']. restorePhysics()
|
||||
runpy.run_module('rp_cmd', run_name='stop') # Stop du script utilisateur
|
||||
|
||||
# Mise à zéro des compteurs
|
||||
rp_map.map_reset()
|
||||
|
||||
# Scripts utilisateur et vagues
|
||||
scene.objects['Terrain']['thread_run']=True
|
||||
runpy.run_module('rp_cmd', run_name='start') # Execution du script utilisateur
|
||||
|
||||
# Arrêt de la pause
|
||||
else:
|
||||
# FIXME : Relancer Ropy
|
||||
pass
|
||||
|
||||
##
|
||||
# Arrêt et réinitialisation du cycle
|
||||
##
|
||||
|
||||
def terrain_stop ():
|
||||
sound_play (sndbuff_click)
|
||||
|
||||
# Arrêt des threads utilisateurs
|
||||
scene.objects['Terrain']['run']=False
|
||||
scene.objects['Terrain']['thread_run']=False
|
||||
runpy.run_module('rp_cmd', run_name='stop') # Stop du script utilisateur
|
||||
|
||||
# Commandes
|
||||
scene.objects['Pause'].setVisible(False,False)
|
||||
scene.objects['Pause'].suspendPhysics()
|
||||
scene.objects['Pause-Hl'].setVisible(False,False)
|
||||
scene.objects['Run'].setVisible(True,False)
|
||||
scene.objects['Run']. restorePhysics()
|
||||
scene.objects['Stop'].setVisible(False,False)
|
||||
scene.objects['Stop'].suspendPhysics()
|
||||
scene.objects['Stop-Hl'].setVisible(False,False)
|
||||
scene.objects['Cmd-text'].setVisible(False,False)
|
||||
|
||||
##
|
||||
# Fin de la map
|
||||
##
|
||||
|
||||
def terrain_end ():
|
||||
scene.objects['Terrain']['run']=False
|
||||
scene.objects['Terrain']['thread_run']=False
|
||||
|
||||
# Commandes
|
||||
scene.objects['Pause'].setVisible(False,False)
|
||||
scene.objects['Pause-Hl'].setVisible(False,False)
|
||||
scene.objects['Run'].setVisible(True,False)
|
||||
scene.objects['Stop'].setVisible(False,False)
|
||||
scene.objects['Stop-Hl'].setVisible(False,False)
|
||||
|
||||
##
|
||||
# Vitesse du jeu
|
||||
##
|
||||
|
||||
def terrain_speed (obj):
|
||||
sound_play (sndbuff_click)
|
||||
speed_mode=[0.25, 0.5, 1,2,4,10]
|
||||
speed_mode_txt=["1/4", "1/2", "1", "2","4","10"]
|
||||
i=speed_mode.index(scene.objects['Terrain']['speed'])
|
||||
|
||||
# Affichage
|
||||
if obj.name=="Speed_up" and i<5:
|
||||
scene.objects['Terrain']['speed']=speed_mode[i+1]
|
||||
scene.objects['Text_speed']['Text']=speed_mode_txt[i+1]
|
||||
if obj.name=="Speed_down" and i>0:
|
||||
scene.objects['Terrain']['speed']=speed_mode[i-1]
|
||||
scene.objects['Text_speed']['Text']=speed_mode_txt[i-1]
|
||||
|
||||
# Maj du fichier de config (vitesse du jeu : data/config/speed)
|
||||
rp_config_tree[0][0].text=str(scene.objects['Terrain']['speed'])
|
||||
buffer_xml = ET.tostring(rp_config_tree)
|
||||
with open("rp_config.xml", "wb") as f:
|
||||
f.write(buffer_xml)
|
||||
|
||||
###############################################################################
|
||||
# Sons
|
||||
###############################################################################
|
||||
|
||||
def sound_play (sound):
|
||||
if scene.objects['Commands']['sound']:
|
||||
audiodev.play(sound)
|
||||
|
||||
def sound_set ():
|
||||
scene.objects['NoSound-cmd'].suspendPhysics()
|
||||
scene.objects['NoSound-cmd'].setVisible(False,False)
|
||||
scene.objects['NoSound-cmd-Hl'].setVisible(False,False)
|
||||
scene.objects['Sound-cmd']. restorePhysics()
|
||||
scene.objects['Sound-cmd-Hl'].setVisible(True,False)
|
||||
scene.objects['Commands']['sound']=True
|
||||
scene.objects['Cmd-text']['Text']= "Mute"
|
||||
scene.objects['Cmd-text'].setVisible(True,False)
|
||||
|
||||
# Maj du fichier de config (sound : data/config/sound -> [0][1].text)
|
||||
rp_config_tree[0][1].text=str(scene.objects['Commands']['sound'])
|
||||
buffer_xml = ET.tostring(rp_config_tree)
|
||||
with open("rp_config.xml", "wb") as f:
|
||||
f.write(buffer_xml)
|
||||
|
||||
def sound_unset ():
|
||||
scene.objects['Sound-cmd'].suspendPhysics()
|
||||
scene.objects['Sound-cmd'].setVisible(False,False)
|
||||
scene.objects['Sound-cmd-Hl'].setVisible(False,False)
|
||||
scene.objects['NoSound-cmd']. restorePhysics()
|
||||
scene.objects['NoSound-cmd-Hl'].setVisible(True,False)
|
||||
scene.objects['Commands']['sound']=False
|
||||
scene.objects['Cmd-text']['Text']= "Unmute"
|
||||
scene.objects['Cmd-text'].setVisible(True,False)
|
||||
|
||||
# Maj du fichier de config (sound : data/config/sound -> [0][1].text)
|
||||
rp_config_tree[0][1].text=str(scene.objects['Commands']['sound'])
|
||||
buffer_xml = ET.tostring(rp_config_tree)
|
||||
with open("rp_config.xml", "wb") as f:
|
||||
f.write(buffer_xml)
|
||||
|
||||
###############################################################################
|
||||
# Commandes
|
||||
###############################################################################
|
||||
|
||||
color_cmd = (0.8, 0.8, 0.8, 1) # Blanc
|
||||
color_cmd_hl = (0.8, 0.619, 0.021, 1) # Jaune
|
||||
|
||||
##
|
||||
# Init
|
||||
##
|
||||
|
||||
def cmd_init():
|
||||
|
||||
# UI : Commands
|
||||
scene.objects['Run-Hl'].setVisible(False,False)
|
||||
scene.objects['Pause'].setVisible(False,False)
|
||||
scene.objects['Pause'].suspendPhysics()
|
||||
scene.objects['Pause-Hl'].setVisible(False,False)
|
||||
scene.objects['Stop'].setVisible(False,False)
|
||||
scene.objects['Stop'].suspendPhysics()
|
||||
scene.objects['Stop-Hl'].setVisible(False,False)
|
||||
scene.objects['ResetView-Hl'].setVisible(False,False)
|
||||
scene.objects['About-cmd-Hl'].setVisible(False,False)
|
||||
scene.objects['About'].setVisible(False,True)
|
||||
|
||||
# UI : Sounds
|
||||
# Read config (sound : data/config/sound -> [0][1].text)
|
||||
if rp_config_tree[0][1].text == "True":
|
||||
sound_set ()
|
||||
else:
|
||||
sound_unset ()
|
||||
audiodev.unlock()
|
||||
|
||||
# UI : Text, ...
|
||||
scene.objects['Cmd-text'].setVisible(False,False)
|
||||
# scene.objects['Points-Map-text'].setVisible(False,False)
|
||||
# scene.objects['Info-1-text'].setVisible(False,False)
|
||||
# scene.objects['Info-2-text'].setVisible(False,False)
|
||||
|
||||
# UI : Mouse
|
||||
# Window size : 738.5 415.5
|
||||
if scene.objects['Mouse_main']['mouse_graphic']:
|
||||
bge.render.setMousePosition(int(bge.render.getWindowWidth() / 2), int(bge.render.getWindowHeight() / 2))
|
||||
bge.render.showMouse(scene.objects['Commands']['debug_mouse'])
|
||||
scene.objects['Mouse_main'].worldPosition = [0.07, -8.11, 4.71035] # Vielle version : [0.118161, -8.24305, 4.71035] ; [0, -3.5, 2], [0, -8, 6]
|
||||
scene.objects['Mouse_main'].worldScale=[30, 30, 30]
|
||||
scene.objects['Mouse_main']['past_x']=0
|
||||
scene.objects['Mouse_main']['past_y']=0
|
||||
scene.objects['Mouse_main']['mouse_up']=0
|
||||
else:
|
||||
scene.objects['Mouse_main'].setVisible(False,False)
|
||||
bge.render.showMouse(True)
|
||||
|
||||
# Speed
|
||||
# Read config (game speed : data/config/speed -> [0][0].text)
|
||||
speed_mode=[0.25, 0.5, 1,2,4,10]
|
||||
speed_mode_txt=["1/4", "1/2", "1", "2","4","10"]
|
||||
scene.objects['Terrain']['speed']=float(rp_config_tree[0][0].text)
|
||||
i=speed_mode.index(scene.objects['Terrain']['speed'])
|
||||
scene.objects['Text_speed']['Text']=speed_mode_txt[i]
|
||||
|
||||
##
|
||||
# Highlight des commandes
|
||||
##
|
||||
|
||||
def cmd_hl(cont):
|
||||
obj = cont.owner
|
||||
|
||||
# Activation
|
||||
if cont.sensors['MO'].status == JUST_ACTIVATED and scene.objects['Terrain']['manip_mode']==0:
|
||||
if obj.name!="Run" and obj.name!="Pause" and obj.name!="Stop":
|
||||
obj.setVisible(False,True)
|
||||
scene.objects[obj.name+'-Hl'].setVisible(True,True)
|
||||
|
||||
# Run et pause
|
||||
if obj.name=="Pause" or obj.name=="Run":
|
||||
if scene.objects['Terrain']['run'] == True:
|
||||
scene.objects['Pause'].setVisible(False,False)
|
||||
scene.objects['Pause-Hl'].setVisible(True,False)
|
||||
else:
|
||||
scene.objects['Run'].setVisible(False,False)
|
||||
scene.objects['Run-Hl'].setVisible(True,False)
|
||||
|
||||
# Stop
|
||||
if obj.name=="Stop":
|
||||
if scene.objects['Terrain']['thread_run']==True:
|
||||
scene.objects['Stop'].setVisible(False,False)
|
||||
scene.objects['Stop-Hl'].setVisible(True,False)
|
||||
|
||||
# Text
|
||||
text_hl ={"Run":"Run (F5)",
|
||||
"Stop":"Stop (F6)",
|
||||
"Pause":"Pause (F5)",
|
||||
"ResetView": "Reset view (Home key)",
|
||||
"About-cmd": "About",
|
||||
"Speed_down": "Speed down (-)",
|
||||
"Speed_up": "Speed up (+)",
|
||||
"Sound-cmd": "Mute",
|
||||
"NoSound-cmd": "Unmute"}
|
||||
scene.objects['Cmd-text']['Text']= text_hl[obj.name]
|
||||
scene.objects['Cmd-text'].setVisible(True,False)
|
||||
|
||||
# Désactivation
|
||||
if cont.sensors['MO'].status == JUST_RELEASED and (scene.objects['Terrain']['manip_mode']==0 or scene.objects['Terrain']['manip_mode']==9):
|
||||
if obj.name!="Run" and obj.name!="Pause" and obj.name!="Stop" and obj.name!="Sound-cmd" and obj.name!="NoSound-cmd" :
|
||||
scene.objects[obj.name+'-Hl'].setVisible(False,True)
|
||||
obj.setVisible(True,True)
|
||||
scene.objects['Cmd-text'].setVisible(False,False)
|
||||
|
||||
# Run et pause
|
||||
if obj.name=="Pause" or obj.name=="Run":
|
||||
if scene.objects['Terrain']['run'] == True:
|
||||
scene.objects['Pause-Hl'].setVisible(False,False)
|
||||
scene.objects['Pause'].setVisible(True,False)
|
||||
scene.objects['Cmd-text'].setVisible(False,False)
|
||||
else:
|
||||
scene.objects['Run-Hl'].setVisible(False,False)
|
||||
scene.objects['Run'].setVisible(True,False)
|
||||
scene.objects['Cmd-text'].setVisible(False,False)
|
||||
|
||||
# Stop
|
||||
if obj.name=="Stop":
|
||||
if scene.objects['Terrain']['thread_run']==True:
|
||||
scene.objects['Stop-Hl'].setVisible(False,False)
|
||||
scene.objects['Stop'].setVisible(True,False)
|
||||
scene.objects['Cmd-text'].setVisible(False,False)
|
||||
|
||||
# Sound
|
||||
if obj.name=="NoSound-cmd" and scene.objects['Commands']['sound']==False:
|
||||
scene.objects['NoSound-cmd-Hl'].setVisible(False,False)
|
||||
scene.objects['NoSound-cmd'].setVisible(True,False)
|
||||
scene.objects['Cmd-text'].setVisible(False,False)
|
||||
if obj.name=="Sound-cmd" and scene.objects['Commands']['sound']==True:
|
||||
scene.objects['Sound-cmd-Hl'].setVisible(False,False)
|
||||
scene.objects['Sound-cmd'].setVisible(True,False)
|
||||
scene.objects['Cmd-text'].setVisible(False,False)
|
||||
|
||||
##
|
||||
# Click sur les commandes
|
||||
##
|
||||
|
||||
def cmd_click (cont):
|
||||
obj = cont.owner
|
||||
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive and scene.objects['Terrain']['manip_mode']==0:
|
||||
if obj.name=="Pause" or obj.name=="Run":
|
||||
terrain_run ()
|
||||
if obj.name=="Stop":
|
||||
terrain_stop ()
|
||||
if obj.name=="Speed_up" or obj.name=="Speed_down":
|
||||
terrain_speed (obj)
|
||||
if obj.name=="ResetView":
|
||||
manip_reset()
|
||||
if obj.name=="Sound-cmd":
|
||||
sound_unset ()
|
||||
if obj.name=="NoSound-cmd":
|
||||
sound_set ()
|
||||
if obj.name=="About-cmd":
|
||||
about_open ()
|
||||
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Gestion du clavier
|
||||
###############################################################################
|
||||
|
||||
##
|
||||
# Mode
|
||||
#
|
||||
# 0 : rien (par défaut)
|
||||
# 1 : Pan avec Shift
|
||||
# 2 : Zoom avec Ctrl
|
||||
# 9 : Fenêtre modal
|
||||
##
|
||||
|
||||
def mode(cont):
|
||||
obj = cont.owner
|
||||
keyboard = bge.logic.keyboard
|
||||
|
||||
# Touche ESC
|
||||
if JUST_ACTIVATED in keyboard.inputs[bge.events.ESCKEY].queue:
|
||||
# Fenêtres modales
|
||||
if scene.objects['Terrain']['manip_mode']==9:
|
||||
if scene.objects['About'].visible:
|
||||
about_close()
|
||||
return
|
||||
else: # Sortir du jeux
|
||||
terrain_stop ()
|
||||
bge.logic.endGame()
|
||||
|
||||
# Fenêtre modale (inhibition des touches hors ESC)
|
||||
if scene.objects['Terrain']['manip_mode']==9:
|
||||
return
|
||||
|
||||
# Shift -> mode 1 : Pan (clic milieu)
|
||||
if JUST_ACTIVATED in keyboard.inputs[bge.events.LEFTSHIFTKEY].queue:
|
||||
obj['manip_mode']=1
|
||||
if JUST_ACTIVATED in keyboard.inputs[bge.events.RIGHTSHIFTKEY].queue:
|
||||
obj['manip_mode']=1
|
||||
|
||||
# Ctrl -> mode 2 : Zoom (clic milieu)
|
||||
if JUST_ACTIVATED in keyboard.inputs[bge.events.LEFTCTRLKEY].queue:
|
||||
obj['manip_mode']=2
|
||||
if JUST_ACTIVATED in keyboard.inputs[bge.events.RIGHTCTRLKEY].queue:
|
||||
obj['manip_mode']=2
|
||||
|
||||
# Pas de modificateur -> mode 0 : Pas de Orbit (mode 0) ici
|
||||
if JUST_RELEASED in keyboard.inputs[bge.events.LEFTSHIFTKEY].queue:
|
||||
obj['manip_mode']=0
|
||||
if JUST_RELEASED in keyboard.inputs[bge.events.RIGHTSHIFTKEY].queue:
|
||||
obj['manip_mode']=0
|
||||
if JUST_RELEASED in keyboard.inputs[bge.events.LEFTCTRLKEY].queue:
|
||||
obj['manip_mode']=0
|
||||
if JUST_RELEASED in keyboard.inputs[bge.events.RIGHTCTRLKEY].queue:
|
||||
obj['manip_mode']=0
|
||||
|
||||
# Touche Home -> Reset de la vue
|
||||
if JUST_ACTIVATED in keyboard.inputs[bge.events.HOMEKEY].queue:
|
||||
manip_reset()
|
||||
|
||||
if scene.objects['Mouse_main']['mouse_graphic']:
|
||||
bge.render.setMousePosition(int(bge.render.getWindowWidth() / 2), int(bge.render.getWindowHeight() / 2))
|
||||
scene.objects['Mouse_main'].worldPosition = [0.07, -8.11, 4.71035] # Vielle version : [0.118161, -8.24305, 4.71035] ; [0, -3.5, 2], [0, -8, 6]
|
||||
scene.objects['Mouse_main'].worldScale=[30, 30, 30]
|
||||
scene.objects['Mouse_main']['past_x']=0
|
||||
scene.objects['Mouse_main']['past_y']=0
|
||||
|
||||
# Touche F5 -> Run et Pause
|
||||
if JUST_ACTIVATED in keyboard.inputs[bge.events.F5KEY].queue:
|
||||
terrain_run ()
|
||||
|
||||
# Touche F6 -> Stop / Init
|
||||
if JUST_ACTIVATED in keyboard.inputs[bge.events.F6KEY].queue:
|
||||
if scene.objects['Terrain']['thread_run']==True:
|
||||
terrain_stop ()
|
||||
|
||||
# Touche +/- du pad -> Vitesse + ou /
|
||||
if JUST_ACTIVATED in keyboard.inputs[bge.events.PADPLUSKEY].queue:
|
||||
terrain_speed (scene.objects['Speed_up'])
|
||||
if JUST_ACTIVATED in keyboard.inputs[bge.events.PADMINUS].queue:
|
||||
terrain_speed (scene.objects['Speed_down'])
|
||||
|
||||
###############################################################################
|
||||
# Manipulation 3D de la scène
|
||||
###############################################################################
|
||||
|
||||
##
|
||||
# Mémorisation de la position et orientation initiales du modèle 3D et de la caméra
|
||||
##
|
||||
|
||||
def manip_init(cont):
|
||||
scene.objects['Camera']['init_lx']=scene.objects['Camera'].worldPosition.x
|
||||
scene.objects['Camera']['init_ly']=scene.objects['Camera'].worldPosition.y
|
||||
scene.objects['Camera']['init_lz']=scene.objects['Camera'].worldPosition.z
|
||||
scene.objects['Camera']['past_lx']=scene.objects['Camera'].worldPosition.x
|
||||
scene.objects['Camera']['past_ly']=scene.objects['Camera'].worldPosition.y
|
||||
scene.objects['Camera']['past_lz']=scene.objects['Camera'].worldPosition.z
|
||||
scene.objects['Terrain']['init_lx']=scene.objects['Terrain'].worldPosition.x
|
||||
scene.objects['Terrain']['init_ly']=scene.objects['Terrain'].worldPosition.y
|
||||
scene.objects['Terrain']['init_lz']=scene.objects['Terrain'].worldPosition.z
|
||||
scene.objects['Terrain']['init_rx']=scene.objects['Terrain'].worldOrientation.to_euler().x
|
||||
scene.objects['Terrain']['init_ry']=scene.objects['Terrain'].worldOrientation.to_euler().y
|
||||
scene.objects['Terrain']['init_rz']=scene.objects['Terrain'].worldOrientation.to_euler().z
|
||||
# scene.objects['Points-Map-text']['init_relativ_lx']=scene.objects['Points-Map-text'].worldPosition.x-scene.objects['Points'].worldPosition.x
|
||||
# scene.objects['Points-Map-text']['init_relativ_ly']=scene.objects['Points-Map-text'].worldPosition.y-scene.objects['Points'].worldPosition.y
|
||||
# scene.objects['Points-Map-text']['init_relativ_lz']=scene.objects['Points-Map-text'].worldPosition.z-scene.objects['Points'].worldPosition.z
|
||||
|
||||
##
|
||||
# Atteindre une orientation (bas niveau)
|
||||
##
|
||||
|
||||
def applyRotationTo(obj, rx=None, ry=None, rz=None, Local=True):
|
||||
rres=0.001 # resolution rotation
|
||||
|
||||
# x
|
||||
if rx is not None:
|
||||
while (abs(rx-obj.worldOrientation.to_euler().x) > rres) :
|
||||
if obj.worldOrientation.to_euler().x-rx > rres:
|
||||
obj.applyRotation((-rres, 0, 0), Local)
|
||||
if rx-obj.worldOrientation.to_euler().x > rres:
|
||||
obj.applyRotation((rres, 0, 0), Local)
|
||||
# print ("delta x ",rx-obj.worldOrientation.to_euler().x)
|
||||
|
||||
# y
|
||||
if ry is not None:
|
||||
while (abs(ry-obj.worldOrientation.to_euler().y) > rres) :
|
||||
if obj.worldOrientation.to_euler().y-ry > rres:
|
||||
obj.applyRotation((0, -rres, 0), Local)
|
||||
if ry-obj.worldOrientation.to_euler().y > rres:
|
||||
obj.applyRotation((0, rres, 0), Local)
|
||||
# print ("delta y ",ry-obj.worldOrientation.to_euler().y)
|
||||
|
||||
# z
|
||||
if rz is not None:
|
||||
while (abs(rz-obj.worldOrientation.to_euler().z) > rres) :
|
||||
if obj.worldOrientation.to_euler().z-rz > rres:
|
||||
obj.applyRotation((0, 0, -rres), Local)
|
||||
if rz-obj.worldOrientation.to_euler().z > rres:
|
||||
obj.applyRotation((0, 0, rres), Local)
|
||||
# print ("delta z ",rz-obj.worldOrientation.to_euler().z)
|
||||
|
||||
##
|
||||
# Reset de la manipulation de la vue
|
||||
##
|
||||
|
||||
def manip_reset():
|
||||
scene.objects['Camera'].worldPosition.x = scene.objects['Camera']['init_lx']
|
||||
scene.objects['Camera'].worldPosition.y = scene.objects['Camera']['init_ly']
|
||||
scene.objects['Camera'].worldPosition.z = scene.objects['Camera']['init_lz']
|
||||
applyRotationTo(scene.objects['Terrain'], 0, 0, 0)
|
||||
scene.objects['Cmd-text']['Text']= ""
|
||||
|
||||
##
|
||||
# Position de départ pour la manipulation de la vue
|
||||
##
|
||||
|
||||
def manip_start(cont):
|
||||
if scene.objects['Terrain']['manip_mode']!=9:
|
||||
obj = cont.owner
|
||||
obj['click_x']=cont.sensors['ClickM'].position[0]
|
||||
obj['click_y']=cont.sensors['ClickM'].position[1]
|
||||
|
||||
##
|
||||
# Cacher le cercle de la manipulation Orbit
|
||||
##
|
||||
|
||||
def manip_stop(cont):
|
||||
# scene.objects['Orbit'].setVisible(False,False)
|
||||
pass
|
||||
|
||||
##
|
||||
# Manipulation du modèle ou de la caméra
|
||||
##
|
||||
|
||||
def manip(cont):
|
||||
obj = cont.owner
|
||||
sensibilite_orbit=0.00005 # Base : 0.0005
|
||||
sensibilite_pan=0.001 # Base : 0.005
|
||||
sensibilite_zoom=0.005 # Base : 0.01
|
||||
delta_x=cont.sensors['DownM'].position[0]-obj['click_x']
|
||||
delta_y=cont.sensors['DownM'].position[1]-obj['click_y']
|
||||
|
||||
# Pan
|
||||
if obj['manip_mode']==1: # Shift
|
||||
scene.objects['Camera'].applyMovement((delta_x*-sensibilite_pan, delta_y*sensibilite_pan, 0), True)
|
||||
# scene.objects['Commands-colbox'].applyMovement((delta_x*-sensibilite_pan, delta_y*sensibilite_pan, 0), True)
|
||||
# scene.objects['Commands-colbox'].applyMovement((delta_x*-sensibilite_pan, delta_y*sensibilite_pan*math.cos(50*2*math.pi*(1/360)), delta_y*sensibilite_pan*math.sin(50*2*math.pi*(1/360))), True)
|
||||
|
||||
if scene.objects['Mouse_main']['mouse_graphic']:
|
||||
scene.objects['Mouse_main'].applyMovement((delta_x*-sensibilite_pan, delta_y*sensibilite_pan, 0), True)
|
||||
|
||||
# Zoom FIXME : marche pas au niveau de la souris
|
||||
if obj['manip_mode']==2: # Ctrl
|
||||
if scene.objects['Mouse_main']['mouse_graphic']:
|
||||
position_scale_x = 0.0005
|
||||
position_scale_y = position_scale_x
|
||||
mouse_x=scene.objects['Mouse_main'].sensors["Mouse"].position[0]-int(bge.render.getWindowWidth() / 2)
|
||||
mouse_y=scene.objects['Mouse_main'].sensors["Mouse"].position[1]-int(bge.render.getWindowHeight() / 2)
|
||||
distance_cam_past= math.sqrt(scene.objects['Camera']['past_ly']**2+scene.objects['Camera']['past_lz']**2)
|
||||
distance_cam = math.sqrt((scene.objects['Camera'].worldPosition.y**2+scene.objects['Camera'].worldPosition.z**2))
|
||||
size_scale = (distance_cam/distance_cam_past) * 0.23
|
||||
scene.objects['Camera'].applyMovement((0, 0, (delta_x+delta_y)*sensibilite_zoom), True)
|
||||
if scene.objects['Mouse_main']['mouse_graphic']:
|
||||
scene.objects['Mouse_main'].applyMovement((mouse_x*(delta_x+delta_y)*sensibilite_zoom*position_scale_x, -mouse_y*(delta_x+delta_y)*sensibilite_zoom*position_scale_y, 0), True)
|
||||
scene.objects['Mouse_main'].worldScale *= (delta_x+delta_y)*sensibilite_zoom*size_scale
|
||||
scene.objects['Camera']['past_ly']=scene.objects['Camera'].worldPosition.y
|
||||
scene.objects['Camera']['past_lz']=scene.objects['Camera'].worldPosition.z
|
||||
|
||||
##
|
||||
# Manipulation du modèle ou de la caméra
|
||||
##
|
||||
|
||||
def manip_wheel(cont):
|
||||
if scene.objects['Terrain']['manip_mode']!=9: # Fenêtre modale
|
||||
obj = cont.owner
|
||||
sensibilite_wheel = 5 # Base : 20
|
||||
if scene.objects['Mouse_main']['mouse_graphic']:
|
||||
position_scale_x = 0.0005
|
||||
position_scale_y = position_scale_x
|
||||
mouse_x=scene.objects['Mouse_main'].sensors["Mouse"].position[0]-int(bge.render.getWindowWidth() / 2)
|
||||
mouse_y=scene.objects['Mouse_main'].sensors["Mouse"].position[1]-int(bge.render.getWindowHeight() / 2)
|
||||
distance_cam_past = math.sqrt((scene.objects['Camera'].worldPosition.y**2+scene.objects['Camera'].worldPosition.z**2))
|
||||
# size_scale = (distance_cam/distance_cam_past) * 0.23
|
||||
size_scale = 0.2
|
||||
# size_scale = 0.23
|
||||
if cont.sensors['WheelUp'].positive:
|
||||
scene.objects['Camera'].applyMovement((0, 0, -sensibilite_wheel), True)
|
||||
if scene.objects['Mouse_main']['mouse_graphic']:
|
||||
distance_cam = math.sqrt((scene.objects['Camera'].worldPosition.y**2+scene.objects['Camera'].worldPosition.z**2))
|
||||
scene.objects['Mouse_main'].applyMovement((-mouse_x*sensibilite_wheel*position_scale_x, mouse_y*sensibilite_wheel*position_scale_y, 0), True)
|
||||
scene.objects['Mouse_main'].worldScale *= sensibilite_wheel* (distance_cam/distance_cam_past) *size_scale
|
||||
elif cont.sensors['WheelDown'].positive:
|
||||
scene.objects['Camera'].applyMovement((0, 0, sensibilite_wheel), True)
|
||||
if scene.objects['Mouse_main']['mouse_graphic']:
|
||||
distance_cam = math.sqrt((scene.objects['Camera'].worldPosition.y**2+scene.objects['Camera'].worldPosition.z**2))
|
||||
scene.objects['Mouse_main'].applyMovement((mouse_x*sensibilite_wheel*position_scale_x, -mouse_y*sensibilite_wheel*position_scale_y, 0), True)
|
||||
scene.objects['Mouse_main'].worldScale /= sensibilite_wheel* (distance_cam_past/distance_cam) *size_scale
|
||||
else:
|
||||
return
|
||||
|
||||
##
|
||||
# Icone de la souris
|
||||
##
|
||||
|
||||
def mouse(cont):
|
||||
if scene.objects['Mouse_main']['mouse_graphic']==False:
|
||||
return
|
||||
obj = cont.owner
|
||||
|
||||
# Ancienne version basée sur la position de la caméra
|
||||
# distance_cam_init= math.sqrt(scene.objects['Camera']['init_ly']**2+scene.objects['Camera']['init_lz']**2)
|
||||
# distance_cam = math.sqrt((scene.objects['Camera'].worldPosition.y**2+scene.objects['Camera'].worldPosition.z**2))
|
||||
# ratio = ((distance_cam_init - distance_cam)/distance_cam_init)*1.39 # trop vite -> +, pas assez vite -> -
|
||||
# scale_x=0.0118-0.0118*ratio
|
||||
# scale_y=scale_x
|
||||
# delta_x=cont.sensors["Mouse"].position[0]-obj['past_x']
|
||||
# delta_y=cont.sensors["Mouse"].position[1]-obj['past_y']
|
||||
# if delta_x<500 and delta_y<500:
|
||||
# scene.objects['Mouse_main'].worldPosition.x += delta_x*scale_x
|
||||
# scene.objects['Mouse_main'].worldPosition.y -= delta_y*scale_y*math.cos(50*2*math.pi*(1/360))
|
||||
# scene.objects['Mouse_main'].worldPosition.z -= delta_y*scale_y*math.sin(50*2*math.pi*(1/360))
|
||||
# scene.objects['Mouse_main']['past_x']=cont.sensors["Mouse"].position[0]
|
||||
# scene.objects['Mouse_main']['past_y']=cont.sensors["Mouse"].position[1]
|
||||
|
||||
# Version basée sur obj.getDistanceTo(scene.objects['Camera'])
|
||||
delta_x=cont.sensors["Mouse"].position[0]-obj['past_x']
|
||||
delta_y=cont.sensors["Mouse"].position[1]-obj['past_y']
|
||||
vect=mathutils.Vector((1,1,1))-obj.getVectTo(scene.objects['Camera'])[1]
|
||||
dist= obj.getDistanceTo(scene.objects['Camera'])
|
||||
# print ("delta_x, delta_y, vect, dist : ", delta_x, delta_y, vect, dist)
|
||||
if obj['past_dist']==0:
|
||||
obj['past_dist']=obj.getDistanceTo(scene.objects['Camera'])
|
||||
ratio = dist/obj['past_dist']
|
||||
# print ("delta_x, delta_y, vect, dist : ", delta_x, delta_y, vect, dist)
|
||||
scale_x=ratio*0.016
|
||||
scale_y=ratio*0.0162
|
||||
# scale_xy=ratio*0.0005
|
||||
scale_xy=ratio*0
|
||||
if delta_x<500 and delta_y<500:
|
||||
# scene.objects['Mouse_main'].applyMovement((delta_x*scale_x, -vect[1]*delta_y*scale_y, -vect[1]*delta_y*scale_y), False)
|
||||
scene.objects['Mouse_main'].applyMovement((delta_x*scale_x+delta_x*delta_y*scale_xy,
|
||||
-delta_y*scale_y*math.cos(50*2*math.pi*(1/360)),
|
||||
-delta_y*scale_y*math.sin(50*2*math.pi*(1/360))), False)
|
||||
obj['past_x']=cont.sensors["Mouse"].position[0]
|
||||
obj['past_y']=cont.sensors["Mouse"].position[1]
|
||||
|
||||
##
|
||||
# Mise en avant de la souris
|
||||
##
|
||||
|
||||
def mouse_up():
|
||||
scene.objects['Mouse_main']['mouse_up']+=1
|
||||
if scene.objects['Mouse_main']['mouse_up'] == 1:
|
||||
decal = 18
|
||||
size_scale = 0.2
|
||||
# print (scene.objects['Mouse_main'].getVectTo(scene.objects['Camera'])[1])
|
||||
vect=scene.objects['Mouse_main'].getVectTo(scene.objects['Camera'])[1]
|
||||
dist_past= scene.objects['Mouse_main'].getDistanceTo(scene.objects['Camera'])
|
||||
scene.objects['Mouse_main'].applyMovement((vect[0]*decal, vect[1]*decal, vect[2]*decal), False)
|
||||
dist= scene.objects['Mouse_main'].getDistanceTo(scene.objects['Camera'])
|
||||
scene.objects['Mouse_main'].worldScale *= (dist/dist_past) *size_scale
|
||||
scene.objects['Mouse_main'].worldScale=[8, 8, 8]
|
||||
|
||||
##
|
||||
# Mise en arrière de la souris
|
||||
##
|
||||
|
||||
def mouse_down():
|
||||
scene.objects['Mouse_main']['mouse_up']-=1
|
||||
if scene.objects['Mouse_main']['mouse_up'] == 0:
|
||||
decal = 18
|
||||
size_scale = 0.2
|
||||
# print (scene.objects['Mouse_main'].getVectTo(scene.objects['Camera'])[1])
|
||||
vect=scene.objects['Mouse_main'].getVectTo(scene.objects['Camera'])[1]
|
||||
dist_past= scene.objects['Mouse_main'].getDistanceTo(scene.objects['Camera'])
|
||||
scene.objects['Mouse_main'].applyMovement((-vect[0]*decal, -vect[1]*decal, -vect[2]*decal), False)
|
||||
dist= scene.objects['Mouse_main'].getDistanceTo(scene.objects['Camera'])
|
||||
scene.objects['Mouse_main'].worldScale /= (dist_past/dist) *size_scale
|
||||
scene.objects['Mouse_main'].worldScale=[30, 30, 30]
|
||||
|
||||
###############################################################################
|
||||
# About
|
||||
###############################################################################
|
||||
|
||||
color_link = (0.799, 0.617, 0.021, 1) # Jaune
|
||||
color_link_hl = (0.8, 0.8, 0.8, 1) # Blanc
|
||||
|
||||
##
|
||||
# Ouvrir le about
|
||||
##
|
||||
|
||||
def about_open():
|
||||
scene.objects['Terrain']['manip_mode']=9 # Fenêtre modale
|
||||
manip_reset()
|
||||
scene.objects['About_title'].color = color_black
|
||||
scene.objects['About_text'].color = color_black
|
||||
scene.objects['About_copyright'].color = color_black
|
||||
scene.objects['About_link-git'].color= color_link
|
||||
scene.objects['About_link-gpl'].color= color_link
|
||||
scene.objects['About_link-upbge'].color= color_link
|
||||
scene.objects['About_link-kay'].color= color_link
|
||||
scene.objects['About_link-kenney'].color= color_link
|
||||
scene.objects['About_close'].color= color_link
|
||||
scene.objects['About'].setVisible(True,True)
|
||||
scene.objects['About'].worldPosition = [0, 1.53623, -1.8] # old [0, 1.53623, -0.892838]
|
||||
scene.objects['About']['timer'] = 0
|
||||
scene.objects['About']['anim'] = True
|
||||
|
||||
##
|
||||
# Animation du about
|
||||
##
|
||||
|
||||
def about_open_anim():
|
||||
pas=0.5
|
||||
scene.objects['About'].localPosition.y -= pas
|
||||
scene.objects['About'].localPosition.z += 0.85*pas
|
||||
# scene.objects['About'].localPosition.y=scene.objects['About'].localPosition.y-1*pas
|
||||
# scene.objects['About'].localPosition.z=scene.objects['About'].localPosition.z+0.85*pas
|
||||
scene.objects['About']['timer']+=1
|
||||
if scene.objects['About']['timer']== 40:
|
||||
scene.objects['About']['anim'] = False
|
||||
|
||||
##
|
||||
# Highlight du about
|
||||
##
|
||||
|
||||
def about_hl(cont):
|
||||
if cont.sensors['MO'].status == JUST_ACTIVATED:
|
||||
if scene.objects['Mouse_main']['mouse_graphic']:
|
||||
mouse_up()
|
||||
scene.objects['Aboutbanner'].color = color_white
|
||||
scene.objects['About_close'].color = color_white
|
||||
scene.objects['About_title'].color = color_white
|
||||
|
||||
if cont.sensors['MO'].status == JUST_RELEASED:
|
||||
if scene.objects['Mouse_main']['mouse_graphic']:
|
||||
mouse_down()
|
||||
scene.objects['Aboutbanner'].color = color_endbanner_bluelight
|
||||
scene.objects['About_close'].color = color_link
|
||||
scene.objects['About_title'].color = color_black
|
||||
|
||||
##
|
||||
# Fermer le about
|
||||
##
|
||||
|
||||
def about_close():
|
||||
sound_play (sndbuff_click)
|
||||
scene.objects['Terrain']['manip_mode']=0
|
||||
scene.objects['About'].setVisible(False,True)
|
||||
scene.objects['About'].worldPosition = [22, 1.53623, -0.892838]
|
||||
scene.objects['Aboutbanner'].color = [0.592, 0.68, 0.407, 1]
|
||||
scene.objects['About']['timer']= 0
|
||||
|
||||
##
|
||||
# Click pour fermer le about
|
||||
##
|
||||
|
||||
def about_close_click(cont):
|
||||
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive :
|
||||
about_close()
|
||||
|
||||
##
|
||||
# Liens du about
|
||||
##
|
||||
|
||||
def about_link(cont):
|
||||
if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive :
|
||||
obj = cont.owner
|
||||
name=obj.name[:-7]
|
||||
link={
|
||||
'About_link-git' : 'https://gitlab.com/phroy/ropy',
|
||||
'About_link-gpl' : 'https://www.gnu.org/licenses/gpl-3.0.html',
|
||||
'About_link-blender': 'https://www.blender.org',
|
||||
'About_link-upbge' : 'https://www.upbge.org',
|
||||
'About_link-kay' : 'https://www.kaylousberg.com',
|
||||
'About_link-kenney' : 'https://www.kenney.nl'}
|
||||
webbrowser.open(link [name])
|
||||
|
||||
# FIXME: souris graphique trop compliqué
|
||||
def about_link_hl(cont):
|
||||
decal = 15
|
||||
if cont.sensors['MO'].status == JUST_ACTIVATED :
|
||||
obj = cont.owner
|
||||
name=obj.name[:-7]
|
||||
scene.objects[name].color = color_link_hl
|
||||
if scene.objects['Mouse_main']['mouse_graphic']:
|
||||
mouse_up()
|
||||
|
||||
if cont.sensors['MO'].status == JUST_RELEASED :
|
||||
obj = cont.owner
|
||||
name=obj.name[:-7]
|
||||
scene.objects[name].color = color_link
|
||||
if scene.objects['Mouse_main']['mouse_graphic']:
|
||||
mouse_down()
|
63
rp_cmd.py
Normal file
63
rp_cmd.py
Normal file
@ -0,0 +1,63 @@
|
||||
import bge # Bibliothèque Blender Game Engine (UPBGE)
|
||||
from rp_lib import * # Bibliothèque Ropy
|
||||
|
||||
###############################################################################
|
||||
# ropy_cmd.py
|
||||
# @title: Commandes du Robot Ropy
|
||||
# @project: Ropy (Blender-EduTech)
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# En: Threads management << DONT CHANGE THIS SECTION >>
|
||||
# Fr: Gestion des tâches (threads) << NE PAS MODIFIER CETTE SECTION >>
|
||||
###############################################################################
|
||||
|
||||
scene = bge.logic.getCurrentScene()
|
||||
|
||||
def start():
|
||||
scene.objects['Terrain']['thread_cmd']=True
|
||||
thread_cmd_start(commands)
|
||||
|
||||
def stop():
|
||||
thread_cmd_stop()
|
||||
|
||||
def end():
|
||||
ct_sleep (2)
|
||||
print ("Thread commands is arrived.")
|
||||
scene.objects['Terrain']['thread_cmd']=False
|
||||
|
||||
###############################################################################
|
||||
# Fonctions
|
||||
###############################################################################
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Commandes
|
||||
###############################################################################
|
||||
|
||||
def commands():
|
||||
|
||||
###############################################################################
|
||||
# Initialisation du niveau :
|
||||
# Niveau 0 : Vide
|
||||
# Niveau 1 : Les premiers pas de Ropy
|
||||
# Niveau 2 : Sécuriser Ropy
|
||||
# Niveau 3 : Partir au bout du monde
|
||||
# Niveau 4 : Faire face à l'inconnu
|
||||
# Niveau 5 : Se rendre utile
|
||||
###############################################################################
|
||||
|
||||
rp_niveau (1) # Saisir le niveau (de 0 à 5)
|
||||
ropy_init.main() # Initialisation de la scène 3D
|
||||
|
||||
|
||||
###############################################################################
|
||||
# En: Externals calls << DONT CHANGE THIS SECTION >>
|
||||
# Fr: Appels externes << NE PAS MODIFIER CETTE SECTION >>
|
||||
###############################################################################
|
||||
|
||||
if __name__=='start':
|
||||
start()
|
||||
if __name__=='stop':
|
||||
stop()
|
||||
|
6
rp_config.xml
Normal file
6
rp_config.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<data>
|
||||
<config>
|
||||
<speed>10.0</speed>
|
||||
<sound>True</sound>
|
||||
</config>
|
||||
</data>
|
850
rp_lib.py
Normal file
850
rp_lib.py
Normal file
@ -0,0 +1,850 @@
|
||||
import bge # Blender Game Engine (UPBGE)
|
||||
import aud # Sounds
|
||||
import threading # Multithreading
|
||||
import trace
|
||||
import sys
|
||||
import time
|
||||
import math
|
||||
import mathutils
|
||||
import random
|
||||
|
||||
###############################################################################
|
||||
# ropy_lib.py
|
||||
# @title: Bibliothèque du Robot Ropy (rp_*)
|
||||
# @project: Ropy (Blender-EduTech)
|
||||
# @lang: fr
|
||||
# @authors: Philippe Roy <philippe.roy@ac-grenoble.fr>
|
||||
# @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=[]
|
||||
|
||||
# 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()
|
||||
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():
|
||||
print ("Thread",type_txt, "#",i,"closed.")
|
||||
else:
|
||||
print ("Thread",type_txt, "#",i,"still open ...")
|
||||
t.kill()
|
||||
t.join()
|
||||
if not t.is_alive():
|
||||
print ("Thread",type_txt, "#",i,"killed.")
|
||||
else:
|
||||
print ("Thread",type_txt, "#",i,"zombie...")
|
||||
zombie_flag=True
|
||||
i +=1
|
||||
if zombie_flag==False:
|
||||
print ("All threads",type_txt, "are closed.")
|
||||
return True
|
||||
else:
|
||||
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")
|
||||
|
||||
###############################################################################
|
||||
# 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)
|
||||
|
||||
# ###############################################################################
|
||||
# # Waves (minions)
|
||||
# ###############################################################################
|
||||
|
||||
# ##
|
||||
# # Création d'un minion
|
||||
# #
|
||||
# # Minion caracteristics : category (class), level, hp, speed, armor, bounty, lifes_damage
|
||||
# # Minion 3d body : body (male,female,old, ...), variante (A,B,C,D, ...), level
|
||||
# ##
|
||||
|
||||
# def ct_minion_create(x,y,cat,level):
|
||||
# category=cat+"-lv"+str(level)
|
||||
# minion_3d= scene.objects['Terrain']['minion_3d']
|
||||
# body = random.choice(minion_3d[category][0])+"_"+random.choice(minion_3d[category][1])+"_"+random.choice(minion_3d[category][2])
|
||||
# return (ct_minion_create_details(x,y,cat,level,body))
|
||||
|
||||
# # Création d'un minion détaillée
|
||||
# def ct_minion_create_details(x,y,cat,level,body="Knight_m_A_common"):
|
||||
# category=cat+"-lv"+str(level)
|
||||
|
||||
# # Pause
|
||||
# while scene.objects['Terrain']['run'] == False:
|
||||
# time.sleep(0.01)
|
||||
|
||||
# # Synchronisation des threads : attente de la création d'une tour
|
||||
# while scene.objects['Terrain']['thread_cmd_lock'] == True:
|
||||
# # print ("ct_minion : thread_cmd_lock =True")
|
||||
# time.sleep(0.01)
|
||||
|
||||
# # Blocage des autres threads pendant l'apparition du minion
|
||||
# scene.objects['Terrain']['thread_cmd_lock'] = True
|
||||
|
||||
# # Object 3D
|
||||
# minion= scene.addObject(body, scene.objects['Terrain'])
|
||||
# minion.worldScale=[0.25,0.25,0.25]
|
||||
# minion.worldPosition=[x,y,0.1]
|
||||
# minion.suspendPhysics (True)
|
||||
# minion.setVisible(False)
|
||||
# scene.objects['Terrain']['idm']=scene.objects['Terrain']['idm']+1
|
||||
# minion['id']=scene.objects['Terrain']['idm']
|
||||
# minion.name="wm("+str(minion['id'])+")" # Wave minion (wm), identifier minion (idm)
|
||||
# scene.objects['Points']['minions'] +=1
|
||||
# scene.objects['Points']['minions_run'] +=1
|
||||
|
||||
# # Gestion de la distance et des minions zombis
|
||||
# minion['dist']=0.0
|
||||
# minion['dist_old']=0.0
|
||||
# minion['dist_last_x']=minion.worldPosition.x
|
||||
# minion['dist_last_y']=minion.worldPosition.y
|
||||
# minion['dist_new']=True
|
||||
|
||||
# # Caracteristics
|
||||
# minion_carac= scene.objects['Terrain']['minion_carac']
|
||||
# minion['cat']=minion_carac[category][0]
|
||||
# minion['level']=minion_carac[category][1]
|
||||
# minion['hp']=minion_carac[category][2]
|
||||
# minion['speed']=minion_carac[category][3]
|
||||
# minion['speed_base']=minion_carac[category][3]
|
||||
# minion['armor']=minion_carac[category][4]
|
||||
# minion['bounty']=minion_carac[category][5]
|
||||
# minion['lifes_damage']=minion_carac[category][6]
|
||||
# minion['buff']=[]
|
||||
# minion['resist']=[]
|
||||
|
||||
# # Actuator Steering
|
||||
# minion.actuators['Steering'].navmesh=scene.objects[scene.objects['Terrain']['navmesh']]
|
||||
# minion.actuators['Steering'].target=scene.objects[scene.objects['Terrain']['endtile']]
|
||||
# minion.actuators['Steering'].distance=2
|
||||
# # minion.actuators['Steering'].distance=0.5
|
||||
# minion.actuators['Steering'].velocity=minion['speed_base']*scene.objects['Terrain']['speed']
|
||||
|
||||
# # Déblocage des autres threads après l'apparition du minion
|
||||
# scene.objects['Terrain']['thread_cmd_lock'] = False
|
||||
# return minion.name
|
||||
|
||||
# ##
|
||||
# # Activation du minion (steering)
|
||||
# ##
|
||||
|
||||
# def ct_minion_go(minion_name):
|
||||
# minion=scene.objects[minion_name]
|
||||
# minion.restorePhysics()
|
||||
# minion.setVisible(True)
|
||||
|
||||
# ##
|
||||
# # Destruction d'un minion
|
||||
# ##
|
||||
|
||||
# def scn_minion_dead(cont):
|
||||
# obj = cont.owner
|
||||
# scene.objects['Points']['minions'] -=1
|
||||
# scene.objects['Points']['minions_run'] -=1
|
||||
# scene.objects['Points']['kills'] +=1
|
||||
# scene.objects['Points']['coins']= scene.objects['Points']['coins']+obj['bounty']
|
||||
# obj.setVisible(False)
|
||||
# obj.suspendPhysics (True)
|
||||
# # obj.endObject()
|
||||
|
||||
# ###############################################################################
|
||||
# # Spells / Casts
|
||||
# ###############################################################################
|
||||
|
||||
# ##
|
||||
# # Buff/debuff Minion
|
||||
# ##
|
||||
|
||||
# def scn_minion_affect(cont):
|
||||
# if scene.objects['Terrain']['run'] == False: # Pause
|
||||
# return
|
||||
# obj = cont.owner
|
||||
# # print (obj.name, obj['buff'])
|
||||
# slow_state=False
|
||||
|
||||
# # Distance parcourue
|
||||
# obj['dist']=obj['dist']+ math.sqrt((obj.worldPosition.x-obj['dist_last_x'])**2+(obj.worldPosition.y-obj['dist_last_y'])**2)
|
||||
# obj['dist_last_x']=obj.worldPosition.x
|
||||
# obj['dist_last_y']=obj.worldPosition.y
|
||||
|
||||
# # Lod
|
||||
# # print(obj.currentLodLevel)
|
||||
|
||||
# # Etats actif
|
||||
# for debuff_i in obj['buff']:
|
||||
# if debuff_i[1] <= 0:
|
||||
# obj['buff'].remove(debuff_i)
|
||||
# continue
|
||||
# if debuff_i[0] == "slow":
|
||||
# slow_state=True
|
||||
# debuff_i[1] -= scene.objects['Terrain']['speed']
|
||||
|
||||
# # Effets
|
||||
# if slow_state:
|
||||
# obj.actuators['Steering'].velocity =(obj['speed_base']*scene.objects['Terrain']['speed'])/3
|
||||
# # obj.actuators['Steering'].velocity =(obj['speed_base']*scene.objects['Terrain']['speed'])/2
|
||||
# else:
|
||||
# obj.actuators['Steering'].velocity = obj['speed_base']*scene.objects['Terrain']['speed']
|
||||
|
||||
# ###############################################################################
|
||||
# # Towers
|
||||
# ###############################################################################
|
||||
|
||||
# ##
|
||||
# # Création d'une tour
|
||||
# #
|
||||
# # Tower caracteristics : category (class), damage, speed, range
|
||||
# ##
|
||||
|
||||
# def ct_build(x,y, cat='Archer tower', tower_name="Tower", color=tower_purple, building="square-A"):
|
||||
# tower_minion_3d= scene.objects['Terrain']['tower_minion_3d']
|
||||
# if cat=='Archer tower': # Archer
|
||||
# category="Archer-lv1"
|
||||
# if cat=='Mage tower': # Mage
|
||||
# category="Mage-lv1"
|
||||
# body = random.choice(tower_minion_3d[category][0])+"_"+random.choice(tower_minion_3d[category][1])+"_"+random.choice(tower_minion_3d[category][2])
|
||||
# return (ct_build_details(x,y, cat, tower_name, color, building, body))
|
||||
|
||||
# ##
|
||||
# # Création d'une tour détaillée
|
||||
# ##
|
||||
|
||||
# def ct_build_details(x,y, cat='Archer tower', tower_name="Tower", color=tower_purple, building="square-A", body="Archer_m_A_common"):
|
||||
|
||||
# # Vérification de la place
|
||||
# if [x,y] in scene.objects['Terrain']['scene_tile_noncontruct'] or [x,y] in scene.objects['Terrain']['scene_tile_tower']:
|
||||
# return False
|
||||
|
||||
# # Vérification du niveau
|
||||
# scene.objects['Points']['level']= scene.objects['Points']['level'] + 1
|
||||
# if scene.objects['Points']['level'] > scene.objects['Points']['level_max'] :
|
||||
# tour= scene.addObject("Tower_error", scene.objects['Terrain'])
|
||||
# tour.worldPosition=[x,y,0.2]
|
||||
# tour.worldScale=[1,1,1]
|
||||
# scene.objects['Terrain']['scene_tile_tower'].append([x,y])
|
||||
# return False
|
||||
|
||||
# # Blocage des autres threads pendant la construction
|
||||
# scene.objects['Terrain']['thread_cmd_lock'] = True
|
||||
|
||||
# # Objets 3D
|
||||
# time.sleep(0.02)
|
||||
# tour= scene.addObject('Tower-'+building, scene.objects['Terrain'])
|
||||
# time.sleep(0.02)
|
||||
# tour.color = color
|
||||
# tour.worldPosition=[x,y,0.2]
|
||||
# tour.worldScale=[1,1,1]
|
||||
# tour.name="tower("+str(x)+','+str(y)+")"
|
||||
# scene.objects['Terrain']['scene_tile_tower'].append([x,y])
|
||||
# tower_minion= scene.addObject(body, scene.objects['Terrain'])
|
||||
# tower_minion['type_towerminion']=False
|
||||
# del tower_minion['type_minion']
|
||||
# tower_minion.name="tm("+str(x)+','+str(y)+")" # Tower minion (tm)
|
||||
# tower_minion.worldPosition=[x,y,1]
|
||||
# tower_minion.worldScale=[0.25,0.25,0.25]
|
||||
|
||||
# # Draw3d
|
||||
# if cat=="Archer tower":
|
||||
# for i in range (3):
|
||||
# ct_add_tower_bullet(x,y,i, "Arrow")
|
||||
# if cat=="Mage tower":
|
||||
# ct_add_tower_cast(x,y)
|
||||
|
||||
# # Sounds
|
||||
# sound_play(sndbuff_build)
|
||||
|
||||
# # Caracteristics
|
||||
# tower_carac= scene.objects['Terrain']['tower_carac']
|
||||
# tour['cat']=tower_carac[cat][0]
|
||||
# tour['tower_name']=tower_name
|
||||
# tour['xp']=0
|
||||
# tour['lvl_current']=1
|
||||
# tour['lvl']=1
|
||||
# tour['damage']=tower_carac[cat][1]
|
||||
# tour['speed']=tower_carac[cat][2]
|
||||
# tour['range']=tower_carac[cat][3]
|
||||
# tour['techno']=[]
|
||||
# tour['cast']="slow"
|
||||
# # tour['cast_duration']=2
|
||||
# tour['cast_duration']=3
|
||||
# tour['target']=[]
|
||||
# tour['target_past']=[]
|
||||
|
||||
# # Capteur Near
|
||||
# tour.sensors['Near'].distance=tour['range']*2.5 # Range : 1 point = 2,5
|
||||
# # tour.sensors['Near'].skippedTicks =round(1/(tour['speed']*scene.objects['Terrain']['speed']))
|
||||
# tour.sensors['Near'].skippedTicks =round(tour['speed']*50*scene.objects['Terrain']['speed']) # Speed : 1 point = 50 tics
|
||||
|
||||
# # Déblocage des autres threads après la construction
|
||||
# scene.objects['Terrain']['thread_cmd_lock'] = False
|
||||
# # print (scene.objects)
|
||||
# return True
|
||||
|
||||
# ##
|
||||
# # Suppression d'une tour
|
||||
# ##
|
||||
|
||||
# def ct_remove(x,y):
|
||||
# for obj_i in scene.objects:
|
||||
# if "type_tower" in obj_i.getPropertyNames():
|
||||
# if x == obj_i.worldPosition.x and y == obj_i.worldPosition.y:
|
||||
# scene.objects["tm("+str(round(obj_i.worldPosition.x))+','+str(round(obj_i.worldPosition.y))+")"].endObject()
|
||||
# obj_i.endObject()
|
||||
# scene.objects['Points']['level']= scene.objects['Points']['level'] - 1
|
||||
|
||||
# ##
|
||||
# # Création d'un projectile
|
||||
# ##
|
||||
|
||||
# def ct_add_tower_bullet(x, y, num, cat="Ball"):
|
||||
# if cat=="Ball":
|
||||
# bullet= scene.addObject("Bullet", scene.objects['Terrain'])
|
||||
# if cat=="Arrow":
|
||||
# bullet= scene.addObject("Arrow", scene.objects['Terrain'])
|
||||
# bullet.name="tower("+str(x)+','+str(y)+")-bullet"+str(num)
|
||||
# bullet.worldPosition=[x,y,1.5]
|
||||
# bullet.worldScale=[0.75,0.75,0.75]
|
||||
# bullet.suspendPhysics (True)
|
||||
# bullet.setVisible(False)
|
||||
# bullet['activated']=False
|
||||
|
||||
# ##
|
||||
# # Création des sorts
|
||||
# ##
|
||||
|
||||
# def ct_add_tower_cast(x, y):
|
||||
# cast= scene.addObject("Cast-slow", scene.objects['Terrain'])
|
||||
# cast.name="tower("+str(x)+','+str(y)+")-cast"
|
||||
# cast.worldPosition=[x,y,1.5]
|
||||
# cast.worldScale=[0.75,0.75,0.75]
|
||||
# cast.suspendPhysics (True)
|
||||
# cast.setVisible(False)
|
||||
# cast['activated']=False
|
||||
|
||||
|
||||
# ##
|
||||
# # Réaction d'une tour
|
||||
# ##
|
||||
|
||||
# def scn_tower_near(cont):
|
||||
# obj = cont.owner
|
||||
# sensor = obj.sensors['Near']
|
||||
|
||||
# # Tir
|
||||
# if sensor.positive and len(sensor.hitObjectList)>0 and scene.objects['Terrain']['run']==True :
|
||||
|
||||
# # Tir sur le plus avancé basé sur les distances parcourues
|
||||
# target=sensor.hitObjectList[0]
|
||||
# target_dist = target['dist']
|
||||
# for obj_i in sensor.hitObjectList:
|
||||
# if obj_i['dist']> target_dist:
|
||||
# target=obj_i
|
||||
# target_dist = target['dist']
|
||||
|
||||
# # Tir sur le plus avancé basé sur l'ordre de passage
|
||||
# # target=sensor.hitObjectList[0]
|
||||
# # target_id = target['navPosition']
|
||||
# # for obj_i in sensor.hitObjectList:
|
||||
# # if obj_i['navPosition']< target_id:
|
||||
# # target=obj_i
|
||||
# # target_id = target['navPosition']
|
||||
|
||||
# # Tir sur le plus avancé basé sur les distances par rapport à la tour -> ne marche pas
|
||||
# # target=sensor.hitObjectList[0]
|
||||
# # if len(sensor.hitObjectList)>1:
|
||||
# # target_eloignement = False
|
||||
# # target_distance_eloignement = 0
|
||||
# # target_distance_approche = 100
|
||||
# # print ("detection:",sensor.hitObjectList)
|
||||
# # for obj_i in sensor.hitObjectList:
|
||||
# # for obj_j in obj['target_past']:
|
||||
# # if obj_j[0]==obj_i.name:
|
||||
# # print ("name :", obj_j[0], "distance :", obj.getDistanceTo(obj_i), "distance old :", obj_j[1], "ecart :", obj.getDistanceTo(obj_i) - obj_j[1])
|
||||
# # # Éloignement
|
||||
# # if obj.getDistanceTo(obj_i) - obj_j[1] > 0: # Ecart de distance
|
||||
# # target_eloignement = True
|
||||
# # if obj.getDistanceTo(obj_i) > target_distance_eloignement:
|
||||
# # target=obj_i
|
||||
# # target_distance_eloignement = obj.getDistanceTo(obj_i)
|
||||
# # # Approche
|
||||
# # else:
|
||||
# # if target_eloignement == False:
|
||||
# # if obj.getDistanceTo(obj_i) < target_distance_approche:
|
||||
# # target=obj_i
|
||||
# # target_distance_approche = obj.getDistanceTo(obj_i)
|
||||
# # if target_eloignement == True:
|
||||
# # print ("Eloignement : target:", target.name, "distance :", obj.getDistanceTo(target))
|
||||
# # print ("")
|
||||
# # else:
|
||||
# # print ("Approche : target:", target.name, "distance :", obj.getDistanceTo(target))
|
||||
# # print ("")
|
||||
# # obj['target_past']=[]
|
||||
# # for obj_i in sensor.hitObjectList:
|
||||
# # obj['target_past'].append([obj_i.name, obj.getDistanceTo(obj_i)])
|
||||
|
||||
# # Orientation du tower minion
|
||||
# towerminion="tm("+str(round(obj.worldPosition.x))+','+str(round(obj.worldPosition.y))+")"
|
||||
# angle =math.atan((target.worldPosition.y-obj.worldPosition.y)/(target.worldPosition.x-obj.worldPosition.x))
|
||||
# if target.worldPosition.x>obj.worldPosition.x:
|
||||
# angle2=math.pi/2+angle-scene.objects[towerminion].worldOrientation.to_euler().z
|
||||
# angle3=angle
|
||||
# else:
|
||||
# angle2=math.pi+math.pi/2+angle-scene.objects[towerminion].worldOrientation.to_euler().z
|
||||
# angle3=math.pi+angle
|
||||
# scene.objects[towerminion].applyRotation((0, 0, angle2), False)
|
||||
|
||||
# # Sounds
|
||||
# if obj['cat']=="Archer tower":
|
||||
# sound_play(sndbuff_archer)
|
||||
# if obj['cat']=="Mage tower":
|
||||
# sound_play(sndbuff_mage)
|
||||
|
||||
# # Ligne (drawLine) (vitesse rapide)
|
||||
# if scene.objects['Terrain']['speed']<4: # Pas d'animation à 10 -> plantage
|
||||
|
||||
# # Archer (tir de flêche)
|
||||
# if obj['cat']=="Archer tower":
|
||||
# if target.name in scene.objects:
|
||||
# for i in range (3):
|
||||
# bullet = scene.objects[obj.name+"-bullet"+str(i)]
|
||||
# if bullet['activated']==False:
|
||||
# bullet.worldPosition=[obj.worldPosition.x, obj.worldPosition.y, obj.worldPosition.z+0.8]
|
||||
# bullet['activated']=True
|
||||
# bullet.setVisible(True)
|
||||
# scene.objects['Terrain']['draw3d_process']=True
|
||||
# scene.objects['Terrain']['draw3d_list'].append([20, "arrow", obj.name, bullet.name, target.name, "normal", 20])
|
||||
# break
|
||||
# if i ==3 :
|
||||
# print ("Plus de bullet de disponible pour la tour : "+obj.name)
|
||||
|
||||
# # Cast zone
|
||||
# if obj['cat']=="Mage tower": # Mage (cast)
|
||||
# cast = scene.objects[obj.name+"-cast"]
|
||||
# cast.worldPosition=[obj.worldPosition.x, obj.worldPosition.y, obj.worldPosition.z+0.8]
|
||||
# cast.worldScale=[0.01,0.01,0.01]
|
||||
# cast.setVisible(True)
|
||||
# scene.objects['Terrain']['draw3d_process']=True
|
||||
# scene.objects['Terrain']['draw3d_list'].append([60, "cast", obj.name, cast.name, "slow", 60])
|
||||
|
||||
# # Rayon
|
||||
# # FIXME : ne marche plus (zoom et pan)
|
||||
# # if obj['cat']=="Test":
|
||||
# # if target.name in scene.objects:
|
||||
# # scene.objects['Terrain']['draw2d_process']=True
|
||||
# # scene.objects['Terrain']['draw2d_list'].append([5, "ray", [obj.worldPosition.x, obj.worldPosition.y, obj.worldPosition.z+0.8], target.name, angle3, ray_yellow,5]) # Suivi du minion
|
||||
|
||||
# # Dégats : pas d'animation à 10
|
||||
# if scene.objects['Terrain']['speed'] >= 4:
|
||||
# target['hp'] = target['hp'] - obj['damage']
|
||||
# if target['hp']<=0:
|
||||
# target['dead']=True
|
||||
|
||||
# # Cast (buff and debuff)
|
||||
# if obj['cat']=="Mage tower":
|
||||
# for target_i in sensor.hitObjectList:
|
||||
# target_i['buff'].append([obj['cast'], obj['cast_duration']])
|
||||
|
||||
# ###############################################################################
|
||||
# # Carte
|
||||
# ###############################################################################
|
||||
|
||||
# ##
|
||||
# # Texte de carte
|
||||
# ##
|
||||
|
||||
# def ct_map_text_wave(wave):
|
||||
# scene.objects['Points-Map-text']['Text']=("Wave " + str(wave))
|
||||
# scene.objects['Points-Map-text'].setVisible(True,False)
|
||||
# scene.objects['Points-Map-text'].color = color_text_yellow
|
||||
# scene.objects['Points-Map-text']['timer']=0
|
||||
# scene.objects['Points-Map-text']['anim']=True
|
||||
|
||||
# ##
|
||||
# # Texte de carte
|
||||
# ##
|
||||
|
||||
# def ct_map_text(text):
|
||||
# scene.objects['Points-Map-text']['Text']=text
|
||||
# scene.objects['Points-Map-text'].setVisible(True,False)
|
||||
|
||||
# ##
|
||||
# # Fin
|
||||
# ##
|
||||
|
||||
# def ct_map_end(x,y):
|
||||
# scene.objects['Map_end'].worldPosition=[x,y,0.2]
|
||||
# scene.objects['Map_end'].worldScale=[0.25,0.25,0.25]
|
||||
|
||||
# ##
|
||||
# # Minion arrivé à la fin
|
||||
# ##
|
||||
|
||||
# def scn_map_end_near(cont):
|
||||
# obj = cont.owner
|
||||
# sensor = obj.sensors['Near']
|
||||
# if sensor.positive :
|
||||
# for obj_i in sensor.hitObjectList :
|
||||
# sound_play(sndbuff_life)
|
||||
# if scene.objects['Points']['lifes']>0:
|
||||
# scene.objects['Points']['lifes']= scene.objects['Points']['lifes']-obj_i['lifes_damage']
|
||||
# scene.objects['Points']['minions_run'] -=1
|
||||
# for obj_i in sensor.hitObjectList :
|
||||
# obj_i.setVisible(False)
|
||||
# obj_i.suspendPhysics (True)
|
||||
# # obj_i.endObject()
|
||||
|
||||
# ##
|
||||
# # Drapeau de fin
|
||||
# ##
|
||||
|
||||
# def ct_map_endflag(x,y):
|
||||
# endflag= scene.addObject("Map_endflag", scene.objects['Terrain'])
|
||||
# endflag.worldPosition=[x,y,0.3]
|
||||
# endflag.worldScale=[0.3,0.3,0.3]
|
||||
# if round(x) == x :
|
||||
# if round(y) == y :
|
||||
# scene.objects['Terrain']['scene_tile_noncontruct'].append([x,y])
|
||||
# else:
|
||||
# scene.objects['Terrain']['scene_tile_noncontruct'].append([x,math.floor(y)])
|
||||
# scene.objects['Terrain']['scene_tile_noncontruct'].append([x,math.ceil(y)])
|
||||
# else:
|
||||
# if round(y) == y :
|
||||
# scene.objects['Terrain']['scene_tile_noncontruct'].append([math.floor(x),y])
|
||||
# scene.objects['Terrain']['scene_tile_noncontruct'].append([math.ceil(x),y])
|
||||
# else:
|
||||
# scene.objects['Terrain']['scene_tile_noncontruct'].append([math.floor(x),math.floor(y)])
|
||||
# scene.objects['Terrain']['scene_tile_noncontruct'].append([math.floor(x),math.ceil(y)])
|
||||
# scene.objects['Terrain']['scene_tile_noncontruct'].append([math.ceil(x),math.floor(y)])
|
||||
# scene.objects['Terrain']['scene_tile_noncontruct'].append([math.ceil(x),math.ceil(y)])
|
||||
|
||||
# ###############################################################################
|
||||
# # Temporisation
|
||||
# ###############################################################################
|
||||
|
||||
# def ct_sleep (duration):
|
||||
# time.sleep(duration*(1/scene.objects['Terrain']['speed']))
|
||||
|
||||
# # def ct_tempo (duration):
|
||||
# # scene.objects['Terrain']['delay_cmd']=0
|
||||
# # while scene.objects['Terrain']['delay_cmd']<duration*(1/scene.objects['Terrain']['speed']):
|
||||
# # # print("Temporization commands :",scene.objects['Terrain']['delay_cmd'])
|
||||
# # time.sleep(0.001)
|
||||
# # # pass
|
||||
|
||||
# # def ct_tempo_wave (duration):
|
||||
# # scene.objects['Terrain']['delay_wave']=0
|
||||
# # while scene.objects['Terrain']['delay_wave']<duration*(1/scene.objects['Terrain']['speed']):
|
||||
# # # print("Temporization waves :",scene.objects['Terrain']['delay_wave'])
|
||||
# # time.sleep(0.001)
|
||||
# # # pass
|
||||
|
||||
# # def ct_tempo_wave_trigger (duree):
|
||||
# # print ("delay wave ", scene.objects['Terrain']['delay_wave'])
|
||||
|
||||
# ###############################################################################
|
||||
# # Affichage
|
||||
# ###############################################################################
|
||||
|
||||
# ##
|
||||
# # Texte du panel d'information
|
||||
# ##
|
||||
|
||||
# def ct_print (text):
|
||||
# # text_info (texte)
|
||||
# if text=="":
|
||||
# scene.objects['Info-1-text'].setVisible(False,False)
|
||||
# scene.objects['Info-2-text'].setVisible(False,False)
|
||||
# else:
|
||||
# lines_txt=text.split("\n", 6)
|
||||
# for i in range (len(lines_txt),6):
|
||||
# lines_txt.append("")
|
||||
# scene.objects['Info-1-text'].setVisible(True,False)
|
||||
# scene.objects['Info-2-text'].setVisible(True,False)
|
||||
# scene.objects['Info-1-text']['Text']=lines_txt[0]+"\n"+lines_txt[1]+"\n"+lines_txt[2]
|
||||
# scene.objects['Info-2-text']['Text']=lines_txt[3]+"\n"+lines_txt[4]+"\n"+lines_txt[5]
|
||||
|
||||
# ###############################################################################
|
||||
# # Dessin 3d
|
||||
# ###############################################################################
|
||||
|
||||
# def scn_draw3d(cont):
|
||||
# obj = cont.owner
|
||||
# if obj.sensors['Draw3d'].positive==False:
|
||||
# return
|
||||
# if len(scene.objects['Terrain']['draw3d_list'])==0:
|
||||
# scene.objects['Terrain']['draw3d_process']=False
|
||||
# return
|
||||
|
||||
# # Dépilage des draws à executer
|
||||
# for draw_cmd in scene.objects['Terrain']['draw3d_list']:
|
||||
|
||||
# # Archer (tir de flêche)
|
||||
# # scene.objects['Terrain']['draw3d_list'].append([20, "arrow", obj.name, bullet.name, target.name, "normal", 20])
|
||||
# if draw_cmd[1]=="arrow":
|
||||
# if draw_cmd[4] in scene.objects:
|
||||
# tower= scene.objects[draw_cmd[2]]
|
||||
# bullet = scene.objects[draw_cmd[3]]
|
||||
# target = scene.objects[draw_cmd[4]]
|
||||
# x0 = tower.worldPosition.x
|
||||
# y0 = tower.worldPosition.y
|
||||
# # z0 = tower.worldPosition.z+0.8 # ajustement +0.8
|
||||
# z0 = tower.worldPosition.z+1 # ajustement +1
|
||||
# x1 = target.worldPosition.x
|
||||
# y1 = target.worldPosition.y
|
||||
# z1 = target.worldPosition.z+0.5 # ajustement +0.5
|
||||
# if x1>x0:
|
||||
# angle_z =math.atan((y1-y0)/(x1-x0))+math.pi/2
|
||||
# else:
|
||||
# angle_z =math.pi+math.atan((y1-y0)/(x1-x0))+math.pi/2
|
||||
# angle_y =math.atan((z1-z0)/(math.sqrt((x1-x0)**2+(y1-y0)**2)))
|
||||
# step_x=(x1-x0)/draw_cmd[6]
|
||||
# step_y=(y1-y0)/draw_cmd[6]
|
||||
# step_z=(z1-z0)/draw_cmd[6]
|
||||
# step = draw_cmd[6]-draw_cmd[0]
|
||||
# bullet.worldPosition=[x0+step_x*step, y0+step_y*step, z0+step_z*step]
|
||||
# bullet.worldOrientation=[0, angle_y, angle_z]
|
||||
# draw_cmd[0] = draw_cmd[0]-scene.objects['Terrain']['speed']
|
||||
|
||||
# # Dégats
|
||||
# if draw_cmd[0]<=0:
|
||||
# bullet['activated']=False
|
||||
# bullet.setVisible(False)
|
||||
# target['hp'] = target['hp'] - tower['damage']
|
||||
# if target['hp']<=0: # Mort
|
||||
# target['dead']=True
|
||||
|
||||
# # Mage (cast)
|
||||
# # scene.objects['Terrain']['draw3d_list'].append([60, "cast", obj.name, cast.name, "slow", 60])
|
||||
# if draw_cmd[1]=="cast":
|
||||
# cast = scene.objects[draw_cmd[3]]
|
||||
# step = draw_cmd[5]-draw_cmd[0]
|
||||
# cast.worldScale=[0.05*step,0.05*step,0.05*step]
|
||||
# # cast.worldScale=[0.75*step,0.75*step,0.75*step]
|
||||
# draw_cmd[0] = draw_cmd[0]-scene.objects['Terrain']['speed']
|
||||
|
||||
# # Fin
|
||||
# if draw_cmd[0]<=0:
|
||||
# cast.setVisible(False)
|
||||
|
||||
# # Suppression des draws finis
|
||||
# i=0
|
||||
# for draw_cmd in scene.objects['Terrain']['draw3d_list']:
|
||||
# if draw_cmd[0]<=0:
|
||||
# scene.objects['Terrain']['draw3d_list'].pop(i)
|
||||
# else:
|
||||
# i=i+1
|
||||
# if len(scene.objects['Terrain']['draw3d_list'])==0:
|
||||
# scene.objects['Terrain']['draw3d_process']=False
|
||||
|
||||
# ###############################################################################
|
||||
# # Dessin 2d (bge.render.drawLine)
|
||||
# ###############################################################################
|
||||
|
||||
# def circle (center, radius, color):
|
||||
# ang = 0.0
|
||||
# # ang_step = 0.1
|
||||
# ang_step = 0.2
|
||||
# while ang< 2 * math.pi:
|
||||
# x0 = center[0]+float(radius*math.cos(ang))
|
||||
# y0 = center[1]+float(radius*math.sin(ang))
|
||||
# x1 = center[0]+float(radius*math.cos(ang+ang_step))
|
||||
# y1 = center[1]+float(radius*math.sin(ang+ang_step))
|
||||
# bge.render.drawLine([x0,y0,center[2]],[x1,y1,center[2]],color)
|
||||
# ang += ang_step
|
||||
|
||||
# ##
|
||||
# # Affiche les draws 2d en cours
|
||||
# #
|
||||
# # Type de draw 2d:
|
||||
# # arrow : [5, "arrow", [obj.worldPosition.x, obj.worldPosition.y, obj.worldPosition.z+0.8],target.name, angle3, ray_yellow,5]
|
||||
# # cast : [30, "cast", [obj.worldPosition.x, obj.worldPosition.y, obj.worldPosition.z+0.8], ray_blue,30]
|
||||
# # ray : [5, "ray", [obj.worldPosition.x, obj.worldPosition.y, obj.worldPosition.z+0.8],[target.worldPosition.x, target.worldPosition.y, target.worldPosition.z], angle3, ray_yellow,5]
|
||||
# ##
|
||||
|
||||
# def scn_draw2d(cont):
|
||||
# obj = cont.owner
|
||||
# if obj.sensors['Draw2d'].positive==False:
|
||||
# return
|
||||
# if len(scene.objects['Terrain']['draw2d_list'])==0:
|
||||
# scene.objects['Terrain']['draw2d_process']=False
|
||||
# return
|
||||
|
||||
# # Dépilage des draws à executer
|
||||
# for draw_cmd in scene.objects['Terrain']['draw2d_list']:
|
||||
|
||||
# # Archer (tir de flêche)
|
||||
# if draw_cmd[1]=="arrow":
|
||||
# if draw_cmd[3] in scene.objects:
|
||||
# # x0 = draw_cmd[2][0]+0.25*(math.cos(draw_cmd[4]))
|
||||
# # y0 = draw_cmd[2][1]+0.25*(math.sin(draw_cmd[4]))
|
||||
# x0 = draw_cmd[2][0]
|
||||
# y0 = draw_cmd[2][1]
|
||||
# z0 = draw_cmd[2][2]
|
||||
# x1 = scene.objects[draw_cmd[3]].worldPosition.x
|
||||
# y1 = scene.objects[draw_cmd[3]].worldPosition.y
|
||||
# z1 = scene.objects[draw_cmd[3]].worldPosition.z-0.1 # ajustement -0.1
|
||||
# distance = math.sqrt((x1-x0)**2+(y1-y0)**2+(z1-z0)**2)
|
||||
# distance_xy = math.sqrt((x1-x0)**2+(y1-y0)**2)
|
||||
# distance_z = z1-z0
|
||||
# angle_z =math.atan((z1-z0)/(distance_xy))
|
||||
# angle_xy =math.atan((y1-y0)/(x1-x0))
|
||||
# step=distance_xy/(2+draw_cmd[6])
|
||||
# step_z=distance_z/(2+draw_cmd[6])
|
||||
# if x1>x0:
|
||||
# angle2=angle_xy
|
||||
# else:
|
||||
# angle2=math.pi+angle_xy
|
||||
# x2=x0+(((6-draw_cmd[0])*step)*(math.cos(angle2)))
|
||||
# y2=y0+(((6-draw_cmd[0])*step)*(math.sin(angle2)))
|
||||
# z2=z0-(((6-draw_cmd[0])*step_z)*(math.sin(angle_z)))
|
||||
# x3=x0+(((6-draw_cmd[0])*step+step)*(math.cos(angle2)))
|
||||
# y3=y0+(((6-draw_cmd[0])*step+step)*(math.sin(angle2)))
|
||||
# z3=z0-(((6-draw_cmd[0])*step_z+step_z)*(math.sin(angle_z)))
|
||||
# bge.render.drawLine([x2,y2, z2], [x3,y3,z3], draw_cmd[5])
|
||||
# draw_cmd[0] = draw_cmd[0]-scene.objects['Terrain']['speed']
|
||||
# # if scene.objects['Terrain']['speed']<1:
|
||||
# # draw_cmd[0] = draw_cmd[0]-scene.objects['Terrain']['speed']
|
||||
# # else:
|
||||
# # draw_cmd[0] = draw_cmd[0]-1
|
||||
# # bge.render.drawLine([draw_cmd[2][0]+((6-draw_cmd[0])*0.25)*(math.cos(draw_cmd[4])), draw_cmd[2][1]+((6-draw_cmd[0])*0.25)*(math.sin(draw_cmd[4])),draw_cmd[2][2]],
|
||||
# # [draw_cmd[2][0]+((6-draw_cmd[0])*0.25+0.25)*(math.cos(draw_cmd[4])), draw_cmd[2][1]+((6-draw_cmd[0])*0.25+0.25)*(math.sin(draw_cmd[4])),draw_cmd[2][2]],
|
||||
# # draw_cmd[5])
|
||||
|
||||
# # Mage (cast)
|
||||
# # FIXME : Problème
|
||||
# if draw_cmd[1]=="cast": # Mage (cast)
|
||||
# circle(draw_cmd[2], 3.1-draw_cmd[0]*0.1, draw_cmd[3])
|
||||
# circle(draw_cmd[2], 3-draw_cmd[0]*0.1, draw_cmd[3])
|
||||
# circle(draw_cmd[2], 2.9-draw_cmd[0]*0.1, draw_cmd[3])
|
||||
# draw_cmd[0] = draw_cmd[0]-scene.objects['Terrain']['speed']
|
||||
# # if scene.objects['Terrain']['speed']<=2:
|
||||
# # draw_cmd[0] = draw_cmd[0]-scene.objects['Terrain']['speed']
|
||||
# # if scene.objects['Terrain']['speed']==4:
|
||||
# # draw_cmd[0] = draw_cmd[0]-draw_cmd[4]/2
|
||||
# # circle(draw_cmd[2], 3, draw_cmd[3]) # simple
|
||||
# # radius=[3,3,2.5,2.5,2,2,1.5,1.5,1,1,1] # basé sur un tableau
|
||||
# # circle(draw_cmd[2], radius[draw_cmd[0]], draw_cmd[3])
|
||||
|
||||
# # Rayon
|
||||
# if draw_cmd[1]=="ray":
|
||||
# if draw_cmd[3] in scene.objects:
|
||||
# x0 = draw_cmd[2][0]+0.25*(math.cos(draw_cmd[4]))
|
||||
# y0 = draw_cmd[2][1]+0.25*(math.sin(draw_cmd[4]))
|
||||
# x1 = scene.objects[draw_cmd[3]].worldPosition.x
|
||||
# y1 = scene.objects[draw_cmd[3]].worldPosition.y
|
||||
# z1 = scene.objects[draw_cmd[3]].worldPosition.z
|
||||
# bge.render.drawLine([x0,y0, draw_cmd[2][2]], [x1,y1,z1], draw_cmd[5]) # suivi minion
|
||||
# # bge.render.drawLine([draw_cmd[2][0]+0.25*(math.cos(draw_cmd[4])), draw_cmd[2][1]+0.25*(math.sin(draw_cmd[4])), draw_cmd[2][2]], draw_cmd[3], draw_cmd[5]) # décalage minion
|
||||
# # bge.render.drawLine(draw_cmd[2], draw_cmd[3], draw_cmd[5]) # simple
|
||||
# draw_cmd[0] = draw_cmd[0]-scene.objects['Terrain']['speed']
|
||||
|
||||
# # Suppression des draws finis
|
||||
# i=0
|
||||
# for draw_cmd in scene.objects['Terrain']['draw2d_list']:
|
||||
# if draw_cmd[0]<=0:
|
||||
# scene.objects['Terrain']['draw2d_list'].pop(i)
|
||||
# else:
|
||||
# i=i+1
|
||||
# if len(scene.objects['Terrain']['draw2d_list'])==0:
|
||||
# scene.objects['Terrain']['draw2d_process']=False
|
50
rp_map1.py
Normal file
50
rp_map1.py
Normal file
@ -0,0 +1,50 @@
|
||||
import bge # Bibliothèque Blender Game Engine (UPBGE)
|
||||
import bpy # Blender
|
||||
from rp_lib import * # Bibliothèque CodeTower
|
||||
import os
|
||||
|
||||
###############################################################################
|
||||
# rp_map1.py
|
||||
# @title: Carte 1 pour Ropy
|
||||
# @project: Ropy (Blender-EduTech)
|
||||
# @lang: fr
|
||||
# @authors: Philippe Roy <philippe.roy@ac-grenoble.fr>
|
||||
# @copyright: Copyright (C) 2020-2022 Philippe Roy
|
||||
# @license: GNU GPL
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
scene = bge.logic.getCurrentScene()
|
||||
|
||||
###############################################################################
|
||||
# Map
|
||||
###############################################################################
|
||||
|
||||
# Initialization
|
||||
def map_init():
|
||||
|
||||
# Base
|
||||
scene.objects['Terrain']['size'] = [-15,15,-10,10] # Map size
|
||||
|
||||
# Landscape
|
||||
# file_path = 'asset/map/map1-landscape.blend'
|
||||
# inner_path = 'Object'
|
||||
# object_name = 'Landscape'
|
||||
# bpy.ops.wm.append(
|
||||
# filepath=os.path.join(file_path, inner_path, object_name),
|
||||
# directory=os.path.join(file_path, inner_path),
|
||||
# filename=object_name)
|
||||
|
||||
# Reset counters
|
||||
def map_reset():
|
||||
scene.objects['Points']['step']=0
|
||||
scene.objects['Points']['nbligne']=0
|
||||
|
||||
# scene.objects['Points']['lifes']=10
|
||||
# scene.objects['Points']['lifes_max']=10
|
||||
# scene.objects['Points']['coins']=0
|
||||
# scene.objects['Points']['level']=0
|
||||
# scene.objects['Points']['level_max']=1
|
||||
# scene.objects['Points']['minions']=0
|
||||
# scene.objects['Points']['minions_run']=0
|
||||
# scene.objects['Points']['wave']=1
|
Loading…
Reference in New Issue
Block a user