Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "game.h"
- #include "..\SDL2_Sources\graphics.h"
- #include <ctime>
- #include "menu.h"
- #include "..\SDL2_Sources\text.h"
- #include "audio.h"
- Graphics ui;
- Audio g_sound;
- std::vector <CPoke*> m_gameMonsters;
- int g_graphicChoice;
- int currentMap = -1;
- vector2 previousPos = {0,0};
- //Dans un premier temps on créé notre classe jeu qui contiendra tout ce qui est nécessaire à la partie et les méthodes principales
- //Veuillez lire les commentaires dans l'ordre car l'explication suit le cours de la page
- CGame::CGame()
- {
- //Initialisation du personnage du joueur
- m_player = new CTrainer("Pseudo");
- //On load tous les monstres possibles dans le jeu pour pouvoir en faire des copies lorsqu'on assigne les pokemons
- m_worldMonsters = new CParsingMonsters("monsters.pkmn");
- //Par défaut on commence sur la map donc on n'est pas en mode combat
- m_isFightMode = false;
- //On set la map de départ
- m_currentMap[0] = "bourg-palette.png";
- m_currentMap[1] = "bourg-palette-filter.png";
- //Non utilisé, fait en prévision d'une upgrade qui permettrait de sauvegarder une partie
- //Ici on chargerait la partie
- m_player->loadBackup("save.txt");
- //Ajout de trois pokemons au player
- m_player->addPoke(m_worldMonsters->getRandPoke(), m_gameMonsters);
- m_player->addPoke(m_worldMonsters->getRandPoke(), m_gameMonsters);
- m_player->addPoke(m_worldMonsters->getRandPoke(), m_gameMonsters);
- //On ajoute trois objets au player
- m_player->addObject(new CPotion("Potion", LIFEUP10));
- m_player->addObject(new CPotion("Super Potion", REGEN100));
- m_player->addObject(new CDrug("Burn Heal", BURNHEAL));
- //Ajout des sons qui pourrons nous servir plus tard
- g_sound.addSound("victory.mp3");
- g_sound.setChannelVolume(0.5, 0);
- g_sound.addSound("normaldamage.mp3");
- g_sound.setChannelVolume(0.5, 1);
- g_sound.addSound("potion_heal.mp3");
- g_sound.setChannelVolume(0.5, 2);
- g_sound.addSound("clicksound.mp3");
- g_sound.setChannelVolume(0.5, 3);
- }
- //Destructeur de la classe jeu
- CGame::~CGame()
- {
- if (m_fightScene)
- delete m_fightScene;
- ui.flushMedia();
- if (m_map)
- delete m_map;
- if (m_player)
- delete m_player;
- if (m_worldCapabilities)
- delete m_worldCapabilities;
- if (m_worldMonsters)
- delete m_worldMonsters;
- }
- //Le jeu commence lorsqu'on utilise la méthode On.
- //Une fois cette méthode lancée, les fonctions s'auto-appelent et nous n'avons plus rien à lancer manuellement depuis le main.
- void CGame::on()
- {
- //Initialisation des graphismes et donc de la classe "ui" pour interface utilisateur
- //Tout ce qui s'affiche à l'écran est géré par cette classe (images, sprites etc regroupés sous le nom de media)
- ui.initGraphics(640, 500, "Pokeschtroumpf", false);
- //Une fois la base du jeu créée et la SDL prête à l'emploi on peut faire le rendu du jeu
- render();
- return;
- }
- void CGame::render()
- {
- //Pour faire le rendu du jeu on lance le mode aventure
- setMapMode();
- //On entre ensuite dans le jeu à proprement parler
- //On ne sortira plus de cette boucle infinie tant que l'utilisateur ne quitte pas le programme
- while (1)
- {
- //A chaque tour on commence par récupérer les événements utilisateur et faire tourner le jeu
- if (!pollEvents())
- break;
- //Ensuite l'interface utilisateur met à jour les éléments à afficher...
- ui.renderContext();
- //...Et les affiche
- ui.updateRender();
- //Enfin on laisse resprirer le CPU
- SDL_Delay(50);
- }
- }
- //Comme expliqué plus haut la fonction pollEvents gère le jeu
- //Lorsque c'est le tour de l'utilisateur polEvents questionnera l'utilisateur sur son choix d'action
- bool CGame::pollEvents()
- {
- /*
- * Lorsque l'on est en mode map (mode aventure) on va directement aller chercher les touches utilisateurs
- * Lorsque l'on est en mode combat (m_isFightMode == true) on va cependant commencer par voir si on a du texte à aficher
- * En effet, il se peut que selon la modalité du lancement du combat on affiche quelque chose à l'écran avant même que le combat
- * à proprement parler commence (dire à l'utilisateur qu'il vient d'être attaqué etc afin qu'il comprenne ce qui lui arrive)
- * Ci-dessous on voit donc deux conditions :
- * -Soit l'utilisateur va jouer après et donc on affiche du texte et on quitte pour lui demander son choix d'action
- * -Soit c'est au tour de l'adversaire et donc on affiche les infos et on le fait jouer.
- */
- if ((m_step == 0) && m_isFightMode && (!m_fightScene->isPlayerTurn()))/*< Si c'est au tour de l'adversaire*/
- {
- if (m_fightScene->getInfoBufferSize() > 0)/*<Je regarde si le buffer de texte contient quelque chose à afficher*/
- {
- m_fightScene->loadNextInfo();
- m_fightScene->showInfo();
- clock_t endwait;
- endwait = clock() + 1 * CLOCKS_PER_SEC;
- while (clock() < endwait) {}
- return 1;
- }
- //Ci-dessous nosu voyons que l'on choisit l'action de l'ennemi
- //Par manque de temps nous l'avons simplement programmé pour qu'il attaque
- m_fightScene->setMode(attack_select);
- //On configure l'animation à effectuer en fonction de son action, ici l'attaque
- m_fightScene->setAnimToRun(animPokeAttack);
- //On le fait directement passer à l'étape d'animation avant le calcul des dommages etc
- m_step = 2;
- }
- else{
- if ((m_isFightMode == true) && (m_fightScene->getMode() == main_menu))/*< Si c'est mon tour*/
- {
- if (m_fightScene->getInfoBufferSize() > 0)/*<Je regarde si le buffer de texte contient quelque chose à afficher*/
- {
- m_fightScene->loadNextInfo();
- m_fightScene->showInfo();
- clock_t endwait;
- endwait = clock() + 1 * CLOCKS_PER_SEC;
- while (clock() < endwait) {}
- return 1;/*< Une fois les informations affichées, je quitte*/
- }
- }
- /*
- * Maintenant si l'on vient de quitter la partie affichage et que l'on est joueur on va atterir ici
- * Cette partie n'est pas accessible à l'"IA" car elle aura directement été redirigée à l'étape (step) 2
- */
- /* Si le suis à l'étape 0 et donc que je n'ai pas fait de choix, j'entre un choix par l'appui sur une touche*/
- while ((m_step == 0) && (SDL_PollEvent(ui.getEvent())))
- {
- switch (ui.getEvent()->type)
- {
- case SDL_QUIT:
- return false;
- break;
- case SDL_KEYDOWN:
- if (m_isFightMode == true)
- {
- //On revérifie que c'est bien au joueur de jouer au cas où
- if (m_fightScene->isPlayerTurn())
- fightKeyDown();
- }
- else
- mapKeyDown();
- break;
- }
- }
- }
- if (m_step == 1)/*Si j'ai sélectionné un choix : on commence par changer de menu/l'affichage selon le contexte*/
- {
- switch (m_fightScene->getMode())
- {
- //Si on est dans un choix du menu principal (attaquer/changer pokemon..)
- //On affiche le prochain sous-menu (liste des attaques/obj/pokemons) et on redemande un choix
- case main_menu:
- m_fightScene->flushInfo(); //Les informations sont affichées que lorsqu'on est dans le menu principal (main_menu)
- switch (g_graphicChoice)
- {
- case 0:
- m_fightScene->setMode(attack_select);
- m_fightScene->setAtkMenu();
- break;
- case 1:
- m_fightScene->setMode(object_select);
- m_fightScene->setObjectMenu();
- break;
- case 2:
- m_fightScene->setMode(poke_select);
- m_fightScene->setPokeMenu();
- break;
- case 3:
- //Le cas 3 correspond, dans le mode combat, au cas où l'on fuit le combat
- if (currentMap == 4)//Si nous étions dans la map de combat sauvage (on a été attaqué ), on peut quitter
- {
- //Lorsque l'on affiche
- m_fightScene->printInfo("You run away...");
- setMapMode();
- }
- else
- {
- //Si nous étions dans un combat de dresseur nous ne pouvons pas quitter
- m_fightScene->printInfo("You can't run away");
- m_fightScene->printInfo("of a trainer fight !");
- }
- break;
- }
- //On remet le choix à -1 pour que l'utilisateur refasse un choix
- g_graphicChoice = -1;
- //On retourne au choix d'une action (step 0)
- m_step = 0;
- break;
- //Si l'on est dans un des sous-menu on valide l'action et on ré affiche le menu principal pendant le temps de l'animation
- //Qui correspond à notre choix
- //On passe donc à l'étape suivante : animation
- case attack_select:
- m_fightScene->setMainMenu();
- m_step++;
- break;
- case poke_select:
- m_fightScene->setMainMenu();
- m_step++;
- break;
- case object_select:
- m_fightScene->setMainMenu();
- m_step++;
- break;
- }
- }
- //on applique l'animation correspondante à l'action (ex: attaque d'un pokemon)
- else if(m_step == 2)
- {
- if (m_fightScene->isPlayerTurn())
- {
- //tant que l'animation n'est pas terminée on ne passe pas à la step suivante
- //Il vaut mieux passer à la phase de calcul après l'animation pour que les stats changent après que l'action ai lieu
- //du point de vue utilisateur
- if (animation(true) == false)
- {
- m_step++;//L'animation est terminée on va donc pouvoir passer à la phase de calcul des dégâts
- }
- }
- else
- {
- //tant que l'animation n'est pas terminée on ne passe pas à la step suivante
- if (animation(false) == false)
- {
- m_step++;
- }
- }
- }
- else if(m_step == 3)//On fait les calculs relatifs à l'action (mise à jour des HP etc)
- {
- switch (m_fightScene->getMode())
- {
- case attack_select:
- if (m_fightScene->isPlayerTurn())
- m_fightScene->attackSelected(g_graphicChoice, false);
- else
- m_fightScene->attackSelected(rand() % m_fightScene->getPoke(1)->getCapabilitiesList()->size(), true);
- g_sound.playChannel(1, 0);
- break;
- case poke_select:
- m_fightScene->pokeSelected(g_graphicChoice);
- break;
- case object_select:
- if (m_fightScene->isPlayerTurn())
- {
- m_fightScene->objectSelected(true, g_graphicChoice);
- g_sound.playChannel(2, 0);
- }
- else
- m_fightScene->objectSelected(false, g_graphicChoice);
- break;
- }
- //Une fois les calculs faits, on s'assure à nouveau que le choix est bien réinitialisé en prévision du prochain choix
- g_graphicChoice = -1;
- //Mise à jour des points de vie à l'écran
- m_fightScene->updateLifeBars();
- m_fightScene->updatePlayerHp();
- //On test si le jeu est terminé
- if (m_fightScene->GameOver())
- {
- if (m_fightScene->getPoke(0)->getStats().m_lifePts <= 0)
- m_fightScene->printInfo("You lose...");
- else if (m_fightScene->getPoke(1)->getStats().m_lifePts <= 0)
- {
- g_sound.playChannel(0, 0);
- m_fightScene->printInfo("Player win !");
- }
- m_fightScene->setMode(main_menu);
- m_step++;
- }
- else
- {
- //Si le jeu n'est pas terminé on retourne au menu principal en mode "pas de choix sélectionné"
- m_fightScene->setMode(main_menu);
- m_step = 0;
- }
- }
- //La dernière étape est seulement utile lorsque le jeu est terminé
- //Il s'agit de remettre les stats en ordre et remettre les objets utilisés à l'utilisateur
- else if (m_step == 4)
- {
- if (m_player->getObjListPtr()->size() < 3)
- {
- m_player->getObjListPtr()->clear();
- m_player->addObject(new CPotion("Potion", LIFEUP10));
- m_player->addObject(new CPotion("Super Potion", REGEN100));
- m_player->addObject(new CDrug("Burn Heal", BURNHEAL));
- }
- m_fightScene->resetStats();
- //On change de mode on se remet en mode aventure
- setMapMode();
- //On retourne en mode "pas de choix" ce qui permettra d'accéder à nouveau aux entrées utilisateur pour le déplacement du personnage
- m_step = 0;
- }
- return 1;
- }
- void CGame::mapKeyDown()
- {
- int i = 0;
- if (m_player)
- {
- switch (ui.getKey())
- {
- case SDLK_ESCAPE:
- break;
- case SDLK_DOWN:
- //On change la direction
- m_player->getSprite()->dir(0);
- //On fait avancer le personnage
- m_player->getSprite()->run();
- //on check si le personnage est dans une zone autorisée
- i = m_map->checkFilter(m_player->getSprite()->getRect2());
- if (i == -1) //i correspond à l'entrée dans une zone de téléportation. Il s'agit en fait de l'index d'une zone de téléportation.
- m_player->getSprite()->restoreBackup(); //Si ce n'est pas le cas on rétablit les anciennes coordonnées
- break;
- case SDLK_UP:
- m_player->getSprite()->dir(3);
- m_player->getSprite()->run();
- i = m_map->checkFilter(m_player->getSprite()->getRect2());
- if (i == -1)
- m_player->getSprite()->restoreBackup();
- break;
- case SDLK_RIGHT:
- m_player->getSprite()->dir(2);
- m_player->getSprite()->run();
- i = m_map->checkFilter(m_player->getSprite()->getRect2());
- if (i == -1)
- m_player->getSprite()->restoreBackup();
- break;
- case SDLK_LEFT:
- m_player->getSprite()->dir(1);
- m_player->getSprite()->run();
- i = m_map->checkFilter(m_player->getSprite()->getRect2());
- if (i == -1)
- m_player->getSprite()->restoreBackup();
- break;
- }
- if (i>=1)
- {
- //Si il y a téléportation on change de map
- switchMap(i);
- }
- }
- if (currentMap == 4)
- {
- //Si on se trouve dans la map "sauvage" il y a une probabilité, à chaque pas, d'être attéqué par un pokemon sauvage
- if (rand() % 100 > 98)
- {
- //Si on est attaqué on sauvegarde les coordonnées du personnage pour le remettre à sa place après le combat
- previousPos.x = m_player->getSprite()->getRect2().x;
- previousPos.y = m_player->getSprite()->getRect2().y;
- //On passe en mode combat
- //le paramètre false établit que le combat ne se passe pas contre un dresseur mais contre un pokemon sauvage
- setFightMode(false);
- }
- }
- }
- void CGame::switchMap(int p_i)
- {
- if (currentMap == 0)
- {
- switch (p_i)
- {
- case 1:
- if (m_map)
- delete m_map;
- //Pour chaque map on charge à la fois l'image de fond et le filtre pour la détection de collisions
- m_map = new CMap("bourg-palette-house2.png", "bourg-palette-house2-filter.png", &ui);
- m_map->setGraphics(ui, m_player, { 251, 300 });
- //On place le personnage dans la bonne direction lors de son arrivée sur la map
- m_player->getSprite()->dir(3);
- currentMap = 1;
- break;
- case 2:
- if (m_map)
- delete m_map;
- m_map = new CMap("bourg-palette-house.png", "bourg-palette-house-filter.png", &ui);
- m_map->setGraphics(ui, m_player, { 254, 300 });
- m_player->getSprite()->dir(3);
- currentMap = 2;
- break;
- case 3://lab
- if (m_map)
- delete m_map;
- m_map = new CMap("bourg-palette-lab.png", "bourg-palette-lab-filter.png", &ui);
- m_map->setGraphics(ui, m_player, { 306, 318 });
- m_player->getSprite()->dir(3);
- currentMap = 3;
- break;
- case 4://route
- if (m_map)
- delete m_map;
- m_map = new CMap("route01.png", "route01-filter.png", &ui);
- m_map->setGraphics(ui, m_player, { 345, 445 });
- m_player->getSprite()->dir(3);
- currentMap = 4;
- break;
- }
- }
- else
- {
- switch (p_i)
- {
- case 5:
- if (currentMap == 1)
- {
- if (m_map)
- delete m_map;
- m_map = new CMap("bourg-palette.png", "bourg-palette-filter.png", &ui);
- m_map->setGraphics(ui, m_player, { 173, 213 });
- currentMap = 0;
- }
- break;
- case 6:
- if (currentMap == 2)
- {
- if (m_map)
- delete m_map;
- m_map = new CMap("bourg-palette.png", "bourg-palette-filter.png", &ui);
- m_map->setGraphics(ui, m_player, { 413, 200 });
- currentMap = 0;
- }
- break;
- case 7:
- if (currentMap == 3)
- {
- if (m_map)
- delete m_map;
- m_map = new CMap("bourg-palette.png", "bourg-palette-filter.png", &ui);
- m_map->setGraphics(ui, m_player, { 439, 365 });
- currentMap = 0;
- }
- break;
- case 8:
- if (currentMap == 4)
- {
- if (m_map)
- delete m_map;
- m_map = new CMap("bourg-palette.png", "bourg-palette-filter.png", &ui);
- m_map->setGraphics(ui, m_player, { 348, 59 });
- currentMap = 0;
- }
- break;
- case 9:
- if (currentMap == 3)
- {
- previousPos.x = m_player->getSprite()->getRect2().x;
- previousPos.y = m_player->getSprite()->getRect2().y +20;
- setFightMode(true);
- }
- break;
- }
- }
- //On afiche la nouvelle map chargée
- m_map->show();
- }
- void CGame::fightKeyDown()
- {
- switch (ui.getKey())
- {
- case SDLK_RETURN:
- g_sound.playChannel(3, 0);
- if (m_fightScene->getMode() == attack_select)
- {
- //On récupère le choix correspondant au menu
- //En effet, la position du curseur est stockée dans le menu lui-même
- //Or lorsqu'on a fait un choix on repasse en menu principal avant calcul donc on perdrait l'information
- g_graphicChoice = m_fightScene->getMenu()->getGraphicChoice();
- int size = m_fightScene->getPoke(0)->getCapabilitiesList()->size();
- //On regarde si le choix n'est pas supérieur au nombre de possibilités d'ataques
- //Ici ce n'est pas notrecas mais c'est dans le cas où un pokemon n'aurait pas 4 capacités
- if (size - 1 < g_graphicChoice)
- return;
- //On regarde si l'attaque est disponible (assez de PP)
- if (!m_fightScene->getPoke(0)->getCapabilitiesList()->at(m_fightScene->getMenu()->getGraphicChoice()).isAvailable())
- return;
- m_fightScene->setAnimToRun(animPokeAttack);
- }
- //Dans le cas où on choisit un pokemon on ne peut pas choisir le pokemon en cours
- //(echap pour revenir au menu principal)
- //C'est pourquoi on affiche à partir de la position 1 et non 0 dans le buffer de pokemons
- //A chaque changement de pokmeon le pokemon en cours est mis à la position 0 dans le buffer
- else if (m_fightScene->getMode() == poke_select)
- g_graphicChoice = m_fightScene->getMenu()->getGraphicChoice() + 1;
- else
- g_graphicChoice = m_fightScene->getMenu()->getGraphicChoice();
- m_step = 1;
- break;
- case SDLK_DOWN:
- g_sound.playChannel(3, 0);
- if (m_fightScene->getMode() == poke_select)
- m_fightScene->getMenu()->cursorMoveList(down, m_fightScene->getPlayerBuffer().size()-1, true);
- else if(m_fightScene->getMode() == object_select)
- m_fightScene->getMenu()->cursorMoveList(down, m_fightScene->getNbObjAvailable()-1, false);
- else
- m_fightScene->getMenu()->cursorMoveQuad(down);
- if (m_fightScene->getMode() == attack_select)
- m_fightScene->printCurrentCapStats(m_fightScene->getMenu()->getGraphicChoice());
- break;
- case SDLK_UP:
- g_sound.playChannel(3, 0);
- if (m_fightScene->getMode() == poke_select)
- m_fightScene->getMenu()->cursorMoveList(up, m_fightScene->getPlayerBuffer().size() - 1, true);
- else if (m_fightScene->getMode() == object_select)
- m_fightScene->getMenu()->cursorMoveList(up, m_fightScene->getNbObjAvailable()-1, false);
- else
- m_fightScene->getMenu()->cursorMoveQuad(up);
- if (m_fightScene->getMode() == attack_select)
- m_fightScene->printCurrentCapStats(m_fightScene->getMenu()->getGraphicChoice());
- break;
- case SDLK_RIGHT:
- g_sound.playChannel(3, 0);
- if (m_fightScene->getMode() == poke_select)
- break;
- else
- m_fightScene->getMenu()->cursorMoveQuad(right);
- if (m_fightScene->getMode() == attack_select)
- m_fightScene->printCurrentCapStats(m_fightScene->getMenu()->getGraphicChoice());
- break;
- case SDLK_LEFT:
- g_sound.playChannel(3, 0);
- if (m_fightScene->getMode() == poke_select)
- break;
- else
- m_fightScene->getMenu()->cursorMoveQuad(left);
- if (m_fightScene->getMode() == attack_select)
- m_fightScene->printCurrentCapStats(m_fightScene->getMenu()->getGraphicChoice());
- break;
- case SDLK_ESCAPE:
- g_sound.playChannel(3, 0);
- if (m_fightScene->getMode() != main_menu)
- {
- m_fightScene->setMainMenu();
- m_fightScene->setMode(main_menu);
- }
- break;
- }
- if (m_isFightMode == false)
- setMapMode();
- }
- //Fonction qui permet le passage en mode combat
- void CGame::setFightMode(bool p_isTrainer)
- {
- m_isFightMode = true;
- //On commence par supprimer tous les graphiques en cours
- ui.flushMedia();
- //On créé l'adversaire dans le cas où c'est un combat contre dresseur
- //On lui assigne aléatoirement trois pokemons
- CTrainer * trainerSpark = new CTrainer("Spark");
- trainerSpark->addPoke(m_worldMonsters->getRandPoke(), m_gameMonsters);
- trainerSpark->addPoke(m_worldMonsters->getRandPoke(), m_gameMonsters);
- trainerSpark->addPoke(m_worldMonsters->getRandPoke(), m_gameMonsters);
- if (!p_isTrainer)
- {
- m_fightScene = new CFight(m_player, m_worldMonsters->getRandPoke(), ui);
- m_fightScene->setGraphics(false);
- }
- else
- {
- m_fightScene = new CFight(m_player, trainerSpark, ui);
- m_fightScene->setGraphics(true);
- }
- //On lance la musique du combat
- g_sound.switchMainMusic("battle.mp3", 0.5);
- g_sound.playMainMusic();
- m_fightScene->enemyBegin();
- }
- void CGame::setMapMode()
- {
- m_isFightMode = false;
- delete m_fightScene;
- //We begin with flushing all previous medias
- ui.flushMedia();
- switch (currentMap)
- {
- //Dans les cas ou currentMap vaut 3 ou 4 c'est qu'on sort du mode combat
- //On remet donc les bonnes map où a commencé le combat et on replace le player au bon endroit
- case 3:
- if (m_map)
- delete m_map;
- m_map = new CMap("bourg-palette-lab.png", "bourg-palette-lab-filter.png", &ui);
- m_map->setGraphics(ui, m_player, previousPos);
- break;
- case 4:
- if (m_map)
- delete m_map;
- m_map = new CMap("route01.png", "route01-filter.png", &ui);
- m_map->setGraphics(ui, m_player, previousPos);
- break;
- default://Par défaut on met la map principale
- currentMap = 0;
- m_map = new CMap(m_currentMap[0], m_currentMap[1], &ui);
- m_map->setGraphics(ui, m_player, { 230, 220 });
- break;
- }
- //On affiche la map
- m_map->show();
- //On change de musique
- g_sound.switchMainMusic("map.mp3", 0.5);
- g_sound.playMainMusic();
- }
- bool CGame::animation(bool isPlayer)
- {
- if (m_fightScene)
- if (m_fightScene->isInAnimState())
- {
- if (isPlayer == true)
- m_fightScene->runAnim(true);
- else
- m_fightScene->runAnim(false);
- }
- else
- return false;
- return true;
- }
- CTrainer* CGame::getTrainer(){ return m_player; }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement