Partie 33: Serrures et nouvelles portes

Téléchargements

Code source
Exécutable de l'éditeur de niveaux (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.

Les portes du niveau 2

Pour le moment, toutes les portes du niveau 2 avaient simplement un bouton pour les ouvrir.
Dans cette partie on va commencer à mettre en place les mécanismes qui étaient utilisés dans le jeu d'origine pour
ouvrir chaque porte, et à leur donner leur apparence finale.

Alors commençons par les numéroter, ensuite on regardera chaque porte une par une.
Ici je les ai numérotées dans le même ordre dans lequel on les ouvre quand on joue à ce niveau.


Portes 1 et 2

Les portes 1 et 2 sont de simples portes qui sont ouvertes par un bouton, alors on n'a pas besoin de changer quoi
que ce soit.
Notez que les images viennent du jeu d'origine. On n'a pas encore de momies.


Porte 3

La porte 3 doit être ouverte avec une clé en or qui est posée à coté.


La clé doit aller dans une serrure qui est juste à une case à droite de la porte.


Maintenant regardons comment coder ces serrures.

Les serrures

Dans l'éditeur, les serrures vont être un nouveau type de murs.

		<wall name="Serrure">
			<image>Lock.png</image>
			<param type="enum" values="Fer;Fontaine">Type</param>
			<param type="script">siOuvert</param>
			<param type="stack"/>
		</wall>
				
Le paramètre "Type" est le décor qu'on va afficher sur le mur. Il y a seulement 2 types de serrures dans ce niveau:
une en fer comme sur l'image au-dessus et une autre qui est déguisée en fontaine.
Le paramètre "siOuvert" donne le script que l'on va exécuter quand la serrure est ouverte.
La plupart des serrures n'ont besoin que d'un objet pour être ouvertes, mais on verra plus tard que certaines en
ont besoin de plusieurs.
Donc pour dire quels objets on aura besoin, on utilisera un tas d'objets comme pour les alcôves.
Mais contrairement aux alcôves, les objets dans ce tas n'apparaitront pas comme des objets réels dans le jeu.
Ca sera seulement une liste d'objets "virtuels" dont la serrure a besoin.


Dans le jeu, le dessin de ces murs est simple: on affiche seulement le décor et on ajoute une zone souris.

		else if (wall->getType() == eWallLock)
		{
			//------------------------------------------------------------------------------
			// serrure
			int type = wall->getEnumParam("Type");
			CRect   rect = walls.drawOrnate(image, tablePos, side, ORNATE_IRON_LOCK + type);

			if (tablePos == CVec2(2, 3) && side == eWallSideUp)
				mouse.addArea(eMouseAreaG_Lock, rect, eCursor_Hand, (void*)mapPos.x, (void*)mapPos.y, (void*)playerSide);
		}
				
Voilà ce que l'on fait quand on clique dans cette zone dans CGame::update():
D'abord on récupère la position du mur et on trouve notre tas d'objets virtuel.

		else if (clickedArea->type == eMouseAreaG_Lock)
		{
			CVec2   pos;
			EWallSide   side;

			pos.x = (int)clickedArea->param1;
			pos.y = (int)clickedArea->param2;
			side = (EWallSide)((int)clickedArea->param3);

			CObjectStack* stack = map.findObjectsStack(pos, side);
				
Ensuite, on boucle sur chaque objet de ce tas pour voir si son type est le même que celui qu'on tient dans notre
main (c'est à dire si c'est la clé).
Si c'est le cas, on retire cet objet à la fois du tas et de notre main.
Remarquez que retirer l'objet du tas nous empêche d'utiliser plusieurs fois le même type de clé dans la serrure.

			for (size_t i = 0; i < stack->getSize(); ++i)
				if (stack->getObject(i).getType() == mouse.mObjectInHand.getType())
				{
					stack->removeObject(i);
					mouse.mObjectInHand.setType(0);
					sound->play(pos, "sound/Switch.wav");
					break;
				}
				
Enfin, si le tas est vide (c'est-à-dire que la serrure a reçu toutes les clés dont elle avait besoin), alors on
exécute le script "siOuvert".

			if (stack->getSize() == 0)
			{
				CWall*  wall = &map.getTile(pos)->mWalls[side];
				std::string script = wall->getScriptParam("siOuvert");
				scripts.execute(script);
			}
		}
				
La plupart des scripts que j'ai ajoutés dans ce niveau sont les mêmes que celui qu'on a utilisé pour la plaque de
pression dans le niveau 1.
On a seulement besoin de mettre le paramètre "estOuverte" à "true".

		Target Tile 1 3
		SetBool estOuverte true
				
Dans quelques cas, on va aussi utiliser un scripts pour fermer une porte, qui sera exactement le même à part qu'on
a un "false à la place du "true".
Et plus tard on verra qu'on a besoin d'un script "switch" qui transforme le "true" en "false" et vice versa.

J'ai ajouté des scripts à toutes les portes qui ont besoin d'une clé dont je parlerai dans cette partie, et j'ai
retiré leurs boutons.

Portes 4 et 6

Les portes 4 et 6 sont deux herses qu'on ouvre toutes les deux avec une clé.

Porte 5

La porte 5 devrait s'ouvrir avec un levier à coté.
On ne va pas implémenter les leviers et les boutons dans cette partie, alors je lui ai laissé un bouton pour
l'ouvrir.

Porte 7


Pour la porte 7, il y a un petit puzzle avec des plaque de pression à résoudre.


Quand vous marchez sur la plaque "A", ça ouvre la porte, mais si vour marchez sur "B", ça la referme.
Alors vous devez contourner "B".
Pour implémenter ce puzzle, on a juste besoin d'assigner un script d'ouverture à "A" et un script de fermeture à
"B".

Porte 8

La porte 8 s'ouvre avec une clé émeraude.


Elle a un décor particulier. Nous parlerons des nouveaux décors à la fin de cette partie.
Elle mène à une pièce où vous trouverez les clés pour les 2 portes suivantes.

Portes 9 et 10

Ces 2 portes s'ouvrent aussi avec des clés.
Entre elles il devrait y avoir un monstre, mais on les ajoutera dans une prochaine partie.


Portes 11

Une autre porte qui s'ouvre avec une clé.

Portes 12 et 13


Ces 2 portes s'ouvrent en résolvant un puzzle plus complexe.


Les plaques bleues changent l'état de la porte 12, et les vertes changent celui de la porte 13.
Vous devriez être capables de traverser ça en marchant simplement en avant et en arrière.
Pour implémenter ça, on a besoin d'une nouvelle commande de script "SwitchBool" qui inverse la valeur d'un
paramètre:

		void CScripts::executeSwitchBool(std::vector<std::string>& words)
		{
			QString param = QString::fromStdString(words[1]);

			if (mTargetType == eTargetType_Tile)
			{
				CTile*  target = (CTile*)mTarget;
				bool    value = target->getBoolParam(param);
				target->setBoolParam(param, !value);
			}
			else
			{
				CWall*  target = (CWall*)mTarget;
				bool    value = target->getBoolParam(param);
				target->setBoolParam(param, !value);
			}
		}
				

Porte 14

Une porte qui s'ouvre avec une clé en or qu'on obtient après avoir combattu quelques monstres.

Porte 15


Pour ouvrir cette porte, vous devez laisser un objet sur la case de la plaque à droite.


J'ai du changer un peu la code des plaques de pression pour prendre en compte les objets qu'on pose dessus.

		if (tile->getType() == eTilePressPlate)
		{
			if (tile->getBoolParam("parChampions") == true && interface.isChampionEmpty(0) == false && player.pos == pos)
			{
				state = true;
			}
			else if (tile->getBoolParam("parObjets") == true)
			{
				CVec2   pos2 = pos * 2;

				if (map.findObjectsStack(pos2, eWallSideMax) != NULL ||
				    map.findObjectsStack(pos2 + CVec2(1, 0), eWallSideMax) != NULL ||
				    map.findObjectsStack(pos2 + CVec2(0, 1), eWallSideMax) != NULL ||
				    map.findObjectsStack(pos2 + CVec2(1, 1), eWallSideMax) != NULL)
				{
					state = true;
				}
			}
				

Porte 16

Vous devez prendre un télé-porteur pour récupérer la clé de cette porte. On les implémentera plus tard.
Pour le moment je laisse un bouton sur la porte.

Portes 17 et 18

Les 2 premières portes horizontales qu'on rencontre, et elles ont un décor de serrure spécial.
Quoi qu'il en soit, elles se déverrouillent avec une clé comme les autres.


Portes 19 et 20

Ces 2 portes ont besoin de boutons et de leviers pour s'ouvrir. On garde ça pour plus tard.

Porte 21

Une autre simple porte qui s'ouvre avec une clé.
Normalement on doit résoudre un puzzle avec un télé-porteur pour obtenir cette clé, mais pour le moment, vous
pouvez la ramasser sans problème.

Porte 22

La porte 22 est une porte que vous devez casser avec vos armes.
On implémentera probablement ça après les attaques des armes.

Porte 23


La porte 23 s'ouvre quand vous mettez une pièce dans la fontaine à droite.
Cette fontaine se comporte comme une serrure. On verra la partie "boisson" plus tard.

Porte 24

Cette porte à aussi besoin d'un levier.

Porte 25

Finalement, la dernière porte du niveau a simplement un bouton sur elle.

Nouveaux décors de portes

Dans cette partie on a rencontré 3 nouveaux décors de portes.
Je les ai ajoutés, mais il y a quelques problèmes.

Le décor des barreaux en bois n'a pas la même couleur que la porte.




C'est parce que les images des portes étaient pré-calculées pour coller à la palette de couleurs du jeu d'origine.
Mais d'un autre coté, on n'a qu'une seule image pour le décor et on le réduit et l'assombrit en utilisant nos
propres fonctions.

La grille arrondie a un autre problème.
C'est un décor particulier car on peut voir à travers.
Voilà à quoi il ressemble.


La couleur rose était utilisée dans le jeu d'origine pour dire que ces pixels devaient être transparents.
Alors d'abord il faut qu'on dessine cette image sur la porte, et ensuite on doit retirer tous les pixels roses.
Voilà le résultat:




Vous pouvez voir qu'il y a un barreau manquant dans la dernière image.
C'est parce que le décor est redimensionné avant qu'on enlève les pixels roses et ça mène à des imprécisions dans
les coordonnées de ces pixels.

Mais on trouvera un moyen de corriger ces problèmes dans la prochaine partie.

En écrivant cette partie, je me suis aussi rendu compte que dans le jeu d'origine, une ombre était dessinée sous
les objets qu'on tient dans la main. Ca les rend plus faciles à voir, en particulier pour les clés. J'ajouterai ça
dans la prochaine partie aussi.