Partie 39: Les monstres partie 1: Groupes dans l'éditeur

Téléchargements

Code source
Exécutable de l'éditeur de niveaux (Windows 32bits)
Exécutable du jeu - exactement le même que la partie 38 (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 graphismes des monstres

Voici les graphismes des monstres:


Chaque monstre peut avoir une image pour chaque direction (de face, de coté, de dos) et une image d'attaque.
La seule exception est le Zytaz (Materializer) qui a une animation de 3 frames.
Mais certains monstres n'auront pas toutes ces images. Par ex. le Crieur n'en a que 2 parce qu'il est symétrique.
On verra l'utilisation de ces images plus tard. Pour le moment elles vont nous permettre de créer une base de
données de monstres.

		<?xml version="1.0" encoding="utf-8"?>
		<monsters>
			<!-- 00 None -->
			<monster name = MONSTER00">
			</monster>

			<!-- 01 Scorpion Géant -->
			<monster name = MONSTER01">
				<img_front>01_Giant_Scorpion_front.png</img_front>
				<img_side>01_Giant_Scorpion_side.png</img_side>
				<img_back>01_Giant_Scorpion_back.png</img_back>
				<img_attack>01_Giant_Scorpion_attack.png</img_attack>
			</monster>

			<!-- 02 Démon Baveux -->
			<monster name = MONSTER02">
				<img_front>02_Swamp_Slime_front.png</img_front>
				<img_attack>02_Swamp_Slime_attack.png</img_attack>
			</monster>
			
			[...]
		</monsters>
				
Les monstres apparaissent dans le jeu en groupes de 1 à 4 par case.


Quand il y a seulement 1 monstre, il peut être sur une de ces 4 positions, mais après un moment il ira au centre de
la case:


Plus tard dans le jeu on verra des monstres qui sont 2 ou 4 fois plus gros que ceux-ci. Le nombre maximum de
monstres sur une case sera donc réduit en conséquence.
Mais on parlera de ça plus tard, pour l'instant on va commencer à inclure ces groupes dans l'éditeur.

L'onglet monstres

La base de données est lue dans l'éditeur et on l'utilise pour afficher un nouvel onglet.


Cet onglet est ajouté à "MainForm.ui.qml".

        Tab {
            id:monstersTab
            title: qsTr("Monstres")
            source:"/MonstersTab.qml"
            clip: true
        }
				
"MonsterTab.qml" est presque le même que les fichiers utilisés pour les autres onglets.

		import QtQuick 2.5
		import QtQuick.Controls 1.4
		import QtQuick.Layouts 1.2

		ScrollView
		{
			ListView
			{
				model:monstersList
				currentIndex: bridge.monsterType
				highlightMoveDuration: 0

				delegate: Item {
					width: parent.width - 12
					height: 25

					Text {
						x: 6
						width: parent.width - 12
						anchors.verticalCenter: parent.verticalCenter
						text: modelData
					}

					MouseArea {
						anchors.fill: parent
						onClicked: bridge.monsterType = index
					}
				}

				highlight: Rectangle { color: "#70c0ff" }
			}
		}
				
"MainForm.ui.qml" contient aussi la partie d'infos de la sélection qui apparait en dessous de l'onglet.

        ScrollView {
            id: monsterSelScroll
            visible: bridge.monsterSelScrollVis
            anchors.fill: parent

            GridLayout {
                id: mSelGrid
                objectName: "mSelGrid"
                rowSpacing: 4
                columnSpacing: 4
                rows: 3
                columns: 2
                anchors.fill: parent

                Label {
                    id: mPosLabel
                    height: 20
                    text: qsTr("Position:")
                    verticalAlignment: Text.AlignVCenter
                    renderType: Text.QtRendering
                }

                Label {
                    id: mPosValue
                    height: 20
                    text: bridge.selPosition
                    verticalAlignment: Text.AlignVCenter
                }

                Label {
                    id: mTypeLabel
                    height: 20
                    text: qsTr("Type:")
                    verticalAlignment: Text.AlignVCenter
                    horizontalAlignment: Text.AlignLeft
                }

                ComboBox {
                    id: mTypeValue
                    model: monstersList
                    currentIndex: bridge.selMonsterType
                }
            }
		}
				

Stocker les monstres

Les groupes de monstres seront stockés dans une liste séparée de la map, comme les objets.

		class CMonsterGroup
		{
		public:
			CMonsterGroup();
			CMonsterGroup(const CMonsterGroup& rhs);
			virtual ~CMonsterGroup();

			void    setType(uint8_t type);
			uint8_t getType();
			CMonsterGroup&  operator=(const CMonsterGroup& rhs);
			void    load(FILE* handle);
			void    save(FILE* handle);

			CParam*     findParamByName(QString name);

			CVec2       mPos;
			std::vector<CParam*>    mParams;

		private:
			void    deleteParams();

			uint8_t mType;
		};

		//---------------------------------------------------------------------------------------------
		class CMap
		{
			[...]
			CMonsterGroup*  addMonsterGroup(CVec2 pos);
			CMonsterGroup*  findMonsterGroup(CVec2 pos);
			void            removeMonsterGroup(CVec2 pos);

			[...]
			std::vector<CMonsterGroup>  mMonsterGroups;
			[...]
				
Pour l'instant les groupes contiennent seulement un type. On ajoutera d'autres paramètres plus tard.

Les outils

Il y a un nouvel outil drawMonster dans "tools.h"

		class drawMonsterTool : public QUndoCommand
		{
		public:
			explicit drawMonsterTool(QUndoCommand *parent = 0);

			bool init(CVec2 pos, int type);
			void undo() override;
			void redo() override;

		private:
			CVec2       mPos;
			int         mType;
			CMonsterGroup   mOldMonster;
		};
				
Cet outil est un peu un mélange entre les outils drawTile et addObject.

		drawMonsterTool::drawMonsterTool(QUndoCommand *parent)
			: QUndoCommand(parent)
		{
		}

		bool drawMonsterTool::init(CVec2 pos, int type)
		{
			mPos = pos / TILE_SIZE;

			if (mPos.x < 0 || mPos.x >= map.mSize.x ||
				mPos.y < 0 || mPos.y >= map.mSize.y)
				return false;

			CMonsterGroup*  group = map.findMonsterGroup(mPos);
			if (group != NULL)
				mOldMonster = *group;
			else
				mOldMonster.setType(0);

			if (mOldMonster.getType() == type)
				return false;

			mType = type;
			return true;
		}

		void drawMonsterTool::undo()
		{
			if (mOldMonster.getType() == 0)
			{
				map.removeMonsterGroup(mPos);
			}
			else
			{
				CMonsterGroup*  group = map.addMonsterGroup(mPos);
				*group = mOldMonster;
			}
			bridge.updateQMLImage();
		}

		void drawMonsterTool::redo()
		{
			CMonsterGroup*  group = map.addMonsterGroup(mPos);
			group->setType(mType);
			bridge.updateQMLImage();
		}
				
Les outils couper/copier/coller nécessitaient des modifications aussi.
Tout comme le dessin des rectangles de sélection.

Comme je l'ai dit plus tôt, les groupes de monstres dans cette version de l'éditeur contiennent seulement un type.
On devra leur ajouter d'autres paramètre, comme le nombre de monstres dans le groupe.
Donc cette version de l'éditeur est seulement temporaire, et je n'ai pas converti les maps au nouveau format.
On continuera ça dans la prochaine partie.