Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.
La shoutbox n'est pas chargée par défaut pour des raisons de performances. Cliquez pour charger.

Forum Casio - Projets de programmation


Index du Forum » Projets de programmation » Asci : un moteur pour jeux de rôles en Python
Shadow15510 Hors ligne Administrateur Points: 5503 Défis: 18 Message

Asci : un moteur pour jeux de rôles en Python

Posté le 13/08/2021 11:36

Bonjour à tous !
Avec la Graph 90 et son Python très… limité pas simple de faire un jeu de rôle… Asci est un moteur conçu pour vous simplifier la vie !

En terme d'utilisation, Asci est assez ergonomique avec notamment des choses plutôt agréable comme la détection des entités par leur nom, ou la gestion de Tiled qui permet de créer des cartes très simplement. Mais si vous voulez exploiter le moteur au maximum, il y a quelques points un peu plus délicat…

Concrètement, à quoi sert ce moteur ? Asci a avant tout pour but de rendre plus simple la création de jeux de rôles en Python. Ainsi, le moteur va se charger en grande partie de l'affichage, de l'avancée du scénario et de toute l'interface utilisateur. Vous de votre côté, il faudra que vous fournissiez une carte et un scénario sous forme d'évènements.

>> Documentation complète <<

>> Télécharger Asci <<

>> Le dépôt gitea <<


La carte du monde
  • c'est à vous de la faire dans une variable à part, mais il faut respecter quelques règles
  • vous évoluez dans le monde façon pokémon : la carte bouge tout autour de vous


Les mécaniques
  • les combats sont laissés au développeur du jeu
  • une liste des données du moteur est modifiable, sauf si vous savez ce que vous faites, n'y touchez pas, ce n'est, en général, pas nécessaire.
  • une liste de statistique est laissée libre, vous pouvez l'utiliser comme vous voulez. Ces statistiques peuvent être modifiée par les dialogues, bien que ce ne soit pas toujours la solution la plus élégante
  • les touches 1, 2, 3 et 5 sont prises pour les déplacement, vous ne pouvez pas y associer de fonctions.


La mise en place du scénario
  • les évèvements se découpent en catégories, à chaque catégorie correspond une fonction dans le code et un (ou des) symbole(s) qui déclenche(nt) ces évènements lorsque le joueur le(s) rencontre
  • les évènements ne sont pas très dur à prendre en main, il s'agit de liste : [XP_gagnée, "texte"].
  • vous pouvez tout à fait mettre en place des dialogues complexes dans lesquels le joueur choisit sa réplique dans une liste



Les entités
  • il s'agit d'une liste de tuples stockée avec la carte ; chaque carte a sa liste d'entités
  • toutes les entités sont repérées par un identifiant (à vous de faire en sorte qu'il soit unique)
  • les entités peuvent être animées et vous pouvez modifier les entités comme vous le souhaitez



1, 2 Suivante
Lephenixnoir Hors ligne Administrateur Points: 24579 Défis: 170 Message

Citer : Posté le 13/08/2021 11:59 | #


Superbe ! Une bonne bibliothèque Python sera un début vraiment excellent, comme pour celle de Farhi. N'oublie pas d'inclure des exemples de code pour permettre aux intéressés de copier/coller un peu et de se lancer rapidement !
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5503 Défis: 18 Message

Citer : Posté le 13/08/2021 12:47 | #


Pour les exemples, Asci (le jeu de rôle) en constituera un beau, mais le moteur ne sera pas tout à fait compatible avec ^^'
Je me note dans un coin d'en faire avec sans doute en petit tuto ou un truc du genre

Ajouté le 13/08/2021 à 15:16 :
Bon, j'ai décidé de me lancer à corps perdu dans la bataille avec le moteur, sans m'occuper des autres opus (oui le choix est discutable mais j'avais envie de faire un truc généraliste xD)

Quelques points sont déjà bien plus clair et d'autres se sont obscurcis xD

La map
  • le format sera une chaîne de caractère sous la forme d'une r-doc-string
  • cette map devra impérativement être stockée dans une variable world elle-même stockée dans un fichier world_map pour simplifier l'édition, je pense regrouper les fichiers que vous devrez faire en un seul, je vous tient au jus
  • lors des déplacements, le joueur reste au centre, tout est géré (au niveau des collisions et des interactions avec les PnJ)
  • les intérieurs, et les combats sont encore sur la todo list donc rien de nouveau : c'est encore un peu flou, surtout les intérieurs xD)


Les mécaniques
  • concernant les statistiques, avec le peu de place que j'ai sur l'écran, j'ai opté pour un système assez simple : XP, PV, point d'attaque, points de défense
  • les points d'XP sont au centre du moteur, c'est eux qui contrôlent toute l'avancée de votre histoire, faire un arbre de progression de l'XP me semble être une bonne idée. Cette méthode peut être naïve ou peu adaptée. J'ai un seul argument : en jouant finement avec, on peut faire des scénarios à plusieurs fins, et il me semble que les RpG à fin multiples ne courent pas les rues (fin de l'unique argument )


Que dire d'autre ? La sauvegarde sera très probablement sous forme d'une liste. Je sais pas trop ce que je pourrais ajouter, ça peut faire peur peut-être vu de l'extérieur, je pense déjà pouvoir vous dire que le plus dur, ça va être les évènements et la gestion de l'XP. La map c'est du ASCII-Art pur et simple. Une fois que votre progression de l'XP est bien nette, il faut juste écrire un petit : game = Asci() ; game.mainloop() et c'est terminé.
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir Hors ligne Administrateur Points: 24579 Défis: 170 Message

Citer : Posté le 13/08/2021 15:26 | #


cette map devra impérativement être stockée dans une variable world elle-même stockée dans un fichier world_map pour simplifier l'édition, je pense regrouper les fichiers que vous devrez faire en un seul, je vous tient au jus

Question : pourquoi est-ce qu'on ne pourrait pas avoir une fonction asci_init_map() à laquelle on donne la chaîne qu'on veut ? Si tu donnes au moteur le contrôle des fichiers les choses se compliquent un peu dans le sens où on est plus vite limité par le moteur (eg. on est limités à une seule world_map) que si les choses se passent via une API.

concernant les statistiques, avec le peu de place que j'ai sur l'écran, j'ai opté pour un système assez simple : XP, PV, point d'attaque, points de défense

Est-ce que tu ne peux pas avoir un dictionnaire pour les stats et laisser le jeu qui utilise ton moteur décider de leurs noms et rôles ?

En gros, si tu veux, peut-être que ton moteur peut être un peu plus petit et laisser de la marge au jeu ! Ce serait dommage si on ne peut coder que les mécaniques de Asci Opus 1 et 2 non ?
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5503 Défis: 18 Message

Citer : Posté le 13/08/2021 15:35 | #


Pour la map, ça doit pouvoir se faire assez facilement effectivement

Pour les stats, c'est un peu plus délicat, elles sont stockés à côté des coordonnées, j'ai essayé de faire en sorte que ce soit simplement modifiable… mais reste un problème, les combats sont normalement géré par le moteur… après je peux ne pas les gérer ? 'fin si je ne connais a priori pas les stats, je ne peux plus gérer les combats ^^'
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir Hors ligne Administrateur Points: 24579 Défis: 170 Message

Citer : Posté le 13/08/2021 15:53 | #


Pour les combats, tu peux implémenter la GUI mais laisser le jeu spécifier ce que les actions font. Par exemple dans un Pokémon tu as 4 attaques toutes uniques (pas juste attaquer/défendre/etc). Si ça peut t'aider donne-toi quelques idées de jeux (Asci-Opus 1 et 2, Pokémon, Final Fantasy) et essaie de construire chaque partie d'une façon qui permette de coder les 3 à la fois.

Il est absolument certain que plus tu laisses de liberté au jeu, moins tu peux faire de choses toi-même (et donc plus tu laisses de travail au jeu). Toute la subtilité c'est d'identifier quelles sont les parties communes à tous les jeux, ou que les auteurs des jeux n'ont pas envie de coder eux-mêmes, et de mettre ça dans le moteur. À toi de voir où tu veux te placer entre «le moteur code très peu : liberté maximale mais beaucoup de travail» et «le moteur code tout : trivial à utiliser mais très limité» !
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5503 Défis: 18 Message

Citer : Posté le 13/08/2021 16:01 | #


Je vois les limitations

Du coup je vais partir sur une sorte de compromis… d'un côté j'ai l'XP, les PV les coordonnées (dont j'ai besoin) et de l'autre j'ai une variable "stat" laissée vierge

De même pour les combats, la fonction sera vide… peut-être passer en argument la fonction de combat ?

Obsolète
Cliquer pour enrouler
Ajouté le 14/08/2021 à 00:07 :
J'ai pas mal avancé !
Un premier tuto est sur le README :

Utilisation

Vous devez commencer par copier le fichier asci_lib.py dans le répertoire de votre jeu. Créez ensuite un fichier qui va correspondre à votre jeu. Nommez-le comme vous voulez, le nom ne présente pas d'importance pour le moteur.

Ici, notre fichier s'appellera sample.py.

Notre fichier va se découper en plusieurs parties :
- l'importation de la bibliothèque asci_lib.py
- la création de la carte
- la création des dialogues
- la création de la fonction qui correspond à votre jeu et finalisation

La carte est un grand tuple qui est de la forme :

carte_monde = (
<carte_du_monde>,
(<carte_maison_1>, (x_entree1, y_entree1), (x_sortie1, y_sortie1)),
(<carte_maison_2>, (x_entree2, y_entree2), (x_sortie2, y_sortie2)),
...)

la <carte_du_monde> et les <carte_maison_X> sont des r-docstrings. Vous pouvez mettre à peu près n'importe quoi, veillez à bien respecter la légende :
- @ : caractère réservé au joueur (ne pas utiliser)
- ^ : porte de maison
- * : PnJ
- $ : adversaire

Dans le cas des maisons, le premier tuple correspond aux coordonnées de la porte de la maison *dans la carte du monde*. Le second tuple correspond aux coordonnées de la porte de la maison *dans la carte de la maison*.

Sur votre carte fraîchement créée, vous avez mis des PnJ (si ce n'est pas le cas, mettez-en, la suite sera plus intéressante ). L'idée est assez simple, il va falloir créer une fonction qui va prendre en argument l'expérience, les points de vie, l'id de la carte (l'index de la carte dans le tuple des maps, 0 : carte du monde, 1 : première maison etc), les coordonnées du joueur et les stat (une liste qui peut contenir des variables nécessaires aux mécaniques de votre jeu). Nous avons donc déjà :

def dialogue(xp, pv, carte_actuelle, x, y, stat):

Cette fonction va renvoyer un dictionnaire ou une liste.

C'est assez important, car, si vous renvoyez un dictionnaire, le dialogue sera lu en fonction des points d'expériences du joueur. Si vous renvoyez une liste, c'est le dialogue de la liste qui sera lu.

Le seul impératif que vous devez absolument respecter est la forme du dictionnaire et des listes.

Le dictionnaire est de la forme :

dialogues = {
    xp_1: [...],
    xp_2: [...],
    ...
    "base": [...]
}

xp_X correspond au nombre de points d'expérience à avoir pour déclencher ce dialogue.
"base" est le dialogue lancé par défaut si aucun autre cas ne marche.

Les listes sont, elles, de la forme :

[xp_gagne, pv_gagne, "le texte du dialogue", booleen, ...]

xp_gagne correspond aux nombres de points d'expérience gagné lors de la lecture de ce dialogue.
pv_gagne même principe qu'avec l'XP, mais avec les points de vie.
booleen détermine s'il s'agit d'un monologue du PnJ ou si vous pouvez répondre au PnJ.
... correspond à des modificateurs des stats. Vous pouvez tout à fait les oublier en première utilisation

La question maintenant est de savoir comment relier les dialogues au PnJ. Vous êtes libre de mettre en place un système d'ID, Nous vous proposons un système peut-être plus simple : les coordonnées des PnJ. Nous allons ainsi avoir une fonction qui va ressembler à :

def dialogue(xp, pv, carte_actuelle, x, y, stat):
    # Pour des raisons de clareté, on déclare un tuple avec les coordonnées
    coords = (x, y)

    # Si nous sommes en extérieur
    if carte_actuelle == 0:
        if coords == (X1, Y1):
            return {...}
        elif coords == (X2, Y2):
            return {...}

    # Si nous sommes dans la première maison de la liste
    elif carte_actuelle == 1:
        ...

    # Si le PnJ est bien sur la map, mais n'a aucun dialogue d'assigné :
    return [0, 0, "Hmm ?", False]

Vous pouvez également créer des dialogues. Pour cela, il vous suffit de mettre le booleen sur True et de mettre les réponses possibles dans le corps du dialogue, par exemple : [0, 0, "Ceci est une question ? 1. Réponse 1 2. Réponse 2", True]. Le numéro de la réponse correspond au nombre de point d'expérience qu'elle rapporte, cela vous permet de gérer les différents cas dans al suite du dialogue.

Il reste à faire une petite fonction qui va créer un "modèle" de jeu de rôle vierge, il faudra lui donner la carte, la fonction des dialogues et ce sera fini !

La fonction est vraiment triviale :

def mon_jeu():
    rpg_python = Asci(carte_monde, dialogue, 10, [])
    rpg_python.mainloop()

Les deux premiers arguments carte_monde et dialogue ont déjà été vu. Le 10 correspond aux nombres de points d'expérience au bout duquel le programme s'arrête, il s'agit de la fin de la partie si vous voulez. La liste passée en dernier argument correspondent aux stats.

Exemples et astuces

Pour commencer simplement, voici une carte assez banale (ne pas oublier la virgule à la fin !) :

carte_monde = (
r"""
_         ###
/o\__     #####
|  <>\     ###  
|____|     /_\

  *


|==|==|==|==|==|==|==|""",)

Nous n'avons pas de maisons, juste un PnJ

Nous allons faire parler notre PnJ ! Et comme on est chaud, on va directement faire un petit dialogue. Pour bien séparer les réaction à la question du reste, je met un niveau d'indentation supplémentaire, ça ne change rien au comportement du code.

def dialogue(xp, pv, carte_actuelle, x, y, stat):
    coords = (x, y)

    if carte_actuelle == 0:
        if coords == (2, 5): return {
            0: [0, 0, "Coucou ! Comment ca va ? 1. Ca va, et toi ? 2. Bof... 3. Je t'emmerde.", True],
                1: [3, 0, "Je vais bien, merci !", False],
                2: [3, 0, "Ow, desole...", False],
                3: [4, 0, "He, reviens quand tu sera de meilleure humeur !", False],

            4: [2, 0, "Bon et bien, je crois bien que cette premiere carte s'est bien passee !", False],
            5: [1, 0, "Je vais y aller, appelle moi si tu as besoin ;)", False],
            6: [1, 0, "A pluche o/", False],

            "base": [0, 0, "Oui ?", False]
            }

    return [0, 0, "Hmm ?", False]

Pour mettre en place vos dialogues (parce que j'espère que vous aurez un peu plus qu'un seul PnJ) faire un arbre de progression de l'XP peut être une bonne idée je vais essayer de le faire en ASCII-art pour vous montrer, mais avec une feuille et un stylo c'est plus simple.

      1    4
     -=----=---
0   / 2    5   \  6  7
------=----=------=--=
    \ 3            /
     -=------------


Il reste la petite fonction à faire :

def mon_jeu():
    rpg_python = Asci(carte_monde, dialogue, 7, [])
    rpg_python.mainloop()


Nous avons le fichier complet :

from asci_lib import *


carte_monde = (
r"""
_         ###
/o\__     #####
|  <>\     ###  
|____|     /_\

  *


|==|==|==|==|==|==|==|""",)


def dialogue(xp, pv, carte_actuelle, x, y, stat):
    coords = (x, y)

    if carte_actuelle == 0:
        if coords == (2, 5): return {
            0: [0, 0, "Coucou ! Comment ca va ? 1. Ca va, et toi ? 2. Bof... 3. Je t'emmerde.", True],
                1: [3, 0, "Je vais bien, merci !", False],
                2: [3, 0, "Ow, desole...", False],
                3: [4, 0, "He, reviens quand tu sera de meilleure humeur !", False],

            4: [2, 0, "Bon et bien, je crois bien que cette premiere carte s'est bien passee !", False],
            5: [1, 0, "Je vais y aller, appelle moi si tu as besoin ;)", False],
            6: [1, 0, "A pluche o/", False],

            "base": [0, 0, "Oui ?", False]
            }

    return [0, 0, "Hmm ?", False]


def mon_jeu():
    rpg_python = Asci(carte_monde, dialogue, 7, [])
    rpg_python.mainloop()


Ajouté le 14/08/2021 à 23:20 :
Mon précédent message est maintenant complètement obsolète
Je vais éviter de trop surcharger le forum avec le mode d'emploi, mais pour faire vite :
- un tuto d'utilisation et des exemples sont disponibles sur le README du dépôt
- le projet est susceptible d'avoir quelques fonctionnalités qui changent, mais rien de majeur n'est prévu.

Le moteur est téléchargeable ici.
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Shadow15510 Hors ligne Administrateur Points: 5503 Défis: 18 Message

Citer : Posté le 26/08/2021 00:22 | # | Fichier joint


Version 1.4.0
J'ai refondu le système d'évènements et de touches pour permettre quelque chose de vraiment généraliste.

Maintenant vous pouvez diviser vos évènements en catégories, chaque catégorie a sa fonction (qui renvoie un dictionnaire d'évènements ou un évènements) et cette fonction est appelée lorsque le joueur atteint un symbole que vous précisez.

De même pour les touches, les touches 4, 6, 7 et 8 ne sont pas utilisées par le moteur, vous pouvez donc les associer à des fonctions et en faire ce que vous voulez

Quels avantages ?
Cette nouvelle version est plus légère que la précédente avec 300 octets de gagné
Plus besoin de déclarer une fonction avec un def ... pass parce que le moteur voulait une fonction dont vous n'avez pas l'utilité pour votre projet : économisez de la place au sein de vos jeux.
Le code est plus aéré : si vous avez beaucoup d'évènements dans des circonstances différentes, vous pouvez séparer les cas plus simplement.
si les noms des fonctions sont bien choisis, le code devient extrêmement clair : evenements : {"*": pnj, "?": point_interet} avec pnj et point_interet des fonctions. De même pour les touches : touches = {7: affichage_stat, 8: inventaire} le mapping apparaît explicitement.
Comme dans la version précédente vous pouvez faire correspondre plusieurs symbole à la même fonction évènementielle. Par exemple si mes PnJ sont des * ou des ?, je peux écrire : evenements = {"*?": pnj}

Toute la documentation a été mise à jour, les exemples aussi
@RDP
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Shadow15510 Hors ligne Administrateur Points: 5503 Défis: 18 Message

Citer : Posté le 30/08/2021 15:36 | # | Fichier joint


Version 1.4.2

Petit changelog
Possibilité de modifier les statistiques au sein d'un évènement. Il suffit d'ajouter à la fin de la liste, un (ou plusieurs) tuple(s) de la forme (index, valeur). Cela va ajouter valeur à stat[index].
Les statistiques étaient déjà modifiables par effet de bord, la liste data qui est essentiel au fonctionnement du moteur l'est aussi. Attention toutefois, des modifications un peu hasardeuse du contenu de cette liste peut tout faire planter. (mais c'est de votre faute )
Vous pouvez maintenant vous amuser à faire des maps tordues avec des pièces cachées dans des maisons, le moteur sait faire !

Bon, en terme de poids, on a encore perdu 100 octets…
@RDP

Ajouté le 03/10/2021 à 15:27 :
Une toute petite mise à jour mineure. Elle ne concerne pas directement Asci, mais le script Python qui permet de convertir les fichiers tmx en carte pour Asci le truc chiant était de relever les coordonnées des portes à la main pour ensuite faire les points de passages. C'est maintenant géré par le script de conversion

Pour être plus clair, le script vous retourne un fichier .py avec la carte et les coordonnées des portes trouvées il vous reste plus qu'à remplir les trois derniers paramètres qui sont l'indice de la carte d'arrivée, et les coordonnées d'arrivées.

La syntaxe à donc légèrement changé : il faut préciser le symbole "porte" :
$ python converter ma_carte.tmx ^ ~
(avec ^ et ~ les portes)

Ajouté le 04/10/2021 à 17:19 :
C'est une idée qui m'a traversée l'esprit et pour l'instant j'ai ni vraiment le temps de m'y consacrer, ni beaucoup d'idée pour la commencer, mais peut-être un jour, il sera possible pour le développeur de modifier la map pendant l'exécution du jeu. J'entend par là, avoir un ennemi qui bouge, un PnJ qui suit le joueur, etc…

Pour l'instant j'essaye de voir de quoi j'ai besoin pour mettre ça en place, mais ça pose pas mal de problème ^^' il faudrait que le développeur connaisse les coordonnées à l'avance, ou alors fasse une fonction qui renvoie les coordonnées. Se pose aussi le problème du rafraîchissement. Mettre à jour les coordonnées à chaque fois que le joueur bouge me semble être la seule possibilité… Sans compter qu'a priori, y a pas de raison que le joueur ne puisse pas interagir avec le PnJ / ennemi / whatever qui bouge, donc il faudrait revoir le système qui gère ça et ne plus uniquement se fier aux coordonnées (qui vont changer au cours du temps).

'fin voila, j'ai pas d'idée de comment le faire, ça va un peu foutre la merde dans ce qui existe, et je manque un peu de temps pour faire ça d'un coup, mais ça me semble rigolo d'avoir un PnJ qui suit le joueur x)
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir Hors ligne Administrateur Points: 24579 Défis: 170 Message

Citer : Posté le 04/10/2021 19:04 | #


Effectivement modifier la map au fur et à mesure ça pose quelques soucis, après tu peux toujours ne t'occuper que de l'affichage et déléguer au programme utilisateur la tâche d'assurer que les objets ne se rentrent pas dedans.
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5503 Défis: 18 Message

Citer : Posté le 04/10/2021 20:39 | #


Mouaip, après les collisions, ça me semble pas être le plus dur à gérer… Il suffit juste de faire une vérification, et j'ai tout pour la faire
J'essaye de garder ça dans un coin de ma tête, si j'ai plus d'idée concrète sur la mise en place, je m'y pencherai de manière plus sérieuse

Ajouté le 31/10/2021 à 21:37 :
Attention, ça va être rapide. Petite mise à jour mineure avec l'ajout d'une fonction de routine exécutée à chaque tour de boucle.
(je vous avait prévenu )

Ajouté le 11/11/2021 à 15:12 :
Version 1.5.2
Quelques changements mineurs
  • Ajout d'un pinceau de terrain sur le tileset Tiled pour faire des chemins
  • Ajustement des coordonnées du joueur (lorsque l'on demande à Asci de démarrer à certaines coordonnées, il y avait une confusion entre les coordonnées du joueur et celle de la carte)
  • Ajout d'une fonction pour afficher du texte formaté correctement (voir la documentation)

@RDP
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Shadow15510 Hors ligne Administrateur Points: 5503 Défis: 18 Message

Citer : Posté le 11/11/2021 17:16 | # | Fichier joint


Juste pour @RDP qui n'était pas passé ^^'

Ajouté le 20/11/2021 à 13:33 :
Heyy ! C'est pour un petit sondage.

Lors des dialogues, il est parfois possible de choisir sa réplique. (le joueur entre alors le numéro de sa réplique).
Le plus naturel serait :
1. de lancer le dialogue suivant directement
2. d'attendre que le joueur reparle au PnJ en question pour avoir la suite (système actuel)

Voila, c'est tout
Merci d'avance de vos réponses o/
(Vous pouvez répondre dans #projets)
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Lephenixnoir Hors ligne Administrateur Points: 24579 Défis: 170 Message

Citer : Posté le 20/11/2021 13:43 | #


Pour moi il faut que le dialogue continue immédiatement
Mon graphe (11 Avril): ((Rogue Life || HH2) ; PythonExtra ; serial gint ; Boson X ; passe gint 3 ; ...) || (shoutbox v5 ; v5)
Shadow15510 Hors ligne Administrateur Points: 5503 Défis: 18 Message

Citer : Posté le 20/11/2021 13:47 | #


C'est effectivement ce que je me dis aussi

L'idée est venue d'un ami qui testait IDK et il a eu l'air surpris quand il a compris qu'il fallait reparler au personnage pour continuer le dialogue. En plus c'est vraiment juste une ligne à changer… xD

Ajouté le 21/11/2021 à 16:20 :
Version 1.5.3

Quelques changements mineurs, notamment :
  • La possibilité de renvoyer un événement vide (ça skip juste l'interaction)
  • Les dialogues automatiques
  • Quelques fix de bugs (en particulier lors des changements de map dans les événements

"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Shadow15510 Hors ligne Administrateur Points: 5503 Défis: 18 Message

Citer : Posté le 02/01/2022 17:59 | # | Fichier joint


Version 1.5.4

Toujours pas de gros changements majeurs. Jusqu'alors le fichier à inclure s'appelait asci_lib.py, raccourci en asci.py à partir de cette version.

Et autre changement, depuis la version 1.5.2, Asci est fourni avec une fonction, print_text qui permet d'afficher du texte formaté pour l'écran, cette même fonction peut dorénavant prendre trois arguments supplémentaires pour gérer les choix multiples. Ainsi vous pouvez préciser la valeur minimale que le joueur peut rentrer, la valeur maximale, et si la valeur n'est pas conforme à ce que vous voulez (pas dans l'intervalle, ou pas transtypable vers un int), la fonction vous renvoie la valeur par défaut.
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Shadow15510 Hors ligne Administrateur Points: 5503 Défis: 18 Message

Citer : Posté le 08/01/2022 22:59 | # | Fichier joint


Version 1.6.0

Une mise à jour avec une nouvelle fonctionnalité : les quêtes parallèles.

Journal des modifications :
  • Ajout d'un système de quête parallèles. Les points d'expériences ne sont plus stockés dans un unique entier, mais dans un dictionnaire : les clefs sont les noms des quêtes et les items sont les points d'XP du joueur dans cette quête.
  • Ajout d'un exemple, sample_4 avec une quête principale qui mène se divise en deux quêtes à faire pour mettre en évidence l'indépendance des quêtes.


La librairie est en fichier joint, la page de téléchargement est à jour, ainsi que le dépôt git, et la documentation aussi.
@RDP
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Shadow15510 Hors ligne Administrateur Points: 5503 Défis: 18 Message

Citer : Posté le 26/01/2022 18:53 | # | Fichier joint


Version 1.6.3

Après quelques fix de bugs, je sort la version 1.6.3 qui ne compote grosso modo qu'une seule mise à jour notable : l'implémentation des déplacement multiples. Lorsque vous êtes dans un jeu, vous pouvez entrez le symbole . suivi d'une liste de déplacement à faire. Le moteur va ainsi traiter les déplacements dans l'ordre. Toute forme d'interaction sera ignorée (pas de dialogue, pas de changement de cartes etc).

Le symbole peut être customisé lors du développement du jeu. En théorie, cela fonctionne pour toutes les actions, mais je pense le restreindre aux seuls déplacements dans une prochaine mise à jour (sinon cela implique de faire attention aux "touches" composées de plusieurs caractères).
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Shadow15510 Hors ligne Administrateur Points: 5503 Défis: 18 Message

Citer : Posté le 28/01/2022 23:31 | # | Fichier joint


Version 1.7.0

Il y a pas mal de chose à dire, utiliser le moteur est incontestablement devenu plus fin, il y a pas mal de chose qui sont pas trop documentable, typiquement des objets comme "Entity" ou "Screen" n'ont pas été conçus pour une utilisation publique, donc y a parfois des arguments un peu bizarres qui se baladent, et c'est pas trop justifiable (typiquement pour récupérer le contenu d'une cellule faut donner 3 arguments (les décalages monde / écran + coordonnées de la case ciblée). Donc si vous voulez utiliser le moteur à fond, je pense que le code est compréhensible, plus les exemples et avec la doc, ça doit être faisable, mais s'il vous reste des questions : n'hésitez pas.

Notez que normalement, y a pas trop besoin de mettre les mains dans le cambouis avec les fonctionnalités de bases, ça marche bien (normalement)

  • Ça faisait longtemps que ça me trottait dans la tête : pouvoir faire bouger des entités sur l'écran. C'est maintenant chose faite ! Les entités sont des objets qui sont stockés avec la map sous forme de tuples. La map a ainsi une liste d'entité avec elle qui correspond à toutes les entités présentent sur cette map.

    Chaque entité a un tuple qui contient son identifiant, son symbole (le caractère affiché à l'écran), ses coordonnées, son comportement et des arguments optionnels utiles pour certains types de comportements.

    Il est possible de programmer des comportements dans des fonctions à part puis de rajouter ces comportements à ceux gérés de bases. Il y a pour l'instant 4 types de comportement :
    - stand by (l'entité ne bouge pas)
    - follow (l'entité suit le joueur)
    - walk (l'entité se déplace entre plusieurs cases données dans l'argument facultatif)
  • C'est clairement mineur par rapport à ça, mais ça m'a bien pris 3-4 heures donc j'en parle j'ai complètement refactorisé mon code. J'avais notamment des gros problèmes avec mon système de coordonnées (j'utilisais tour à tour trois repères différents ce qui a fini par donner un joyeux bordel) maintenant, c'est plus propre : tout se passe en prenant l'angle supérieur gauche du monde comme origine.


@RDP
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Shadow15510 Hors ligne Administrateur Points: 5503 Défis: 18 Message

Citer : Posté le 29/01/2022 11:44 | # | Fichier joint


Version 1.7.1

Une toute petite mise à jour par rapport à la précédente :
  • Suppression des codes de test que j'ai oublié d'enlever
  • Simplification des syntaxes laissées à l'utilisateur, notamment pour la gestion de l'écran
  • Modification légère, les entités sont maintenant données au développeur sous la forme d'un dictionnaire où les identifiants sont les clefs, donc c'est très rapide (et simple) de retrouver l'entité activée pour la modifier


Après quelques tests sur IDK, le moteur est bien fonctionnel, on peut noter que la calculatrice charge un peu à chaque frame (on voit le logo de chargement s'annuler), mais il n'y a pas de lag.
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Shadow15510 Hors ligne Administrateur Points: 5503 Défis: 18 Message

Citer : Posté le 30/01/2022 13:55 | # | Fichier joint


Version 1.7.2

Désolé pour les mises à jour très rapprochées ^^'
Celle-ci est assez importante malgré le fait qu'il ne s'agisse que de patch.
  • une animation permanent a été ajoutée : l'entité ne bouge pas et son comportement ne peut plus être modifié
  • le comportement "follow" a été complètement revu, notamment des glitchs où l'entité était affichée en dehors de la map ou bloquait le passage au joueur sont maintenant résolus.
  • l'outil de formatage de texte était une fonction récursive, ça marchait plutôt bien, mais certains très gros textes, la calculatrice n'en voulait pas ce qui obligeait à découper le texte à afficher en plusieurs petits. J'ai réécrit la fonction qui est maintenant itérative, donc plus de problème.
  • la syntaxe des mouvements multiples a été revu pour accepter les mouvements donnés sous la forme : .deplacement*nombre on peut combiner les déplacements en les séparant par des virgules : .1*3,5*1 est maintenant géré (les *1 peuvent être omis)
  • Asci calculait à chaque tour la liste des entités visibles, cette liste était actualisée un peu n'importe comme et certains calculs étaient effectués plusieurs fois. En supprimant cette liste et en optimisant les calculs, j'ai récupéré un peu de perf (les entités sont affichées en même temps que les animations sont mises à jour ce qui permet de ne parcourir la liste des entités qu'une seule fois)
  • ça ne change rien pour l'utilisateur, mais en interne les entités étaient stockées dans une liste, il s'agit maintenant d'un dictionnaire, donc l'accès à une entité se fait en temps constant alors qu'il fallait regarder toute la liste avant. Notez que cela ne change pas la manière dont les cartes sont conçues : il faut toujours donner une liste de tuples.

@RDP (à fusionner avec les deux changelogs précédents siouplaît )
"Ce n'est pas parce que les chose sont dures que nous ne les faisons pas, c'est parce que nous ne les faisons pas qu'elles sont dures." Sénèque

Mb88 Hors ligne Rédacteur Points: 1211 Défis: 3 Message

Citer : Posté le 21/02/2022 11:37 | #


Avec une version pour calculette monochrome ça serait parfait !
(Je préfère clairement le Python au Casio Basic)
1, 2 Suivante

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v4.3 © créé par Neuronix et Muelsaco 2004 - 2024 | Il y a 119 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd