ebmDevMag.com home
ebm Developer's Magazine
links

developer's mag
main page

article
part 1
part 2
part 3
part 4
part 5
part 6
part 7


6 - Pen Detection and Handling

The HandlePen() function takes the WM_PEN_DOWN message and determines if it is a valid press - if so, mark it X or O, and check if the game is over. Testing is via the m_owner array and the m_state variable. The only part not yet discussed is how to figure out which cell the pen is in.

The Initialize() function sets the entries in the m_rect structure to indicate the 'hot spot' for each pen press. It does it by looking at the two vertical and two horizontal bars in the game, and using GetX(), GetY(), GetWidth(), and GetHeight() to calculate the rectangular areas defined by them, storing the values for future use.

Although this can waste memory (the width and height of each cell are identical), I recommend this approach in ebm programs for a couple of reasons. Generating the rectangle once means the whole code can access it; here, DrawItem() uses it in centering the X or O in each cell. Another reason is that the RECT structure is ideally suited for pen detection, as shown in the HandlePen() function:
  void paTicTacToe::HandlePen(CViewable *from, S32 data)
  {
    // check if we've pressed on an empty square, and handle move
    if (m_state==STATE_GAME_OVER)
      return; // ignore unless game on
    int x=data>>16, y=data&0x0000FFFFL; // get coordinates of pen press
    // go through m_rect list to see if we have a hit
    for (int i=0;i<9;i++)
    {
      if (GUI_PointInRect(&m_rect[i],x,y)) // on one of our spots?
      {
        if (m_owner[i]) // already owned?
          return;  // ignore
        // new entry selected - mark it appropriately
        m_owner[i]=(m_move&1)+1; // 1 or 2 depending on player 1/2
        ++m_move; // record another move
        DrawItem(i); // display it
        // after move, we now check if game over, or exit and wait for next message
        int result=CheckGame(); // -1 if draw, 1/2 if winner
        switch (result) // if done, alert player
        {
          case 1:
            GUI_Alert(ALERT_WARNING,"Congratulations, Player 1 Won!");
            break;
          case 2:
            GUI_Alert(ALERT_WARNING,"Congratulations, Player 2 Won!");
            break;
          case -1:
            GUI_Alert(ALERT_WARNING,"It's a Draw!");
            break;
        }
        if (result) // over?
          m_state=STATE_GAME_OVER; // note game done
        return;
      }
    }
  }
Using GUI_PointInRect(), we quickly determine if we are pressing on a game cell.

Looking over the rest of the function, we see the complete game logic. We filter out invalid pen presses by the rectangle test and checking that the game is not over. We additionally use m_owner to make sure we aren't selecting an occupied cell. Finally, we turn on the appropriate cell and check for end of game.

Although we've coded a Draw() function that displays the whole screen (the GUI_NeedUpdate() call in NewGame invokes it), calling Draw() for every move is a cycle-stealer, and makes the game sluggish. Instead, we code two routines - DrawItem() for an individual entry, and Draw() to do it all (and which in turn calls DrawItem() once for each cell). This way, we get both speed and flexibility in item drawing.

Previous Section
Next Section

Copyright © 2001-2006 ebmDevMag.com - Legal Notice