360 lines
11 KiB
C++
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;
|
|
}
|
|
}
|