How to write a controller if one command has different meanings in different conditions?

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • How to write a controller if one command has different meanings in different conditions?

      In GCC4, it seems that for a controller, a same command always has a same meaning.
      For example, for the TeapotController, if 'w' is pressed down, the controller will always dispatch EvtData_StartThrust and will do nothing else.

      I'm writting a simple tile-based strategy game. In the game, the player can drag the world scene, and this drag may have different meanings:
      - If the player drags a tile while there's no unit on it, or there's a moved unit on it, the drag means that he wants to move the whole scene to somewhere (for a better vision).
      - If the player drags a tile while there is a unit that hasn't moved on it, the drag means that he wants to move the unit without moving the scene.

      I've considered some ways to deal with it:
      - Write a controller which simply dispatch something like "EvtDataDrag" when the scene is dragged. It's the scripts' job to find a proper way to deal with the event.
      I don't know if this is good because the controller almost translates nothing, and the scripts' job will be heavy when the logic gets more complex.
      - Write a controller which detects the states of the game and dispatch "EvtDataDragScene" or "EvtDataMoveUnit" in proper conditions.
      This may be bad because the controller seems to know too much.
      - Write two controllers, one for the scene and one for the unit. When dragged, the controller for scene will always dispatch "EvtDataDragScene", and the controller for unit will always dispatch "EvtDataMoveUnit".
      This seems to be hard to code because a single drag may activate both the controllers. This should be avoided but I don't know how.

      Which way is good? Or is there another better way?
    • I would lean towards option two, the controller determines which event to dispatch. For me, the controller's purpose is to translate what the player has done and then send out the event to notify the appropriate system to handle it (ie graphics for moving the scene and game logic for moving the unit).
    • The problem with option 2 is that it makes the controller know too much about the implementation of the game. I would actually go with option 1 and send out a generic drag event. The purpose of the controller is not to handle all of that logic, it's to decouple the origin of input commands. In other words, it disguises which "button" signals the drag event (left mouse button? right mouse button? instant replay? AI? tutorial?).

      It's up to the game logic to process the drag however it sees fit. Otherwise, your controller is going to have a bunch of game logic checks.

      -Rez
    • In my engine, I've implemented controller input like your first option. A configuration file lists various "input actions", and allows multiple "device inputs" (buttons, mice axis etc) to be mapped to each one in a many -> many relationship. eg. You can have 2 separate keys on the keyboard that each trigger the "ThrustForward" action, and you can also have those keys trigger other actions simultaneously. All that my controller code does is read the configs and map device inputs into the desired input actions. The only thing to come out of my controller class is a single event type called InputActionEvent, which contains normalized data about the input event. That means that the rest of the code doesn't know how an input event was triggered - useful to stop yourself from hard coding behavior based on assumptions. (eg. Code that assumes a Fire button is a two state button; either pressed or not (Xbox 360 controller trigger is actually an analog joystick axis.) It's also really useful if you want to record your inputs for demos, or for the AI to trigger input actions.

      What I would probably do in your case is implement a "drag layer" class (or even just a function if that's all that's needed) that listens for drag events and determines where it should go. Is there a unit on that square? Make it move! If not, move the terrain instead! It means that your controller itself doesn't need to know about the game logic, and your units & terrain don't need to perform the hit detection prior to responding. The hit detection will have to be done anyway, but it can be done in it's own function. The bonus of a drag layer is that you can also easily add other types of dragging - like marquee selection of units - with ease.