Partie 11: Interface du jeu - Partie 1

Téléchargements

Code source
Exécutable de l'éditeur de niveaux - exactement le même que la partie 10 (Windows 32bits)
Exécutable du jeu (Windows 32bits)

Avant d'essayer de compiler le code, allez dans l'onglet "Projets" dans le menu de gauche, séléctionnez l'onglet "Run" pour votre kit,
et mettez dans "Working directory" le chemin de "editor\data" pour l'éditeur ou "game\data" pour le jeu.

Ajouter du mouvement

Si vous avez joué au jeu dans les parties précédentes, vous avez peut-être remarqué qu'on a l'impression de "glisser" dans
la map au lieu de marcher.
C'est parce que les graphismes (spécialement le sol) ne changent pas quand on bouge d'une case à l'autre.
Pour éviter ce problème sans avoir à dessiner plus de graphs, les développeurs de Dungeon Master utilisaient une simple astuce:
le retournement.
A chaque fois que vous marchez sur une nouvelle case (et à chaque fois que vous tounez aussi) le sol, le plafond et les murs de
face sont retournés horizontalement.


Les murs de cotés sont échangés avec leurs contreparties retournées. Par ex. le Wall20_L est remplacé par un Wall20_R retourné.
Ces changements sont surtout visibles sur le sol. Sur les murs seuls quelques pixels changent. Mais c'est suffisant pour nous
donner l'impression de vraiment se "déplacer" entre chaque case.
Donc j'ai du un peu changer la fonction drawImage() et les routines d'affichage. Si vous cherchez "flip" dans le the code, vous
trouverez tous les changements.

La même astuce était utilisée dans beaucoup d'autres jeux: Eye of the Beholder, Black Crypt, Might & Magic 3...

L'interface



J'ai commencé à dessiner quelques éléments de l'interface et de mettre en place la plupart des fonctions nécessiares.
Jetez un oeil à "interface.h":

		#ifndef INTERFACE_H
		#define INTERFACE_H

		#include <QTimer>
		#include <QImage>
		#include "../common/sources/system/cmaths.h"
		#include "character.h"

		#define MAIN_INTERFACE_COLOR    QColor(0, 204, 204)

		class CInterface
		{
		public:
			// Etat principal de l'interface
			enum EMainState
			{
				eMainGame = 0,  // fenêtre standard avec la vue 3D
				eMainInventory  // écran d'inventaire
			};

			// Etats de la zone des armes
			enum EWeaponsAreaState
			{
				eWeaponsAreaWeapons = 0,    // Les 4 zones d'armes
				eWeaponsAreaAttacks,        // Les attaques d'une arme
				eWeaponsAreaDamage          // Les dommages quend on frappe un monstre
			};

			CInterface();
			~CInterface();

			void    display(QImage* image);
			bool    isInInventory();

		private:
			bool    isChampionEmpty(int num);
			bool    isChampionDead(int num);

			bool    isWeaponEmpty(int num);
			bool    isWeaponGreyed(int num);

			bool    isArrowsGreyed();

			void    drawBar(QImage* image, int num, CVec2 pos, CCharacter::EStatsNames statName);
			void    drawChampion(QImage* image, int num);
			void    drawSpells(QImage* image);
			void    drawWeaponsArea(QImage* image);
			void    drawWeapon(QImage* image, int num);
			void    drawArrows(QImage* image);
			void    drawInventory(QImage* image);
			void    greyRectangle(QImage* image, CRect rect);
			int     getWeapon(int num);
			CCharacter::SStat   getStat(int num, CCharacter::EStatsNames statName);

			EMainState          mainState;
			EWeaponsAreaState   weaponsAreaState;
			int     currentChampion;
			int     currentWeapon;
			QTimer* weaponCoolDown[4];
		};

		extern CInterface   interface;

		#endif // INTERFACE_H
				
J'ai aussi du mettre en place quelques fonctions pour les statistiques des personnages. Voici "character.h":

		#ifndef CHARACTER_H
		#define CHARACTER_H

		#include <string>

		class CCharacter
		{
		public:
			enum EBodyParts
			{
				eBodyPartHead = 0,
				eBodyPartNeck,
				eBodyPartTorso,
				eBodyPartLeftHand,
				eBodyPartRightHand,
				eBodyPartLegs,
				eBodyPartFeets,
				eBodyPartCount
			};

			enum EStatsNames
			{
				eStatHealth = 0,
				eStatStamina,
				eStatMana,
				eStatStrength,
				eStatDexterity,
				eStatWisdom,
				eStatAntiFire,
				eStatAntiMagic,
				eStatLoad,
				eStatCount
			};

			struct SStat
			{
				int value;
				int maxValue;
				int startValue;
			};

			CCharacter();
			bool    isDead();

			int     picture;
			std::string name;
			SStat   stats[eStatCount];
			int     bodyObjects[eBodyPartCount];
		};

		#endif // CHARACTER_H
				
Enfin j'ai mis quelques valeurs par défaut pour les stats des personnages dans "game.cpp" pour tester les différents états.

Vous pouvez voir en détail comment les différents états sont gérés dans "interface.cpp".
Je continuerai surement ce travail dans la partie 13.

Le niveau 1



J'ai dessiné une première version du niveau 1 du jeu. Bien sur, il manque plusieurs éléments: les escaliers, les portes,
les tableaux pour choisir les champions, le passage secret pour la fin alternative...
Et beaucoup de petites décorations.
On va commencer à ajouter ces éléments dans la prochaine partie.

Evidemment, j'ai du changer la position de départ du joueur aussi. Vous pouvez voir ça dans "main.cpp" juste après le
chargement de la map.