00001
00002
00003
00004
00005
00006
00007
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
00067
00068 void
00069 WorldMap::prepareBg()
00070 {
00071
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
00087
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
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
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
00150
00151 void
00152 WorldMap::own_cleanState()
00153 {
00154 SoundAgent::agent()->stopMusic();
00155 }
00156
00157
00158
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
00181
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
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
00242
00243
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
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