Notre frise chronologique

  • Naissance du groupe

    Le groupe d'amis se forme et fait connaissance dans un parc d'accrobranche. Des idées émergent déjà pour le projet de S2. Ils veulent faire un jeu où l'on incarne un sorcier en reprenant un grand nombre de codes du style RPG.

    Les discussions vont bon train alors que nos compères s'amusent à grimper aux arbres. Le groupe se rend compte que leur idée est ambitieuse et ils décident de se mettre au travail plus tôt que prévu par l'école.

    Au courant de cette journée, ils se rendent compte qu'ils ont besoin d'un nom pour une chasse aux trésors dans le parc. Dylan a un T-shirt Star Wars et propose le nom d'Epistars. Le groupe est d'accord et le nom est adopté.

    De plus, en découvrant les intérêts de chacun, ils se rendent compte qu'ils ont tous des compétences complémentaires pour réaliser leur projet. Dylan est un grand artiste, Baptiste un grand joueur, Anouar un grand chef et Antoine un grand matheux.

    Antoine

    Epistars naît

  • Le vrai début du site

    Le vrai parce qu'il y a eu plein de versions avant lui. En passant par des animations powerpoint et autres exagérations, les retours du groupe m'ont fait aller vers quelque chose d'un peu plus sobre. !(essai précédent)

    Le choix du thème

    Je ne les ai pas écouté par rapport à l'esprit du site. Ils voulaient retrouver l'ambiance fantaisie/magique du jeu dans le site. Sauf qu'intégrer du "vieux" dans un site web c'est très délicat... J'ai préféré partir sur une direction artistique plus moderne et neutre en terme de charte graphique. En ajoutant de légères touches comme : la fumée bleue qui suit la souris ou le pixel art général, l'esprit du jeu serait retranscrit par les images. Et de mon expérience, les gens sont plus sensibles aux images qu'aux couleurs.

    Le choix du CMS/framework

    Le choix du framework svelte a été fait dès le début, principalement parce que c'est mon préféré. De plus, il est très simple à utiliser et à comprendre, ce qui est un plus pour un projet de groupe. Pour la partie serveur, j'aurais bien pris SvelteKit mais je voulais rendre l'écriture des posts le plus simple possible pour motiver toute l'équipe à en écrire. Astro est alors apparu comme une solution attrayante. C'est un générateur de site statique qui permet d'utiliser différents frameworks tels que Svelte pour programmer. Mais une fonctionnalité très séduisante consiste à utiliser un dossier de fichiers au format markdown comme une collection, ce qui est très adéquat pour implémenter un système.

    Antoine

    Début du site

  • Créer un blog performant et fonctionnel nécessite du temps, de la patience et de la persévérance. C'est exactement ce que j'ai découvert en programmant ce site lors de mon séjour en Allemagne. Il m'a fallu 5 jours de travail acharné pour finaliser ce projet et le rendre accessible à tous.

    Au cours de ce processus, j'ai dû faire face à plusieurs défis, notamment en ce qui concerne la fluidité du site avec toutes les animations en scroll. Cependant, grâce à mon expérience et à ma connaissance de la programmation, j'ai pu surmonter ces difficultés et créer un site réactif et rapide.

    Mais ce n'est pas tout. J'ai également voulu ajouter une touche personnelle à ce site en intégrant une fumée bleue qui suit la souris de l'utilisateur. Bien que cet effet ait pu affecter la performance du site, j'ai travaillé dur pour trouver le juste équilibre entre esthétisme et rapidité. Le résultat en vaut vraiment la peine !

    En fin de compte, je suis fier de présenter ce blog que j'ai créé avec passion et détermination. J'espère qu'il vous plaira autant qu'il m'a plu de le concevoir et de le programmer. Alors, que dire de plus ? Profitez de votre visite sur ce site et n'hésitez pas à laisser vos commentaires !

    Antoine

    Systeme de blog

  • Le multijoueur fonctionne

    (enfin presque) Le multijoueur possède les fonctionnalités pour héberger et rejoindre une partie. Le travail a été plutôt simplifié par Unity Relay puisqu'il existe nativement un système de parties protégées par un code, exactement ce qu'il nous faut. La joie était présente lorsque ça a marché pour la première fois, mon personnage bougeait en temps réel chez mon coloc Baptiste; dont le personnage bougeait en temps réel chez moi !

    Avant cela, le debug était pénible. Unity ne permet de lancer 2 instances du jeu dans l'éditeur... Solution : faire un build à chaque modification pour lancer le .exe. Heureusement, beaucoup de choses se simplifient grâce à l'absence de sécurité. Aucune vérification de l'identité du joueur, pas de vérification de la validité des données reçues, le paradis des cheaters ! On part du principe que les codes de parties ne sont partagés qu'entre amis, et que les amis ça se fait confiance.

    Cependant, héberger et rejoindre n'est que le début du projet, la plupart du travail sur le multijoueur sera sûrement de gérer tous les bugs et les cas particuliers. Ces problèmes ont déjà été imaginés dès le début de notre aventure, c'est pourquoi il nous semblait important que le système du multijoueur soit implenté en amont de tout le reste afin que les fonctionnalités se construisent dessus et non l'inverse.

    Un bon démarrage

    Il est aussi important de noter que c'était la première fois pour ma part que je travaillais sur Unity sérieusement. J'ai découvert beaucoup de choses et j'ai aussi dû implémenter des bases pour que le multi soit contextualisé. C'est ainsi que j'ai exploré les solutions pour faire notre jeu en isométrique et que j'ai commencé à implémenter des éléments d'interface. Voir du concret a été un bon boost de motivation pour continuer à travailler sur le projet.

    Antoine

    Multijoueur

  • Réalisation de l'inventaire

    Une tâche qui doit être réalisée assez tôt pour que toutes les fonctonnalités qui en dépendent puissent être implémentées. Ce travail a nécessité un peu d'UI mais surtout beaucoup de réflexion sur la manière de stocker les objets. Il a fallu construire toutes les bases théoriques pour faire un système robuste et évolutif. C'est à ce moment là que j'ai enfilé mon chapeau de chef d'architecture.

    Classes

    Les items sont découpés en 3 classes : Item, Equipment et Consumable. Item est la classe mère de ces deux dernières. Elle contient les propriétés communes à tous les items : nom, description, icône, etc. Equipment et Consumable contiennent les propriétés spécifiques à ces deux types d'items. Par exemple, Equipment contient les propriétés de l'équipement (armure, dégâts, etc.) et Consumable contient les propriétés du consommable (effet, durée, etc.). Cela permet de créer des items qui sont à la fois des équipements et des consommables, comme un bouclier qui donne des dégâts en plus.

    Pour gérer ces statistiques, j'ai créé une classe Stats qui est un dictionnaire permettant de stocker des flottants associés à des chaînes de caractères tout en connaissant le type de statisque. En effet, il faut différencier hp +50 et hp +50% par exemple. Cela permet de faire des calculs plus complexes sur les statistiques tout en gardant une certaine flexibilité. Ainsi, chaque objet qui intéragit avec les statisque est une instance de Stats : equipment, consumable, player, etc.

    J'ai aussi implémenté des recettes pour avoir un squelette de base mais ce sera une tâche à finir plus tard.

    Pour ajouter des items ou des recettes, il suffit de modifier les fichiers qui agissent comme des bases de donnée. Ces bases de données renvoient l'objet associé à son id. Chaque item (ou recette) n'est instancié qu'une fois puisque ses propriétés ne changent pas. Ce n'est juste pas le cas pour l'équipement dont une nouvelle instance est créée dès que l'objet est récupéré dans la base de données puisque ses stats subissent un passage à l'aléatoire.

    Stockage

    L'inventaire est infini, il s'agit simplement d'une liste de tuples (item, amount). Pour le système de sauvegarde, on pourrait imaginer que les items ne soient représentés que par leur id et que dans le cas des équipement, amount représente la seed.

    Interface

    Les joueurs n'ont pas de coffre, il est donc important de leur fournir un inventaire complet en fonctionnalités. C'est pourquoi, on peut choisir de montrer "tout", "équipement", "consommables" et "ressources". En plus de ce filtre, on peut trier par ordre alphabétique, par rareté et par quantité, chacun dans l'ordre croissant ou décroissant.

    Futur

    Il reste à implémenter : un "tooltip", la possibilité de jeter des items, de les utiliser et de les équiper. Il faudra aussi implémenter les statistiques du joueur.

    Antoine

    Inventaire

  • Réalisation du Level Design

    Lorsqu'on a regardé la plupart des jeux produits les années précédentes, on s'est vite rendu compte que le level design était souvent négligé et par conséquent souvent "baclé". Pour éviter de créer le même problème dans Hermita, on a décidé que je m'occuperai directement de commencer à construire les zones de jeu pour être sûr de ne pas louper cette étape, qui est, mine de rien essentielle.

    L'île du housing

    Premièrement, il a fallu déterminer le nombre de maps que j'allais devoir faire, nous sommes donc partis sur une première map qui serait l'île de la partie solo/housing du jeu.

    Il n'y avait pas beaucoup de contraintes à part préparer les emplacements où intégrer les différents établis et le portail donc j'ai choisi de faire quelque chose de plutôt simple et petit pour donner un petit côté tranquille et chaleureux. (je ne suis pas encore convaincu par les couleurs que j'ai choisi donc elle vont peut être changer au cours du développement)

    Le premier niveau

    Ensuite, pour la partie multijoueur/aventure du jeu, nous avions pris la décision de ne faire qu'un seul niveau pour le moment comme nos niveaux sont d'une taille assez conséquente. Les contraintes pour ce niveaux ont été d'y insérer 3 zones de thèmes différents ainsi qu'une zone où se déroulerait le combat final.

    J'ai donc décidé de séparer l'île en 3 :

    • Une première île dans le thème d'un temple en ruine où se trouveraient : le portail de spawn, la zone de combat du dernier boss, ainsi que quelques emplacements de camps de mobs très simples pour que le joueur puisse s'exercer sur des petits monstres de bas niveau avant d'aller dans la suite du jeu.
    • Une seconde île composée de 2 zones : une zone en ruine pour faire lien avec la première île et une zone de forêt qui se trouve autour des ruines. Dans ces 2 zones, différents types de mobs seront trouvés ainsi que les emplacements des 2 premiers mini boss.
    • Une troisième île qui accueillera encore de nouveaux types de mobs ainsi que le 3ème mini boss du niveau.

    Progression actuelle

    Pour l'instant, l'île du Housing a été faite, ainsi que la première île du niveau 1. Les tracés des routes et des points d'intérêts des autres zones sont déjà implémentés mais ils ne sont pas encore décorés et aménagés car je suis entrain de dessiner les assets pour en parallèle.

    L'idée globale des zones ayant été faite, il ne nous manque plus qu'à dessiner les différents assets et à les placer correctement, pour un rendu qui, je l'espère, sera plaisant à jouer.

    Baptiste

    Level Design

  • Première passage à l'oral

    Globalement, le pojet a avancé comme prévu avec un peu de retard pour les déplacements avec les collisions. En termes de timing, les choses étaient assez serrées, nous avons commencé à rédiger le rapport de soutenance la veille de l'oral et la présentation a été réalisée le matin même. Une première expérience de rush intense avec une nuit assez courte.

    Résultat : 17/20

    Antoine

    Soutenance 1

  • Déplacements dans un environnement

    Pour se déplacer dans un monde en trois dimensions comme celui d'Hermita, un simple déplacement en 2 dimensions ne suffit pas pour donner l'illusion recherchée par le point de vue isométrique. De plus il faut gérer les collisions pour pouvoir implémenter une recherche de chemin qui fasse sens et un joueur qui ne puisse pas marcher dans le vide ou passer à travers les murs. Nos besoins étant peu communs, il n'y a pas de solution toute faite pour gérer les collisions comme on le voulait; Pas de tutoriel non plus. Il a donc fallu réinventer la roue et tout implémenter avec du code. Les collisions sont inspirées des collisions avec les dalles de Minecraft. Une dalle peut être vue comme la moitié d'un cube dans sa verticalité et changer de niveau en hauteur ne prend pas de temps.

    Similairement à Minecraft, si le joueur rencontre une différence de hauteur égale à 1, sa position est instantanément modifiée pour qu'il soit à la bonne hauteur. Cela permet de s'éviter une animation de saut et offre une meilleure expérience de jeu pour le joueur. Cependant, ce changement brusque de position est gênant quand la caméra est attachée au joueur puisque la caméra subit des à-coups qui peuvent être désagréables. Pour éviter cela, j'ai implémenté un petit script pour la caméra qui utilise Vector3.SmoothDamp() pour que la caméra se déplace progressivement vers la position du joueur à une vitesse limitée. En conclusion, ces collisions permettent un déplacement agréable pour le joueur puisqu'il est complètement libre de se déplacer dans le monde là où beaucoup de jeux isométriques 2D limitent le joueur à un déplacement sur une grille comme dans Dofus. De plus comme ce système utilise la tilemap du monde, le Game Designer n'a pas besoin de gérer les collisions à la main comme certaines solutions suggérées par Unity.

    Antoine

    Collisions

  • Intelligences Artificielles

    Recherche de chemin

    Une fois les collisions gérées, il est possible d'implémenter un algorithme de recherche de chemin. Pour cela, j'ai utilisé l'algorithme A*. Le principe est simple mais certains détails sont à prendre en compte pour que l'algorithme fonctionne correctement dans un monde isométrique. D'abord pour la distance, la diagonale verticale d'une dalle est 2 fois plus courte que l'horizontale mais dans le monde théorique, la diagonale est la même que l'horizontale. De plus, la différence de hauteur ne compte pas dans le coût du déplacement puisque les changements de niveau se font instantanément. Aussi, il a fallu changer les directions qu'essaient de prendre les entités pour que l'algorithme fonctionne correctement. En effet, dans un monde isométrique, les entités peuvent se déplacer dans 8 directions et non 4 comme dans un monde 2D. Et parcourir la même distance en diagonale et en ligne droite n'est pas une bonne idée car gauche; haut; n'arrive pas au même endroit que haut+gauche; et donc l'algorithme ne fonctionnerait pas correctement. Quand on parcourt 1.4142 pour aller en diagonale et le résultat est bien plus probant. Pour le reste de l'implémentation, il s'agit d'un classique algorithme A* avec une liste de priorités pour les nœuds à explorer. Pour ce faire, j'ai créé la classe Node qui implémente l'interface IComparable pour pouvoir être utilisée dans la liste de priorités. Une fois le chemin reconstruit, la suite des étapes est renvoyée sous forme de liste de int qui correspondent aux directions à prendre. Sur l'image on peut voir que le gobelin évite bel et bien le mur qui se trouve entre lui et le joueur. Il est aussi possible de voir que le monstre n'atteint pas parfaitement la position du joueur. Cela dépend de la distance recherchée entre le monstre et le joueur. C'est un paramètre que le Game Designer peut modifier pour que le monstre soit plus ou moins agressif. Si d'aventure un monstre attaquait à distance comme un archer, il suffit de modifier ce paramètre pour que le monstre soit plus ou moins loin du joueur.

    Antoine

    IA

  • Réalisation d'un multijoueur plus robuste

    Gestion d'erreurs

    Dans un monde parfait, on se concentre sur ce qui marche et on le fait marcher encore mieux. Mais dans la vraie vie, Alice va se tromper de mot de passe, Bob va essayer de cliquer sans code et Charlie n'aura pas de connexion internet. Pour tous ces olibrius, il faut prévoir des messages d'erreur qui expliquent ce qui ne va pas. \par Pour vérifier si le joueur est connecté à internet, j'utilise UnityWebRequest en faisant une requête à http://google.com et en vérifiant si ça ne génère pas d'erreur. Le reste consiste simplement à de petits tests insérés dans le code. Ces petits détails permettent de fournir un produit qui paraît plus fini et en cas de problème, on aura quelque chose à montrer pendant la soutenance même si nous n'avons pas de réseau en amphithéâtre. \subsubsection{Interface en jeu} Jouer avec ses amis est l'essence même de notre jeu. Pour rendre cette expérience fluide, il faut que toutes les opérations liées au multijoueurs se déroulent de manière très fluide. Par exemple, taper le mot de passe à chaque fois que l'on veut rejoindre une partie ou quand on veut envoyer un code est très pénible. J'ai rajouté une interface qui s'ouvre avec la touche Échap. Pour éviter cela, j'ai transformé le code qui s'affichait en haut à droite en un bouton qui copie le code dans le presse-papier. Ceci est facilement réalisable avec GUIUtility.systemCopyBuffer = "ABCDEF"; et permet de gagner du temps. On peut aussi trouver dans cette interface des boutons pour quitter la partie ou quitter le jeu.

    Antoine

    Multijoueur Robuste

  • Finalisations du site

    Page d'accueil

    Mon objectif ici était de faire une page très épurée avec des éléments originaux. Il s'agit d'une page classique avec quatre sections dont trois qui présentent les différents aspects du jeu. La première section donne juste le nom du jeu et le nom du groupe. La section est composée d'un simple texte avec des dalles qui se déplacent en arrière-plan avec le scroll et avec des vitesses différentes. Chaque section est associée à des animations de dalles différentes. La section sur le combat fait sauter les dalles avec une animation brusque pour inspirer l'action. Cet effet est réalisé grâce à une courbe de Bézier générée avec https://cubic-bezier.com. La section sur l'aspect d'aventure fait bouger les dalles dans différentes directions de façon douce pour inspirer la découverte. La section sur le crafting fait changer la taille des dalles pour inspirer un sentiment de construction. En plus de cela, les animation possèdent des petites animations d'apparition et de disparition quand l'utilisateur scroll.

    Page de téléchargement

    Pour les gens qui veulent aller vite, il faut quelque chose de concis où tout est rapide et intuitif. Comme vous pouvez le voir dans la, la page de téléchargement est très simple. Une tentative a été faite avec des images en pixel art mais si les parchemins offrent un rendu satisfaisant, les icônes des systèmes d'exploitation ne sont pas aussi réussies. Ceci est amené à changer dans le futur. L'image des parchemins est générée par DALL-E et retouchée dans Photoshop.

    Performances

    Le site web est hébergé gratuitement, des effets très gourmands en ressources ont été implémentés pour une visuel marquant et agréable. Malgré tout cela, le site se débrouille très bien avec un score plus que satisfaisant sur Google Lighthouse. Ceci est rendu possible grâce à l'utilisation d'Astro qui réduit très fortement le temps de chargement des pages avec des méthodes de Server Side Rendering et de Static-Site Generating. On rencontre rarement des sites aussi rapides avec des simulations de fluides et des animations complexes associées au scroll. Ces résultats justifient donc au final l'idée de ne pas utiliser Sveltekit malgré sa fonctionnalité intéressante de Single Page Application.

    Antoine

    Site amélioré