IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement 2D, 3D et Jeux Discussion :

Comment gérer proprements les balles dans un shooter ?


Sujet :

Développement 2D, 3D et Jeux

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 16
    Points : 14
    Points
    14
    Par défaut Comment gérer proprements les balles dans un shooter ?
    Bonjour à tous,

    Je me demandais comment devais être géré les balles et ou les tirs dans les jeux sur un langage orienté objet.
    Dans mon cas, je possède deux objets :
    • Ship
    • Bullet


    S'agissant d'un shoot em up ( entre autre ) il y a plusieurs balles qui sont tirées par le joueur et non pas une seule balle à l'écran.
    Mes sujets de réflexion ont été :
    1. Les Bullets sont stocker dans un tableau qui est un membre de ma class Ship qui a donc tirée les Bullets, c'est donc la class Ship qui s'occupe de gérer les Bullet ( allocution, suppression, déplacement etc...)
    2. Lorsque le Ship tire il émet une sorte de signal indiquant à mon code principale qu'une Bullet doit être tirée, elle est donc créer dans le "main" et stocké dans un tableau dans le main qui s'occupe lui même des déplacement allocution etc...


    Je ne voit pas comment devrai être gérer correctement et proprement cet aspect du gameplay

    J'ai également une classe Game ( qui en gros fait partie d'un moteur que j'ai coder ) qui sert a gérer l'initialisation et la suppression de pas mal de choses, peut être devrais-je mettre toutes mes entités dedans dans un gros tableau.

    Vraiment je ne sais pas ce qui serait le plus propre

    N’hésitez pas a me dire votre point de vue et a m'expliquer pourquoi j'en serais ravi

    Merci a vous

  2. #2
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 214
    Points : 10 140
    Points
    10 140
    Par défaut
    Déjà ne part pas sur un truc compliqué , tu fait juste un tableau avec un tri et cela suffit , enfin le tri peut être évité ou réduit si on gère bien les bullet

    Pour ma part j'ai créer plus une fonction qui ressemble a cette description :
    Lorsque le Ship tire il émet une sorte de signal indiquant à mon code principale qu'une Bullet doit être tirée, elle est donc créer dans le "main" et stocké dans un tableau dans le main qui s'occupe lui même des déplacement allocution etc...

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 16
    Points : 14
    Points
    14
    Par défaut
    Merci de ta réponse, en effet je suis plutôt d'accord, les balles ne doivent théoriquement pas être managées par le vaisseaux qui les tirent, ça n'as pas beaucoup de sens, au final gérer ça de manière extérieur d'une classe est peut être une meilleur idée

  4. #4
    En attente de confirmation mail

    Profil pro
    Inscrit en
    Septembre 2013
    Messages
    639
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 639
    Points : 2 347
    Points
    2 347
    Par défaut
    Bonjour Vuillemin,

    Je vais t'expliquer ce que j'avais fait pour mon jeu Nulltron (dont tu peux trouver une version exécutable Windows ainsi que les sources vers le bas de la page http://52028761.fr.strato-hosting.eu/multi/jeux.html ), et pour le prototype de mon jeu Xoon.

    Dans Nullotron, les balles sont considérées comme des sprites ordinaires. Toutes les balles tirées par le joueur et encore visibles à l'écran sont rangées dans un tableau (elles en sont supprimées quand elles sortent de l'écran ou quand elles rencontrent un ennemi). Toutes les balles tirées par les ennemis sont rangées dans un autre tableau. Il y a ainsi plusieurs tableaux, un par "catégorie" de sprite :

    - les ennemis ;
    - les balles du joueur ;
    - les balles ennemies ;
    - le joueur.

    Avantages de cette approche :

    1-) pour dessiner tous les sprites, il suffit de dessiner ces tableaux dans l'ordre (ainsi, par exemple, les balles sont systématiquement dessinées
    après les ennemis) ;

    2-) pour tester les collisions, c'est facile :
    - on teste, par exemple, toutes les collisions possibles entre une balle du joueur et un vaisseau ennemi ;
    - mais on ne teste pas, par exemple, les collisions entre une balle du joueur et le joueur.


    Cela avait très bien fonctionné pour Nullotron, mais ce ne serait sans doute pas suffisant pour un jeu plus complexe.

    Le plus important c'est de trouver les bons algos et les bonnes structures de données qui donneront une solution à la fois "complète" (elle te permet de faire tout ce que tu as prévu) et la plus simple possible. Ensuite seulement tu vois comment découper tout cela en classes. Quand l'approche algorithmique est bonne, les classes à créer paraissent plus évidentes.

    PS 1 : dans un de mes deux jeux, je crois que ce sont des listes doublement chaînées plutôt que des tableaux.

    PS 2 : si tu regardes le code de Nullotron, tu verras qu'il est très complexe par-rapport au résultat final... c'est parce que c'était la première fois que je codais un shoot them up et que j'avais voulu jusqu'au bout garder toutes les possibilités de réglages au cas où il aurait fallu faire des changements de dernière minute... donc j'ai un code très riche dans lequel tout est configurable : tel type d'ennemi est déplacé de temps de pixels toutes les n millisecondes, la détection de collisions est faites toutes les p millisecondes, on met à jour l'affichage toutes les q millisecondes, on appelle telle fonction quand tel ennemi meurt, etc. J'ai une file de priorité d'événements (exemple d'événement : au bout de r millisecondes, on déplace tel sprite en appelant telle fonction) dont le "déroulement" est la boucle principale de mon jeu (ce qui veut dire que cette boucle contient à la fois la gestion des entrées et le déroulement de la file). Tout ceci rend le code vraiment compliqué, mais en même temps c'était encore le plus simple pour garder le haut niveau de souplesse que je voulais.

    PS 3 : ce n'est pas du tout du code objet... mais certains de ses principes ne sont pas incompatibles avec l'objet... c'est jusque que, par exemple, j'ai remplacé la dérivation des classes par des void* et des pointeurs de fonctions à fond. C'est du C quoi. Et ça tourne avec SDL 1.2.

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 28
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2014
    Messages : 16
    Points : 14
    Points
    14
    Par défaut
    Hello CodeurPlusPlus

    Merci de ta réponse. Je suis partie sur cet approche au final et il va s'en dire que c'est de loin la plus simple et la plus claire :p
    Je suis curieux et du coup je vais regarder tes codes j'en apprendrais surement beaucoup

    En faite cela fait quelque année que je code, mais étant autodidacte il n'y a eu personne pour juger mes erreurs, et ayant fait un stage en développement en Python ( je suis un grand fan du C++ mais ce n'était pas si différent :p ) mon tuteur m'a fait remarque que mes classe n'était pas spécialiser et fessait un peu n'importe quoi ^^ du coup j'essaye de m'améliorer

    En tout cas merci beaucoup

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Je ne vois rien de choquant à ce que ce soit l'arme qui possède la liste des balles tirées.
    Ainsi en switchant d'arme ou en détruisant ton ship, tu peux aisément supprimer les balles déjà tirées si tu veux, et tu peux facilement mettre une limite au nombre de tir simultanné en limitant le nombre de balles existantes.
    Et ça fait un point d'entrée "naturel", alors que "stocké dans un tableau dans le main qui s'occupe lui même des déplacement allocution" est de très loin la pire idée possible. Le main doit être et resté simple et clean, il n'y a quasiment aucun code dans le main en dehors de la boucle d'update du jeu.
    Quant au tri etc... inutile, avec une liste en push_back elles seront déjà triées par date de tir, la plus récente est la dernière, et (à priori) ça suffit.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  7. #7
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 214
    Points : 10 140
    Points
    10 140
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Quant au tri etc... inutile, avec une liste en push_back elles seront déjà triées par date de tir, la plus récente est la dernière, et (à priori) ça suffit.
    Oui enfin ça dépend
    Si tu as des tirs multidirectionnel , ça dépend ou se trouve le vaisseau imaginant qu'il tire puisse tirer devant et derrière , ceux de derrière quitteront l'écran plus rapidement que ceux de devant (plus récente ou pas).
    On gros le deuxième tir peut quitter l'écran plus rapidement que le premier.
    Mème principe si les tir ont des pattern plus compliqué.

    Et ça fait un point d'entrée "naturel", alors que "stocké dans un tableau dans le main qui s'occupe lui même des déplacement allocution" est de très loin la pire idée possible. Le main doit être et resté simple et clean, il n'y a quasiment aucun code dans le main en dehors de la boucle d'update du jeu.
    C'est un jugement personnel , je ne voir rien de choquant dans le game loop de voir une fonction : Tir();

  8. #8
    Membre émérite Avatar de Cirrus Minor
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2014
    Messages
    953
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2014
    Messages : 953
    Points : 2 612
    Points
    2 612
    Par défaut
    Ce que je fais en général, c'est un gestionnaire d'entités qui possède une unique liste vers toutes les entités du jeu (joueur, ennemis, projectiles, etc...) dérivant d'une classe de base.
    Ça permet aussi de trier toutes les entités du jeu s'il y a besoin. On peut imaginer dans un Papi-Commando-like un soldat derrière une balle derrière un arbre, etc...

  9. #9
    Membre expert

    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Février 2006
    Messages
    1 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2006
    Messages : 1 031
    Points : 3 092
    Points
    3 092
    Par défaut
    - les ennemis ;
    - les balles du joueur ;
    - les balles ennemies ;
    - le joueur.
    Wow et dès qu'il y un nouveau type de bullet ou une nouvelle image on ajoute un tableau ?
    Clairement non....
    Toutes les méthodes décrites fonctionnent évidemment mais tu as demandé une manière propre alors voilà :

    - Ajouter un shoot passe par un shootManager et s'ajoute dans une liste unique, quelque soit sa provenance. ( dans la mesure où il peut y avoir des milliers de shoots en même temps on évite de passer par l'ECS classique )
    - Dans ce shootManager les shoots sont updatés de manières à gérer leur comportement ( dans un idéal on va utiliser BulletML pour ca ) (allez on peut potentiellement faire une seconde liste pour les shoots simples qui ne nécessitent pas un tel traitement mais c'est de l'optimisation à faire que si l'on constate un soucis )
    - La création d'un shoot créer un sprite qui sera gérer par le moteur graphique qui fera ses tris propres à lui même
    - La création d'un shoot créer un collider physique avec les informations nécessaires pour ne gérer que les collisions utiles et qui sera géré par le moteur physique.
    - Enjoy
    Suivez le développement de Chibis Bomba
    twitter : https://twitter.com/MoD_DiB
    DevBlog : http://moddib.blogspot.fr/

  10. #10
    En attente de confirmation mail

    Profil pro
    Inscrit en
    Septembre 2013
    Messages
    639
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 639
    Points : 2 347
    Points
    2 347
    Par défaut
    Citation Envoyé par MoDDiB Voir le message
    Wow et dès qu'il y un nouveau type de bullet ou une nouvelle image on ajoute un tableau ?
    Non, il n'y a que quatre tableaux en tout.

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Kannagi Voir le message
    Oui enfin ça dépend
    Si tu as des tirs multidirectionnel , ça dépend ou se trouve le vaisseau imaginant qu'il tire puisse tirer devant et derrière , ceux de derrière quitteront l'écran plus rapidement que ceux de devant (plus récente ou pas).
    On gros le deuxième tir peut quitter l'écran plus rapidement que le premier.
    Mème principe si les tir ont des pattern plus compliqué.
    Et ? Ca ne change strictement rien.
    Tu parcours ta liste, s'il faut supprimer un élément, on s'en moque pas mal de savoir s'il est en tête, queue ou au milieu.

    Citation Envoyé par Kannagi Voir le message
    C'est un jugement personnel , je ne voir rien de choquant dans le game loop de voir une fonction : Tir();
    En travaillant sur un vrai jeu conséquent, le code dans le main est réduit au strict minimum.
    En fait nos boucles main ressemble à ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    main() {
    // on gère des arguments
    // on initialise un objet Game et plein de conneries
    while(game->running()) {
    // dispatch events
    // update
    // display
    }
    Et c'est tout. Découper son code c'est pas optionnel.
    Si je vois une fonction Tir dans Game... j'espère que c'est juste pour un projet étudiant et par manque de temps, et encore.


    Citation Envoyé par MoDDiB Voir le message
    Wow et dès qu'il y un nouveau type de bullet ou une nouvelle image on ajoute un tableau ?
    Clairement non....
    Bah bien sur que non.. comme tu le dis, un type de bullet c'est juste un paramètre d'une classe bullet. Tout comme l'image d'affichage liée.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  12. #12
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 214
    Points : 10 140
    Points
    10 140
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Et ? Ca ne change strictement rien.
    Tu parcours ta liste, s'il faut supprimer un élément, on s'en moque pas mal de savoir s'il est en tête, queue ou au milieu.
    Je répondais a cela : la plus récente est la dernière , ce qui n'est pas forcément le cas.
    Oui si tu fait du push_back , cla doit résoudre le probleme de tri si tu le fait en C et que tu as un tableau , il faudra pas afficher l'ensemble de tableau donc le tri peut être une solution , ou encore si tu es un retro dev comme moi , en assembleur ce genre de manip est plus complexe , enfaite un tas ou il y a l'ensemble des bullets me semble le plus judicieux.

    Citation Envoyé par Bousk Voir le message
    En travaillant sur un vrai jeu conséquent, le code dans le main est réduit au strict minimum.
    En fait nos boucles main ressemble à ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    main() {
    // on gère des arguments
    // on initialise un objet Game et plein de conneries
    while(game->running()) {
    // dispatch events
    // update
    // display
    }
    Et c'est tout. Découper son code c'est pas optionnel.
    Si je vois une fonction Tir dans Game... j'espère que c'est juste pour un projet étudiant et par manque de temps, et encore.
    Je suis content de savoir que je suis encore étudiant
    C'est un choix architecture pas la mienne , on peux juste rajouter quelque bloc je vois pas le souci ,si cela te dérange de voir juste quelque fonction dans la boucle c'est ton probleme , c'est pas vraiment un choix architecture parce que c'est mieux , tu moment que le code est modulaire est bien découpé c'est le principal.

  13. #13
    Membre expert

    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Février 2006
    Messages
    1 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2006
    Messages : 1 031
    Points : 3 092
    Points
    3 092
    Par défaut
    Citation Envoyé par Kannagi Voir le message
    Je suis content de savoir que je suis encore étudiant
    C'est un choix architecture pas la mienne , on peux juste rajouter quelque bloc je vois pas le souci ,si cela te dérange de voir juste quelque fonction dans la boucle c'est ton probleme , c'est pas vraiment un choix architecture parce que c'est mieux , tu moment que le code est modulaire est bien découpé c'est le principal.
    Pour de l'optimisation et faire tourner le jeu sur des petits processeurs inférieurs à 4mhz pourquoi pas, mais sinon si je vois une fonction tir() dans ma classe game qui gère le main le gars qui me fait ça il va passer un mauvais moment !
    Un exemple tout bête : je rejoins le projet pour bosser sur le menu principal, je parcours le code pour y arriver et là dans le code pour y arriver je tombe sur une fonction tir() qui n'a absolument rien à voir avec ce que je dois faire ( et rien à voir avec le but de la classe actuelle qui plus est ) ; je ne suis absolument pas censé voir ça...
    Dans l'absolu une classe = un but même si pour de l'optim c'est pas toujours évident en jeux vidéo il faut s'y conforter au maximum, ça permet tout simplement de bosser à plusieurs dans de bonnes conditions.
    Suivez le développement de Chibis Bomba
    twitter : https://twitter.com/MoD_DiB
    DevBlog : http://moddib.blogspot.fr/

Discussions similaires

  1. [TWebBrowser] Comment trouver tous les liens dans une page ?
    Par xenos dans le forum Composants VCL
    Réponses: 1
    Dernier message: 15/01/2006, 23h36
  2. Comment accéder tous les ComboBox dans ma fiche
    Par Xavier dans le forum C++Builder
    Réponses: 8
    Dernier message: 04/11/2005, 20h41
  3. Réponses: 2
    Dernier message: 17/06/2005, 23h03
  4. comment savoir définir les figure dans opengl
    Par romainhoarau2764 dans le forum OpenGL
    Réponses: 1
    Dernier message: 05/03/2005, 19h30
  5. Comment gérez-vous les NULL dans 1 insert ?
    Par qi130 dans le forum Bases de données
    Réponses: 4
    Dernier message: 12/02/2005, 22h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo