//----------------------------------------------------------------- int main(int argc, char *argv[]) { try { Application app; try { app.init(argc, argv); app.run(); } catch (HelpException &e) { printf("%s\n", e.what()); } catch (BaseException &e) { LOG_ERROR(e.info()); } app.shutdown(); return 0; } catch (BaseException &e) { LOG_ERROR(e.info()); } catch (std::exception &e) { LOG_ERROR(ExInfo("std::exception") .addInfo("what", e.what())); } catch (...) { LOG_ERROR(ExInfo("unknown exception")); } return 1; }
/** * Reinit the sound subsystem. */ void SDLSoundAgent::reinit() { m_music = NULL; m_looper = NULL; m_soundVolume = MIX_MAX_VOLUME; m_musicVolume = MIX_MAX_VOLUME; if(SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) { throw SDLException(ExInfo("SDL_InitSubSystem")); } SDL_AudioSpec spec, have; spec.freq =48000; spec.format=AUDIO_S16SYS; spec.channels = 2; spec.samples=4096; spec.callback = 0; SDL_OpenAudio(&spec, &have); Mix_Init(MIX_INIT_FLAC | MIX_INIT_MOD | MIX_INIT_MP3 | MIX_INIT_OGG); int frequency = OptionAgent::agent()->getAsInt("sound_frequency", 44100); if(Mix_OpenAudio(frequency, MIX_DEFAULT_FORMAT, 2, 1024) < 0) { throw MixException(ExInfo("Mix_OpenAudio")); } Mix_AllocateChannels(16); SoundAgent::reinit(); }
/** * Break long string. * String is trimed at ' ' * but not at " . " (single char surrounded with spaces). * * @param buffer buffer to change */ void SubTitleAgent::trimRest(std::string &buffer) { int i; for (i = buffer.size() - 1; i >= 0; --i) { if (buffer[i] == ' ' && !(i - 2 >= 0 && buffer[i - 2] == ' ')) { break; } } if (i <= 0) { LOG_WARNING(ExInfo("unbreakable string") .addInfo("string", buffer)); if (buffer.size() > 4) { buffer.erase(buffer.size() - 4); } else { buffer = ""; } } else { buffer.erase(i); } }
/** * Create one way output out of room. * @throws LogicException when output_DIR is not known */ Cube * ModelFactory::createOutputItem(const std::string &kind, const V2 &loc, const std::string &shape) { Dir::eDir outDir = Dir::DIR_NO; if ("output_left" == kind) { outDir = Dir::DIR_LEFT; } else if ("output_right" == kind) { outDir = Dir::DIR_RIGHT; } else if ("output_up" == kind) { outDir = Dir::DIR_UP; } else if ("output_down" == kind) { outDir = Dir::DIR_DOWN; } else { throw LogicException(ExInfo("unknown border dir") .addInfo("kind", kind)); } Cube *model = new Cube(loc, Cube::FIXED, Cube::NONE, false, new Shape(shape)); model->setOutDir(outDir); return model; }
//----------------------------------------------------------------- void GameState::noteFg() { LOG_DEBUG(ExInfo("noteFg").addInfo("name", getName())); m_onBg = false; own_noteFg(); }
/** * Play music. * @param file path to music file (i.e. *.ogg) * @param finished send this message when music is finished. * If finished is NULL, play music forever. */ void SDLSoundAgent::playMusic(const Path &file, BaseMsg *finished) { // The same music is not restarted when it is not needed. if (m_playingPath == file.getPosixName() && ms_finished == NULL && finished == NULL) { return; } stopMusic(); m_playingPath = file.getPosixName(); if (finished) { ms_finished = finished; m_music = Mix_LoadMUS(file.getNative().c_str()); if (m_music && (0 == Mix_PlayMusic(m_music, 1))) { Mix_HookMusicFinished(musicFinished); } else { LOG_WARNING(ExInfo("cannot play music") .addInfo("music", file.getNative()) .addInfo("Mix", Mix_GetError())); } } else { m_looper = new SDLMusicLooper(file); m_looper->setVolume(m_musicVolume); m_looper->start(); } }
/** * Load a few moves. * @throws LoadException for bad load */ void LevelLoading::nextLoadAction() { if (m_paused) { return; } if (m_loadedMoves.empty()) { m_access->room()->beginFall(false); m_access->room()->finishRound(false); } else { for (int i = 0; i < m_loadSpeed && !m_loadedMoves.empty(); ++i) { try { char symbol = m_loadedMoves[0]; m_loadedMoves.erase(0, 1); m_access->room()->loadMove(symbol); } catch (LoadException &e) { throw LoadException(ExInfo(e.info()) .addInfo("remain", m_loadedMoves)); } } } }
/** * Bind keystroke. * @param stroke keystroke * @param msg message to raise, will be deleted * @throws LogicException when keystroke is occupied */ void KeyBinder::addStroke(const KeyStroke &stroke, BaseMsg *msg) { std::pair<t_strokes::iterator,bool> status = m_strokes.insert( std::pair<KeyStroke,BaseMsg*>(stroke, msg)); if (!status.second) { throw LogicException(ExInfo("keystroke is occupied") .addInfo("keystroke", stroke.toString())); } else { LOG_DEBUG(ExInfo("binding keystroke") .addInfo("keystroke", stroke.toString()) .addInfo("msg", msg->toString())); } }
/** * Handle incoming message. * Messages: * - quit ... application quit * - inc_loglevel ... inc loglevel by 1 (max LEVEL_DEBUG) * - dec_loglevel ... dec loglevel by 1 (min LEVEL_ERROR) */ void Application::receiveSimple(const SimpleMsg *msg) { if (msg->equalsName("quit")) { m_quit = true; } else if (msg->equalsName("inc_loglevel")) { int level = Log::getLogLevel() + 1; if (level <= Log::LEVEL_DEBUG) { OptionAgent::agent()->setParam("loglevel", level); } } else if (msg->equalsName("dec_loglevel")) { int level = Log::getLogLevel() - 1; if (level >= Log::LEVEL_ERROR) { OptionAgent::agent()->setParam("loglevel", level); } } else if (msg->equalsName("flush_stdout")) { fflush(stdout); } else { LOG_WARNING(ExInfo("unknown msg") .addInfo("msg", msg->toString())); } }
//----------------------------------------------------------------- void BaseAgent::shutdown() { LOG_DEBUG(ExInfo("shutdown").addInfo("name", getName())); own_shutdown(); m_initialized = false; }
/** * Install own video and input handler. */ void GameState::installHandlers() { LOG_DEBUG(ExInfo("installHandlers").addInfo("state", getName())); InputAgent::agent()->installHandler(m_handler); VideoAgent::agent()->acceptDrawer(m_drawer); }
//----------------------------------------------------------------- void GameState::noteBg() { LOG_DEBUG(ExInfo("noteBg").addInfo("name", getName())); own_noteBg(); m_onBg = true; }
/** * Forward message to her destination. * @param msg message, will be deleted * @throws NameException when listener cannot be found */ void MessagerAgent::forwardNewMsg(BaseMsg *msg) { std::auto_ptr<BaseMsg> sure_delete(msg); const std::string &listenerName = msg->getListenerName(); LOG_DEBUG(ExInfo("received new message") .addInfo("msg", msg->toString())); t_listeners::iterator it = m_listeners.find(listenerName); if (m_listeners.end() == it) { throw NameException(ExInfo("cannot find listener") .addInfo("name", listenerName)); } msg->sendActual(it->second); }
//----------------------------------------------------------------- void BaseAgent::init() { LOG_DEBUG(ExInfo("init").addInfo("name", getName())); //NOTE: agent can call oneself in init() m_initialized = true; own_init(); }
/** * Clean state after run. * @throws LogicException when state is not active */ void GameState::cleanState() { LOG_DEBUG(ExInfo("cleanState").addInfo("name", getName())); if (!m_active) { throw LogicException(ExInfo("clean - state is not active") .addInfo("name", getName())); } own_cleanState(); unHandlers(); m_active = false; m_onBg = false; m_manager = NULL; removeWatchers(); MessagerAgent::agent()->removeListener(getName()); }
/** * Callback called when music is finished. * NOTE: no one exception can be passed to "C" SDL_mixer code */ void SDLSoundAgent::musicFinished() { try { if (ms_finished) { ms_finished->sendClone(); } else { LOG_WARNING(ExInfo("NULL == ms_finished")); } } catch (std::exception &e) { LOG_WARNING(ExInfo("musicFinished error") .addInfo("what", e.what())); } catch (...) { LOG_ERROR(ExInfo("musicFinished error - unknown exception")); } }
/** * @throws LogicException when agent is not initialized. */ void BaseAgent::update() { if (!m_initialized) { throw LogicException(ExInfo("agent is not ready") .addInfo("name", getName())); } own_update(); }
/** * Read dots postions and level descriptions. * @throws LogicException when cannot parse data file */ void WorldMap::initMap(const Path &mapfile) { WorldBranch parser(NULL); m_startNode = parser.parseMap(mapfile, &m_ending, m_descPack); if (NULL == m_startNode) { throw LogicException(ExInfo("cannot create world map") .addInfo("file", mapfile.getNative())); } }
/** * Reactivate state after pause. * @throws LogicException when state is already active */ void GameState::resumeState() { if (m_active) { throw LogicException(ExInfo("resume - state is already active") .addInfo("name", getName())); } m_active = true; own_resumeState(); }
/** * @throws LogicException when state is not active */ void GameState::updateState() { if (!m_active) { throw LogicException(ExInfo("update - state is not active") .addInfo("name", getName())); } own_updateState(); }
/** * Return new cloned surface. * @return new surface, free it after use * @throws SDLException when function fails */ SDL_Surface * SurfaceTool::createClone(SDL_Surface *surface) { SDL_Surface *clone = SDL_ConvertSurface(surface, surface->format, surface->flags); if (NULL == clone) { throw SDLException(ExInfo("ConvertSurface")); } return clone; }
//----------------------------------------------------------------- void GameState::initState(StateManager *manager) { LOG_DEBUG(ExInfo("initState").addInfo("name", getName())); MessagerAgent::agent()->addListener(this); m_manager = manager; m_active = true; m_onBg = false; own_initState(); }
/** * Supported options are '-h', '-v'. * @throws HelpException when only help is need * @throws LogicException when used option is unknown */ void OptionAgent::parseDashOpt(const std::string &arg, const OptionParams ¶ms) { if ("-h" == arg || "--help" == arg) { throw HelpException(ExInfo(getHelpInfo(params))); } else if ("-v" == arg || "--version" == arg) { throw HelpException(ExInfo(getVersionInfo())); } else if ("-c" == arg || "--config" == arg) { throw HelpException(ExInfo(params.getConfig(m_environ))); } else { throw LogicException(ExInfo("unknown option") .addInfo("arg", arg) .addInfo("use", getParam("program") + " --help")); } }
/** * Handle incoming message. * Messages: * - quit ... quit state */ void GameState::receiveSimple(const SimpleMsg *msg) { if (msg->equalsName("quit")) { quitState(); } else { LOG_WARNING(ExInfo("unknown msg") .addInfo("msg", msg->toString())); } }
/** * @throws LogicException when state is not active */ void GameState::pauseState() { if (!m_active) { throw LogicException(ExInfo("pause - state is not active") .addInfo("name", getName())); } own_pauseState(); m_active = false; m_onBg = false; }
//----------------------------------------------------------------- void KeyBinder::removeStroke(const KeyStroke &stroke) { t_strokes::iterator it = m_strokes.find(stroke); if (m_strokes.end() != it) { delete it->second; m_strokes.erase(it); } else { LOG_WARNING(ExInfo("keystroke does not exist") .addInfo("keystroke", stroke.toString())); } }
/** * Handle incoming message. * Messages: * - param_changed(loglevel) ... set loglevel */ void Application::receiveString(const StringMsg *msg) { if (msg->equalsName("param_changed")) { std::string param = msg->getValue(); if ("loglevel" == param) { Log::setLogLevel(OptionAgent::agent()->getAsInt("loglevel")); } } else { LOG_WARNING(ExInfo("unknown msg") .addInfo("msg", msg->toString())); } }
/** * Define controls symbols for extra fish. * Format: "fish_extra-UDLR" * @throws LogicException when symbols are not specified */ ControlSym ModelFactory::parseExtraControlSym(const std::string &kind) { static const std::string PREFIX = "fish_extra-"; if (kind.size() != PREFIX.size() + 4) { throw LogicException(ExInfo("you must specify control symbols") .addInfo("kind", kind)); } char up = kind[PREFIX.size()]; char down = kind[PREFIX.size() + 1]; char left = kind[PREFIX.size() + 2]; char right = kind[PREFIX.size() + 3]; return ControlSym(up, down, left, right); }
//----------------------------------------------------------------- void WorldMap::runIntro() { #ifdef HAVE_SMPEG Path movieFile = Path::dataReadPath("images/menu/intro.mpg"); if (movieFile.exists()) { pushState(new MovieState(movieFile)); return; } LOG_WARNING(ExInfo("cannot find intro") .addInfo("file", movieFile.getNative())); #endif pushState(new DemoMode(Path::dataReadPath("script/share/demo_intro.lua"))); }
//----------------------------------------------------------------- void OptionAgent::parseParamOpt(const std::string &arg, const OptionParams ¶ms) { std::string name; std::string value; if (splitOpt(arg, &name, &value)) { params.checkValidity(name, value); setParam(name, value); } else { throw LogicException(ExInfo("unknown option") .addInfo("arg", arg) .addInfo("use", getParam("program") + " --help")); } }