Site logo

Triceraprog
La programmation depuis le Crétacé

  • La Maison dans la colline, partie 3 ()

    Suite de la série sur le développement du jeu La maison dans la colline sur VG5000µ. Après, un exposé du contexte dans la première partie, puis un aperçu des outils utilisés dans la seconde partie, cet article aborde l'idée du jeu et de son évolution au fur et à mesure du développement.

    La première idée

    LE VG5000µ est une machine que je commence à bien connaître, et, comme expliqué dans le premier article, j'étais en train d'approfondir les capacités du VDP lorsque ce petit défi a commencé. Je voulais me servir des mes nouvelles connaissances et je suis parti sur l'idée de faire un affichage « fin » et sans clignotement.

    L'idée de faire un jeu d'aventure graphique me trottait dans la tête depuis quelques temps, et c'est un genre qui collait bien à mes objectifs. Peu de mouvements à l'écran, donc l'affichage pourrait être maîtrisé.

    Initialement, le jeu se passe dans un manoir, c'est-à-dire un lieu avec de nombreuses pièces. Et puis, c'est le classique des jeux graphiques ou textuels, repris aussi par des standards comme « Alone in the Dark » en jeu vidéo, ou « Mansions of Madness » en jeu de plateau. Les jeux où le but est de sortir d'une maison fermée ne manquent pas.

    Rapidement, je fais quelques croquis pour me fixer une idée de ce à quoi le jeu ressemblerait. Un peu de place pour l'affichage de la pièce courante vue de dessus, de la place pour un texte et un inventaire.

    Premières notes manuscrites du jeu.

    Creuser les idées

    Dans ce genre de jeux, il s'agit de résoudre des énigmes qui prennent la forme de trouver les bons objets pour les amener aux bons endroits. Il peut y avoir quelques énigmes plus complexes à résoudre, mais je veux m'arrêter là. Le temps va passer vite, et il faut rester sur du faisable, et sachant que ça sera déjà probablement trop.

    Je lance quelques idées d'objets. Une torche électrique. Une boite d'allumettes. Ah, donc autant remplacer la torche pas une lanterne à allumer. Des livres. Des clés. C'est vague, mais cela me permet de définir quels types d'interactions le personnage du jeu peut avoir. Ah, et des portes aussi.

    Au tout début, les interactions sont nombreuses : prendre, lire, utiliser, combiner, poser, ouvrir... Mais je sens que cela va faire beaucoup. Je voudrais aussi essayer que le jeu soit jouable avec la manette, à un seul bouton (ce ne sera pas le cas au final). Cette contrainte me fait réfléchir à réduire le nombre d'interactions, ou en tout cas de faire en sorte qu'elles soient automatiques : si je fais une action sur un livre, c'est pour le lire. Si je fais une action devant une porte en ayant une clé, c'est pour l'ouvrir. Et ainsi de suite. Mais pour le moment, je ne creuse pas plus avant. Je laisse cette idée mûrir.

    Je veux aussi me détacher des jeux d'époque dont une partie de la difficulté est de comprendre comment manipuler le jeu. De ce côté-ci, je veux apporter de la modernité (toute relative) : en jouant, les objets sur lesquels ont peut agir doivent être facilement identifiables, et les actions possibles indiquées en fonction du contexte. Ça va probablement raboter la durée du jeu, mais cela sera beaucoup plus agréable.

    Concernant la durée d'ailleurs, je ne vise pas quelque chose de très long. Les quelques personnes susceptibles de jouer à ce jeu ne cherchent probablement pas une expérience de douze heures. Ni même d'une heure. Trente minutes pour quelqu'un qui ne connaît pas la solution, ça semble bien. Même si je cherche à ce que le jeu soit agréable à jouer et un bon moment à passer, c'est avant tout une preuve de concept d'affichage sur VG5000µ. Et c'est un hobby à mes heures perdues.

    Ci-dessous, une maquette préliminaire du jeu avec des essais de rendu. On y voit un essaie de personnage plus large. Les portes sont différentes aussi.

    Maquette préliminaire du jeu.

    Évolutions

    Toutes ces idées, je les notes sur un carnet (électronique), et je n'hésite pas à les annoter, les modifier, les corriger, en fonction des développements, du temps qui passe, des choses plus faciles à programmer que d'autres, des simplifications,... Cette espèce de document de design est un document vivant, que j'adapte au fur et à mesure.

    Je commence à coller un scénario sur mes éléments de gameplay, afin d'expliquer les contraintes. Pourquoi est-ce que le personnage ne peut pas sortir de la maison une fois qu'il y est entrée. Que s'est-il passé dans les différentes pièces.

    En retour, le scénario influe sur le design. Comment est-ce que j'agence les pièces, quels objets vont dans quelles pièces, qu'est-ce que je fais faire aux gens qui jouent ?

    C'est allers et retours entre conception du jeu, de niveaux, du scénario et du programme nourrissent peu à peu ces différentes parties et les font avancer de concert.

    Le manoir initial se transforme en une maison à moitié troglodyte, car c'est un moyen assez « simple » d'avoir un environnement d'intérieur de maison et de grotte dans un espace assez restreint. C'est un peu tiré par les cheveux mais bon, on est dans du jeu vidéo rétro. Je me trouve même assez sobre par rapport à certaines productions.

    Petit à petit se construit aussi un double objectif afin de pouvoir terminer le jeu. Sortir de la maison, mais aussi pouvoir reprendre la voiture qui nous a amené sur les lieux.

    J'ajoute aussi un peu de « lore » avec quelques objets qui ne sont pas nécessaires, mais qui font transparaître une histoire assez simple, mais je pense suffisante pour l'ambition toute relative de ce jeu. J'ai donc écrit un petit background sur les évènements passés de cette maison. Qui sait ? Peut-être que je compléterai l'histoire grâce à d'autres jeux dans le futur.

    Léger

    La constante, c'est de rester léger. Comme je l'ai évoqué, c'est un petit défi de programmation hobbyiste. Il ne faut surtout pas hésiter à couper, et donc prévoir des choses de manières à ce qu'elles puissent facilement être enlevées en modifiées.

    Je suis assez satisfait du résultat, même si j'y vois plein de petites erreurs, ou maladresses, en y jouant.

    Diagramme montrant les étapes du jeu.


  • Mattel Aquarius, scan des touches en assembleur ()

    Le scan du clavier, sur Mattel Aquarius, à lieu dans la ROM à l'adresse $1e80. Cette fonction traite les minuscules, les majuscules mais aussi les raccourcis BASIC, en injectant au fur et à mesure les touches nécessaires comme si elles avaient été tapées au clavier.

    C'est beaucoup trop pour un scan de clavier dans un jeu, et peut même poser quelques soucis. Mais c'est une bonne base pour écrire une routine de lecture de clavier, car la lecture des valeurs des touches n'est pas forcément très simples.

    Ce que nous apprends la lecture de la routine en ROM est qu'il semble falloir attendre une stabilité dans les valeurs avant d'accepter la touche. En effet, la routine fait plusieurs lectures et ne considère la touche appuyée que si cette lecture est stable.

    Voici une version de la routine, où j'ai enlever ce qui était traitement de raccourcis BASIC, ainsi que le traitement des touches de modifications. Ainsi, la traduction ne se fait qu'avec les touches minuscules.

    Attention, je n'ai pas encore testé cette routine sur du matériel réel !

    La routine

    Dans cette version, le décodage de la touche est faite par rapport aux minuscules. En changeant vers la fin la valeur de HL de lower_key_table-1 vers upper_key_table-1, il est possible d'obtenir un décodage avec des majuscules.

    Il est aussi possible de ne traiter que des codes de touches, sans traductions. Dans ce cas là, il suffit de remplacer les trois instructions après accept_key par un simple LD A, E.

    Les deux emplacements en RAM, qui commencent ce code source, doivent être en RAM et être adaptés à votre programme.

    latest_keycode_pressed: EQU     0380eh
    keyword_delay_value:    EQU     0380fh
    
    lower_key_table:        EQU     01f38h
    upper_key_table:        EQU     01f66h
    
    check_key:
        EXX
    
        LD         BC,0xff
        IN         A,(C)
        CPL
        AND        0x3f
        LD         HL,latest_keycode_pressed
        JR         Z,no_key_scanned            ; ?No row were selected, quick skip?
        LD         B,0x7f                      ; Input row 7
        IN         A,(C)
        CPL
        AND        0xf                         ; Only 4 keys in lower bits
        JR         NZ,decode_key_scan
        LD         B,0xbf                      ; Input rows 6 to 0
    
    loop_input_rows:
        IN         A,(C)
        CPL
        AND        0x3f                        ; 5 keys in lower bits
        JR         NZ,decode_key_scan
        RRC        B
        JR         C,loop_input_rows
    
    no_key_scanned:
        INC        HL
        LD         A,0x46
        CP         (HL)                        ; Compare with delay
        JR         C,return_no_key_value
        JR         Z,reset_latest_key
        INC        (HL)                        ; Increment delay
    
    return_no_key_value:
        XOR        A
        EXX
        RET
    
    reset_latest_key:
        INC        (HL)
        DEC        HL
        LD         (HL),0x0
        JR         return_no_key_value
    
    decode_key_scan:
        LD         DE,0x0
    
    count_row:
        INC        E
        RRA
        JR         NC,count_row
        LD         A,E                         ; E is the active row
    
    count_add_column:
        RR         B
        JR         NC,keycode_found
        ADD        A,0x6                       ; Add 6 for each column
        JR         count_add_column
    
    keycode_found:
        LD         E,A
        CP         (HL)                        ; HL = 0380eh
        LD         (HL),A
        INC        HL
        JR         NZ,new_key_delay            ; That's a new key, we need a bit of selay
        LD         A,0x4
        CP         (HL)
        JR         C,commit_key_delay_continued
        JR         Z,accept_key                ; Wait if over, accept key!
        INC        (HL)                        ; Increment delay from 4 to 6 iteratively
        JR         return_no_key_value
    
    commit_key_delay_continued:
        LD         (HL),0x6                    ; Set the delay for the second pass
        JR         return_no_key_value
    
    new_key_delay:
        LD         (HL),0x0
        JR         return_no_key_value
    
    accept_key:
        LD         IX,lower_key_table-1
        ADD        IX,DE
        LD         A,(IX+0x0)                  ; Read decoded Key value
    
    return_key_value
        EXX
        RET
    

  • Mattel Aquarius, entrées des commandes BASIC ()

    Commençant à étudier le Mattel Aquarius afin de participer à la nouvelle session de « Retro Programmers United for Obscure Systems », et devant le manque de documentation, j'ai regardé ce qu'il y avait dans la ROM. Et c'est un BASIC Microsoft qui y est implémenté, ce qui est bien pratique puisque c'est un BASIC que j'ai bien étudié à travers le VG5000µ.

    J'ai donc ressorti ma trousse à outils et voici la liste des points d'entrées des commandes et fonctions du BASIC.

    La première colonne est le token BASIC, la seconde l'adresse du point d'entrée en ROM et la troisième le nom.

    Les commandes

        128     $0c21         end
        129     $05bc         for
        130     $0d13         next
        131     $071c         data
        132     $0893         input
        133     $10cc         dim
        134     $08be         read
        135     $0731         let
        136     $06dc         goto
        137     $06be         run
        138     $079c         if
        139     $0c05         restore
        140     $06cb         gosub
        141     $06f8         return
        142     $071e         rem
        143     $0c1f         stop
        144     $0780         on
        145     $07b5         lprint
        146     $1b15         copy
        147     $0b3b         def
        148     $0b6d         poke
        149     $07bc         print
        150     $0c4b         cont
        151     $056c         list
        152     $0567         llist
        153     $0ccd         clear
        154     $1c2c         cload
        155     $1c08         csave
        156     $1a4f         pset
        157     $1a4c         preset
        158     $1ad6         sound
        159     $0bbd         new
    

    Les fonctions

        178     $14f5         sgn
        179     $15b1         int
        180     $1509         abs
        181     $3803         usr
        182     $10a8         fre
        183     $0b2e         lpos
        184     $0b33         pos
        185     $1775         sqr
        186     $1866         rnd
        187     $1385         log
        188     $17cd         exp
        189     $18d7         cos
        190     $18dd         sin
        191     $1970         tan
        192     $1985         atn
        193     $0b63         peek
        194     $0ff3         len
        195     $0e29         str
        196     $1084         val
        197     $1002         asc
        198     $1013         chr
        199     $1021         left
        200     $1050         right
        201     $1059         mid
        202     $4ec5         point
    

    Cela peut aider à donner des points d'entrée pour comprendre comment fonctionne la machine.


  • La Maison dans la colline, partie 2 ()

    Suite de la série sur le développement du jeu La maison dans la colline sur VG5000µ. Après, la première partie, qui donnait le contexte de création, voici donc la deuxième partie, où j'aborde les outils de développement utilisés.

    Les bases

    Lorsque je développe un logiciel, je veux pouvoir me consacrer sur un temps contiguë maximum au cœur du projet. Même, et peut-être surtout, lorsque ce développement est un hobby, et que j'ai peu d'heures à y consacrer, ici et là en fonction de mon temps libre.

    Ainsi, une fois le projet en développement, lorsque j'ai une petite demi-heure par-ci ou une grosse heure par là, je veux pouvoir m'installer et me consacrer à la valeur de ce projet. À son développement concret.

    Pour moi, cela signifie que tout ce que je peux automatiser et qui me permettra de profiter de ces temps là au maximum doit l'être fait en amont. Si je dois cliquer sur des boutons, faire des manipulations, lancer ou configurer des logiciels à chaque fois que je fais un essai, voire même à chaque fois que je débute une session, c'est un temps précieux qui est inutilisé. Chaque manipulation est aussi une occasion de faire une erreur.

    Dans le passé sur ce site, j'ai déjà présenté quelques outils destinés à me faciliter la tâche. Et dès les essais sur l'EF9345 dont je parlais dans l'article précédent, j'ai remis en place un script qui permet de lancer l'émulateur automatiquement, configuré avec lancement du chargement.

    Comme je me doutais que le programme allait gagner en taille, j'ai ajouté au script une manière de passer l'émulateur en vitesse accélérée le temps du chargement.

    Ainsi, dès que je termine une compilation, je n'ai que quelques secondes à attendre avant de retrouver le jeu, prêt à être testé, dans l'émulateur.

    Le framework

    Afin de pouvoir itérer sur le jeu, particulièrement sur son gameplay, j'ai choisi de développer dans un mélange de C et d'assembleur. Le C permet des modifications simples de morceaux de code sans trop se poser de questions bas niveau. L'assembleur permet d’accélérer certaines parties une fois qu'elles sont fixes, ainsi qu'un accès rapide au matériel.

    Car en effet, si j'ai choisi de faire un jeu d'aventure graphique, je tiens à deux choses au niveau de l'affichage :

    • que l'affichage d'une pièce soit très rapide (si ce n'est immédiat),
    • que les mouvements à l'écran ne provoquent aucun clignotement

    Difficile voire impossible à faire cela en BASIC. Plus facile à faire en C, mais c'est l'assembleur qui me permettra de vraiment réaliser ces objectifs.

    De même, je voulais initialement que le jeu tienne sur une machine sans extension mémoire. Malheureusement, je ne réaliserai pas cet objectif. De peu...

    z88dk

    Quelques temps (années ?) auparavant, j'avais croisé le chemin de z88dk, un framework de programmation en C dédié aux machines Z80. Cela me semblait être une bonne occasion pour l'essayer, avoir l'espoir qu'il vienne avec des fonctionnalités intéressantes qui me feraient gagner du temps.

    Après tout, il y a des outils de création de programme assemblés dans une suite complète, une bibliothèque C pour Z80, un support VG5000µ et un fichier crt.s déjà configuré et configurable. Ça, se sont les avantages.

    Après usage pendant toute la durée du projet, voici les inconvénients :

    • le programme principal qui appelle les autres pour la compilation n'a pas une syntaxe d'option standard, et cela me posera des problèmes avec cmake,
    • le compilateur par défaut n'est pas le meilleur, je m'en rendrai compte beaucoup plus tard, vers la fin du projet. Il est possible d'utiliser un compilateur alternatif, qui optimise visiblement mieux. Malheureusement, les deux ne se comportent pas tout à fait de la même façon, et j'ai préférer ne pas changer en chemin. On verra pour un futur projet peut-être,
    • le support VG5000µ est axé sur une utilisation en mode texte, et passe par le système implémenté par la ROM, sans accès direct à l'EF9345. Ce n'est pas cohérent avec ce que je veux faire, et je n'utiliserai finalement aucune fonction spécifiquement dédiée au VG5000µ.

    Au final, je ne suis pas entièrement convaincu par z88dk, qui à l'air de prendre une orientation plutôt CP/M et machined un peu plus puissantes qu'un VG5000µ.

    Gestion de la construction

    Pour le gestionnaire de construction de version, je suis parti sur cmake. C'est très probablement surdimensionné, mais je connais son utilisation classique. Ici, je voulais pousser plus loin et aborder sa configuration de chaîne de compilation « exotique ».

    J'ai beaucoup appris sur cmake au passage ; ma solution finale n'est pas entièrement solide, je confirme à nouveau que Stack Overflow n'est d'aucune aide dès que vous avez un soucis qui n'est pas basique, que la documentation de cmake est toujours peu aidante... et qu'un Makefile tout simple aurait été probablement tout aussi efficace. Mais je m'emmêle toujours les pinceaux avec un Makefile dès que je quitte les règles de bases.

    cmake est probablement trop automatique sur certains points, et il n'est pas toujours facile de lui faire comprendre que la buildchain utilisé ne se comporte pas tout à fait comme ce à quoi il s'attend.

    Enfin maintenant c'est fait, et même si je dois corriger certaines petites choses au niveau des dépendances entre les .c, les .h et les .asm, ça marche globalement bien.

    Éditeur de code

    cmake était surdimensionné ? Que dire de l'éditeur de code que j'ai utilisé. CLion... vim ou visual studio code auraient suffit. Et il m'est arrivé d'utiliser vim pendant le développement pour quelques modifs rapides. Mais là encore, je connais bien CLion, ses outils, sa configuration, et l'habitude, ça compte.

    De toute façon, mes outils d'automatisation ne sont dépendants ni de cmake, ni de clion, ce sont donc des choix indépendants.

    Paré au départ !

    Ou presque. J'ai cité les outils de développement principaux. Mais je parlais en introduction d'automatiser la mise en place de l'environnement de développement. Pour cela, j'utilise le terminal kitty associé à un script. Lorsque je lance ce script, le terminal se met en place avec les bon terminaux ouverts dans les bons répertoire, et des outils textes déjà lancés (ranger pour la gestion de fichier, lazygit pour la gestion de version, nb pour la prise de notes, le script d'automatisation à l'écoute).

    Ainsi, démarrer une session depuis un ordinateur fraîchement allumé me prend deux clics pour avoir l'intégralité de l'environnement en place, et j'ai tout ce qu'il me faut pour la session. Cela aurait été un seul si je n'avais pas choisi Clion.

    Alors... clic, clic... et la suite au prochain épisde.

    Capture montrant l'explorateur textuel Ranger dans le répertoire du jeu.


  • Plouf ... in space ()

    En attendant de revenir sur le déroulé du développement de « La maison dans la colline », voici un article beaucoup plus court pour présenter ma contribution à la session la plus récente de « Retro Programmers United for Obscure Systems », consacrée à Exelvision.

    La découverte de la machine

    Exelvision, une entreprise française, a produit au milieu des années 80 une série de machines assez originales. Ce sont des machines de type familial, mais avec un look un peu pro, un choix audacieux mais probablement désastreux d'une connectique sans fil pour le clavier et les joysticks, de la synthèse vocale, et des capacités graphiques plutôt correctes.

    Pour ce challenge, je me suis orienté vers la première de ces machines, l'EXL 100, dont vous pouvez trouver une présentation détaillée sur ce site.

    C'est une machine que je ne connaissais pas vraiment. Ou tout du moins, je ne m'étais pas penché sur ces caractéristiques, son architecture ni même sur les périphériques disponibles. Et la surprise fut là.

    Côté processeur principal, je savais qu'il faisait dans l'original, un TMS 7020. Côté RAM, tout est côté vidéo, associée à un TMS 3556, non accessible directement par le TMS 7020. Ça promet. Toute cette place mémoire, 32 ko tout de même, hors de porté du bus principal. Et en RAM principale ? ... 2 ko. Deux tout petits kilo octets, déjà très occupés par le système.

    Je me tourne vers le BASIC pour découvrir la machine. Celui-ci est disponible sur cartouche. Et ses données sont bien en VRAM, le seul endroit où il y a de la place. Les performances sont en adéquation. C'est lent. Pas très lent, il y a pire, mais lent tout de même.

    La machine peut bien supporter des extensions mémoires, mais l'architecture laisse peu de place au doute : c'est une machine qui est faite pour lancer ses programmes sur cartouches en priorité, à moins de lui adjoindre l'extension disquettes, qui fait entrer la machine dans une toute autre dimension.

    Ces matériels ne sont pas très courant, et semblent complexifier la machine, je décide donc de cibler l'EXL100 de base, sans extension.

    Les deux premières pistes

    La première piste que j'explore est technique : celle de proposer le logiciel sur cartouche. L'avantage me semble être une rapidité d'exécution. L'inconvénient est que je n'ai aucune idée de comment fonctionne la ROM de la machine, de ce qu'il faut pour la faire reconnaître. Ça se trouve bien entendu, mais je ne connais pas non plus l'assembleur TMS 7020. Je laisse l'idée rapidement de côté, il y a trop d'inconnues pour moi sur cette machine.

    La seconde piste est logicielle : écrire une machine virtuelle qui tiendrait dans la petite RAM de la machine pour exécuter un byte code présent dans la VRAM. L'idée me plaît bien et j'y réfléchi un temps tout en consultant les documentations de la machine. Mais encore un fois, je m'aperçois des particularités de la machine. Je crains le hors sujet.

    Au final, faisons simple : un petit jeu en BASIC pour s'entraîner. Et si j'ai le temps, loger un peu d'assembleur pour accélérer certaines parties.

    Plouf

    Puisque j'ai besoin de creuser ma connaissance de la machine, je ne peux pas me lancer dans quelque chose de compliqué. Je vais donc chercher dans les classiques. Après quelques hésitations, je choisi la bataille navale. C'est un jeu qui peut se représenter avec des graphismes détaillé tout comme en caractères, c'est assez simple à programmer. Petit inconvénient, il me faudra une IA pour un jeu à une seule personne.

    Je cherche un petit twist tout de même pour ne pas aller dans le trop classique et je me dis que faire bouger les bateaux entre deux tours pourrait être sympa sans trop complexifier le jeu. Là encore, c'est débrayable, si je n'ai pas le temps, je ferai sans.

    Et donc c'est parti.

    Le BASIC

    La plupart des BASICs de l'époque se ressemblent, souvent parce qu'ils sont soient des adaptations du BASIC Microsoft, soit parce qu'ils ont été créés avec une syntaxe similaire, ou en tout cas en suivant cette branche d'évolution du BASIC.

    Sans être complètement différent, le BASIC Exelevision a des particularités. Entre autre, il a un concept de routines appelables sans tenir compte de son numéro de ligne. Pratique à première vue. De plus, dans ces routines, les variables sont locales. C'est plutôt attrayant.

    Rapidement, les routines semblent être une fausse bonne idée. En premier lieu, même si le numéro de ligne n'a pas d'importance, elles doivent absolument se trouver à la fin du programme, sous peine d'erreur (et les erreurs sont sous forme de nombres seulement, mieux vaut avoir le manuel sous les yeux). Et puis la localité des variables est tout ou rien. Et on ne peut pas passer de tableaux à ces routines.

    Au final, je ne garde qu'une paire de fonctionnalités sous forme de routines. Le reste sera fait avec ce bon vieux GOSUB et des numéros de ligne.

    Le BASIC permet aussi un traitement d'exception, avec de la récupération d'erreurs. C'est plutôt pas mal... mais je ne penserai à m'en servir que tard dans le développement. Ce BASIC semble cependant un peu capricieux, avec des commandes qui parfois ne veulent pas être sur la même ligne et parfois oui... je n'ai pas vraiment compris les raisons.

    Le démarrage d'un programme après un RUN est assez long, et de plus en plus long avec l'avancée du projet. J'acquière la certitude que RUN effectue une vérification du programme. Peut-être pas une compilation, quoi que je n'en sais rien, mais il est capable de détecter avant démarrage les erreurs de numéros de lignes dans les GOTO/GOSUB, et les mauvais appariement de boucles FOR/NEXT.

    C'est pratique pour le premier cas, parfois un peu obscure pour le second, car la ligne en erreur n'est pas toujours celle où se trouve vraiment l'erreur.

    Cependant, c'est une fonctionnalité notable, car peu présente, voire pas, sur d'autres BASIC de cette époque.

    Le jeu

    Je n'ai pas grand chose à dire sur le jeu lui-même. La principale difficulté est d'arriver à caser deux grilles à l'écran. L'algorithme de déplacement et collision des bateaux me pose aussi quelques soucis, et debugguer n'est pas des plus plaisants, même sur émulateur. Cette machine est peu utilisée, peu connue, et le manque d'outils se fait cruellement sentir.

    Mais je crois bien que ça sera le cas à chaque fois pour ces Game Jams, étant donné que le but est d'aller sur des machines sur lesquels il y a peu de développement.

    Mon principal problème est la vitesse. Le jeu est affreusement lent. Vraiment. Le fait que les bateaux bougent et collisionnent pour faire demi tour demande de longs calculs. Un temps, j'imagine couper les collisions et dire que après tout, ce sont des sous-marins et qu'ils peuvent passer l'un sur l'autre.

    Cependant, cela complexifie la compréhension du jeu, ainsi que la gestion des tirs, qui peuvent toucher plusieurs sous-marins en même temps. Je décide donc qu'il est temps de s'essayer à un peu d'assembleur.

    Optimisations assembleur

    Le TMS 7020, de la série TMS 7000, est un processeur connu, même si pas aussi utilisé dans les ordinateurs personnes que le Z80 ou le 6809. Il est donc supporté par des assembleurs et en particulier par celui-ci, que je connais déjà. Parfait.

    J'avais déjà commencé à lire des ressources sur la programmation de cette machine et ses 128 registres. Quel luxe... ou presque, car c'est dans cette mémoire interne que se loge la pile aussi. Ça reste quand même bien spacieux.

    Et au final, c'est un processeur plutôt agréable. Très simple à programmer. La plus grosse difficulté étant plutôt, à nouveau, de comprendre l'environnement de la machine, les registres à préférer et/ou à laisser tranquille. Comment discuter avec le processeur vidéo et accéder à la VRAM. Mais là encore, il y a de nombreux exemples dans de la documentation.

    La machine, bien que peu connue et peu dynamique, a eu déjà eu des retro-développeurs dans le passé proche. La route est pavée. Un peu laissée à l'abandon, mais pavée quand même, et c'est agréable. Merci à eux.

    Au final, transférer en assembleur mes routines les plus coûteuses se révèle extrêmement bénéfique. J'en aurais bien transféré plus, mais d'après la documentation, j'ai évalué à un peu moins de 500 octets la place disponible de manière « sûre ». On devrait pouvoir pousser un peu plus, mais je n'avais pas le temps de pousser les tests. Restons prudent.

    ... in Space

    Pendant le développement, j'ai souvent hésité. Est-ce que ce sont des bateaux ? Est-ce que ce sont des vaisseaux spaciaux ? Initialement, je comptais redéfinir des caractères afin d'avoir un affichage un peu plus joli. Le temps manquant, je suis resté sur le jeu de caractères disponibles dans le BASIC, qui heureusement à quelques caractères permettant de tracer des lignes en mode basse résolution.

    Pas non plus le temps d'enjoliver en utilisant un peu de mode haute résolution, qui peut se partager l'écran sur cette machine avec le mode texte. L'essentiel du développement se fait pendant mes vacances de fin d'années, et donc juste à la fin de la période de la Game Jam.

    Donc bateau ou vaisseau... cela n'a pas vraiment d'importance en soi.

    Oui mais, dans cette Game Jam, même si on n'en est qu'à la deuxième session, il est de « tradition » de pousser un peu la qualité en ayant une couverture de jeu, une illustration, un manuel, ou un peu de tout ça. Et les jeux de l'époque misaient beaucoup sur ce packaging pour faire travailler l'imagination.

    Donc je dois choisir. Et je choisi l'espace... même si le fond de l'écran pendant le jeu reste bleu foncé. Les vaisseaux ne sont pas coulés après avoir été touchés, mais désactivés, ce qui me donne une justification au RADAR, qui réagi aux morceaux de vaisseaux touchés.

    Il me reste une IA à bricoler. Je fais simple : si le RADAR ne donne pas d'information, le coup prochain se fera au hasard. S'il donne une information, le tir se fera d'autant de cases que la distance indiquée par le RADAR, réparties en horizontal et en vertical. Cela ne prend pas en compte le déplacement des vaisseaux, ni les touches précédentes, mais après quelques parties, je juge que c'est suffisant pour mettre une petite pression à l'humain.

    Conclusion

    Une machine originale, qui demande vraiment à y revenir. Un jeu qui ne vole pas très haut, mais qui a été intéressant à optimiser et comme toujours, à terminer et présenter.

    Si vous aussi vous voulez jouer avec des torpilles photoniques, c'est par ici.

    Écran de jeu de Plouf... in Space


« (précédent) Page 5 / 22 (suivant) »

Tous les tags

3d (14), 6809 (1), 8bits (1), Affichage (24), AgonLight (2), Alice (1), Altaïr (1), Amstrad CPC (1), Apple (1), Aquarius (2), ASM (30), Atari (1), Atari 800 (1), Atari ST (2), Automatisation (4), BASIC (30), BASIC-80 (4), C (3), Calculs (1), CDC (1), Clion (1), cmake (1), Commodore (1), Commodore PET (1), CPU (1), Debug (5), Dithering (2), Divers (1), EF9345 (1), Émulation (7), Forth (3), Game Jam (1), Hector (3), Histoire (1), Hooks (4), i8008 (1), Image (16), Jeu (14), Jeu Vidéo (4), Livre (1), Logo (2), Machine virtuelle (2), Magazine (1), MAME (1), Matra Alice (2), MDLC (7), Micral (2), Motorola (1), MSX (1), Musée (2), Nintendo Switch (1), Nombres (3), Optimisation (1), Outils (3), Pascaline (1), Photo (2), Programmation (3), Python (1), ROM (15), RPUfOS (5), Salon (1), SC-3000 (1), Schéma (5), Synthèse (14), Tortue (1), VG5000 (62), VIC-20 (1), Z80 (20), z88dk (1)

Les derniers articles

Environnement de développement pour Picthorix
Un jeu en Forth pour Hector HRX : Picthorix
Yeno SC-3000 et condensateurs
Suite de tests pour VG5000µ
Un peu d'Atari ST
Le Forth sur Hector HRX
J'MSX 24 et un micro jeu
Récréation 3D, Matra Alice
Tuiles des plus très-curieuses
Notes sur le Motorola 6809

Atom Feed

Réseaux