0
\$\begingroup\$

I've got a player Class which can walk to a certain point on the screen when left mouse is pressed:

if (mState.LeftButton == ButtonState.Released && oldMouseState.LeftButton == ButtonState.Pressed)
            {

                    if (mState.X > CurrentPosition.X)
                    {
                        CurrentDirection = Direction.Right;
                    }
                    else if (mState.X < CurrentPosition.X)
                    {
                        CurrentDirection = Direction.Left;
                    }

                    CurrentDestination = new Vector2(mState.X, mState.Y);
                    CurrentState = PlayerState.Moving;
                    reachedDestination = false; 
            }

Now I have several Characters on screen. If I want to select one of them I also do a left click, which sets the character to selected.

    if (mState.LeftButton == ButtonState.Released && oldMSstate.LeftButton == ButtonState.Pressed)
            {
                if (player1.BoundingBox.Contains(new Point(mState.X, mState.Y)))
                {
                    if (!player1.Selected)
                    {
                        player1.Selected = true;
                        player2.Selected = false;
                    }
                }
if (player2.BoundingBox.Contains(new Point(mState.X, mState.Y)))
                {
                    if (!player2.Selected)
                    {
                        player2.Selected = true;
                        player1.Selected = false;
                    }
                }
}

The problem is that as soon as one of the characters is selected it also performs the moving animation. This is beacuse for the trigger is the same for both moving to destination and selecting.

Do you know any way to avoid this behaviour and still keep using the left click for both?

Thanks in advance!

\$\endgroup\$
  • \$\begingroup\$ Whose state does mState refer to - player1 or player2? \$\endgroup\$ – Nikola Dimitroff Jul 25 '13 at 14:13
  • \$\begingroup\$ It is the global mouseState as both players are managed in a LevelManager class. \$\endgroup\$ – チーズパン Jul 25 '13 at 14:35
1
\$\begingroup\$

On touch devices, developers are freely given two seperate events in the form of "touch and hold" and "tap". You could try to implement this manually. Since you seem to want to use the same button for both actions, I think the best solution would be implementing some sort of miniscule delay between clicking a point, and them moving to it (say, 200ms). If the click is released before the 200ms, then count it as a "click", and check if a character's bounding box is in the click. I should note that this delay will be a heavy hit on gameplay if your action is fast-paced, and you may have to increase that 200 number if some of your players have a tendency to make longer presses. (I know plenty of amature computer users who always "firmly" click on files/links for a full second)

The alternative is: If you have some sort of class to handle the controls (ie, handles rebinding of controls, or other forms of input like touch/controller) then add a feature to let a particular event be "cancelled" once one class has handled it. Javascript has something like that. Ensure that your unit-selection runs first, and cancel the click event since it's already been processed. The downside to this approach is that if someone misclicks a character, they'll walk towards them.

Having played some top-down games of the kind, I can't tell you how annoying it is to have the controls for "Throw a grenade at a razor-faced demon" and "Run closer to the razor-faced demon with your grenade" to be a few pixels apart.

\$\endgroup\$
  • \$\begingroup\$ You seem to have experience with running into demons. Do you think it could be a better choice to pit character selection on hotkeys. I am not planning on having more than three characters on the screen. \$\endgroup\$ – チーズパン Jul 25 '13 at 15:19
  • 1
    \$\begingroup\$ Well, the game Trine has you controlling multiple characters. They just used the numbers 1,2,3. To enhance learning, you could show each character's portrait in sequence somewhere onscreen, with the numbers "1, 2, 3"; and also allow people to click those portraits. If a particular action doesn't have infinite exact options (ie, move to particular position, aim gun at particular point) and there are not dozens of potential actions, it's generally better assigned to a keyboard button. \$\endgroup\$ – Katana314 Jul 25 '13 at 15:46
1
\$\begingroup\$

Clicking should be handled in a separate layer. In the past, I've called this layer the HUD (heads up display), and it handles unit selection, giving commands to the selected units, moving the view port, and other user activities that are not part of "the game". So instead of having each unit check where the user has clicked, have your HUD handle each click and pass commands down to the units. That way, you can check to see if you've selected a unit, and if not, then move the selected unit.

In very rough pseudocode:

class HUD
{
    Unit selectedUnit;
    ...
    void HandleClick(e)
    {
        bool unitWasSelected = false;
        foreach(unit in world)
        {
            if(unit was clicked)
            {
                unitWasSelected = true;
                selectedUnit= unit;
            }
        }
        if(!unitWasSelected)
        {
            selectedUnit.Move();   // Send a command down
        }
    }
    ...
}

My HUD manages which units are selected, and even draws the selection circles around the selected units. I've gone so far that my selected units have no idea that they are selected, any why should they? A real separation of responsibilities is nice.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.