[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

4.2.4.11 AppMazing Main Class

AppMazing is the main application class. Besides the usual Crystal Space setup code it also contains the event handling code.

 
class AppMazing :
  public csApplicationFramework, public csBaseEventHandler
{
private:
  /**
   * A reference to the 3D renderer plugin.
   */
  csRef<iGraphics3D> g3d;

  /**
   * A reference to the 3D engine plugin.
   */
  csRef<iEngine> engine;

  /**
   * The main loader.
   */
  csRef<iLoader> loader;

  /**
   * The view.
   */
  csRef<iView> view;

  /**
   * The collision detection system.
   */
  csRef<iCollideSystem> cdsys;

  /**
   * The virtual clock.
   */
  csRef<iVirtualClock> vc;

  /**
   * Set up everything that needs to be rendered on screen.  This routine is
   * called from the event handler in response to a cscmdProcess broadcast
   * message.
   */
  virtual void ProcessFrame();

  /**
   * Finally, render the screen.  This routine is called from the event handler
   * in response to a cscmdFinalProcess broadcast message.
   */
  virtual void FinishFrame();

  /**
   * Handle keyboard events, such as key presses and releases.  This routine is
   * called from the event handler in response to a csevKeyboard event.
   */
  virtual bool OnKeyboard(iEvent&);

  /// The Game.
  Game game;

public:
  /**
   * Constructor.
   */
  AppMazing();

  /**
   * Destructor.
   */
  virtual ~AppMazing();

  iCamera* GetCamera () const { return view->GetCamera (); }
  iEngine* GetEngine () const { return engine; }
  iLoader* GetLoader () const { return loader; }
  iCollideSystem* GetCollisionDetectionSystem () const { return cdsys; }
  Game& GetGame () { return game; }

  /**
   * Final cleanup.
   */
  virtual void OnExit();

  /**
   * Main initialization routine.  This routine should set up basic facilities
   * (such as loading startup-time plugins, etc.).  In case of failure this
   * routine will return false.  You can assume that the error message has been
   * reported to the user.
   */
  virtual bool OnInitialize(int argc, char* argv[]);

  /**
   * Run the application.  Performs additional initialization (if needed), and
   * then fires up the main run/event loop.  The loop will fire events which
   * actually causes Crystal Space to "run".  Only when the program exits does
   * this function return.
   */
  virtual bool Application();
  
  // Declare the name of this event handler.
  CS_EVENTHANDLER_NAMES("application.mazing")
      
  /* Declare that we're not terribly interested in having events
     delivered to us before or after other modules, plugins, etc. */
  CS_EVENTHANDLER_NIL_CONSTRAINTS
};

This is the basic Crystal Space setup code. All game logic is handled in the Game class of which we have one instance here (`game').

 
CS_IMPLEMENT_APPLICATION

AppMazing::AppMazing() : csApplicationFramework(), game (this)
{
  SetApplicationName("mazing");
}

AppMazing::~AppMazing()
{
}

Just the constructor and the destructor.

 
void AppMazing::ProcessFrame()
{
  csTicks elapsed_time = vc->GetElapsedTicks ();
  game.Handle (elapsed_time);

  // Tell 3D driver we're going to display 3D things.
  if (!g3d->BeginDraw (engine->GetBeginDrawFlags () | CSDRAW_3DGRAPHICS))
    return;

  view->Draw ();
}

void AppMazing::FinishFrame()
{
  g3d->FinishDraw();
  g3d->Print(0);
}

ProcessFrame() and FinishDraw() are automatically called every frame. In ProcessFrame() we will let the Game class handle all game logic and finally we will render the 3D view. We use the virtual clock to get the elapsed time since previous frame.

 
bool AppMazing::OnKeyboard(iEvent& ev)
{
  // We got a keyboard event.
  if (csKeyEventHelper::GetEventType(&ev) == csKeyEventTypeDown)
  {
    // The user pressed a key (as opposed to releasing it).
    utf32_char code = csKeyEventHelper::GetCookedCode(&ev);
    if (code == CSKEY_ESC)
    {
      // The user pressed escape, so terminate the application.  The proper
      // way to terminate a Crystal Space application is by broadcasting a
      // csevQuit event.  That will cause the main run loop to stop.  To do
      // so we retrieve the event queue from the object registry and then
      // post the event.
      csRef<iEventQueue> q =
        csQueryRegistry<iEventQueue> (GetObjectRegistry());
      if (q.IsValid())
        q->GetEventOutlet()->Broadcast(csevQuit(GetObjectRegistry()));
    }
    else
    {
      return game.OnKeyboard (ev);
    }
  }
  return false;
}

In this function we handle all keyboard events. The escape key is handled here because that's not related to game logic. All other keys are passed to the Game instance.

 
bool AppMazing::OnInitialize(int argc, char* argv[])
{
  iObjectRegistry* r = GetObjectRegistry();

  // Load application-specific configuration file.
  if (!csInitializer::SetupConfigManager(r, 0, GetApplicationName()))
    return ReportError("Failed to initialize configuration manager!");

  // RequestPlugins() will load all plugins we specify.  In addition it will
  // also check if there are plugins that need to be loaded from the
  // configuration system (both the application configuration and CS or global
  // configurations).  It also supports specifying plugins on the command line
  // via the --plugin= option.
  if (!csInitializer::RequestPlugins(r,
	CS_REQUEST_VFS,
	CS_REQUEST_OPENGL3D,
	CS_REQUEST_ENGINE,
	CS_REQUEST_FONTSERVER,
	CS_REQUEST_IMAGELOADER,
	CS_REQUEST_LEVELLOADER,
        CS_REQUEST_PLUGIN ("crystalspace.collisiondetection.opcode",
		iCollideSystem),
	CS_REQUEST_REPORTER,
	CS_REQUEST_REPORTERLISTENER,
	CS_REQUEST_END))
    return ReportError("Failed to initialize plugins!");

  // "Warm up" the event handler so it can interact with the world
  csBaseEventHandler::Initialize(r);
 
  // Set up an event handler for the application.  Crystal Space is fully
  // event-driven.  Everything (except for this initialization) happens in
  // response to an event.
  if (!RegisterQueue (r, csevAllEvents(GetObjectRegistry())))
    return ReportError("Failed to set up event handler!");

  return true;
}

void AppMazing::OnExit()
{
}

bool AppMazing::Application()
{
  iObjectRegistry* r = GetObjectRegistry();

  // Open the main system. This will open all the previously loaded plugins
  // (i.e. all windows will be opened).
  if (!OpenApplication(r))
    return ReportError("Error opening system!");

  // Now get the pointer to various modules we need.  We fetch them from the
  // object registry.  The RequestPlugins() call we did earlier registered all
  // loaded plugins with the object registry.  It is also possible to load
  // plugins manually on-demand.
  g3d = csQueryRegistry<iGraphics3D> (r);
  if (!g3d)
    return ReportError("Failed to locate 3D renderer!");

  engine = csQueryRegistry<iEngine> (r);
  if (!engine)
    return ReportError("Failed to locate 3D engine!");

  loader = csQueryRegistry<iLoader> (r);
  if (!loader)
    return ReportError("Failed to locate the map loader!");

  cdsys = csQueryRegistry<iCollideSystem> (r);
  if (!cdsys)
    return ReportError("Failed to locate the collision detection system!");

  vc = csQueryRegistry<iVirtualClock> (r);
  if (!vc)
    return ReportError("Failed to locate the virtual clock!");

  // Setup game.
  if (!game.SetupGame ())
    return false;

  // Create a view.
  view = csPtr<iView> (new csView (engine, g3d));
  view->GetCamera ()->SetSector (engine->FindSector ("room_0_0_0"));
  view->GetCamera ()->GetTransform ().SetOrigin (csVector3 (0, 0, 0));
  iGraphics2D* g2d = g3d->GetDriver2D ();
  view->SetRectangle (0, 0, g2d->GetWidth (), g2d->GetHeight ());

  // Start the default run/event loop.  This will return only when some code,
  // such as OnKeyboard(), has asked the run loop to terminate.
  Run();

  return true;
}

These are the main initialization functions. We also create our view here.

 
int main(int argc, char** argv)
{
  csPrintf ("mazing version 1.0 by Jorrit Tyberghein.\n");

  /* Runs the application.  
   *
   * csApplicationRunner<> cares about creating an application instance 
   * which will perform initialization and event handling for the entire game. 
   *
   * The underlying csApplicationFramework also performs some core 
   * initialization.  It will set up the configuration manager, event queue, 
   * object registry, and much more.  The object registry is very important, 
   * and it is stored in your main application class (again, by 
   * csApplicationFramework). 
   */
  return csApplicationRunner<AppMazing>::Run (argc, argv);
}

Finally the main program.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated using texi2html 1.76.