Trapped Hero

Un rogue like réalisé en C avec la SDL.

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Trapped Hero

Introduction :

Bonjour je suis encore assez jeune (lycée) et j’ai débuté la programmation au début de l’année 2017 et un peu plus tard je me suis mis au C , je me demande encore pourquoi o_O , avec un cour qui commence a dater. A la fin du cour je voulais réaliser quelque chose de concret avec ce que j’ai appris , et m’améliorer : j’ai choisis de réaliser un rogue like car l’idée me trottais dans la tête et ça m’a parut assez simple.

Il ressemblera a quoi ton jeu vidéo ?

Information :

Trapped Hero est un rogue like codé en C et utilisant la SDL 2. C’est mon premier projet donc je suis encore débutant. Pour ceux qui ne connaissent pas , les rogue likes sont des jeux dont le gameplay s’inspire de rogue :magicien: . C’est un jeu d’exploration de donjon (qui a la particularité d’être généré aléatoirement),avec combat , objet etc… , dans lequel il faut aller de plus en plus loin en descendant de plus en plus loin dans les entrailles de celui-ci avec à la fin , lorsqu’ils en ont une :D , un boss. La plupart se jouent dans une console ,donc le jeu peu paraître assez hostile a première vu, mais cela dans le but de ce concentrer sur le gameplay du jeu et non le graphisme. Pour plus d’information la page wikipédia des rogue like assez complète.

L’histoire :

Un esprit (mauvais , noir …) s’est installé dans la région du village ou vit le héro . Son père et une troupe partent pour le détruire et personne ne reviens de l’expédition ..... donc après une ellipse il décide de ce venger donc il ce forme (le joueur décide de la formation : (il avait avant choisi l’espèce) qui est soit archer , mage ou chevalier puis il choisi une professionnalisation : chevalier (pro style au moyen age), samouraï , arbalétrier , mage blanc ou noir etc.....) donc cela va permettre de mettre en place des caractéristiques quasiment unique a chaque partie (si il décide de ne pas faire la même combinaison a chaque fois ) même certaine combinaison ne marcherons pas très bien dans le sens où par exemple un troll dont la précision est faible ne pourra jamais choisir d’être samouraï car cela donnerai un perso nul avec de la force mais qui ne peut pas l’utiliser avec la professionnalisation qu’il a reçu lui donnant plus de précision etc.... Le personnage par ensuite en expédition mais tombe dans une crevasse et suite a éboulement dut a son passage le joueur est bloqué dans le tunnel dans lequel il est tombé … sauf que ce tunnel est le donjon dans lequel l’esprit maléfique s’abrite . Le perso ne peut retourner au village qu’avec des parchemin spéciaux qui permettent de se téléporter a un endroit magique précis autour duquel il ne peut s’éloigner de plus d’un certain nombre de carreaux du coup a l’aide de ces parchemin le joueur peut acheter des objet au village mais il ne peut remporter (a l’aide d’un autre parchemin qui ramènera à l’endroit ou il avait utiliser l’autre dans le donjon ) que des objet et pas des personnes .... et ensuite le principe classique d’un rogue-like : aller le plus loin possible dans le donjon et atteindre le boss surtout que le joueur va apprendre que la seul sortie du donjon se trouve a l’endroit ou il y a le boss et qu’il ne pourra l’utiliser qu’après avoir vaincu le boss.

Objectif finaux de gameplay :

Je souhaite réaliser un rogue like donc le jeu aura :

  • Une carte généré aléatoirement.
  • Un choix d’espèce au début du jeu.
  • Un système de boutique, donc des objets, et de niveau.

Mais en plus de ces principes je souhaite rajouter un système de combat plus complexe en proposant plusieurs choix d’attaques en fonction du personnage et de ces armes. Et le jeu sera affiché dans une fenêtre avec des tiles (ce qui n’est pas le cas de tous les rogues likes.

Donc ça en est ou ?

Ça fait donc 2 mois et demi que je suis sur ce projet et pour l’instant j’ai réalisé les choses suivantes :

  • Une carte généré aléatoirement (c’est ce qui m’a pris le plus de temps)
  • L’affichage de la carte dans ne fenêtre
  • Déplacer le personnage sur la carte (et on peut ouvrir les coffres !! bien qu’il n’y ai rien dedans pour l’instant)
Voila a quoi ressemble le jeu (pour l’instant)

J’ai réalisé tous les tiles utilisé dans le jeu a l’exception du personnage que j’ai trouvé sur open game art (licence CC0).

Les fonctionnalités que je souhaite réaliser :

A chaque post de mise a jour je mettrais dans cette partie les fonctionnalités que j’ai réalisé et celle que je me fixe comme objectif pour la prochaine mise a jour.

À réaliser :

  • Un menu (simple ou on peut quitter ou jouer)
  • Un système de sauvegarde du jeu et de lecture de sauvegarde. (et ajout de cette option dans le menu)

Je posterais une mise a jour toutes les semaines.

Quelques liens utiles :

Bien sur le code source du projet est sur GitHub (Il y a peu de commit car je l’ai mis hier :) ). N’hésitez pas a me donner des conseil ou indiquer des parties de code peu clair ou mauvaise : c’est le but de ce topic et du projet améliorer le code et m’améliorer en codant ce jeu :D

P.S. : Désolé si il y a des fautes d’orthographe j’ai essayé d’en corriger un maximum mais ça n’a jamais été mon point fort :euh: .

Édité par Linux

N’hésitez pas a aller voir le code source de mon projet Trapped Hero sur GitHub

+3 -0
Auteur du sujet

Bonjour (ou plutôt bonsoir) :D .

La mise a jour

Je poste ce message de mise a jour pour indiquer tout d’abord que les messages de mise a jour seront posté au moins une fois par semaine. Ensuite (et surtout) pour indiquer que le menu a été réalisé plus rapidement :magicien: , car plus simple , que prévu (c’est pas beau ça ? ). Donc comme une image peut remplacer un long discourt :

Le menu

Bon le graphisme n’est pas encore optimal mais le plus important y est : les boutons!

Les fonctionnalités que je souhaite réaliser :

Étant donné que le menu a été réalisé rapidement je me fixe comme objectif pour la fin de la semaine :

  • Un système de sauvegarde du jeu et de lecture de sauvegarde. (et ajout de cette option dans le menu) (comme la dernière fois)
  • Un système de voile qui cache au joueur les partie encore inexploré par le joueur et griser les parties visitées mais hors du chant de vus du personnage (ce dernier sera important lorsqu’il y aura des ennemis).

Conclusion

Encore une fois n’hésitez pas a me donner des conseil ou me corriger sur des parties de code ( que vous trouverez sur GitHub ) cela ne fera que m’améliorer car par exemple j’ai l’impression de faire des fonctions trop longues mais je ne vois pas comment les raccourcir.

Bonne fin de soirée (ou journée ) :D .

Édité par Linux

N’hésitez pas a aller voir le code source de mon projet Trapped Hero sur GitHub

+0 -0

Je n’ai que vaguement regardé le code, et mes connaissances en C sont limitées, donc je ne te donnerais pas de conseils très techniques. Du coup, je vais plutôt te dire ce que moi j’aurais fait à ta place.

Tu utilises des switch où toutes les branches font essentiellement la même chose, comme par exemple dans le code suivant issu de afficher_carte.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
        switch(carte->terrain[i].type){
            case VIDE :
                SDL_RenderCopy(carteSDL->renderer , carteSDL->vide , NULL  , &rect );
                //printf("  ");
                break;
            case CHEMIN :
                SDL_RenderCopy(carteSDL->renderer , carteSDL->chemin[carte->terrain[i].numeroTile] , NULL  , &rect );
                //printf("@ " );
                break;
            case MUR:
                SDL_RenderCopy(carteSDL->renderer , carteSDL->mur[carte->terrain[i].numeroTile] , NULL  , &rect );
                //printf("[]" );
                break;
            case MUR_SALLE :
                SDL_RenderCopy(carteSDL->renderer , carteSDL->mur[carte->terrain[i].numeroTile] , NULL  , &rect );
                //printf("##");
                break;
            case SOL_SALLE :
                SDL_RenderCopy(carteSDL->renderer , carteSDL->chemin[carte->terrain[i].numeroTile] , NULL  , &rect );
                //printf("..");
                break;
            case PORTE :
                if(carte->terrain[i].orientation==HORIZONTALE){
                    //printf("__");
                    SDL_RenderCopy(carteSDL->renderer , carteSDL->porte , NULL  , &rect );
                }
                else if(carte->terrain[i].orientation==VERTICALE){
                    //printf("| ");
                    SDL_RenderCopy(carteSDL->renderer , carteSDL->porte , NULL  , &rect );
                }
                break;
            case MUR_CHEMIN :
                SDL_RenderCopy(carteSDL->renderer , carteSDL->mur[carte->terrain[i].numeroTile] , NULL  , &rect );
                //printf("+ ");
                break;
        }

L’idée que ton code devrait véhiculer est que chaque branche du switch va se charger de récupérer la bonne texture à afficher, or ici tout est embrouillé dans ton appel de SDL_RenderCopy. Le code suivant récupère d’un part la bonne texture, et l’affiche ensuite. Le code résultant contient quelques lignes de plus que le code original, mais il contient beaucoup moins de caractère et est surtout plus simple à lire.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
SDL_Texture* texture = NULL;
switch(carte->terrain[i].type) {
    case VIDE:
        texture = carteSDL->vide;
        break;
    case CHEMIN:
        texture = carteSDL->chemin[carte->terrain[i].numeroTile];
        break;
    // ...
}
SDL_RenderCopy(carteSDL->renderer, texture, NULL, &rect);

Dans le même fichier, tu as une fonction quitterSDL. Déjà une telle fonction n’a rien à faire dans un fichier qui a pour vocation d’afficher une carte. D’autre part, tu répètes ton code :

1
2
3
4
5
6
7
8
9
   if(carteSDL->chemin[0]!=NULL){
        SDL_DestroyTexture(carteSDL->chemin[0]);
    }
    if(carteSDL->chemin[1]!=NULL){
        SDL_DestroyTexture(carteSDL->chemin[1]);
    }
    if(carteSDL->chemin[2]!=NULL){
        SDL_DestroyTexture(carteSDL->chemin[2]);
    }

Ce code peut être compacté très facilement (et tout en restant clair) par une boucle for :

1
2
3
4
5
6
7
8
for (int i = 0 ; i < 3 ; ++i)
{
    SDL_Texture* texture = carteSDL->chemin[i];
    if (texture)
    {
        SDL_DestroyTexture(texture);
    }
}
+3 -0
Auteur du sujet

Merci pour ces conseils , le premier permet vraiment de rendre le code plus lisible (en plus cela m’a permis de rajouter des commentaires ^^ ) par contre il fallait penser a mettre la valeur de la texture a NULL après copiage et mettre une condition sur le copiage pour ne pas copier des texture vides.

Ce code peut être compacté très facilement (et tout en restant clair) par une boucle for :

C’est vrai qu’il était un peu répétitif… je trouve par contre que la variable intermédiaire stockant l’adresse de la texture est moins utile dans ce cas là.

Déjà une telle fonction n’a rien à faire dans un fichier qui a pour vocation d’afficher une carte.

Je leur ait créé un fichier a ces fonctions :magicien: (il était temps) en fait j’ai écrit ces fonctions en les plaçant dans ce fichier car c’était celui utilisant le plus la SDL puis petit a petit ces fonctions ce sont entassé…

Merci pour ces remarques , j’ai mis a jour le code en suivant tes conseils :D .

N’hésitez pas a aller voir le code source de mon projet Trapped Hero sur GitHub

+0 -0
Auteur du sujet

Bonjour (ou plutôt bonsoir ) je poste pour annoncer (avec un peu de retard) une nouvelle mise a jour .

Alors il y a quoi de nouveau ?

Donc j’ai put faire le système d’enregistrement de la carte (plus évolué que je le voyait au début) donc a partir du menu (qui a était un peu modifié) :

Les bouton ont été un peu réorganisés

On accède a un autre menu (nouveau) qui permet de choisir entre trois sauvegarde :

Le graphisme est encore à améliorer…

Ce menu permet de charger une carte ou sélectionner un endroit pour enregistrer sa carte.

Malheureusement je n’ai pas eu le temps de faire le système de voile que je reporte a la fin de la semaine. :euh:

Pour la prochaine mise a jour

Comme dit juste avant le système de voile mais aussi d’autres petites modifications :

  • Résoudre différents bug lié au cadrage sur les bords de la carte
  • L’ajout d’étages

Donc encore une fois le code source est sur GitHub (le lien est dans ma signature) et commentez le : cela ne fera que m’améliorer.

Merci d’avoir lu :D

N’hésitez pas a aller voir le code source de mon projet Trapped Hero sur GitHub

+0 -0

Salut,

Je le rajoute en favori sur Github pour ne pas oublié de regarder et commenter le code… Mais je peux déjà dire que tu as des fonctions beaucoup trop longues comme reajusterCadrage et que tu devrais regarder des ressources sur le Tile Mapping ; il n’y en a pas (encore ?) sur Zeste de Savoir, mais il y a le tutoriel de Fvirtman trouvable sur OpenClassrooms et sur Developpez.

J’ai jamais fait de Rogue-Like, mais ton projet me donne envie d’en faire un. ^^ En tout cas, bravo pour t’être lancé dans l’aventure, je vais essayer de suivre ça de près.

Je fais un carnage si ce car nage car je nage, moi, Karnaj ! - Le comble pour un professeur de mathématique ? Mourir dans l’exercice de ses fonctions.

+0 -0
Auteur du sujet

Bonjour,

Merci ça fait toujours plaisir d’avoir des retours.

tu devrais regarder des ressources sur le Tile Mapping

Je note car quelques conseil pour l’affichage ne serait pas de trop

tu as des fonctions beaucoup trop longues comme reajusterCadrage

Si celle ci te parait longue je ne te conseil pas d’aller voir du coté de generateur_chemin.c et plus particulièrement contourner():-° (même si j’essaye maintenant de reduire le plus la taille des fonctions )

bravo pour t’être lancé dans l’aventure

Ben c’est en partie grâce a ton tutoriel sur la SDL 2 qui m’a permis de me lancer donc encore merci. :D

N’hésitez pas a aller voir le code source de mon projet Trapped Hero sur GitHub

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte