I never thought development of web games can be that simple until I started development of my first game with Adobe Flex. I made two games, without any prior experience with Action script, in only ten months: "Fitter" and "RGB".

I found many answers to my questions on different forums and web sites, and it is time to share my knowledge with Flex community.

Sunday, January 10, 2010

Handling mouse events

In the previous chapter we focused mostly on drawing of game options, but in this chapter we will make some changes, so that game options will work like buttons.

To accomplish this, we have to instruct the application to let us know when mouse is moved or its buttons are pressed/released, and respond accordingly. This is called mouse event handling. Event handling plays important role in Flex development and if you would like to learn more about events and event handling, check this tutorial from Adobe Flex live Docs.

We will add three event handlers to gamePanel: mouseDown, mouseUp and mouseMove. Change mx:Canvas tag in SnakesAdventure.mxml like this:

<mx:Canvas id="gamePanel" x="0" y="0" width="100%" height="100%" mouseDown="MouseDown(event)" mouseUp="MouseUp(event)" mouseMove="MouseMoved(event)"/>

Within a single line, we instruct the application to execute:
- MouseDown function when any mouse button is pressed
- MouseUp function when any mouse button is released
- MouseMoved function when mouse is moved

All three functions will be implemented in file SnakesAdventure.as, but first we will make some changes in the file that will make implementation of options behaviour a little bit easier. Add three new constants after SCREEN_WIDTH and SCREEN_HEIGHT constants:

private static const OPTION_NEW_GAME:int = 0;
private static const OPTION_CONTINUE:int = 1;
private static const OPTION_SETTINGS:int = 2;

private var pressedOption:int = -1;

We assigned one constant value for each option in game menu. We also defined new variable pressedOption, where we will keep index of pressed option. At the beginning no option is pressed, that's why we assigned the variable value -1.

We will used three new constants in the block of code bellow, where we will simplify code that draws game options. Replace the code with existing code that draws game options (function Draw_GameOptions).

for (var i:int = OPTION_NEW_GAME; i <= OPTION_SETTINGS; i++)
{
  var srcY:int = pressedOption == i ? 160 : 80;

  if (i == OPTION_CONTINUE)
    srcY = 0;

  screenBuffer.copyPixels(gameOptionBackgroundBitmap,
                          new Rectangle(0, srcY, 340, 80),
                          new Point(70,235 + i * 70 + (pressedOption == i ? 1 : 0)));

  switch (i)
  {
  case OPTION_NEW_GAME:
    srcY = 0;
    break;
  case OPTION_CONTINUE:
    srcY = 100;
    break;
  case OPTION_SETTINGS:
    srcY = 150;
    break;
  }

  screenBuffer.copyPixels(gameOptionsBitmap,
                          new Rectangle(0, srcY, 260, 50),
                          new Point(110,250 + i * 70 + (pressedOption == i ? 1 : 0))); }

In previous version we had six copies of copyPixel commands, three for background and three for labels. In this version we have just two, because we put the drawing code inside loop with three iterations, one for each option. In both commands we check if option is pressed and if it is, we draw background and label one pixel lower. We also use background image that is a little bit smaller and has white glow around.

Now we can finally handle mouse events. We will implement three functions:
- MouseDown will check if mouse click occurred inside any option and in case it was, set the index of option to pressedOption variable
- MouseUp resets the value of pressedOption
- MouseMoved, checks if mouse cursor left the area of pressed option and resets the value of pressedOption

private function MouseDown(event:MouseEvent):void
{
  var mx:int = event.localX;
  var my:int = event.localY;

  for (var i:int = OPTION_NEW_GAME; i <= OPTION_SETTINGS; i++)
    if (i != OPTION_CONTINUE)
      if ((mx >= 110) && (mx < 370) && (my >= 250 + i * 70) && (my < 300 + i * 70))
        pressedOption = i;
}

private function MouseUp(event:MouseEvent):void
{
  var mx:int = event.localX;
  var my:int = event.localY;

  pressedOption = -1;
}

private function MouseMoved(event:MouseEvent):void
{
  var mx:int = event.localX;
  var my:int = event.localY;

  for (var i:int = OPTION_NEW_GAME; i <= OPTION_SETTINGS; i++)
    if (pressedOption == i)
      if ((mx < 110) || (mx > 370) || (my < 250 + i * 70) || (my > 300 + i * 70))
        pressedOption = -1;
}

In each function we first set position of mouse cursor to local variables.

MouseDown loops through all options and in case it is not continue option (because it is currently disabled) checks if mouse cursor is inside area, where option label is drawn. In case it is, pressedOption variable gets the value of option index. Consequently, program will draw option with same index as pressedOption variable value differently. Different (slightly smaller) background image will be used for drawing and option will be located one pixel lower. While the user holds the mouse button, option will be pressed.

MouseUp is called when mouse button is released. Value of pressedOption is set to -1, even if it was already -1. But if it was not, consequently, program will draw option with default background and it will appear like option was released.

MouseMoved also resets value of pressedOption to -1, but only if mouse cursor left the pressed option area.

Complete project with source files and content files is available for download as usual.

5 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Hi, Thanks for best flex game tutorials....

    When I put : <
    mx:Canvas id="gamePanel" x="0" y="0" width="100%" height="100%" mouseDown="MouseDown(event)" mouseUp="MouseUp(event)" mouseMove="MouseMoved(event)" / >

    It says: Incorrect number of arguments. Expected no more than 0.

    ReplyDelete
  3. I am using SDK 4.5.1, and in above mentioned problem it allows me only on mouse parameter/argument, does not allow last 2

    ReplyDelete
  4. Hi Thanks,

    I didn't define event argument in MouseUp() & MouseMoved()

    Problem solved....!

    ReplyDelete
  5. In should be mouseMove="MouseMoved(event)" /> A double quote is missing.

    ReplyDelete