Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

WorldMap.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004 Ivo Danihelka (ivo@danihelka.net)
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  */
00009 #include "WorldMap.h"
00010 
00011 #include "LevelNode.h"
00012 #include "NodeDrawer.h"
00013 #include "LevelStatus.h"
00014 #include "ResImagePack.h"
00015 #include "StateManager.h"
00016 #include "WorldInput.h"
00017 
00018 #include "Log.h"
00019 #include "Path.h"
00020 #include "WorldBranch.h"
00021 #include "OptionAgent.h"
00022 #include "VideoAgent.h"
00023 #include "SoundAgent.h"
00024 #include "LogicException.h"
00025 #include "ResDialogPack.h"
00026 #include "LevelDesc.h"
00027 #include "Level.h"
00028 #include "Pedometer.h"
00029 #include "LayeredPicture.h"
00030 #include "MenuOptions.h"
00031 #include "DemoMode.h"
00032 #include "PosterScroller.h"
00033 
00034 //-----------------------------------------------------------------
00035 WorldMap::WorldMap()
00036 {
00037     m_selected = NULL;
00038     m_startNode = NULL;
00039     m_ending = NULL;
00040     prepareBg();
00041 
00042     m_drawer = new NodeDrawer();
00043     m_descPack = new ResDialogPack();
00044     m_levelStatus = new LevelStatus();
00045     takeHandler(new WorldInput(this));
00046     registerDrawable(m_bg);
00047     registerDrawable(this);
00048 }
00049 //-----------------------------------------------------------------
00050 WorldMap::~WorldMap()
00051 {
00052     if (m_startNode) {
00053         delete m_startNode;
00054     }
00055     if (m_ending) {
00056         delete m_ending;
00057     }
00058     delete m_bg;
00059     m_descPack->removeAll();
00060     delete m_descPack;
00061     delete m_drawer;
00062     delete m_levelStatus;
00063 }
00064 //-----------------------------------------------------------------
00065 /**
00066  * Prepare background with buttons.
00067  */
00068     void
00069 WorldMap::prepareBg()
00070 {
00071     //TODO: allow to set differect images
00072     m_bg = new LayeredPicture(
00073             Path::dataReadPath("images/menu/map.png"),
00074             V2(0, 0),
00075             Path::dataReadPath("images/menu/map_lower.png"),
00076             Path::dataReadPath("images/menu/map_mask.png"));
00077 
00078     m_maskIntro = m_bg->getMaskAt(V2(0, 0));
00079     m_maskExit = m_bg->getMaskAt(V2(m_bg->getW() - 1, 0));
00080     m_maskCredits = m_bg->getMaskAt(V2(0, m_bg->getH() - 1));
00081     m_maskOptions = m_bg->getMaskAt(V2(m_bg->getW() - 1, m_bg->getH() - 1));
00082     m_activeMask = m_bg->getNoMask();
00083 }
00084 //-----------------------------------------------------------------
00085 /**
00086  * Read dots postions and level descriptions.
00087  * @throws LogicException when cannot parse data file
00088  */
00089     void
00090 WorldMap::initMap(const Path &mapfile)
00091 {
00092     WorldBranch parser(NULL);
00093     m_startNode = parser.parseMap(mapfile, &m_ending, m_descPack);
00094     if (NULL == m_startNode) {
00095         throw LogicException(ExInfo("cannot create world map")
00096                 .addInfo("file", mapfile.getNative()));
00097     }
00098 }
00099 //-----------------------------------------------------------------
00100 /**
00101  * Display menu and play menu music.
00102  */
00103     void
00104 WorldMap::own_initState()
00105 {
00106     m_levelStatus->setRunning(true);
00107     own_resumeState();
00108 }
00109 //-----------------------------------------------------------------
00110     void
00111 WorldMap::own_updateState()
00112 {
00113     if (m_ending && m_selected == m_ending) {
00114         runSelected();
00115     }
00116     else {
00117         watchCursor();
00118     }
00119 }
00120 //-----------------------------------------------------------------
00121 /**
00122  * Display menu and play menu music.
00123  */
00124     void
00125 WorldMap::own_resumeState()
00126 {
00127     if (m_levelStatus->wasRunning()) {
00128         LevelNode *nextLevel = NULL;
00129         if (m_levelStatus->isComplete()) {
00130             markSolved();
00131             if (checkEnding()) {
00132                 nextLevel = m_ending;
00133             }
00134         }
00135         m_selected = nextLevel;
00136         m_levelStatus->setRunning(false);
00137 
00138         SoundAgent::agent()->playMusic(
00139                 Path::dataReadPath("music/menu.ogg"), NULL);
00140         OptionAgent *options = OptionAgent::agent();
00141         options->setParam("caption", findDesc("menu"));
00142         options->setParam("screen_width", m_bg->getW());
00143         options->setParam("screen_height", m_bg->getH());
00144         VideoAgent::agent()->initVideoMode();
00145     }
00146 }
00147 //-----------------------------------------------------------------
00148 /**
00149  * Stop music.
00150  */
00151     void
00152 WorldMap::own_cleanState()
00153 {
00154     SoundAgent::agent()->stopMusic();
00155 }
00156 //-----------------------------------------------------------------
00157 /**
00158  * Mark node or mask under cursor as selected.
00159  */
00160     void
00161 WorldMap::watchCursor()
00162 {
00163     V2 mouseLoc = getInput()->getMouseLoc();
00164     m_selected = m_startNode->findSelected(mouseLoc);
00165 
00166     m_activeMask = m_bg->getMaskAtWorld(mouseLoc);
00167     if (m_activeMask == m_maskIntro
00168             || m_activeMask == m_maskExit
00169             || m_activeMask == m_maskCredits
00170             || m_activeMask == m_maskOptions)
00171     {
00172         m_bg->setActiveMask(m_activeMask);
00173     }
00174     else {
00175         m_bg->setNoActive();
00176     }
00177 }
00178 //-----------------------------------------------------------------
00179 /**
00180  * Start level under pressed button.
00181  * Start pedometer when level is solved already.
00182  */
00183     void
00184 WorldMap::runSelected()
00185 {
00186     Level *level = createSelected();
00187     if (level && m_selected) {
00188         m_levelStatus->prepareRun(m_selected->getCodename(),
00189                 m_selected->getPoster(),
00190                 m_selected->getBestMoves(),
00191                 m_selected->getBestAuthor());
00192         level->fillStatus(m_levelStatus);
00193 
00194         if (m_selected->getState() == LevelNode::STATE_SOLVED) {
00195             Pedometer *pedometer = new Pedometer(m_levelStatus, level);
00196             pushState(pedometer);
00197         }
00198         else {
00199             pushState(level);
00200         }
00201     }
00202     else {
00203         if (m_activeMask == m_maskIntro) {
00204             runIntro();
00205         }
00206         else if (m_activeMask == m_maskExit) {
00207             quitState();
00208         }
00209         else if (m_activeMask == m_maskCredits) {
00210             runCredits();
00211         }
00212         else if (m_activeMask == m_maskOptions) {
00213             runOptions();
00214         }
00215     }
00216 }
00217 //-----------------------------------------------------------------
00218 /**
00219  * Return selected level or NULL.
00220  */
00221 Level *
00222 WorldMap::createSelected() const
00223 {
00224     Level *result = NULL;
00225     if (m_selected) {
00226         result = m_selected->createLevel();
00227         result->fillDesc(this);
00228     }
00229     return result;
00230 }
00231 //-----------------------------------------------------------------
00232     void
00233 WorldMap::markSolved()
00234 {
00235     if (m_selected) {
00236         m_selected->setState(LevelNode::STATE_SOLVED);
00237     }
00238 }
00239 //-----------------------------------------------------------------
00240 /**
00241  * Try run ending node.
00242  * Ending node is started when all levels were solved.
00243  * @return true when ending is started
00244  */
00245     bool
00246 WorldMap::checkEnding() const
00247 {
00248     bool result = false;
00249     if (m_ending && m_selected != m_ending) {
00250         if (m_selected->isLeaf()) {
00251             if (m_startNode->areAllSolved()) {
00252                 result = true;
00253             }
00254         }
00255     }
00256     return result;
00257 }
00258 //-----------------------------------------------------------------
00259     void
00260 WorldMap::drawOn(SDL_Surface *screen)
00261 {
00262     m_drawer->setScreen(screen);
00263     m_startNode->drawPath(m_drawer);
00264     if (m_selected) {
00265         m_drawer->drawSelected(findLevelName(m_selected->getCodename()));
00266     }
00267 }
00268 //-----------------------------------------------------------------
00269 std::string
00270 WorldMap::findLevelName(const std::string &codename) const
00271 {
00272     std::string result;
00273     const LevelDesc *desc =
00274         dynamic_cast<const LevelDesc*>(m_descPack->findDialogHard(codename));
00275     if (desc) {
00276         result = desc->getLevelName();
00277     }
00278     else {
00279         result = codename;
00280     }
00281     return result;
00282 }
00283 //-----------------------------------------------------------------
00284 std::string
00285 WorldMap::findDesc(const std::string &codename) const
00286 {
00287     std::string result;
00288     const LevelDesc *desc =
00289         dynamic_cast<const LevelDesc*>(m_descPack->findDialogHard(codename));
00290     if (desc) {
00291         result = desc->getDesc();
00292     }
00293     else {
00294         result = "???";
00295     }
00296     return result;
00297 }
00298 //-----------------------------------------------------------------
00299     void
00300 WorldMap::runIntro()
00301 {
00302     //TODO: intro as video
00303     pushState(new DemoMode(Path::dataReadPath("script/share/demo_intro.lua")));
00304 }
00305 //-----------------------------------------------------------------
00306     void
00307 WorldMap::runCredits()
00308 {
00309     pushState(new PosterScroller(
00310                 Path::dataReadPath("images/menu/credits.png")));
00311 }
00312 //-----------------------------------------------------------------
00313     void
00314 WorldMap::runOptions()
00315 {
00316     MenuOptions *options = new MenuOptions();
00317     pushState(options);
00318 }
00319 

Generated on Wed Jun 1 09:54:32 2005 for Fish Fillets - Next Generation by  doxygen 1.4.2