Touhou
Posté le 24/10/2020 22:44
Je connais un admin qui serait pas content parce que je créé pas de topic sur un projet en cours… C'est chose faite
Comme vous le savez sûrement si vous passez de temps en temps sur le site,
Lephenixnoir a créé un truc qui s'appelle
gint, et qui révolutionne la programmation d'addins comme MonochromeLib a pu le faire.
Le concept m'a plu, du coup j'ai commencé à avoir des idées. Dont une qui m'a paru être assez simple mais complète, faire un shot'em'up, en particulier un remake de Touhou. La série de jeu est assez connue, y'a déjà tout un tas d'assets, et techniquement ça utilise un paquet de concepts.
Bref, je suis parti là dessus.
Je bosse énormément via Git, le dépôt du projet est ici →
Darks/Touhou.
Je pense faire un fichier de releases notes pour indiquer comment ça avance, mais sachez que c'est avant tout une expérimentation des possibilités offertes par gint ainsi que de l'apprentissage de ma part (ça fait plus de 5 ans que j'ai pas sorti un truc en C).
Ne vous étonnez pas si je poste peu sur ce topic, c'est soit que ça se passe en local, soit sur la forge, soit pas (parce que je fais autre chose, comme développer la v5 par exemple…).
Releases notes
TBD…
Citer : Posté le 24/10/2020 22:47 | #
Merci.
Du fond du coeur.
Citer : Posté le 24/10/2020 22:48 | #
Hé dis, hé dis, est-ce qu'il y aura la musique de Touhou aussi ?
Citer : Posté le 24/10/2020 22:49 | #
Ça dépend si gint fourni l'API nécessaire
Citer : Posté le 27/10/2020 00:35 | # | Fichier joint
Bon, j'ai un peu bossé sur les dialogues ce soir, du coup je vous présente une petite démo du rendu. Le code est dispo sur la branche dialogs du dépot.
Démo en fichier joint
Et bon anniv' Tituya
Au passage Lephe, t'aurais une idée pour rendre un peu plus propre la fonction display_text ? Là c'est un one-shot pour la démo, mais ça gère pas le soft wrap, et c'est un peu moche je trouve.
Et quelques commentaires sur la manière de faire, entre autre pour les events clavier
Citer : Posté le 27/10/2020 00:55 | #
Cette demo donne tout simplement envie de jouer au jeu final !
Vraiment, même si ce n'est "que" du dialogue, on voit que c'est soigné et que le jeu va être de qualité
Bonne chance !
(Et de toute façon, vous pouvez pas dire le contraire)
MultipliCasio
RDM Calculs
Back Mirror
A Switch To The Top C
Citer : Posté le 27/10/2020 09:26 | #
C'est vraiment stylé cette démo rien que pour un dialogue, ça donne super envie !
Pour ce qui est du code, c'est sûr qu'on va pas t'apprendre à coder... voilà ce que je peux suggérer :
• Tu dois absolument traiter tous les événements entre chaque frame. e=pollevent() ne peut pas suffire parce que s'il y a plusieurs événements dans la file tu ne vas en sortir qu'un et laisser les autres s'accumuler. C'est d'autant plus important que tu as couplé un frame graphique avec un frame d'input, et donc il faut garder en tête le fait que cette boucle peut être lente si le rendu n'arrive pas à suivre. Et c'est également très important parce que tu utilises keydown() et si la file d'événements n'est pas vide ou quasi-vide keydown() ne reflète pas l'état instantané du clavier.
Pour faire ça proprement, il y a plusieurs options. La méthode bourrine consiste à utiliser clearevents() qui fait des pollevent() jusqu'à ce qu'il n'y ait plus rien. La bonne nouvelle c'est que tu es à jour donc tu peux utiliser keydown(), la mauvaise c'est que tu peux rien faire d'autre parce que tu viens de jeter tous les événements aux ordures (d'où le nom de la fonction).
La méthode moins bourrine consiste à lire et traiter les événements un par un. La méthode fine et lag-aware consiste à traiter un par un les événements tout en tenant utilisant la valeur de e.time pour prendre en compte le fait qu'ils ne sont pas simultanés (intéressant uniquement pour un vrai bon moteur de jeu temps réel, pas un moteur de dialogues, mais qui sait ça pourrait t'arriver *cough cough*).
• Dans le jeu final je suggère d'avoir un FPS cap sous la forme d'un timer dont tu attends l'interruption entre deux frames. C'est déjà un peu le cas parce que tu arrives sur chaque dupdate() avant que le frame précédent soit fini d'envoyer, mais c'est pas hyper sérieux de s'appuyer sur le bottleneck de l'écran. Ici c'est une simple question de pas trop pomper la batterie, surtout si tu overclockes dans le moteur principal ou que tu veux ajuster la vitesse des écrans.
• Nombre de caractères par microseconde : check. Excellente unité de mesure, rien à dire.
• Tu as correctement utilisé des float pour le positionnement du texte, mais de l'autre côté tu utilises un sinus/cosinus en double précision. Non que la fonction soit longue, mais l'approximation polynomiale a moins de coefficients dans cosf() donc autant en profiter. Oublions pas que tout est en soft-fp et ça c'est catastrophiquement lent dans les cas défavorables.
• Évite de créer des copies a priori inutiles d'images, non pas que tu manquerais de mémoire, mais parce que le tas de l'OS est assez fragile et il se détériore avec le temps. Mieux vaut limiter le nombre de malloc().
• Le traitement du texte est lent, ça se voit parce que tu passes de façon très consistente de 68 FPS quand il n'y a pas de texte à 64-62 FPS quand les plus longs messages sont visibles à l'écran. Pour faire ça proprement, dsize() n'est pas tout à fait appropriée puisque tu es obligé de passer un temps quadratique à évaluer des caractères. En réalité, tu pourrais juste faire dsize() sur chaque caractère individuellement et ajouter l'espacement entre chaque pour ton calcul, mais ce serait pas robuste ni future-proof : le jour où je rajoute du kerning ou des ligatures, ça sera vite invivable (et vraiment problématique) de reproduire la logique interne de topti dans ton évaluation de taille.
De ce point de vue-là, je pense qu'il serait propice d'avoir une fonction supplémentaire dans gint pour faciliter le job. Pour ce job en particulier je pense que la fonction inverse de dsize() serait appropriée : tu spécifies la taille et il te donne le nombre max de caractères qu'il peut afficher. Si on garantit que les ligatures sont plus larges que les caractères individuels, et avec une bonne option pour prévoir les tirets en cas de coupure à l'intérieur d'un mot je pense qu'on peut gérer la plupart des situations correctement.
Citer : Posté le 27/10/2020 11:40 | #
Hello j'ai check un peu l'arborescence, et pour les tile set pour le coup pourquoi tu as pleins de fichiers ? Typiquement tu pourrais regrouper les ennemis, etc...
Et faire un dsubimg().
Pourras-tu survivre plus de 20 secondes dans ce fameux tunnel appelé Graviton
Rebondis entre les murs en évitant les piques dans SpikeBird
Pourras-tu éviter de te faire écraser dans FallBlocs (élu Jeu Du Mois)
La version 2048 tactile amélioré au plus haut point : 2048 Delux !
Pars à la recherche des morceaux d'étoile dans Lumyce (élu Jeu Du Mois)
Citer : Posté le 27/10/2020 13:55 | #
Merci Lephe pour les retours, je ferais une màj ce soir.
Kirafi, c'est plus ou moins du legacy. En fait déjà je compte générer les différents ennemis dans un module fxconv : c'est juste un changement de chroma pour la plupart. Et oui dans ce cas passer par un tileset. Ce qui est dans dans le dépôt, c'est juste la sortie de mon script de test.
Au passage, h'en profite pour signaler que le dsubimg est efficace si tous les sprites ont la même dimension. Par exemple je ne peux pas faire ça sur les witches puisqu'elles ne sont pas toutes identiques. En soit je pourrais, mais après pour faire un affichage dynamique en fonction de la taille ça rajoute des métadonnées qui sont déjà fournies si je sépare les fichiers (img.width, img.height, etc.)
Citer : Posté le 27/10/2020 14:01 | #
Juste pour préciser, le problème avec dsubimage() n'est pas que c'est lent quand les sous-images sont de différentes tailles mais que c'est casse-tête de se souvenir de la taille de chaque image. Dans ta formulation j'ai eu un doute au début.
Dans tous les cas, contrairement à la Graph mono, il n'y a pas grand-chose à gagner en stockage à grouper ensemble des images (sauf si elles sont très petites), après c'est surtout une histoire de pas avoir une infinité de variables.
Citer : Posté le 27/10/2020 14:08 | #
Problème qui sera résolu avec le module custom fxconv qui me générera des tableaux de pointeurs tout seul comme un grand.