system.cpp
来自「Source code (C++) of the Amoebax game fo」· C++ 代码 · 共 777 行 · 第 1/2 页
CPP
777 行
/// of the system class.////// \param fadeOut Tells if add a fade out when the state is removed.///voidSystem::removeActiveState (bool fadeOut){ if ( !m_States.empty () ) { IState *stateToDelete = m_States.back (); // Remove the state from the active states list. m_States.pop_back (); // And add it to the list of states to delete at the end of the frame. m_StatesToDelete.push_back (stateToDelete); if ( fadeOut ) { setActiveState (new FadeOutState (), FadeNone); } }}////// \brief Removes all states until the only remaining state is the main menu.////// The main menu should be the first state, since this function removes/// all states until one is left.///voidSystem::returnToMainMenu (void){ while ( m_States.size () > 2 ) { removeActiveState (false); } removeActiveState (true);}////// \brief Redraws the state's background.///voidSystem::redrawStateBackground (void){ if ( 0 != m_ActiveState && m_InvalidatedRegion.x1 < m_InvalidatedRegion.x2 && m_InvalidatedRegion.y1 < m_InvalidatedRegion.y2 ) { SDL_Rect redrawRegion; redrawRegion.h = m_InvalidatedRegion.y2 - m_InvalidatedRegion.y1; redrawRegion.w = m_InvalidatedRegion.x2 - m_InvalidatedRegion.x1; redrawRegion.x = m_InvalidatedRegion.x1; redrawRegion.y = m_InvalidatedRegion.y1; m_ActiveState->redrawBackground (&redrawRegion, getScreenSDLSurface ()); m_InvalidatedRegion.x1 = std::numeric_limits<int16_t>::max (); m_InvalidatedRegion.y1 = std::numeric_limits<int16_t>::max (); m_InvalidatedRegion.x2 = std::numeric_limits<int16_t>::min (); m_InvalidatedRegion.y2 = std::numeric_limits<int16_t>::min (); }}////// \brief System's main loop.////// This is the loop that drivers the whole system./// The call to this function doesn't return until the/// system must shown down, in which case the application/// can exit.///voidSystem::run (void){ assert (0 != getScreenSDLSurface () && "Tried to run the system without initializing it."); bool end = false; do { // Get the active state or set it 0 if no state is active. if ( m_States.empty () ) { m_ActiveState = 0; } else { m_ActiveState = m_States.back (); } // If we are going too fast, slow down so we won't burn the CPU. FrameManager::update (); // If there's no active state, then we are done. if ( 0 == m_ActiveState ) { SDL_Event quitEvent; quitEvent.type = SDL_QUIT; SDL_PushEvent (&quitEvent); } // If the current active state is different from the previously // active state, then activate the current state. else if ( m_ActiveState != m_PreviousActiveState ) { m_ActiveState->activate (); invalidateWholeScreen (); } // Process all pending events. SDL_Event event; while ( SDL_PollEvent (&event) ) { if ( SDL_QUIT == event.type ) { end = true; } else if ( 0 != m_ActiveState ) { switch ( event.type ) { case SDL_JOYAXISMOTION: m_ActiveState->joyMotion (event.jaxis.which, event.jaxis.axis, event.jaxis.value); break; case SDL_JOYBUTTONDOWN:#if defined (IS_GP2X_HOST) && !defined (__SYMBIAN32__) if ( GP2X_BUTTON_VOLUP == event.jbutton.button ) { Options::getInstance ().incrementVolume (); m_VolumeDisplayTime = k_VolumeDisplayTime; applyVolumeLevel (); } else if ( GP2X_BUTTON_VOLDOWN == event.jbutton.button ) { Options::getInstance ().decrementVolume (); m_VolumeDisplayTime = k_VolumeDisplayTime; applyVolumeLevel (); } else#endif // IS_GP2X_HOST { m_ActiveState->joyDown (event.jbutton.which, event.jbutton.button); } break; case SDL_JOYBUTTONUP: m_ActiveState->joyUp (event.jbutton.which, event.jbutton.button); break;#if !defined (IS_GP2X_HOST)|| defined (__SYMBIAN32__) case SDL_ACTIVEEVENT: if ( event.active.state & SDL_APPACTIVE ) { // Window is minimized. if ( 0 == event.active.gain ) { Music::pause (); pause (); } } break; case SDL_KEYDOWN: // ALT+RETURN is reserved to toggle full screen if ( SDLK_RETURN == event.key.keysym.sym && (event.key.keysym.mod & KMOD_ALT) != 0 ) { toggleFullScreen (); } else { m_ActiveState->keyDown (event.key.keysym.sym); } // Check if unicode translation is enabled // and send the unicode code if so. if ( isUnicodeTranslationEnabled () && 0 != event.key.keysym.unicode ) { m_ActiveState->unicodeCharacterPressed (event.key.keysym.unicode); } break; case SDL_KEYUP: m_ActiveState->keyUp (event.key.keysym.sym); break;#endif // !IS_GP2X_HOST } } } // Update and render the active state. if ( 0 != m_ActiveState ) { // Update the state's logic. m_ActiveState->update (FrameManager::getElapsedTime ()); // Remove any previously set clip rectangle. SDL_SetClipRect (getScreenSDLSurface (), NULL); // Draw the state's background for the invalided screen region. redrawStateBackground (); // Render the state. m_ActiveState->render (getScreenSDLSurface ()); }#if defined (IS_GP2X_HOST) && !defined (__SYMBIAN32__) // Show the current volume level if it has been changed. if ( m_VolumeDisplayTime > 0 ) { // Remove any previously set clip rectangle. SDL_SetClipRect (getScreenSDLSurface (), NULL); // Show the display. uint16_t x = Options::getInstance ().getScreenWidth () / 2 - m_VolumeDisplay->getWidth () / 2; uint16_t y = Options::getInstance ().getScreenHeight () / 2 - m_VolumeDisplay->getHeight () / 2; m_VolumeDisplay->blit (x, y, getScreenSDLSurface ()); // Show the current level in white (upper part of the // image) and the remaining up to the maximum level // in gray (lower part of the image.) //uint8_t volumeLevel = Options::getVolumeLevel (); uint16_t width = m_VolumeLevel->getWidth () * Options::getInstance ().getVolumeLevel () / Options::getMaxVolumeLevel (); if ( !isSoundEnabled () ) { width = 0; } x = Options::getInstance ().getScreenWidth () / 2 - m_VolumeLevel->getWidth () / 2; y += m_VolumeDisplay->getHeight () - 10 - m_VolumeLevel->getHeight () / 2; m_VolumeLevel->blit (0, 0, width, m_VolumeLevel->getHeight () / 2, x, y, getScreenSDLSurface ()); x += width; m_VolumeLevel->blit (width, m_VolumeLevel->getHeight () / 2, m_VolumeLevel->getWidth () - width, m_VolumeLevel->getHeight () / 2, x, y, getScreenSDLSurface ()); // Update the time to show the display. m_VolumeDisplayTime -= FrameManager::getElapsedTime (); }#endif // IS_GP2X_HOST // Refresh the screen. SDL_Flip (getScreenSDLSurface ()); // Deletes the not longer used states. if ( !m_StatesToDelete.empty () ) { std::for_each (m_StatesToDelete.begin (), m_StatesToDelete.end (), DeleteObject<IState> ()); m_StatesToDelete.clear (); } // Set the active state as the previous active state. m_PreviousActiveState = m_ActiveState; } while ( !end );}////// \brief Sets the current active state.////// The System class takes ownership of the \a state class/// and is responsable to delete it when no longer needed.////// \param state The state to set as the current active state./// \param fade Tells which type of fade to set when the state is active.///voidSystem::setActiveState (IState *state, uint8_t fade){ assert ( 0 != state && "Tried to set a NULL state as the active."); m_States.push_back (state); if ( FadeIn == (fade & FadeIn) ) { m_States.push_back (new FadeInState (state)); } if ( FadeOut == (fade & FadeOut) ) { m_States.push_back (new FadeOutState ()); }}////// \brief Sets the video mode reading the parameters from the options.///voidSystem::setVideoMode (void){ // Check if we should go to full screen. uint32_t videoFlags = SDL_SWSURFACE; if ( Options::getInstance ().isFullScreen () ) { videoFlags |= SDL_FULLSCREEN; } // Sets the video mode. m_Screen = SDL_SetVideoMode (Options::getInstance ().getScreenWidth (), Options::getInstance ().getScreenHeight (), Options::getInstance ().getScreenDepth (), videoFlags); if ( 0 == m_Screen ) { // First check if the video settings are the defaults (which should // be the most secure) and if they aren't, reset back to them and // try again. if ( !Options::getInstance ().isVideoOptionsAtDefault () ) { Options::getInstance ().setDefaultVideoOptions (); setVideoMode (); // If the system was already initialized, then tell // the user that her video settings couldn't be set. if ( !m_States.empty () ) { setActiveState (new VideoErrorState (m_States.back ()), FadeNone); } } else { throw std::runtime_error (SDL_GetError ()); } } // Get the current screen's scale factor. // Take into consideration the "odd" factor we need to have when // using a 1024x768 screen resolution. if ( 1024 == m_Screen->w ) { m_ScreenScaleFactor = 0.75f; } else { m_ScreenScaleFactor = std::max (m_Screen->w / k_ScreenMaxWidth, m_Screen->h / k_ScreenMaxHeight); } // Hide the cursor on the screen. Do only if the video mode is set // to full screen, otherwise it feels awkward to make the cursor desappear // when it passes over the window... SDL_ShowCursor (Options::getInstance ().isFullScreen () ? SDL_DISABLE : SDL_ENABLE);}////// \brief Pressents a fatal error to the user.////// \param error The actual error message.///voidSystem::showFatalError (const std::string &error){ std::string title ("There was a fatal error an the application could not continue"); std::ostringstream fullMessage; fullMessage << "Reinstall the application and try again." << std::endl; fullMessage << "If the error still occurs, please contact the" << std::endl; fullMessage << "authors at <" << PACKAGE_BUGREPORT << "> "; fullMessage << "attaching the following error message: " << std::endl; fullMessage << std::endl << error << std::endl;#if defined (IS_WIN32_HOST) MessageBox (NULL, (title + "\r\n" + fullMessage.str ()).c_str (), "Amoebax", MB_ICONERROR);#elif defined (IS_OSX_HOST) OSXAlert (title.c_str (), fullMessage.str ().c_str ());#else std::cerr << title << std::endl; std::cerr << fullMessage.str () << std::endl;#endif}////// \brief Toggles between full screen and windowed mode.///voidSystem::toggleFullScreen (void){ Options::getInstance ().setFullScreen (!Options::getInstance ().isFullScreen ()); changeVideoMode ();}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?