Un menu en python pour les jeux sur la numworks

Projets

Un jeu commence souvent par un écran de paramétrage. Celui-ci doit être ergonomique, intuitif, et permettre à l’utilisateur final de personnaliser son expérience ludique. Cette article présente l’un des tout premier menu adaptable conçu en python pour la calculatrice NumWorks, ainsi que 3 exemples d’utrilisation.

Le contexte

Avec la sortie de la version 13.2.0 d’Epsilon, l’OS qui anime la calculatrice NumWorks, les capacités de la calculatrice à exécuter des scripts python a été doublée.

Le tas python « heap » est ainsi passé de 16ko à un peu plus de 31ko.
Et on peut donc désormais se lancer dans des projets un peu plus ambitieux.

Après avoir développé chacun un démineur en python pour la NumWorks, nous avons décidé de mettre au point un système de menu commun, paramétrable, utilisable dans ces deux démineurs et dans le snake que Arthur Jacquin a développé.

Ce menu a été codé pour permettre un maximum de souplesse, donc n’hésitez pas à l’utiliser comme tel ou à l’adapter.

D’un écran statique à un menu dynamique

Le « menu » originel de l’un des deux démineurs n’est en fait que du texte, affiché quelques secondes, uniquement lors du premier lancement du jeu. On ne peut pas interagir, et il va falloir intuiter le fonctionner des différentes touches.

Sur une application de calcul mental, nous avions conçu un vrai menu en mode texte :

Avec un système de navigation interne au menu primitif mais fonctionnel.

L’idée était donc de créer un menu ergonomique, sur la couche graphique de la NumWorks.

Les quelques croquis conceptuels ci-dessous illustrent parfaitement le cheminement fait d’essais/erreurs pour concevoir un menu simple, intuitif, ergonomique. La démarche est évidemment ponctuée de tests de positionnement.

Croquis

Test

Vertical ou horizontal ? Hybride ? Finalement, c’est l’affichage vertical qui est retenu, avec une coloration de l’objet actif pour une navigation claire, simple, en flat design.

Fonctionnalités

  • S’accorde avec la couleur de l’OS (Epsilon est orange, Omega rouge),
  • Permet le paramétrage de 1 à 5 paramètres, comportant autant d’options que souhaité,
  • Permet une option par défaut pour les paramètres,
  • Design épuré, minimaliste,
  • Possibilité d’afficher des informations sur plusieurs lignes.

Brancher le menu sur votre programme

Il suffit ensuite d’appeler la fonction menu() avec votre application. Elle retourne une liste des paramètres validés.

Il est souhaitable de faire cet appel proprement, et de prévoir le cas ou le menu n’est pas disponible, ainsi si le menu n’est pas présent sur la calculatrice, alors le jeu fonctionnera quand même avec des paramètres par défaut.

Par exemple :

try:
    mines, co, cr = menu("MINESWEEPER",
         "Lancer la partie",
         ["Mines", 22, 32, 42, 12],
         ["Commandes", " Nav: Flèches", " Déminer: OK", "Drapeau: DEL", "Rejouer: OK"],
         ["Crédits", "Arthur J.", "Vincent R."])[0]
except :
    mines = 20

Pour les utilisateurs avancés de ce menu, il est également possible de modifier les paramètres d’affichage avec une version souple (les versions du menu seront déclinées en fin d’article), permettant ainsi d’afficher plus de 5 paramètres, des chaînes de caractères plus longues, ou d’ajuster selon vos goûts.

Un branchement plus détaillé est présenté à la fin de cet article.

Paramètres de la fonction()

Le deuxième paramètre est le nom de l’action correspondant à la validation des paramètres, ici « Lancer la partie ».

Les paramètres suivants sont stockés dans des listes, il peut y en avoir jusqu’à 4 ou 5 et le dernier gère l’affichage sur deux lignes de manière optionnelle. Chaque paramètre comporte, dans l’ordre :

  • 1 nom (chaîne de caractère)
  • 1 ou plusieurs options

Affichage d’information

Les paramètres, comme leur nom l’indique, sont destinés à paramétrer l’expérience qui suivra ce menu. Cependant, vous pouvez également les utiliser pour afficher des informations, telles que les crédits ou les commandes. C’est notamment pour cela qu’est prévu l’affichage sur plusieurs lignes (qui est optionnel).

L’affichage multiligne n’est utilisable uniquement sur le dernier paramètre, et réduit évidemment le nombre de paramètres possibles. Pour l’activer, il suffit de séparer le contenu de la première ligne et celui de la deuxième par un dollar ($), par exemple :

  • « Auteur$Vincent Robert »
  • « Site web$nsi.xyz/snake »
  • « Navigation$Flèches »

Le dollar ($) est un caractère ACSII standard mais il faudra le saisir depuis le workshop, il n’est pas disponible de le saisir directement sur la calculatrice.

Epsilon ou Omega ?

L’essai d’une fonction exclusive à Omega suffit, et permet un accord visuel de l’objet actif avec la barre de titre de l’écran :

def omega(): # Vérificateur d'OS
    try: get_keys()
    except: return False
    else: return True

Détection des touches

Les différents projets, et notamment les jeux, nécessitent très souvent un système de détection des touches pressées. La fonction wait() est destinée à cet usage, et s’importe en même temps que le menu. Pratique !

def wait(buttons = range(53)): # Attends qu'une des touches précisées soit pressée
    while True:
        for i in buttons:
            if keydown(i):
                while keydown(i): True # Fonction anti-rebond
                return i

La fonction, par défaut, attendra qu’une des 46 touches soit pressée. Cependant, pour plus d’efficacité et pour n’avoir à traiter uniquement les signaux qui vous intéressent, vous pouvez passer en paramètre la liste des touches à interroger.

La table des codes clavier de la NumWorks est accessible sur cet article de Ti-Planet.

Table des codes clavier

Tester le menu

Le menu est disponible ici :

MenuVersion AVersion B
VariationsLe titre est en noir, quelques variations dans le code mais le rendu final est identiqueLe titre est en bleue, quelques variations dans le code mais le rendu final est identique
Téléchargermenu.pymenu.py
Démonstrationmenu_demo.pymenu_demo.py
Développementmenu_devn.a.

Pour le voir en action directement dans le workshop, vous pouvez utiliser une version non branchée mais autonome, ce sont les scripts menu_demo.py.

Une version de développement est également disponible, si vous souhaitez changer ou tester d’autres réglages : menu_dev.py

À la parution de cet article, quelques scripts utilisent ce menu, ce qui peut vous donner une idée plus concrète des usages possibles du menu :

Liendemine.pysnake.pycalcul.py
Taille8.42 ko8.42 ko8.42 ko
Auteur principalRobert VincentArthur JacquinFedyna Kevin
Menu

Ces applications existent en deux versions :

app.py est l’application qui intègre une copie du code du menu, app_se.py désigne une édition spéciale, allégée de menu qui est appelé depuis un autre script. Ainsi, le code du menu est mutualisé, ce code occupe donc moins de place car l’espace de stockage des scripts sur la calculatrice est limité.

Les applications app_se.py peuvent se lancer à priori sans le menu, mais dans ce cas là, il n’est pas possible de paramétrer l’application. On a encore quelques bug à résoudre, un try import semble ne pas fonctionner … On travaille sur ce sujet. Les applications sans _se sont par contre fonctionnelles.

Si l’équipe de Numworks nous lit, on aimerait bien

  • profiter un peu des 8 Mo de la ROM de la N0110, et donc avoir plus de 32ko pour stocker nos scripts
  • Que les touches les touches manquantes soient mappés sur le workshop, c’est à dire qu’il faut mapper toutes les touches en fait et non pas seulement 7…

Brancher proprement le menu sur une application

Un branchement propre est un branchement qui se comporte ainsi :

  • Si au lancement du script, la fonction menu() n’est pas détectée alors le jeux ou l’application se lance avec les paramètres par défaut, c’est un fonctionnement dégradé mais l’application marche. (On a encore quelques bug à résoudre)
  • Si au lancement du script, la fonction menu() est détectée, le menu se lance.

Exemple de branchement qui intègre le mode de fonctionnement dégradé :

def start():
    global mines, triche, graphisme
    try:
        mines, triche, graphisme, com, cre = menu("Démineur", "Lancer la partie",
                                                  ["Mines", 19, 22, 25, 28, 31, 33, 36, 39, 42, 7, 10, 13, 16],
                                                  ["Mode Triche", "non", "oui"],
                                                  ["Graphisme", "sobre", "classique"],
                                                  ["Commandes", "Nav: Flèches", "Déminer: OK", "Drapeau: Retour",
                                                   "Rejouer: Maison", "Triche: shift"],
                                                  ["Crédits", "Site web$nsi.xyz/demine", "Auteur$Vincent Robert",
                                                   "Contributeur$Bisam tiplanet.org",
                                                   "Contributeur$Critor tiplanet.org", "Contributeur$Arthur Jacquin"])
        triche = 0 * (triche == "non") + 1 * (triche == "oui")
        graphisme = 0 * (graphisme == "sobre") + 1 * (graphisme == "classique")
    except:
        mines, triche, graphisme = 19, 0, 0
    jeux()

Pour que tout ceci marche, il faut que la calculatrice importe le script menu.py et le script qui utilise le menu lors de la bascule vers la console d’éxécution. Ce fonctionnement ne peut malheureusement pas être simulé sur le workshop, mais sur calculatrice cela fonctionne.

Depuis le gestionnaire de script python, il suffit d’activer les options :
« Importation auto dans la console » des deux scripts.

Vous pouvez réagir à cet article sur le topic tiplanet.org de cette news :
Snake, calcul mental, et interface lancement jeux Python