level editor : give the mouse a state machine?

Started by
13 comments, last by MdLeadG 19 years, 7 months ago
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!
FTA, my 2D futuristic action MMORPG
Advertisement
go for it. If you can make the code more readable and flexable, then do it.
HxRender | Cornerstone SDL TutorialsCurrently picking on: Hedos, Programmer One
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.

About code readability, I find

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,
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).
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.
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.
thanks everyone for your replies...

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]
FTA, my 2D futuristic action MMORPG
Goto www.objectmentor.com and get the taskmaster article. You would have tasks associated with toolbar buttons(but don't have to be). Your task object would inherit from a generic task interface and when you click a toolbar button ie. selecting different task, you would switch current task for the selected task and all mouse messages would go to that new task object. As to the question about how to make sense of fsm, very simple. Write your task fsm on paper and then copy that straight into code. That's the beauty of fsm. You don't grok the code but the paper. You have to implement some sort of mouse handling logic because if you just brute force it then the logic becomes total mess and it will be harder to insert new task logic into existing mess. I use this taskmaster architecture in my editor and it works wonders. Heck, once I had tasks hooked to my right mouse popup menu button. I also have logic where I select task based on mouse clicks in the view rather than clicks on toolbar. Like when choosing between various xform modes of an object so you can then drag it with a mouse and change its shape rather than have separate xform buttons on the toolbar which is lame. One can also hookup 3D camera to its fsm and handle all camera movements that way. Doing it w/o fsm results in mess.
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.
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.

This topic is closed to new replies.

Advertisement