diff --git a/#rp_doc.py# b/#rp_doc.py# new file mode 100644 index 0000000..4cf4a1d --- /dev/null +++ b/#rp_doc.py# @@ -0,0 +1,715 @@ +import bge # Bibliothèque Blender Game Engine (UPBGE) +import rp_map1 # Map definition +import webbrowser + +############################################################################### +# rp_doc.py +# @title: Documentation du Rover Ropy +# @project: Ropy (Blender-EduTech) +# @lang: fr +# @authors: Philippe Roy +# @copyright: Copyright (C) 2020-2023 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. +############################################################################### + +scene = bge.logic.getCurrentScene() + +# Colors +color_doc_chap = (0, 1, 0.857,1) # Turquoise +color_doc_fct = (0, 1, 0.857,1) # Turquoise +color_doc_hl = (0.799, 0.617, 0.021, 1) # Jaune +color_doc_activate = (0.936, 0.033, 1, 1) # Rose +color_doc_mission = (1, 0.192, 0.03, 1) # Orange + +# 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 + +# Cards description +card_description ={} + +# Missions +card_description.update(rp_map1.get_missions_description()) +missions_card=rp_map1.get_missions_card() + +################################################################################ +# Documentation Rover +################################################################################ + +rover_card=["forward-card", "turn-card", "delineate-card", "detect-card", "radar-card", "twins-card"] +rover_card=rover_card+["speed-card", "paint-card", "battery-card", "beacon-card"] + +# Avancer et reculer +rp_forward_title="Avancer et reculer" +rp_forward_text=" rp_avancer() \n →-> Avance d'un pas en avant. \n \n rp_reculer() \n -> Recule d'un pas." +rp_forward_type="standard" +card_description.update({"forward-card" : [rp_forward_title, rp_forward_text, rp_forward_type]}) + +# Tourner +rp_turn_title="Tourner" +rp_turn_text=" rp_gauche() \n -> Tourne à gauche (90°).\n \n rp_droite() \n -> Tourne à droite (90°)." +rp_turn_type="standard" +card_description.update({"turn-card" : [rp_turn_title, rp_turn_text, rp_turn_type]}) + +# Baliser +rp_delineate_title="Baliser" +rp_delineate_text=" rp_marquer() \n -> Place une balise sur la case. \n \n Ropy possède que 20 balises, il ne \n peut pas en poser une de plus.\n\n Avec l'amélioration \"Balise +\", le \n nombre de balise transportées est \n étendu à 200." +rp_delineate_type="standard" +card_description.update({"delineate-card" : [rp_delineate_title, rp_delineate_text, rp_delineate_type]}) + +# Détecter +rp_detect_title="Détecter" +rp_detect_text=" rp_detect() \n -> Détecte un obstacle.\n \n La fonction retourne : \n - \"True\" si il a un obstacle, \n - \"False\" si il n'y a pas d'obstacle." +rp_detect_type="standard" +card_description.update({"detect-card" : [rp_detect_title, rp_detect_text, rp_detect_type]}) + +# Radar +rp_radar_title="Radar" +rp_radar_text=" Le radar n'est toujours pas \n opérationnel ! \n \n Mais où est donc encore passé Thomas !" +rp_radar_type="mission" +card_description.update({"radar-card" : [rp_radar_title, rp_radar_text, rp_radar_type]}) + +# Jumeau numérique +rp_twins_title="Jumeau numérique" +rp_twins_text=""" Via une liaison série, Ropy peut être \n le jumeau numérique d'un robot réel. \n + rp_jumeau(port, vitesse=115200) \n -> Active le jumeau réel par la liaison \n série. Si le port n'est pas spécifié, il \n est recherché automatiquement. \n + rp_serie_msg(texte) \n -> Envoi un message \n \n texte=rp_serie_rcpt() \n -> Reçoit un message""" + +# Message envoyé (asynchrone) : \n avancer : a, reculer : r, droite : d, \n gauche g, marquer : m et forer : f \n\n\n """ +rp_twins_type="standard" +card_description.update({"twins-card" : [rp_twins_title, rp_twins_text, rp_twins_type]}) + +# Cards description pour le magasin +storecard_description ={} + +# Speed - Vitesse +rp_speed_title="Vitesse" +rp_speed_text=" L'amélioration \"Vitesse\" permet de \n changer la vitesse des déplacements \n par l'interface (en bas à gauche).\n\n" +rp_speed_text=rp_speed_text + " La vitesse est modifiable par codage : \n" +rp_speed_text=rp_speed_text + " rp_vitesse(nouvelle_vitesse), où \n la vitesse est une valeur de 0,1 à 10.\n\n La fonction rp_vitesse() retourne la \n vitesse actuelle." +rp_speed_store="Permet de modifier\nla vitesse des \ndéplacements." +rp_speed_purchased="Je vois ... \n l'efficacité, hein ! \n Vous verrez avec \n ces moteurs,\n c'est autre vie." +rp_speed_type="upgrade" +card_description.update({"speed-card" : [rp_speed_title, rp_speed_text, rp_speed_store, rp_speed_purchased, rp_speed_type]}) + +# Paint - Peinture +rp_paint_title="Peinture" +rp_paint_text=" rp_couleur(objets, couleur) \n -> Change la couleur du groupe \n d'objets 3d. \n" +rp_paint_text=rp_paint_text + " - La couleur est un tuple au format \n (R,V,B,Alpha) avec des valeurs de 0 à 1.\n" +rp_paint_text=rp_paint_text + " - objets peut être : \"Rover 1\",\n \"Rover 2\", \"Rover 3\", \"Station 1\", \n \"Station 2\", \"Station 3\", \"Station 4\", \n \"Balises\" ou \"Balise 1\" à \"Balise 200\".\n\n" +rp_paint_text=rp_paint_text + " rp_couleur_init(objets) \n -> Réinitialise la couleur des objets.\n rp_couleur_init() réinitialise tout !" +rp_paint_store="On refait la déco ?" +rp_paint_purchased="Rien de tel qu'un \n peu de couleur \n dans ce monde \n de brute !" +rp_paint_type="upgrade" +card_description.update({"paint-card" : [rp_paint_title, rp_paint_text, rp_paint_store, rp_paint_purchased, rp_paint_type]}) + +# Battery + - Batterie + +rp_battery_title="Batterie +" +rp_battery_text=" L'amélioration \"Batterie +\" permet \n d'augmenter la capacité de la batterie \n du Rover à 200 pas (contre 20 pas). \n\n" +rp_battery_text=rp_battery_text + " La fonction rp_batterie() retourne \n la charge actuelle de la batterie \n (valeur de 0 à 100 %)." +rp_battery_store="Augmente la capacité \nde la batterie à 200 \nmouvements (contre \n20, plutôt faible ...).\n\n" +rp_battery_purchased="Très bon choix ! \n Cette batterie \n vous va comme \n un gant." +rp_battery_type="upgrade" +card_description.update({"battery-card" : [rp_battery_title, rp_battery_text, rp_battery_store, rp_battery_purchased, rp_battery_type]}) + +# Beacon + - Balise + +rp_beacon_title="Balise +" +rp_beacon_text=" L'amélioration \"Balise +\" permet \n d'augmenter le nombre de balises \n pouvant être posées à 200 (contre 20). \n\n" +rp_beacon_text=rp_beacon_text + " La fonction rp_balise() retourne \n le nombre de balises dejà posées \n lors du trajet." +rp_beacon_store="Porte le nombre de \nbalises transportées\nà 200 (contre 20)." +rp_beacon_purchased="Les colis viennent \n tout juste d'être \n livrés. Un vrai sapin de Noël, \nce terrain !" +rp_beacon_type="upgrade" +card_description.update({"beacon-card" : [rp_beacon_title, rp_beacon_text, rp_beacon_store, rp_beacon_purchased, rp_beacon_type]}) + +############################################################################### +# Documentation Python +############################################################################### + +# python_card=["function-card", "alternative-card", "loop-card", "flow-card", "text-card", "list-card", "dict-card", "oop-card", "console-card", "sleep-card"] +python_card=["function-card", "alternative-card", "loop-card", "flow-card", "text-card", "list-card", "dict-card", "console-card", "sleep-card", "python-card"] + +# Fonction +rp_function_title="Fonction" +rp_function_text=" La définition d'une fonction se fait \n avec \"def\". La fonction peut \n renvoyer une valeur avec \"return\". \n\n" +rp_function_text=rp_function_text + " def fonction_1 (arguments) : \n instruction_1 \n instruction_2 \n ....\n return valeurs_renvoyées \n\n" +rp_function_text=rp_function_text + " Les arguments sont des données \n transmises à la fonction." +rp_function_url=[["w3schools.com : functions","https://www.w3schools.com/python/python_functions.asp"]] +card_description.update({"function-card" : [rp_function_title, rp_function_text, rp_function_url]}) + +# Alternative +rp_alternative_title="Alternative" +rp_alternative_text=" L'alternative permet d'éxécuter des \n instructions en fonction d'un test. \n" +rp_alternative_text=rp_alternative_text + " Elle se programme en suivant la \n suite : si ... alors ... sinon ... où \n" +rp_alternative_text=rp_alternative_text + " \"si\" est \"if \" et \"sinon\" est \"else\". \n\n" +rp_alternative_text=rp_alternative_text + " if condition :\n" +rp_alternative_text=rp_alternative_text + " instruction_1\n" +rp_alternative_text=rp_alternative_text + " else : \n" +rp_alternative_text=rp_alternative_text + " instruction_2\n\n" +rp_alternative_text=rp_alternative_text + "Le sinon (\"else\") est facultatif." +rp_alternative_url=[["w3schools.com : if ... else","https://www.w3schools.com/python/python_conditions.asp"]] +card_description.update({"alternative-card" : [rp_alternative_title, rp_alternative_text, rp_alternative_url]}) + +# Boucles +rp_loop_title="Boucles" +rp_loop_text=" Il y a deux types de boucle : \n - avec \"for\" pour définir un nombre \n de répétition (ici N), \n - avec \"while\" (tant que) pour \n prendre en compte une condition. \n \n" +rp_loop_text=rp_loop_text + " for i in range (n) : \n instruction \n \n" +rp_loop_text=rp_loop_text + " while condition : \n instruction" +rp_loop_url=[["w3schools.com : for","https://www.w3schools.com/python/python_for_loops.asp"], + ["w3schools.com : while","https://www.w3schools.com/python/python_while_loops.asp"]] +card_description.update({"loop-card" : [rp_loop_title, rp_loop_text, rp_loop_url]}) + +# Flux +rp_flow_title="Contrôle du flux" +rp_flow_text=" Les structures (if, while, for) peuvent \n être gérées plus finement par les \n fonctions \"break\", \"continue\" et \"pass\". \n\n" +rp_flow_text= rp_flow_text + "- \"break\" : Termine l'itération en cours \n et arrête la boucle.\n" +rp_flow_text= rp_flow_text + "- \"continue\" : Termine l'itération en \n cours et reprend la boucle.\n" +rp_flow_text= rp_flow_text + "- \"pass\" : Instruction vide." +rp_flow_url=[["w3schools.com : break","https://www.w3schools.com/python/ref_keyword_break.asp"], + ["w3schools.com : continue","https://www.w3schools.com/python/ref_keyword_break.asp"], + ["w3schools.com : pass","https://www.w3schools.com/python/ref_keyword_pass.asp"]] +card_description.update({"flow-card" : [rp_flow_title, rp_flow_text, rp_flow_url]}) + +# Chaîne de caractères +rp_text_title="Chaîne de caractères" +rp_text_text=""" Une chaîne de caractères correspond \n à un texte (mot, phrase). Elle est \n délimitée par " ou ' : texte = "Bonjour !" \n +- texte1 + texte2 : concaténe plusieurs \n chaînes. +- len(texte) : longueur du texte. +- "\\n" : caractère aller à la ligne. +- texte[i] : le caractère du rang i. +- texte[2:5] : les caractères du \n rang 2 au rang 5. +- texte.replace("a","b") : remplace les \n "a" par des "b". """ +rp_text_url=[ + ["Doc. Python v3 Français : string","https://docs.python.org/fr/3/library/string.html"], + ["w3schools.com : strings","https://www.w3schools.com/python/python_strings.asp"]] +card_description.update({"text-card" : [rp_text_title, rp_text_text, rp_text_url]}) + +# Liste +rp_list_title="Liste" +rp_list_text=""" Une liste est une séquence d'éléments. \n Elle est délimitée par des crochets : + liste = ["pomme", 7, "rouge", True] \n +- liste[i] : renvoie l'élément du rang i \n de la liste (commence à 0). +- liste.append("neige") : ajoute "neige" \n à la fin de la liste. +- len(liste) : nombre d'éléments. +- liste.sort() : classe par ordre \n croissant la liste. +- liste.remove("rouge") : enlève la \n première occurence de "rouge".""" +rp_list_url=[ + ["Doc. Python v3 Français : list","https://docs.python.org/fr/3/library/stdtypes.html#sequence-types-list-tuple-range"], + ["w3schools.com : lists","https://www.w3schools.com/python/python_lists.asp"]] +card_description.update({"list-card" : [rp_list_title, rp_list_text, rp_list_url]}) + +# Dictionnaire +rp_dict_title="Dictionnaire" +rp_dict_text=""" Un dictionnaire est une collection \n d'éléments. Il est délimité par des \n accolades, chaque valeur est associée + à une clé unique : dct={'nom':"Haddock",\n 'prénom':"Archibald", 'année': 1940} \n +- dct[clé] : valeur liée à la clé. +- dct.update('domicile' : "Moulinsart") : \n met à jour les paires de clé/valeur. +- len(dct) : nombre d'éléments. +- list(dct) : liste des clés. +- dct.pop('année') : enlève la valeur \n associée à la clé (ici 1940).""" +rp_dict_url=[ + ["Doc. Python v3 Français : dict","https://docs.python.org/fr/3/library/stdtypes.html#mapping-types-dict"], + ["w3schools.com : dictionaries","https://www.w3schools.com/python/python_dictionaries.asp"]] +card_description.update({"dict-card" : [rp_dict_title, rp_dict_text, rp_dict_url]}) + +# Objet (POO) +rp_oop_title="Programmation\norientée objet (POO)" +rp_oop_text="\nFIXME" +rp_oop_url=[["w3schools.com : classes & objects","https://www.w3schools.com/python/python_classes.asp"]] +card_description.update({"oop-card" : [rp_oop_title, rp_oop_text, rp_oop_url]}) + +# Console +rp_console_title="Console" +rp_console_text=" Si vous avez executé Ropy dans un \n terminal avec l'option \"-con\", vous \n pouvez utiliser le terminal comme \n console de debuggage.\n\n" +rp_console_text= rp_console_text + " print(\"Bonjour !\") \n -> Affiche le texte dans la console.\n\n" +rp_console_text= rp_console_text + " variable = input () \n -> Permet la saisie, par exemple : \n" +rp_console_text= rp_console_text + " entree = \"\"\n while entree == \"\" :\n entree = input ()" +rp_console_url=[["w3schools.com : print","https://www.w3schools.com/python/ref_func_print.asp"], + ["w3schools.com : input","https://www.w3schools.com/python/ref_func_input.asp"]] +card_description.update({"console-card" : [rp_console_title, rp_console_text, rp_console_url]}) + +# Temps +rp_sleep_title="Gestion du temps" +rp_sleep_text=" Vous pouvez créer des temporisations \n dans le déroulement du script.\n\n" +rp_sleep_text= rp_sleep_text + " time.sleep(x) \n -> Marque d'un temps d'arrêt de \n x secondes.\n\n" +rp_sleep_text= rp_sleep_text + " Il faudra préalablement importer la \n bibliothèque \"time\" avec \"import time\"." +rp_sleep_url=[["docs.python.org : sleep","https://docs.python.org/fr/3/library/time.html#time.sleep"]] +card_description.update({"sleep-card" : [rp_sleep_title, rp_sleep_text, rp_sleep_url]}) + +# Python +rp_python_title="Langage Python" +rp_python_text=""" Python est un langage de \n programmation interprété open source. + Python vise à être visuellement épuré \n avec une syntaxe clairement séparée \n des mécanismes de bas niveau.\n + Python possède beaucoup de \n bibliothèques spécialisées. + Multiplateformes et multiparadigme, + il est utilisé dans de nombreux \n contextes : scriptage, prototypage, \n calcul numérique, enseignement, ou \n encore comme langage de commande.""" +rp_python_url=[["python.org","https://python.org"], ["AFPy","https://www.afpy.org"]] +card_description.update({"python-card" : [rp_python_title, rp_python_text, rp_python_url]}) + +############################################################################### +# Interface +############################################################################### + +## +# Initialisation de la tablette +## + +def init(): + + # Mettre les couleurs sur les icones (chapitres et cartes) + chap=("general", "missions", "rover", "python") + for page in chap: + scene.objects["Doc-"+page].color = color_doc_chap + scene.objects["Doc-"+page+"-text"].color = color_doc_chap + for i in range(len(missions_card)): + scene.objects[missions_card[i]].color = color_doc_fct + scene.objects[missions_card[i]+"-icon"].color = color_doc_fct + scene.objects[missions_card[i]+"-text"].color = color_doc_fct + for i in range(len(rover_card)): + scene.objects[rover_card[i]].color = color_doc_fct + scene.objects[rover_card[i]+"-icon"].color = color_doc_fct + scene.objects[rover_card[i]+"-text"].color = color_doc_fct + for i in range(len(python_card)): + scene.objects[python_card[i]].color = color_doc_fct + scene.objects[python_card[i]+"-icon"].color = color_doc_fct + scene.objects[python_card[i]+"-text"].color = color_doc_fct + scene.objects['Book_level_button'].color = color_doc_chap + scene.objects['Book_level_button'].setVisible(False,True) + scene.objects['Book_python_url_title'].setVisible(False,True) + scene.objects['Book_python_url0'].color = color_doc_chap + scene.objects['Book_python_url0'].setVisible(False,True) + scene.objects['Book_python_url1'].color = color_doc_chap + scene.objects['Book_python_url1'].setVisible(False,True) + scene.objects['Book_python_url2'].color = color_doc_chap + scene.objects['Book_python_url2'].setVisible(False,True) + scene.objects["mission_"+str(scene.objects['Points']['mission'])+"-card"].color = color_doc_mission + scene.objects["mission_"+str(scene.objects['Points']['mission'])+"-card-icon"].color = color_doc_mission + scene.objects["mission_"+str(scene.objects['Points']['mission'])+"-card-text"].color = color_doc_mission + + # Chargement du texte + # text_load() + text_dynamic_load() # en dynamique + + # Mémorisation de la position des pages + for page in chap: + scene.objects["Doc_chap-"+page]['init_lx']=scene.objects["Doc_chap-"+page].worldPosition.x + scene.objects["Doc_chap-"+page]['init_ly']=scene.objects["Doc_chap-"+page].worldPosition.y + scene.objects["Doc_chap-"+page]['init_lz']=scene.objects["Doc_chap-"+page].worldPosition.z + + # Page par défaut + scene.objects['Doc']['page_chap'] = "general" + +## +# Ouvrir la tablette +## + +def open(): + + # Placer la tablette + # scene.objects['Doc'].worldPosition = [0, -21, 15.75] + scene.objects['Doc'].worldPosition = [0, -21, 15.8] + scene.objects['Doc_close'].color = color_doc_chap + scene.objects['Doc'].setVisible(True,True) + # text_hide() + text_dynamic_hide() + + # Placer le nouveau chapitre + name_chap = scene.objects['Doc']['page_chap'] + scene.objects['Doc-'+name_chap].color = color_doc_activate + scene.objects['Doc-'+name_chap+'-text'].color = color_doc_activate + scene.objects['Doc_chap-'+name_chap].worldPosition = scene.objects['Doc'].worldPosition + scene.objects['Doc_chap-'+name_chap].setVisible(True,True) + + # Affichage ou pas du bouton de selection de la mission + if name_chap == "missions": + name_fct = scene.objects['Doc_chap-missions']['page_fct'] + if name_fct !="": + if scene.objects[name_fct]['mission'] <= scene.objects['Points']['level'] and scene.objects[name_fct]['mission'] != scene.objects['Points']['mission']: + scene.objects['Book_level_button'].setVisible(True,True) + else: + scene.objects['Book_level_button'].setVisible(False,True) + else: + scene.objects['Book_level_button'].setVisible(False,True) + + # Upgrade + if name_chap == "rover": + upgrade_card=("battery", "beacon", "paint", "speed") + for i in range(len(upgrade_card)): + if scene.objects['Points']['upgrade_'+upgrade_card[i]]==True: + scene.objects[upgrade_card[i]+'-card'].setVisible(True,True) + scene.objects[upgrade_card[i]+'-card-colbox'].restorePhysics() + else: + scene.objects[upgrade_card[i]+'-card'].setVisible(False,True) + scene.objects[upgrade_card[i]+'-card-colbox'].suspendPhysics() + + # URL Python + if name_chap == "python": + name_fct = scene.objects['Doc_chap-python']['page_fct'] + scene.objects['Book_python_url_title'].setVisible(False,True) + scene.objects['Book_python_url0'].setVisible(False,True) + scene.objects['Book_python_url1'].setVisible(False,True) + scene.objects['Book_python_url2'].setVisible(False,True) + if name_fct !="": + scene.objects['Book_python_url_title'].setVisible(True,True) + for i in range(len(card_description[name_fct][2])): + scene.objects['Book_python_url'+str(i)]['Text'] = card_description[name_fct][2][i][0] + scene.objects['Book_python_url'+str(i)].setVisible(True,True) + + # Afficher le texte de la carte active + if name_chap != "general" and scene.objects['Doc_chap-'+name_chap]['page_fct'] !="": + name_fct = scene.objects['Doc_chap-'+name_chap]['page_fct'] + scene.objects['Doc_title']['Text'] = card_description[name_fct][0] + scene.objects['Doc_title'].setVisible(True, False) + text_dynamic_show(name_fct) + # text_show(name_fct) + else: + scene.objects['Doc_title']['Text'] = " " + scene.objects['Doc_title'].setVisible(False,True) + text_dynamic_hide() + # text_hide() + +## +# Fermeture du livre +## + +def close(): + # sound_play (sndbuff_book_close) + chap=("general", "missions", "rover", "python") + for page in chap: + scene.objects["Doc_chap-"+page].setVisible(False,True) + scene.objects["Doc_chap-"+page].worldPosition.x = scene.objects["Doc_chap-"+page]['init_lx'] + scene.objects["Doc_chap-"+page].worldPosition.y = scene.objects["Doc_chap-"+page]['init_ly'] + scene.objects["Doc_chap-"+page].worldPosition.z = scene.objects["Doc_chap-"+page]['init_lz'] + scene.objects['Doc'].setVisible(False,True) + scene.objects['Doc'].worldPosition = [35, -2, 2] + +## +# Highlight du livre +## + +def hl (cont): + + # Activation + if cont.sensors['MO'].status == JUST_ACTIVATED : + obj = cont.owner + name=obj.name[:-7] + name_text=name+"-text" + name_icon=name+"-icon" + + # Close ou lien + if name == "Doc_close" or name == "Book_level_button": + scene.objects[name].color = color_doc_hl + elif name == "Book_python_url0" or name == "Book_python_url1" or name == "Book_python_url2": + scene.objects[name].color = color_doc_hl + else: + if "Doc-" in name : # Chapitre + if name[4:] == scene.objects['Doc']['page_chap']: + scene.objects[name].color = color_doc_activate + scene.objects[name_text].color = color_doc_activate + else: + scene.objects[name].color = color_doc_hl + scene.objects[name_text].color = color_doc_hl + else: # Carte + name_chap = scene.objects['Doc']['page_chap'] + if name == scene.objects['Doc_chap-'+name_chap]['page_fct'] : + scene.objects[name].color = color_doc_activate + scene.objects[name_text].color = color_doc_activate + scene.objects[name_icon].color = color_doc_activate + else: + scene.objects[name].color = color_doc_hl + scene.objects[name_text].color = color_doc_hl + scene.objects[name_icon].color = color_doc_hl + + # Désactivation + if cont.sensors['MO'].status == JUST_RELEASED : + obj = cont.owner + name=obj.name[:-7] + name_text=obj.name[:-7]+"-text" + name_icon=obj.name[:-7]+"-icon" + + # Close + if name == "Doc_close" or name == "Book_level_button": + scene.objects[name].color = color_doc_fct + elif name == "Book_python_url0" or name == "Book_python_url1" or name == "Book_python_url2": + scene.objects[name].color = color_doc_fct + else: + if "Doc-" in name : # Chapitre + if name[4:] == scene.objects['Doc']['page_chap']: + scene.objects[name].color = color_doc_activate + scene.objects[name_text].color = color_doc_activate + else: + scene.objects[name].color = color_doc_fct + scene.objects[name_text].color = color_doc_fct + else: # Carte + name_chap = scene.objects['Doc']['page_chap'] + if name == scene.objects['Doc_chap-'+name_chap]['page_fct'] : + scene.objects[name].color = color_doc_activate + scene.objects[name_text].color = color_doc_activate + scene.objects[name_icon].color = color_doc_activate + else: + if name == "mission_"+str(scene.objects['Points']['mission'])+"-card": + scene.objects[name].color = color_doc_mission + scene.objects[name_text].color = color_doc_mission + scene.objects[name_icon].color = color_doc_mission + else: + scene.objects[name].color = color_doc_fct + scene.objects[name_text].color = color_doc_fct + scene.objects[name_icon].color = color_doc_fct + +## +# Afficher le chapitre +## + +def chapter(cont): + if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive and cont.sensors['Click'].positive: + # sound_play (sndbuff_book_flip) + obj = cont.owner + scene.objects['Doc_title']['Text'] = " " + + # Enlever l'ancien chapitre + scene.objects['Doc-'+scene.objects['Doc']['page_chap']].color = color_doc_chap + scene.objects['Doc-'+scene.objects['Doc']['page_chap']+'-text'].color = color_doc_chap + scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']].worldPosition.x = scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']]['init_lx'] + scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']].worldPosition.y = scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']]['init_ly'] + scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']].worldPosition.z = scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']]['init_lz'] + if scene.objects['Doc']['page_chap'] != "general" and scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']]['page_fct'] !="": + # text_hide(scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']]['page_fct']) + text_dynamic_hide(scene.objects["Doc_chap-"+scene.objects['Doc']['page_chap']]['page_fct']) + + # Placer le nouveau chapitre + name_chap= obj.name[4:-7] + scene.objects['Doc-'+name_chap].color = color_doc_activate + scene.objects['Doc-'+name_chap+'-text'].color = color_doc_activate + scene.objects['Doc']['page_chap'] = name_chap + scene.objects['Doc_chap-'+name_chap].worldPosition = scene.objects['Doc'].worldPosition + scene.objects['Doc_chap-'+name_chap].setVisible(True,True) + + # Bouton de selection de la mission + if name_chap == "missions": + name_fct = scene.objects['Doc_chap-missions']['page_fct'] + if name_fct !="": + if scene.objects[name_fct]['mission'] <= scene.objects['Points']['level'] and scene.objects[name_fct]['mission'] != scene.objects['Points']['mission']: + scene.objects['Book_level_button'].setVisible(True,True) + else: + scene.objects['Book_level_button'].setVisible(False,True) + else: + scene.objects['Book_level_button'].setVisible(False,True) + + # Upgrade + if name_chap == "rover": + upgrade_card=("battery", "beacon", "paint", "speed") + for i in range(len(upgrade_card)): + if scene.objects['Points']['upgrade_'+upgrade_card[i]]==True: + scene.objects[upgrade_card[i]+'-card'].setVisible(True,True) + scene.objects[upgrade_card[i]+'-card-colbox'].restorePhysics() + else: + scene.objects[upgrade_card[i]+'-card'].setVisible(False,True) + scene.objects[upgrade_card[i]+'-card-colbox'].suspendPhysics() + + # URL Python + if name_chap == "python": + name_fct = scene.objects['Doc_chap-python']['page_fct'] + scene.objects['Book_python_url_title'].setVisible(False,True) + scene.objects['Book_python_url0'].setVisible(False,True) + scene.objects['Book_python_url1'].setVisible(False,True) + scene.objects['Book_python_url2'].setVisible(False,True) + if name_fct !="": + scene.objects['Book_python_url_title'].setVisible(True,True) + for i in range(len(card_description[name_fct][2])): + scene.objects['Book_python_url'+str(i)]['Text'] = card_description[name_fct][2][i][0] + scene.objects['Book_python_url'+str(i)].setVisible(True,True) + + # Afficher le texte de la carte active + if name_chap != "general" and scene.objects['Doc_chap-'+name_chap]['page_fct'] !="": + name_fct = scene.objects['Doc_chap-'+name_chap]['page_fct'] + scene.objects['Doc_title']['Text'] = card_description[name_fct][0] + scene.objects['Doc_title'].setVisible(True, False) + text_dynamic_show(name_fct) + # text_show(name_fct) + else: + scene.objects['Doc_title']['Text'] = " " + scene.objects['Doc_title'].setVisible(False,True) + text_dynamic_hide() + # text_hide() + +## +# Afficher les details de la fonction à partir d'une carte +## + +def card (cont): + if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive : + # sound_play (sndbuff_book_flip) + obj = cont.owner + name_chap = scene.objects['Doc']['page_chap'] + name_fct= obj.name[:-7] + scene.objects['Doc_title']['Text'] = " " + + # Enlever l'ancienne carte + if scene.objects['Doc_chap-'+name_chap]['page_fct'] !="": + # text_dynamic_hide(name_old_fct) + # text_hide(scene.objects['Doc_chap-'+name_chap]['page_fct']) + text_dynamic_hide(scene.objects['Doc_chap-'+name_chap]['page_fct']) + + # Placer la carte de la mission active + if scene.objects['Doc_chap-'+name_chap]['page_fct'] == "mission_"+str(scene.objects['Points']['mission'])+"-card": + scene.objects[scene.objects['Doc_chap-'+name_chap]['page_fct']].color = color_doc_mission + scene.objects[scene.objects['Doc_chap-'+name_chap]['page_fct']+'-text'].color = color_doc_mission + scene.objects[scene.objects['Doc_chap-'+name_chap]['page_fct']+'-icon'].color = color_doc_mission + else: + scene.objects[scene.objects['Doc_chap-'+name_chap]['page_fct']].color = color_doc_fct + scene.objects[scene.objects['Doc_chap-'+name_chap]['page_fct']+'-text'].color = color_doc_fct + scene.objects[scene.objects['Doc_chap-'+name_chap]['page_fct']+'-icon'].color = color_doc_fct + + # Afficher le texte de la carte + scene.objects['Doc_chap-'+name_chap]['page_fct'] = name_fct + scene.objects[name_fct].color = color_doc_activate + scene.objects[name_fct+'-icon'].color = color_doc_activate + scene.objects[name_fct+'-text'].color = color_doc_activate + scene.objects['Doc_title']['Text'] = card_description[name_fct][0] + scene.objects['Doc_title'].setVisible(True, False) + # text_show(name_fct) + text_dynamic_show(name_fct) + + # URL Python + if name_chap == "python": + scene.objects['Book_python_url_title'].setVisible(False,True) + scene.objects['Book_python_url0'].setVisible(False,True) + scene.objects['Book_python_url1'].setVisible(False,True) + scene.objects['Book_python_url2'].setVisible(False,True) + if name_fct !="": + scene.objects['Book_python_url_title'].setVisible(True,True) + for i in range(len(card_description[name_fct][2])): + scene.objects['Book_python_url'+str(i)]['Text'] = card_description[name_fct][2][i][0] + scene.objects['Book_python_url'+str(i)].setVisible(True,True) + + # Sélection de la mission + if "mission_" in name_fct : + if scene.objects[name_fct]['mission'] <= scene.objects['Points']['level'] and scene.objects[name_fct]['mission'] != scene.objects['Points']['mission']: + scene.objects['Book_level_button'].setVisible(True,True) + else: + scene.objects['Book_level_button'].setVisible(False,True) + +## +# Sélectionner le niveau +## + +def level_button (cont): + if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive : + # sound_play (sndbuff_book_flip) + obj = cont.owner + name_fct = scene.objects['Doc_chap-missions']['page_fct'] + if name_fct !="": + mission_select=scene.objects[name_fct]['mission'] + if mission_select <= scene.objects['Points']['level'] and mission_select != scene.objects['Points']['mission']: + scene.objects["mission_"+str(scene.objects['Points']['mission'])+"-card"].color = color_doc_fct + scene.objects["mission_"+str(scene.objects['Points']['mission'])+"-card-icon"].color = color_doc_fct + scene.objects["mission_"+str(scene.objects['Points']['mission'])+"-card-text"].color = color_doc_fct + scene.objects['Points']['mission'] = mission_select + scene.objects['Points-Map-text']['Text']="Mission "+str(scene.objects['Points']['mission']) + scene.objects['Book_mission']['Text'] = "Mission en cours : "+str(scene.objects['Points']['mission']) + scene.objects['Book_level_button'].setVisible(False,True) + +## +# Aller à la page Python externe +## + +def python_link (cont): + if cont.sensors['Click'].status == JUST_ACTIVATED and cont.sensors['MO'].positive : + # sound_play (snd_click) + name_fct = scene.objects['Doc_chap-python']['page_fct'] + if name_fct !="": + i= cont.owner.name[15:-7] + webbrowser.open(card_description[name_fct][2][int(i)][1]) + +############################################################################### +# Génération dynamique des pages +############################################################################### + +## +# Cacher le texte +## + +def text_dynamic_hide(card=None): + if card is None: + for card in card_description: + for i in range (13): + scene.objects['Doc_text-l'+str(i+1)+'-'+str(card)].setVisible(False, False) + else: + for i in range (13): + scene.objects['Doc_text-l'+str(i+1)+'-'+card].setVisible(False, False) + +## +# Afficher le texte +## + +def text_dynamic_show(card=None): + if card is None: + for card in card_description: + for i in range (13): + scene.objects['Doc_text-l'+str(i+1)+'-'+str(card)].setVisible(True, False) + else: + for i in range (13): + scene.objects['Doc_text-l'+str(i+1)+'-'+card].setVisible(True, False) + +## +# Préchargement des textes +## + +def text_dynamic_load(): + for i in range (13): + scene.objects['Doc_text-l'+str(i+1)+'-ref']['Text'] = "" + + # Création des objets 3D + for card in card_description: + lines = card_description[card][1].split("\n") + for i in range (13): + doc_text= scene.addObject('Doc_text-l'+str(i+1), None, 0.00, True) + doc_text.setParent(scene.objects['Doc']) + doc_text.name = 'Doc_text-l'+str(i+1)+'-'+str(card) + doc_text.worldPosition.x = scene.objects['Doc_text-l'+str(i+1)+'-ref'].worldPosition.x + doc_text.worldPosition.y = scene.objects['Doc_text-l'+str(i+1)+'-ref'].worldPosition.y + doc_text.worldPosition.z = scene.objects['Doc_text-l'+str(i+1)+'-ref'].worldPosition.z + doc_text.setVisible(False, False) + if i >= len(lines): + scene.objects['Doc_text-l'+str(i+1)+'-'+str(card)]['Text']="" + else: + if len(lines[i]) ==0: + scene.objects['Doc_text-l'+str(i+1)+'-'+str(card)]['Text']="" + else: + # scene.objects['Doc_text-l'+str(i+1)+'-'+str(card)]['Text']=lines[i] + scene.objects['Doc_text-l'+str(i+1)+'-'+str(card)].blenderObject.data.body=lines[i] # Bug de la propriétés 'Text' (UPBGE) -> passage par 'body' de bpy (Blender) + +############################################################################### +# Store +############################################################################### + +## +# Texte pour le store +## + +def upgrade_description (card): + name_fct =card[6:] + if name_fct in card_description: + return card_description[name_fct][2] + else: + return "" + +def upgrade_talk (card): + name_fct =card[6:] + if name_fct in card_description: + return card_description[name_fct][3] + else: + return "" + +############################################################################### +# Sounds +############################################################################### + +def sound_play (sound): + pass # FIXME + # if scene.objects['Commands']['sound']: + # audiodev.play(sound) diff --git a/README.md b/README.md index f3a65f7..5903b14 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Ropy est un rover martien qui se programme en Python. Les aventures de Ropy permettent la découverte de la programmation procédurale et du language Python. A travers les différents missions, donc de manière graduée, les élèves vont apprendre à manipuler les structures algorithmiques et à les coder en Python. -[![Ropy présentation](img/ropy-v2-presentation.png)](https://tube-sciences-technologies.apps.education.fr/w/b11be555-bd05-462b-8ff6-177ec18c1830) +[![Ropy présentation](img/lien_video.png)](https://tube-sciences-technologies.apps.education.fr/w/b11be555-bd05-462b-8ff6-177ec18c1830) ![Poster](img/poster-02.png) diff --git a/img/ropy-v2-presentation.png b/img/lien_video.png similarity index 100% rename from img/ropy-v2-presentation.png rename to img/lien_video.png diff --git a/img/ropy-jumeau_numerique.png b/img/ropy-jumeau_numerique.png deleted file mode 100755 index f04484d..0000000 Binary files a/img/ropy-jumeau_numerique.png and /dev/null differ diff --git a/img/screenshot-v1-def.jpg b/img/screenshot-v1-def.jpg deleted file mode 100644 index e2a861f..0000000 Binary files a/img/screenshot-v1-def.jpg and /dev/null differ diff --git a/img/screenshot-v2-def.png b/img/screenshot-v2-def.png deleted file mode 100644 index 511b2bd..0000000 Binary files a/img/screenshot-v2-def.png and /dev/null differ diff --git a/img/screenshot-v2.jpg b/img/screenshot-v2.jpg index 0ede52e..293c158 100644 Binary files a/img/screenshot-v2.jpg and b/img/screenshot-v2.jpg differ diff --git a/img/screenshot-v2b.jpg b/img/screenshot-v2b.jpg deleted file mode 100644 index 293c158..0000000 Binary files a/img/screenshot-v2b.jpg and /dev/null differ diff --git a/ropy-32.blend b/ropy-32.blend index 76267fa..6758978 100644 Binary files a/ropy-32.blend and b/ropy-32.blend differ diff --git a/rp_doc.py b/rp_doc.py index b1eaf3b..c749b6a 100644 --- a/rp_doc.py +++ b/rp_doc.py @@ -47,6 +47,7 @@ rover_card=rover_card+["speed-card", "paint-card", "battery-card", "beacon-card" # Avancer et reculer rp_forward_title="Avancer et reculer" rp_forward_text=" rp_avancer() \n -> Avance d'un pas en avant. \n \n rp_reculer() \n -> Recule d'un pas." +# rp_forward_text=" rp_avancer() \n → Avance d'un pas en avant. \n \n rp_reculer() \n → Recule d'un pas." rp_forward_type="standard" card_description.update({"forward-card" : [rp_forward_title, rp_forward_text, rp_forward_type]})