Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


AzureBlaze

Member Since 27 Apr 2011
Offline Last Active Yesterday, 09:59 AM

Topics I've Started

Managing engine subsystem interactions

11 June 2015 - 02:45 AM

This question was kind of derived from the other thread,

http://www.gamedev.net/topic/668960-engine-design-global-interfaces/

But since it has degenerated into another singleton war, I guess I'll start a new one.

 

I'm currently using the "Passing around pointers to anyone interested." method. But since I have a huge set of subsystems, and I don't know who could be interested in what, I wrap all the subsystems as forward declared pointers in a giant context object.

 

Suppose a feature is one kind of entity will play a footstep sound according to the material it is standing on, syncing with its' animation, this is what I'll do:

class Foo :public Entity{
  //called every frame,
  //or maybe a event triggered by animation frame or physics contact...
  virtual void update(){
    if (this.animation.isFootstepFrame()){
      //find what we are standing on
      //don't have to be a raycast, could be contact checking, sensors, etc...
      Entity ground = this.context.physics.Raycast(this, downward);
      
      //Entity have properties as string-string pair
      string materialName = ground.getProperty("Material");
      //lookup the actual material from its' name
      Material material = this.context.MaterialRegistry.getByName(materialName);
      string stepSound = material.getStepSound();
      this.context.audio.playSoundEffect(stepSound,this.position);

      //do other stuffs
      //a lot of subsystem is involved
      this.context.camera.shake();
      this.context.scene.AddEntity(new FootPrint(this.context, this.position);
      /*
      FootPrint::FootPrint(...):
        Entity(context)
      {
        this.texture = context.resourceManager.getTexture("footprint.png");
        ...
      }
      */
      this.footStep.RaiseEvent(this);
      /*
      somewhere else
      void OnFooFootStep(Foo *f){
        f.context.logger.log("footstep");
      }
      */
    }
    //the script could do a huge variety of stuffs,
    //possiblely using any subsystems.
    this.script.run(this);
  }
};

This method is working great for me, for now.

 

I read that context objects are considered anti-pattern, but don't understand why.  Also with all those "contexts" floating around and easily retrievable, I feel it is not a lot better than a global, other than I can have multiple contexts.

 

Are there better solutions than this "I don't know what you'll need so I'll give you everything"?


Intellua - a Lua Editor with auto-complete support

11 April 2014 - 07:26 AM

Recently my Lua scripts started to get out of hand because I'm adding more and more common utility functions and custom Lua classes. Remembering function signatures became more difficult and using classes without auto-complete is pure pain. I decided to improve my original Lua editor (was designed originally only to auto-complete APIs exposed from my game), and I think more people could benefit from it. I present Intellua:

 

example.png

 

Intellua is a open source (although the code is still messy and undocumented now so it is not recommended to look at it now.) C# project base on scintilla and scintillaNET that provides auto-complete via static code analysis.

 

Features are:

  • Auto-completion and brief document for functions, variables, class and class members.
  • Game APIs and classes can be documented with Doxygen and import into Intellua (specifically designed for those binded by luabind, but others might also apply)
  • Lua functions and classes can be declared and documented with special lua comments.
  • Object type deduction through assignments and function return type.
  • Manually assigning type for objects.
  • Independent from execution environment.

Most other Lua editors seems to support auto-complete via dynamically inspecting tables. From my past experience (might be wrong since years has past and it could improve.) the result might be messy(unneeded private stuff appears) or inacurrate(inherited members through meta-table missing). By using static analysis Intellua believe a object is what you told Intellua it is, this gives more control over the result.

 

Here's a demo of writing and using a simple class in Intellua

 

The Intellua project is hosted at http://code.google.com/p/intellua/


Alternative to context objects

19 December 2012 - 03:02 AM

Hi,

I have a "Stage" class which act sort of like a context object and contains every service and module that will be used in the same level. Most services live and die with the stage, but some are reference to upper services in the game. The stage also contains a list of entities who will use the services.

Entities come in vast varieties and each uses different services, so I pass the Stage object in their constructor and let them decide what to use.

Some entities need to load a sprite, which will be cached for later use in the same stage:
stage->getResourceManager()->getSprite(...);

Some entities need to check for map collisions:
stage->getMap()->testCollision(...);

Some entities need to override camera control:
stage->getCameraController()->setPosition(...);

This works, but every time I add a new service to Stage, every entity needs to be recompiled as they all depend on Stage, which is somehow annoying.

I also have a factory which maintains a map of every entity and its "Key", so I can read and create entities from a file. The factory have to call functions with same signatures, such as
Entity *Create(Stage *stage);
so passing individual service a certain entity need to its constructor don't seems feasible.

I have written several games, and they all end up having a huge class containing everything anyone might need. Is there a better solution to this?

I have looked into the service locator pattern but I'm not sure it is the right solution like this:
static_cast<ResourceManager*>(stage->getService("ResourceManager"))->getSprite(...);

Singletons won't work because there might be more than one Stage (split screen 2P, etc...)

PARTNERS