[ < ] | [ > ] |  | [ << ] | [ 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.