PocketEmpires/HumanPlayerBtn.cpp

360 lines
11 KiB
C++

/* *******************************************************************
* Includes
* ******************************************************************/
#include "HumanPlayer.h"
#include "System.h"
#include "Cursor.h"
#include <Buttons.h>
#include <Gamebuino.h>
#include <stdint.h>
#include <string.h>
#include <limits.h>
/* *******************************************************************
* Defines
* ******************************************************************/
/* *******************************************************************
* Types definition
* ******************************************************************/
/* *******************************************************************
* Global variables definition
* ******************************************************************/
/* *******************************************************************
* Local variables definition
* ******************************************************************/
/* *******************************************************************
* Local prototypes declaration
* ******************************************************************/
/* *******************************************************************
* Functions definition
* ******************************************************************/
/*****************************************************************//**
*
* \brief Event handler executed when human player presses
* left arrow button.
*
*********************************************************************/
void HumanPlayer::buttonHandler(void)
{
for (size_t szBtn = 0; szBtn < NUM_BTN; szBtn++)
{
if (gb.buttons.timeHeld(static_cast<uint8_t>(szBtn)) > 0)
{
/* Update player attributes
* according to pressed button. */
playerButtonPressedHandler(szBtn);
/* Update camera attributes
* according to pressed button. */
cameraButtonPressedHandler(szBtn);
}
else if (gb.buttons.released(static_cast<uint8_t>(szBtn)))
{
/* Key has not been pressed. */
/* Update player attributes
* according to released button. */
playerButtonReleasedHandler(szBtn);
}
}
}
/*****************************************************************//**
*
* \brief This function executes button pressed handler events
* used on a \ref HumanPlayer object.
*
* \param szBtn
* Pressed button ID.
*
*********************************************************************/
void HumanPlayer::playerButtonPressedHandler(const size_t szBtn)
{
/* This array of member functions lists
* button pressed event handlers for each button. */
static void (HumanPlayer::*const apBtnHandlerTable[NUM_BTN])(void) =
{
[BTN_LEFT] = NULL,
[BTN_UP] = NULL,
[BTN_RIGHT] = NULL,
[BTN_DOWN] = NULL,
[BTN_A] = &HumanPlayer::onABtnPressed,
[BTN_B] = &HumanPlayer::onBBtnPressed
};
/* Key has been pressed. Execute both
* HumanPlayer and Camera handlers, if available. */
/* Get pointer to HumanPlayer member function for selected button. */
void (HumanPlayer::*const pBtnHandler)(void) = apBtnHandlerTable[szBtn];
if (pBtnHandler != NULL)
{
/* HumanPlayer member function
* pointer is available. Execute. */
(this->*pBtnHandler)();
}
else
{
/* Undefined callback for selected button. */
}
}
/*****************************************************************//**
*
* \brief This function executes button pressed handler events
* used on a \ref Camera object.
*
* \param szBtn
* Pressed button ID.
*
*********************************************************************/
void HumanPlayer::cameraButtonPressedHandler(const size_t szBtn)
{
if (not _cam.isLocked())
{
static void (Camera::*const apBtnCameraHandlerTable[NUM_BTN])(Cursor&) =
{
[BTN_LEFT] = &Camera::onLeftBtnPressed,
[BTN_UP] = &Camera::onUpBtnPressed,
[BTN_RIGHT] = &Camera::onRightBtnPressed,
[BTN_DOWN] = &Camera::onDownBtnPressed
};
/* Get pointer to Camera member function for selected button. */
void (Camera::*const pCameraBtnHandler)(Cursor&) = apBtnCameraHandlerTable[szBtn];
if (pCameraBtnHandler != NULL)
{
/* Camera member function pointer
* is available.
* Note: "const" qualifier must be
* removed since camera button event
* handler modifies Camera class members. */
((Camera&)_cam.*pCameraBtnHandler)(_cursor);
}
else
{
/* Undefined callback for selected button. */
}
}
}
/*****************************************************************//**
*
* \brief This function executes button released handler events
* used on a \ref HumanPlayer object.
*
* \param szBtn
* Released button ID.
*
*********************************************************************/
void HumanPlayer::playerButtonReleasedHandler(const size_t szBtn)
{
/* This array of member functions lists
* button pressed event handlers for each button. */
static void (HumanPlayer::*const apBtnHandlerTable[NUM_BTN])(void) =
{
[BTN_LEFT] = NULL,
[BTN_UP] = NULL,
[BTN_RIGHT] = NULL,
[BTN_DOWN] = NULL,
[BTN_A] = &HumanPlayer::onABtnReleased,
[BTN_B] = &HumanPlayer::onBBtnReleased
};
/* Key has been pressed. Execute both
* HumanPlayer and Camera handlers, if available. */
/* Get pointer to HumanPlayer member function for selected button. */
void (HumanPlayer::*const pBtnHandler)(void) = apBtnHandlerTable[szBtn];
if (pBtnHandler != NULL)
{
/* HumanPlayer member function
* pointer is available. Execute. */
(this->*pBtnHandler)();
}
else
{
/* Undefined callback for selected button. */
}
}
/*****************************************************************//**
*
* \brief Event handler executed when human player presses
* A button.
*
*********************************************************************/
void HumanPlayer::onABtnPressed(void)
{
switch (_eState)
{
case PLAYER_STATE_IDLE:
/* Select nearest unit, if possible. */
_eState = selectUnit();
break;
case PLAYER_STATE_UNIT_SELECTED:
if (_ABtnFrames < UCHAR_MAX)
{
/* Increase number of frames
* A button has been pressed. */
_ABtnFrames++;
}
break;
default:
/* Undefined player state. Exit. */
break;
}
}
/*****************************************************************//**
*
* \brief Event handler executed when human player presses
* B button.
*
*********************************************************************/
void HumanPlayer::onBBtnPressed(void)
{
enum
{
/* Number of frames that B button must
* be pressed in order to cancel unit selection. */
CANCEL_SELECTION_FRAMES = 10
};
if (++_BBtnFrames >= CANCEL_SELECTION_FRAMES)
{
switch (_eState)
{
case PLAYER_STATE_UNIT_SELECTED:
{
/* Iterator that will be used
* to move along _unitsMap. */
size_t i;
for (i = 0; i < (sizeof (_unitsMap) / sizeof (_unitsMap[0])); i++)
{
Unit& u = _unitsMap[i];
/* Reset selected flags. */
u.setSelected(false);
}
/* Reset to default state. */
_eState = PLAYER_STATE_IDLE;
}
/* Fall through. */
case PLAYER_STATE_IDLE:
/* Fall through. */
default:
/* Reset pressed B button frames counter. */
_BBtnFrames = 0;
/* Undefined player state. Exit. */
break;
}
}
}
/*****************************************************************//**
*
* \brief Event handler executed when human player releases
* A button.
*
*********************************************************************/
void HumanPlayer::onABtnReleased(void)
{
switch (_eState)
{
case PLAYER_STATE_UNIT_SELECTED:
{
enum
{
/* Number of frames where A button
* must be pressed in order to enter
* unit menu. */
ENTER_MENU_FRAMES = 5
};
if (_ABtnFrames >= ENTER_MENU_FRAMES)
{
/* Enable unit menu. */
_eState = PLAYER_STATE_UNIT_MENU;
}
else
{
/* Short button press. Exit. */
}
}
/* Fall through. */
case PLAYER_STATE_IDLE:
/* Fall through. */
default:
/* Undefined player state. Exit. */
/* Reset pressed A button frames counter. */
_ABtnFrames = 0;
break;
}
}
/*****************************************************************//**
*
* \brief Event handler executed when human player releases
* B button.
*
*********************************************************************/
void HumanPlayer::onBBtnReleased(void)
{
switch (_eState)
{
case PLAYER_STATE_UNIT_SELECTED:
{
/* Iterator that will be used
* to move along _unitsMap. */
size_t i;
for (i = 0; i < (sizeof (_unitsMap) / sizeof (_unitsMap[0])); i++)
{
Unit& u = _unitsMap[i];
if (u.isSelected())
{
/* Get cursor coordinates. */
const uint16_t x = _cursor.getX();
const uint16_t y = _cursor.getY();
/* Move unit to cursor position. */
u.moveTo(x, y);
}
else
{
/* Unit is not selected by the player. Continue. */
}
}
}
/* Fall through.*/
case PLAYER_STATE_IDLE:
/* Fall through. */
default:
/* Undefined player state. Exit. */
/* Reset pressed B button frames counter. */
_BBtnFrames = 0;
break;
}
}