RTS Sample App         A good starting point for a Real Time Strategy (RTS) style application

Introduction

This framework should provide a good starting point for a Real Time Strategy (RTS) style application.

Major features include:

  • Uses the PLSM2 SceneManager
  • Input via SDL. (Use the DLL listed at the end of that wiki article)
  • Uses CEGUI for the UI.
  • Key remapping capabilities, with saving/retrieving from a text file.
  • Game State architecture, with loading and exit screens.
  • Object selection: area dragging and single object (hold CTRL key to add to selection).
  • Multiple unit selections: CTRL-0 through CTRL-9 create a selection, and 0 - 9 recall that selection.
  • Mini-map.
  • Compass/location indicator.
  • Dual SceneNode camera implementation, with pitch restrictions.


Discussions regarding this application can be found here: RTS style sample app

Patches required to Ogre

Addition to the SDL file SDL_keysym.h

At the end of the first enum declaration (which starts with SDLK_UNKNOWN), add the following definitions:

/* Add any other keys here */
   SDLK_LMB       = 323,   // Mouse button 1
   SDLK_RMB       = 324,   // Mouse button 2
   SDLK_MMB       = 325,   // Mouse button 3
   SDLK_WHEEL_UP  = 326,   // Mouse wheel UP
   SDLK_WHEEL_DN  = 327,   // Mouse wheel DOWN
   SDLK_LAST

(Don't re-add SDLK_LAST. It is listed here just to demonstrate where the addition goes.

Downloads/History

The application was built using Microsoft Visual Studio 7.1.

10/04/2005 Initial release.

Full application, with Debug and Release versions of DLLs and LIBs: Full App (22491k)

Source and data only, no DLLs or LIBs: Src Only (4078k)

10/20/2005 Updated to CEGUI 1.0.5 (as of 10/20/05)

IMPORTANT: This uses the latest CEGUI from their CVS. It will NOT work with the version shipped with Ogre! (as of 10/20/05)

The include files from CEGUI will have to be copied to Ogre\Dependencies\include.

Full application, with Debug and Release versions of DLLs and LIBs: Full App (21688k)

Source and data only. No DLLs or LIBs: Src Only (4078k)

Minimal update: all source and changed/new data. No DLLs or LIBs: Update (356k)

10/24/2005 Changed PlayState to use Functors instead of static member functions.

Source only: Src Only (12k)

Program Flow and the Game States

There are three Game States in this application:

  1. IntroState
  2. PlayState
  3. CreditsState


The program starts in main.cpp, which simply creates an instance of a GameManager object, and tells that object to "start" (Ogre initialization), then to switch to the IntroState.

IntroState

The IntroState first displays the IntroScreen bitmap, then waits for PLSM2 to complete loading. In a full application, this is where the rest of game initialization would occur.

PlayState

The PlayState is where the meat of the game runs. (mmmm.... meat)

New commands should be added in the function InitializeCommandMap, with a corresponding new command handler.

CreditsState

On entry to the CreditsState, the CreditsScreen bitmap is displayed for a predetermined amount of time (exitable by hitting ESC), then the application is shut down.

NotificationsOverlay

This is a handy way of providing notifications to the user.
It is implemented as a FIFO (first-in-first-out) stack, with up to 10 (easily configurable in code) notifications on-screen simultaneously.
Each notification will be displayed for 30 seconds (again, easily configurable in code), then go away.

Usage is simple:

notificationsOverlay->AddNotification(textString, ColourValue(1.0, 1.0, 1.0, 1.0));

Sample of notifications display:

Client_2005-10-20.jpg

Using the UI

In order to get the UI to play nicely with the InputHandler, the InputHandler must be notified
when a keyboard-enabled component of the UI (such as an editBox) gets or loses focus.

For instance, in the KeyConfig dialog, the last line of the show() function informs the InputHandler that the UI has the focus:

InputHandler::getInstance()->SetGUIHasFocus(TRUE);

And in the HandleCancelButton() function, it tells InputHandler it has lost focus:

InputHandler::getInstance()->SetGUIHasFocus(FALSE);

For an editBox that is displayed, but doesn't have focus, an event handler must be added to inform the InputHandler when the user selects that editBox.

In the Console dialog, the editBox (which is always displayed) is wired to an event:

rootWindow->getChild(EntryBoxID)->subscribeEvent(Editbox::EventMouseClick, Event::Subscriber(&Console::handleMouseClick, this));

And in the handleMouseClick() function, the InputHandler is informed in the usual way that the UI has the focus:

InputHandler::getInstance()->SetGUIHasFocus(TRUE);

This allows the InputHandler to decide when to send key commands to the PlayState, so as the user types in an editBox, those keystrokes won't be interpreted as commands.