# level editor : give the mouse a state machine?

## Recommended Posts

hi, im working on my level editor and have come up with a few problems. for example, there are different types of things you can add to the map. you can add a regular tile, or an NPC, or a link-to-another-map tile, etc. also, i want to allow the user the place free floating map objects on the map.i want it so they press a button, enter the data for the object, then a transparent version of the objects hovers over their mouse untill they click on the map, which then places the object where they click. the problem is, clickong on the map, any of these things could happen, so how do i judge what thing should happen when? IE, how do i know if the player wants to place a tile he has selected, or an NPC he has selected, or whatever? theres 2 ways ive thought about this. have a master class and have npc-map-object, regular-tile, link-tile, etc. all derive from it, then when i click, just do current_selected->on_click(). but, i was thinking this is kind of ugly... i could use a state machine! instead of using polymorphism and pointers, i could just use a state machine. so instead of current_mouse_selection->on_click(); it would be:
if(click)
{
switch(mouse_state)
{
case PLACING_MAP_OBJECT:
place_object();
}

so, what do you think? should i go with the state machine instead? it seems cleaner, i mean, isnt this sort of "Abuse" of inheritense? i try not to do that. thanks for any help!

##### Share on other sites
go for it. If you can make the code more readable and flexable, then do it.

##### Share on other sites
The path you do not like is obviously better.

If you code a FSM to perform mouse action then you'll have to modify your FSM each time you want to modify the behavior of particular mouse action. Adding an object will aslo require you modify the FSM.

void Window::onClick(POINT p){   if (getDoc()->getSelObj())   {       getDoc()->getSelObj()->onClick(getMouseObject(), p);   }}

Far more readable than a switch witch will need that I scroll the code to find what function is called in a particular case.

This is not an abuse of inheritance at all. All the objects inhertits from a MouseActionable object [which is NOT the base object of your tile/npc/whatever class hierarchy], which seems perfeclty fine to me. Your mouse management code is simpler and do not depends on the objects you are handling, which seems perfecly fine to me again. You have less code to write to add a new MouseActionnable object, which seems perfectly fine to me too :)

Hope I'm clear, and HTH,

##### Share on other sites
Conceptually, the mouse does only have a few states: left button state, right button state, position etc. It does not make any real sense to give the mouse any more properties, since it's meant to only be a point-and-click instrument in the first place.

What happens when you click on something is the clicked thing's responsibility. The mouse should not have the smallest idea about what it clicked on in the first place, as this would in most cases break encapsulation and modularity.

On the other hand, you might be needing a brush object: in some cases, a click of the mouse on a certain object will have different effects depending on what was previously clicked. You can then create a brush object that is modified by mouse actions, and is used by the clicked object when it needs to perform an action.

For instance, a tilemap would be associated with a brush, and perform different actions upon a click whether the brush was a tile, or an eraser, or an object. After that, it's up to you to decide what the brush and clickable object know about each other, but remember that it will not break modularity or encapsulation if you allow a brush to know "more" about a clickable object's interface (for instance, you would be using tilemap brushes only tilemaps, so tilemap brushes would be allowed to know more about generic tilemap interfaces they can then use to modify the tilemap).

##### Share on other sites
Aye, a mouse has very little state, all you really need it to do is generate events (clicked, dragged, etc.). Then I use a collection of 'tools' which the user can chose betwee. The currently active tool then receives all the mouse events for it to act on them as it needs.

Thats handy 'cos then any internal state for each tool (like current object to place, configurations, image etc.) gets nicely wrapped up in each individual tool so it persists when the user changes between the different tools. Bung in a simple Tool interface and a tool selector to swich between them and you can easily add new tools without needing to change any of the framework code.

##### Share on other sites
Slightly dissenting... I actually use both. Like keyboard input can be both in 'text input' and 'keystroke trigger' modes, my mouse handler can be in 'selection' and 'click event' modes. The selection mode sends a stack of every object that is hit [rather than just the top object]. Then if the current state wants a tile, it can pick the top tile out of the list and ignore the rest. If it wants a npc, pick those from the list.

In practice, this tends to be fairly awkward, but it allows for a great amount of flexibility and the ability to select objects irregardless of the rendering context they're in [for example, selecting a target for a spell can now be done via the overland map, or from a sortable list, or from a description of a city's residents]

But then again, this is my first win32 game, and inheritance is one of my weak points.

##### Share on other sites

i guess i was thinking that the mouse will need some form of state machine at lease in this situation:

i want to allow the user to add a free floating map object to the map. by free floating object i mean something like a building, a street light, etc, only it doesnt have to be tiles, it can just be a whole image.

now to do this, there would be an "add free floating object" button. you would click this, and be prompted "what is the width /height, what is the path to the texture". after putting in this info, i want that object to be hovering over the mouse, transparently, and then when the user clicks the object is placed on the map where the user clicked.

but how could i do this? wouldnt i need to give my mouse states? something like NO_STATE and PLACING_MAP_OBJ. then my button / gui would get the w/h/texture, then somehow i would have to fill in the x/y of the map object when placed. or maybe i would fill in the x/y immediately, so the map object would be rendering itself at its own x/y, and the x/y would constantly be set to the mouse position untill the user pressed? hmmm, i guess i just have to think about the logic some more. thanks again

EDIT: by the way, im using OpenGL and SDL for everything. this means no nice and friendly GUI stuff. everything is kind of sloppily done with quads and unicode input. kind of nasty, but it gets the job done. im thinking my next game ill use a real API or C# or something instead.

[Edited by - graveyard filla on September 4, 2004 5:55:20 PM]

##### Share on other sites
I use that 'task' system as well. I have a base class IEditorMode, with 2 derived classes (so far, I want to keep as few as posible) a terrain editing mode, and a unit editing mode. There is a control bar (it is MFC) with a tab control in it, each tab has a corrosponding mode pointer. It passes off mouse messages to the mode specified by the selected tab.

##### Share on other sites
The "brush" or "tool" being talked about is kind of like a "mouse state". Except instead of being some enumeration representing a state, it's an object representing a State (or Strategy), which is a nice OO idea. The mouse itself has no concept of 'placing a picture', but the mouse's 'condition-of-placing-a-picture' certainly does.

See here and here.

##### Share on other sites
hmm, im a little confused, i checked out the links but im still confused.

anyway, so the general consesus is to use polymorphism instead of a state machine? for some reason, i think using a state machine is cleaner.. maybe im doing one of them / both wrong? im going to explain the problem again then the 2 options i think i have.

the problem:

in the map editor, i display the map on the screen. now there are different things i can add to the map. i can add an NPC, i can add a map-warp-tile, i can add a regular tile, etc.

so how do i decide, when the user clicks on the map, exactly what he wants to do? the way i have it now is i set up different keys... IE, while hovering the mouse over the map and pressing N, it places an NPC there, while hovering and pressing M, it places a map-warp-tile there, while hovering and right clicking the mouse, it places a regular tile.

i dont want to have to remember which keys to press, and neither does my artist. how can i have to so i can just click on an NPC brush, or map-warp brush, or regular tile brush, it selects the given brush, then when i click on the map (right click with the mouse), it places the currently selected brush.

there are 2 ways i can do this. either a state machine, or polymorphism. first ill show the poly way.

-make a Selectable_Brush base class.

-have Npc, Map-Warp, and Tile all derive from it. now i can just use a pointer to a Selectable_Brush to represent my currently selected brush.

so Selectable Brush is the base, and the other 3 derive from it. Then i give Selectable brush functions like Select() and Place(). then i just do something like if(click the tile map) selectable_brush = some_tile(). if (click the npc button) selectable_brush->Place()

the other choice is State machines. to be honest, i think that perhaps the inheritense way is more elegant, but using a state machine i think is more obviouse. this is my map editor which i dont work on frequently, so when i come back at the code in 2 months, i want to remember as much as possible how things work. im thinking with a state machine, it will be right in my face how everything works. basically there will be 3 things

- each frame, run through the current mouse state, and depending on what it is, draw a transparent version of that item over the mouse curer

-each frame, check if the user right clicks, if he does, run through a case statement checking the state, calling the appropriate function based on the state

-do the same as with poly. if (user clicks tilemap) current_state = PLACING_TILE. same for npc/map warps.

so, what do you think again? as of rigght now im about to implement the state machine, simply because its easier to do, and more obviouse. if this was my game, i would more then likely do the inheritense route because its more elegant, but since i dont work on the editor much, in a few months when i come back to the code, i want to remember what the hell i was doing. so, could i get your opnions again? =) thanks!

##### Share on other sites
FSMs come in handy when you have lots of states and events in a task object and you try to make sense out of it. Otherwise you might make state flags and when a mouse button is pressed you can check whether you have pushed some tool button down and recorded a state and see if you're in that state now so that you can place down a certain style brush. With simple thing like this you might not even need inheritance. Just some flags to check in mouse event handlers.

##### Share on other sites
You could also try a Chain Of Command pattern. That works well for widget hierarchies. What you do is say:

If ( mouse clicky ) {   GUI->MouseDown( x, y );   }GUI::MouseDown() {   foreach toplevel child widget {      child->MouseDown(x,y);      }   }Widget::MouseDown() {   if ( i am waiting for a mouse click for my own use ) {      // do stuph;      }   else {      foreach child widget {         child->MouseDown(x,y);         }      }   }

pardon my strange indentation style.

##### Share on other sites
thanks everyone for your replies. ive decided to go with the state machine. its very nice and tidy and its working good. thanks again

##### Share on other sites
Quote:
 Original post by graveyard fillanow to do this, there would be an "add free floating object" button. you would click this, and be prompted "what is the width /height, what is the path to the texture". after putting in this info, i want that object to be hovering over the mouse, transparently, and then when the user clicks the object is placed on the map where the user clicked.but how could i do this? wouldnt i need to give my mouse states? something like NO_STATE and PLACING_MAP_OBJ. then my button / gui would get the w/h/texture, then somehow i would have to fill in the x/y of the map object when placed. or maybe i would fill in the x/y immediately, so the map object would be rendering itself at its own x/y, and the x/y would constantly be set to the mouse position untill the user pressed? hmmm, i guess i just have to think about the logic some more. thanks again

Just an obvservation ... Conceptually, it's the editor that's placing objects down, not the mouse. Clicking the mouse should tell the editor to go into a placing_object state, whether that be directly or with an object tool, like OrangyTang was discussing.

Unless you plan to implenment the entire slew of Mechwarrior hotkeys with the mouse alone, mouse states might be to your disadvantage.

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628329
• Total Posts
2982104

• 22
• 9
• 9
• 13
• 11