Bien joué ...
Finalement y a plein de jeu qui se rapproche de ce principe, tel que FF ( les premiers ) et Breath of Fire. Lorsque je dis "se rapproche" je parle de la gestion des cartes.
Les combats !
Les combats !
Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi
Ma page sur DVP
Mon Portfolio
Qui connaît l'erreur, connaît la solution.
Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi
Ma page sur DVP
Mon Portfolio
Qui connaît l'erreur, connaît la solution.
Nous avons à présent les potions :-)
Dans le jeu original il y en avait 8 :
Jaune : guérison
Rouge : Guérison des maladies (toutes)
Verte : Poison
Blue : Endormir
Orange : Réveiller
Noir : invisibilité
Blanche : vison
Mauve: protection
Du coup, on les a ajouté comme on le voit ici :
On peut bien sûr en acheter/vendre et les utiliser. Je n'ai pas encore fait de magasin par contre :-)
Jc
PS: On a dépassé les 10k lignes :-) :yeah:
Et voilà, chose promise, chose dûe : un magasin de potions :-)
La ville de Novea commence à se remplir avec les magasins qui se multiplient !
Prochaine étape : les sorts !
Jc
On dirait que ça avance bien ! JHuste une remarque : ta feuille de sprite n'a pas l'air de bonne qualité...
Vous souhaitez participer aux rubriques Qt (tutoriels, FAQ, traductions) ou HPC ? Contactez-moi par MP.
Créer des applications graphiques en Python avec PyQt5
Créer des applications avec Qt 5.
Pas de question d'ordre technique par MP !
Non pas vraiment. Gardez en tête que les sprites était en 16*16 pixels ! Donc forcément, moi je l'agrandi un peu ben ca donne ca... Je peux la changer pour une autre feuille qui n'a pas été au préalable agrandie.
Je ferai ce genre de choix/changement une fois que la première version du moteur est fini. Il me reste les sorts à gérer et les combats et on aura déjà pas mal de choses.
LittleWhite -> pour les sorts, je vais avoir besoin de combats vu que certains sont pour les combats donc bientôt ;-)
Jc
Pour LittleWhite:
Histoire de vous faire rire un vendredi soir, la première image du premier combat :
C'est vide, ce n'est pas encore prêt mais c'est un début :-)
Bonne soirée à tous !
Jc
Comme on dit, la première chose qu'il faut pour commencer, c'est avoir une page blanche ( ou ouvrir l'editeur de code ) ( bon d'accord, y a peut être moi qui dit ça )
Bonne continuation
Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi
Ma page sur DVP
Mon Portfolio
Qui connaît l'erreur, connaît la solution.
Comme quoi un peu d'UML ou de réflexion serait pas mal :
Petit rappel:
- Nous avions:
1) Character qui hérite de Class
2) Npc qui contient une instance de Character et qui hérite de AnimatedObject
La map gére des AnimatedObject.
- A la place d'avoir un Character dans un Npc et perdre cette information lors de l'ajout du groupe, il s'est avéré qu'on avait besoin de l'AnimatedObject pour les combats.
Du coup, j'ai dû mettre à jour mon code et c'est vraiment plus propre à présent :
Class < Character < AnimatedObject < Npc.
Du coup, on a toute les informations nécessaire et quasiment gratuitement nous avons ce screen shot :
On a les persos en place, on peut les bouger chacun leur tour, la gestion de collision est directement intégrée vu que c'était déjà dans Map. J'ai éteint les questions de visibilité pour les combats (on verra).
A présent, je dois ajouter des ennemis et ce sera un bon début ;-)
Jc
C'est dingue comme tu travailles vite et bien.
Impressionnant.
Disons que beaucoup de choses sont déjà mis en place donc c'est assez rapide d'ajouter au modéle existant. J'ai eu pas mal de chance car je n'ai pas encore fait de grosse gaffe (je ne pense pas du moins).
Sans UML et en improvisant au fur et à mesure, j'ai de la chance ;-).
Pour revenir sur comment les combats sont gérés et comment on fait pour passer d'une vue à une autre, c'est assez facile et assez pratique (moins de 350 lignes de code pour ca !).
Du code GeneralViewState qui vous a donné quasiment tous les screenshots jusqu'à présent, nous avons un code qui permet de faire une attaque :
On commence donc par regarder si la case est occupée. Si oui, on ajoute le nom de la personne qu'on attaque au text et ensuite on remplit une structure de transfert d'information.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 //Handle talking state event bool GeneralViewState::handleAttackingState (SDL_Event &ev) { Cell *cell; bool res = handleSpecialState (ev, &cell); if (cell != NULL && cell->isOccupied ()) { AnimatedObject *obj = cell->getAnimatedObject (); appendText (obj->getName ()); SCombatViewInfo *scvi = new SCombatViewInfo (); scvi->group = group; scvi->textArea = textarea; scvi->groupView = groupView; scvi->combatName = "data/combat.txt"; Engine::getInst ()->setNewGameState ("combatViewHandler", scvi); } return res; }
En effet, GeneralViewState est le possesseur du groupe, de la zone texte, de la vue du groupe. Il sait aussi quel combat faire (pour le moment codé en dur, mais ensuite on fera un truc nettement plus sympa :-)).
Enfin, on dit au moteur qu'on veut changer d'état et on passe le pointeur de la structure. On utilise simplement un string pour faire référence au combat, le moteur trouvera l'état dans sa map interne.
La fonction du moteur est assez simple :
On a une mise en place du nouvel état et un appel à la fonction handleInfo.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 //Set new game state void Engine::setNewGameState (std::string s, void *info) { newState = states[s]; newStateName = s; if (newState == NULL) Logging::log(0, "Warning new state is NULL" ,NULL); newState->handleInfo (info); }
D'un point de vue gestion de l'information pour le combat, on a la récupération des pointeurs nécessaire, on vide la zone texte (plus tard je vais ajouter un système de pile de texte, ce sera mieux).
Et on charge le combat.
Le moteur, lors d'une mise à jour, va vérifier si newState est non null et si c'est le cas, fera le nécessaire pour passer d'un état à un autre de facon transparente.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 void CombatViewState::handleInfo (void *info) { SCombatViewInfo *scvi = static_cast <SCombatViewInfo *> (info); group = scvi->group; groupView = scvi->groupView; textArea = scvi->textArea; //Free textArea textArea->clear (); sendText ("Combat - Started!"); loadCombatView (scvi->combatName); delete scvi, scvi = NULL; }
Un fichier de combat est défini par :
La première ligne est l'information de la map (donc conventions et fichier .bmp).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 data/combat_map_grass.txt #Maximum players 8 #Now have the start positions of the players 7 6 6 7 8 7 5 8 7 8 9 8 6 9 8 9
Ensuite nous avons les positions de départ des joueurs. On a dans ce jeu un maximum de 8 joueurs dans le groupe (c'était le maximum dans le jeu de base).
Le chargement se fait donc très facilement, chargement de la map par la classe Map :
Récupération des positions des joueurs et, si on a assez de joueurs dans le groupe, on met à jour sa position et on l'insére dans la map.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 bool CombatViewState::loadCombatView (std::string fileName) { Logging::log(0, "Loading a combat view", NULL); LineParser lp (fileName, true); //Get Map line std::string map_name = lp.getNextLine (); loadMap (map_name);
Ensuite, le premier joueur aura le focus.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 unsigned int maxPlayers = lp.getNumber (); //Get positions of players for (unsigned int i = 0; i < maxPlayers; i++) { int x, y; lp.getCouple (&x, &y); if (i < group->getNumCharacters ()) { AnimatedObject *character = group->getCharacterAnimated (i); character->setPos (x, y); Cell *cell = map->getCell (y, x); assert (cell); cell->occupy (character); } }
Le focus permet de gérer qui on est en train de jouer. Comment est-ce qu'on gére cela ? C'est très facile !
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 //Set first player as focus map->setFocus (group->getCharacterAnimated (0));
Si on appuie sur une direction, on appelle la fonction correspondante pour la map et la map gére les collisions comme avant. Par contre, à la place d'utiliser le groupe comme auparavant, la map utilise l'objet ayant le focus.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
37
38
39
40
41
42
43
44
45 bool CombatViewState::handleDefaultState (SDL_Event &ev) { std::string text = ""; bool res = true; switch (ev.key.keysym.sym) { case SDLK_UP: map->goUp (); break; case SDLK_DOWN: map->goDown (); break; case SDLK_RIGHT: map->goRight (); break; case SDLK_LEFT: map->goLeft (); break; case SDLK_SPACE: text = "Pass"; break; case SDLK_z: inState = INVENTORY_COMBAT_STATE; text = "Checking inventory"; groupView->showInventory (); break; default: //Did not handle this key res = false; break; } if (text != "") sendText (text); //Now pass the focus to the next character currentFocus++; currentFocus %= group->getNumCharacters (); map->setFocus (group->getCharacterAnimated (currentFocus)); return res; }
Une fois un événement géré, on passe le focus au prochain caractère et le passage de l'un à l'autre se fait de facon transparente pour tout le monde.
Espérant cela a été clair,
Jc
Petite mise à jour hier soir et nous avons la première image d'un combat avec des ennemis.
Ici, nous attaquons les gardes :-)
Ils ne font encore rien, nous ne pouvons pas encore attaquer mais cela arrivera rapidement ;-)
Jc
Vous souhaitez participer aux rubriques Qt (tutoriels, FAQ, traductions) ou HPC ? Contactez-moi par MP.
Créer des applications graphiques en Python avec PyQt5
Créer des applications avec Qt 5.
Pas de question d'ordre technique par MP !
C'est pas mal le système de combat
Après, je trouve que le jeux va être difficile ( 200 gardes contre 3 gus ( dans leur garage ) )
Sinon, en lisant le code, on remarque ça
Et ce que le logger quitte le programme ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 if (newState == NULL) Logging::log(0, "Warning new state is NULL" ,NULL); newState->handleInfo (info);
Car s'il ne le fait pas ... nous avons un plantage ... ( et en plus, sans flush sur l'entrée du log ... et bah le message risque de ne pas s'afficher ( même avec un flush, je crois )).
Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi
Ma page sur DVP
Mon Portfolio
Qui connaît l'erreur, connaît la solution.
Je suis entièrement d'accord ... c'est pour cela que j'en parle. Mais on pouvait avoir un doute à cause du dernier paramètre ... ( on ne sait jamais :p bien que je ne vois pas trop à quoi il sert ).
Envoyé par fearyourself( source )Envoyé par Bill Gates
Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi
Ma page sur DVP
Mon Portfolio
Qui connaît l'erreur, connaît la solution.
Oui mais tu n'es pas supposé attaqué un garde ;-)
Non le logger ne fait que logger, par contre, j'ai corrigé ca samedi en fait ;-). Un joli petit if est mis pour protéger l'appel ;-)Sinon, en lisant le code, on remarque ça
Et ce que le logger quitte le programme ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 if (newState == NULL) Logging::log(0, "Warning new state is NULL" ,NULL); newState->handleInfo (info);
Car s'il ne le fait pas ... nous avons un plantage ... ( et en plus, sans flush sur l'entrée du log ... et bah le message risque de ne pas s'afficher ( même avec un flush, je crois )).
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager