Historique des modifications - Message

Message #1884

Sujet: Présentation de la bibliothèque AGE


Type Date Auteur Contenu
Dernière modification 27-03-2007 21:37:35 Agar
Je ne savais pas trop où poster ça. Vu que c'est un projet sur lequel je bosse et qu'il est presque terminé (les 3/4 du code sont bouclés et ça devrait être fini d'ici un mois), j'ai opté pour la section "projets terminés". Je m'excuse d'avance pour la publicité mensongère.

Voici donc mon projet: AGE. AGE, pour Adaptable Game Engine.

Introduction

AGE est une bibliothèque DLL écrite en C# permettant la création de toutes formes de jeux/applications multimédia. Elle utilise IrrlichtNETCP pour la vidéo, Bass.NET (pas IrrKlang, qui n'offre pas assez de possibilités) pour le son et ODE.NET pour la physique.

L'utilisation du moteur est simple : il suffit de créer une instance de la classe AGEEngine (imaginez-la comme une sorte de IrrlichtDevice, la mère de tout le reste). Ensuite, cette classe a pour principale fonction de créer des entités via les diverses méthodes AddEntity().

1- Le concept d'entité

C'est quoi donc, une entité? En fait, tout élément du monde de AGE dérive de la classe abstraite AGEEntity. L'idée est de faire en sorte que cet objet soit la SEULE chose dont vous ayez besoin pour ajouter un élément à votre jeu. Vous voulez lui faire émettre un son? Pas de problème, le moteur gérera la stéréo et le volume automatiquement en fonction de sa position relative à la caméra. Vous préférez qu'il émettre un vrombissement permanent ? Très bien, AGE s'occupe de tout: quand l'entité passera à côté de vous, le volume et la stéréo évolueront automatiquement. Oui, l'effet Doppler est géré. De la même façon, plus besoin de se prendre la tête à "lier" l'objet du moteur physique à l'objet du moteur vidéo. Une entité a un modèle 3D (ou autre chose d'ailleurs, ça peut être un skydome, une fontaine de particules, un billboard, etc...), c'est un fait, mais elle a aussi une masse, une vitesse, etc... En gros c'est un « objet » complet, comme dans le monde réel. Quand je me casse la gueule de ma chaise, il n'y a pas mon modèle 3D d'un côté, ma physique de l'autre et un informaticien derrière qui se bagarre pour lier les deux : pourquoi cela devrait-il être différent dans un moteur de jeu ?

Mais le concept d'entité va plus loin : au delà du moteur de jeu, l'entité est donc supposée être un "objet" du monde. Pourquoi alors faudrait-il stocker ailleurs les éléments qui ne relèvent pas du moteur mais du gameplay ? La classe AGEEntity contient donc une sorte de hashtable (pour ceux qui ne connaissent pas, c'est un tableau qui lie une clé -ici une string- à une valeur) baptisée Properties. Vous voulez que votre entité ait des points de vie? Ajoutez une valeur health de type integer à ses propriétés. Pour y accéder, vous n'aurez qu'à faire MyAGEEntity.Property[health]. Une propriété peut être de n'importe quel type (même une autre entité ou une autre table de propriétés, mais là bon courage), et peut aussi être un tableau.

Maintenant, si vous voulez que votre entité reste tranquille à regarder les étoiles scintiller dans la skybox au dessus de sa tête, vous pouvez le faire. Mais si vous voulez qu'elle ait un comportement un peu plus dynamique, rien de plus simple. Tout se fait via des events et des delegates. Par exemple, l'évènement OnEachFrame est appelé 10 fois par seconde. Ecrivez une petite méthode d'intelligence artificielle, et hop, en une ligne de code (MyAGEEntity.OnEachFrame += MyAIRoutine()) vous pouvez l'assigner à toutes les entités qui doivent l'utiliser. D'autres évènements seront prévus pour tout ce qui peut se produire (clic sur l'entité, collisions, proximité, etc...)

En résumé : avant, un personnage c'était un node Irrlicht + un Geom ODE + tout un machin truc pour le son + une classe en plus qui gérait son comportement. Maintenant, c'est une entité AGE.

2- Autres fonctionnalités

En plus de cela, AGE contient (pour l'instant, ça va s'alourdir avec le temps) :

  • Une classe
AGEInputHandler qui permet de gérer (via des événements) à peu près tous les « inputs » dont on peut avoir besoin dans une application multimédia. Cela va des classiques OnMouseMove(), OnMouseWheel() et OnKeyUp() à d'autres plus exotiques comme OnJoystickMove(), par exemple.

  • Une classe
AGEAudioPlayer qui permet de jouer un son/une musique (wav, ogg, mp3 ou midi) et d'altérer sa position dans l'espace mais aussi sa fréquence (par exemple pour simuler le moteur d'une voiture qui accélère). Une variation aléatoire de la fréquence peut aussi être spécifiée (pour que le son d'un flingue sonne un peu plus grave ou plus aigu d'une détonation à l'autre, par exemple).

  • Un nouveau type de caméra en plus de la caméra FPS et de la caméra "targeted" : la caméra "rotating". Sa rotation est passée via un
Vector3D comme pour un node "normal", y compris sur l'axe Z (axe "roll"). Ceux qui se sont cassés les dents à essayer de simuler un cockpit d'avion sous Irrlicht savent de quoi je parle.

  • AGE étend également les possibilités de Irrlicht en ce qui concerne les jeux 2D. Certes, Irrlicht a toujours permis de créer des jeux en 2D, mais bon, c'était pas pratique: il fallait, à chaque boucle "
BeginScene()EndScene()", redessiner tout le bordel, calculer la position modifiée par rapport à la "caméra". Il n'y avait pas d'équivalent 2D du SceneManager. Maintenant, c'est fini : une entité peut être 2D. C'est à dire qu'elle aura une taille, une texture et une position (comme un Node 3D de Irrlicht). Quand à la classe Camera2D, elle a une position et un "field of view" comme sa contrepartie 3D que vous connaissez déjà. Du coup, plus à se fatiguer à calculer les coordonées-écran de vos petits personnages de votre jeu de rôles 2D à l'ancienne, AGE le fait pour vous.

3- L'espace AGE.Library

AGE contient également, dans le namespace AGE.Library, toute une batterie de classes "gadgets" qui peuvent servir pour divers types de jeux, entre autre (il y en a beaucoup) :

  • La classe
AGERandom a un constructeur qui admet en paramètre une chaîne pouvant contenir toutes sorte de plages de valeurs aléatoires : rentrez "1-8" et un chiffre entre un et huit sera généré lors du tirage. Entrez "3d6+4" et la classe simulera le jet de 3 dés à 6 faces auquel 4 sera ajouté (ce qui permet, entre autre, de distribuer les résultats de façon non linéaire – selon une distribution de Gauss, pour être plus précis). Il est également possible de spécifier des valeurs "plancher" et "plafond" pour que, par exemple, le résultat de votre tirage de "2d8-4" ne soit jamais inférieur à 1.

  • La classe
NameGenerator permet de générer aléatoirement des noms en combinant création aléatoire de syllabes et parties "fixées". Par exemple, spécifier un prénom dans une liste de prénoms existants (fournis via un tableau de strings) et laisser le nom de famille être généré totalement aléatoirement. Ou seulement la deuxième partie du nom de famille pour un écossais dont le nom commencera forcément par "Mac". Enfin c'est juste un exemple. Ici un programme en ligne qui fait grosso modo la même chose, pour vous donner une idée.

  • La classe
LevelGenerator crée, d'après certains paramètres, un niveau de "donjon" (utile pour un jeu de rôle, ou pour le mode "skirmish" d'un FPS par exemple) ou une carte géographique (avec la distribution des différentes "tiles" : eau, montagnes, rochers, neige... Par exemple pour un wargame, ou les niveaux en extérieur d'un jeu de rôle). Ici un programme en ligne qui fait grosso modo la même chose, pour vous donner une idée.

  • La classe
AGEXMLFile permet de gérer facilement des fichiers XML pour enregistrer/lire les paramètres de jeu, ou pour permettre de créer des jeux "moddables" (si chaque unité d'un wargame est un fichier XML dans le répertoire "units", et bien le jeu gagne beaucoup en durée de vie par rapport à une version où elles seraient "hardcoddées" dans le code source, non?)

  • La classe
AGEEncryptedXMLFile fait la même chose, sauf que le fichier XML enregistré est crypté via un algorithme RC2. Utile pour les sauvegardes de jeu, histoire que le petit Kévin, 11 ans, ne s'amuse pas à se rajouter quelques vies vite fait. On pourrait faire la même chose en utilisant un fichier binaire pour les sauvegardes, me dites-vous? Ouais, mais là vous conservez la souplesse d'utilisation du XML.

4- Et maintenant ?

Et bien voilà... J'attends vos suggestions, vos conseils, vos critiques... Pensez-vous que tout ce projet est une bonne idée ou pas ? Qu'aimeriez vous y voir de plus ?

Tenez-moi informé, j'en ferai de même d'ici un mois environ, quand la version 0.1 de AGE sera mise en ligne. Je rechercherai alors des gens pour m'aider à écrire une API, tester tout ça à fond et m'aider à réaliser le plus vite possible une version totalement crossplatform (certains morceaux du code de la version actuelle, comme ceux utilisés pour le moment pour le son et le joystick sont windows only).

Voilà voilà. Merci d'avoir lu jusqu'ici !
Création du message 27-03-2007 21:27:23 Agar
Je ne savais pas trop où poster ça. Vu que c'est un projet sur lequel je bosse et qu'il est presque terminé (les 3/4 du code sont bouclés et ça devrait être fini d'ici un mois), j'ai opté pour la section "projets terminés". Je m'excuse d'avance pour la publicité mensongère.

Voici donc mon projet: AGE. AGE, pour Adaptable Game Engine.

Introduction

AGE est une bibliothèque DLL écrite en C# permettant la création de toutes formes de jeux/applications multimédia. Elle utilise IrrlichtNETCP pour la vidéo, Bass.NET (pas IrrKlang, qui n'offre pas assez de possibilités) pour le son et ODE.NET pour la physique.

L'utilisation du moteur est simple : il suffit de créer une instance de la classe AGEEngine (imaginez-la comme une sorte de IrrlichtDevice, la mère de tout le reste). Ensuite, cette classe a pour principale fonction de créer des entités via les diverses méthodes AddEntity().

1- Le concept d'entité

C'est quoi donc, une entité? En fait, tout élément du monde de AGE dérive de la classe abstraite AGEEntity. L'idée est de faire en sorte que cet objet soit la SEULE chose dont vous ayez besoin pour ajouter un élément à votre jeu. Vous voulez lui faire émettre un son? Pas de problème, le moteur gérera la stéréo et le volume automatiquement en fonction de sa position relative à la caméra. Vous préférez qu'il émettre un vrombissement permanent ? Très bien, AGE s'occupe de tout: quand l'entité passera à côté de vous, le volume et la stéréo évolueront automatiquement. Oui, l'effet Doppler est géré. De la même façon, plus besoin de se prendre la tête à "lier" l'objet du moteur physique à l'objet du moteur vidéo. Une entité a un modèle 3D (ou autre chose d'ailleurs, ça peut être un skydome, une fontaine de particules, un billboard, etc...), c'est un fait, mais elle a aussi une masse, une vitesse, etc... En gros c'est un « objet » complet, comme dans le monde réel. Quand je me casse la gueule de ma chaise, il n'y a pas mon modèle 3D d'un côté, ma physique de l'autre et un informaticien derrière qui se bagarre pour lier les deux : pourquoi cela devrait-il être différent dans un moteur de jeu ?

Mais le concept d'entité va plus loin : au delà du moteur de jeu, l'entité est donc supposée être un "objet" du monde. Pourquoi alors faudrait-il stocker ailleurs les éléments qui ne relèvent pas du moteur mais du gameplay ? La classe AGEEntity contient donc une sorte de hashtable (pour ceux qui ne connaissent pas, c'est un tableau qui lie une clé -ici une string- à une valeur) baptisée Properties. Vous voulez que votre entité ait des points de vie? Ajoutez une valeur health de type integer à ses propriétés. Pour y accéder, vous n'aurez qu'à faire MyAGEEntity.Property[health]. Une propriété peut être de n'importe quel type (même une autre entité ou une autre table de propriétés, mais là bon courage), et peut aussi être un tableau.

Maintenant, si vous voulez que votre entité reste tranquille à regarder les étoiles scintiller dans la skybox au dessus de sa tête, vous pouvez le faire. Mais si vous voulez qu'elle ait un comportement un peu plus dynamique, rien de plus simple. Tout se fait via des events et des delegates. Par exemple, l'évènement OnEachFrame est appelé 10 fois par seconde. Ecrivez une petite méthode d'intelligence artificielle, et hop, en une ligne de code (MyAGEEntity.OnEachFrame += MyAIRoutine()) vous pouvez l'assigner à toutes les entités qui doivent l'utiliser. D'autres évènements seront prévus pour tout ce qui peut se produire (clic sur l'entité, collisions, proximité, etc...)

En résumé : avant, un personnage c'était un node Irrlicht + un Geom ODE + tout un machin truc pour le son + une classe en plus qui gérait son comportement. Maintenant, c'est une entité AGE.

2- Autres fonctionnalités

En plus de cela, AGE contient (pour l'instant, ça va s'alourdir avec le temps) :

  • Une classe
AGEInputHandler qui permet de gérer (via des événements) à peu près tous les « inputs » dont on peut avoir besoin dans une application multimédia. Cela va des classiques OnMouseMove(), OnMouseWheel() et OnKeyUp() à d'autres plus exotiques comme OnJoystickMove(), par exemple.

  • Une classe
AGEAudioPlayer qui permet de jouer un son/une musique (wav, ogg, mp3 ou midi) et d'altérer sa position dans l'espace mais aussi sa fréquence (par exemple pour simuler le moteur d'une voiture qui accélère). Une variation aléatoire de la fréquence peut aussi être spécifiée (pour que le son d'un flingue sonne un peu plus grave ou plus aigu d'une détonation à l'autre, par exemple).

  • Un nouveau type de caméra en plus de la caméra FPS et de la caméra "targeted" : la caméra "rotating". Sa rotation est passée via un
Vector3D comme pour un node "normal", y compris sur l'axe Z (axe "roll"). Ceux qui se sont cassés les dents à essayer de simuler un cockpit d'avion sous Irrlicht savent de quoi je parle.

  • AGE étend également les possibilités de Irrlicht en ce qui concerne les jeux 2D. Certes, Irrlicht a toujours permis de créer des jeux en 2D, mais bon, c'était pas pratique: il fallait, à chaque boucle "
BeginScene()EndScene()", redessiner tout le bordel, calculer la position modifiée par rapport à la "caméra". Il n'y avait pas d'équivalent 2D du SceneManager. Maintenant, c'est fini : une entité peut être 2D. C'est à dire qu'elle aura une taille, une texture et une position (comme un Node 3D de Irrlicht). Quand à la classe Camera2D, elle a une position et un "field of view" comme sa contrepartie 3D que vous connaissez déjà. Du coup, plus à se fatiguer à calculer les coordonées-écran de vos petits personnages de votre jeu de rôles 2D à l'ancienne, AGE le fait pour vous.

3- L'espace AGE.Library

AGE contient également, dans le namespace AGE.Library, toute une batterie de classes "gadgets" qui peuvent servir pour divers types de jeux, entre autre (il y en a beaucoup) :

  • La classe
AGERandom a un constructeur qui admet en paramètre une chaîne pouvant contenir toutes sorte de plages de valeurs aléatoires : rentrez "1-8" et un chiffre entre un et huit sera généré lors du tirage. Entrez "3d6+4" et la classe simulera le jet de 3 dés à 6 faces auquel 4 sera ajouté (ce qui permet, entre autre, de distribuer les résultats de façon non linéaire – selon une distribution de Gauss, pour être plus précis). Il est également possible de spécifier des valeurs "plancher" et "plafond" pour que, par exemple, le résultat de votre tirage de "2d8-4" ne soit jamais inférieur à 1.

  • La classe
NameGenerator permet de générer aléatoirement des noms en combinant création aléatoire de syllabes et parties "fixées". Par exemple, spécifier un prénom dans une liste de prénoms existants (fournis via un tableau de strings) et laisser le nom de famille être généré totalement aléatoirement. Ou seulement la deuxième partie du nom de famille pour un écossais dont le nom commencera forcément par "Mac". Enfin c'est juste un exemple. Ici un programme en ligne qui fait grosso modo la même chose, pour vous donner une idée.

  • La classe
LevelGenerator crée, d'après certains paramètres, un niveau de "donjon" (utile pour un jeu de rôle, ou pour le mode "skirmish" d'un FPS par exemple) ou une carte géographique (avec la distribution des différentes "tiles" : eau, montagnes, rochers, neige... Par exemple pour un wargame, ou les niveaux en extérieur d'un jeu de rôle). Ici un programme en ligne qui fait grosso modo la même chose, pour vous donner une idée.

  • La classe
AGEXMLFile permet de gérer facilement des fichiers XML pour enregistrer/lire les paramètres de jeu, ou pour permettre de créer des jeux "moddables" (si chaque unité d'un wargame est un fichier XML dans le répertoire "units", et bien le jeu gagne beaucoup en durée de vie par rapport à une version où elles seraient "hardcoddées" dans le code source, non?)

  • La classe
AGEEncryptedXMLFile fait la même chose, sauf que le fichier XML enregistré est crypté via un algorithme RC2. Utile pour les sauvegardes de jeu, histoire que le petit Kévin, 11 ans, ne s'amuse pas à se rajouter quelques vies vite fait. On pourrait faire la même chose en utilisant un fichier binaire pour les sauvegardes, me dites-vous? Ouais, mais là vous conservez la souplesse d'utilisation du XML.

4- Et maintenant ?

Et bien voilà... J'attends vos suggestions, vos conseils, vos critiques... Pensez-vous que tout ce projet est une bonne idée ou pas ? Qu'aimeriez vous y voir de plus ?

Tenez-moi informé, j'en ferai de même d'ici un mois environ, quand la version 0.1 de AGE sera mise en ligne. Je rechercherai alors des gens pour m'aider à écrire une API, tester tout ça à fond et m'aider à réaliser le plus vite possible une version totalement crossplatform (certains morceaux du code de la version actuelle, comme ceux utilisés pour le moment pour le son et le joystick sont windows only).

Voilà voilà. Merci d'avoir lu jusqu'ici !

Retour

Options Liens officiels Caractéristiques Statistiques Communauté
Préférences cookies
Corrections
irrlicht
irrklang
irredit
irrxml
Propulsé par Django
xhtml 1.0
css 2.1
884 membres
1440 sujets
11337 messages
Dernier membre inscrit: Saidov17
193 invités en ligne
membre en ligne: -
RSS Feed