Version of Robotron arcade game using LPC1768, a Gameduino shield, a serial EEPROM (for high scores), two microswitch joysticks and two buttons plus a box to put it in. 20 levels of mayhem.

Dependencies:   25LCxxx_SPI CommonTypes Gameduino mbed

GameObject.cpp

Committer:
RichardE
Date:
2013-06-17
Revision:
18:70190f956a24
Parent:
10:bfa1c307c99d

File content as of revision 18:70190f956a24:

/*
 * SOURCE FILE : GameObject.cpp
 *
 * The abstract base class for all graphical game objects.
 *
 */

#include "GameObject.h"
#include "GameObjectLocator.h"
#include "ArenaConst.h"
#include "GDExtra.h"
#include "EnemyFactory.h"

/**********************************/
/* INITIALISE AN ARRAY OF OBJECTS */
/**********************************/
// Really only intended for the initialisation of enemy objects and humans.
// Each object in the array is allocated a consecutive sprite number and is positioned
// randomly in the arena. The objects movement is restricted to within the arena.
// Pass pointer to array of pointers to GameObjects in objects.
// Pass number of pointers in the array in objectCount.
// Pass pointer to a sprite number in spriteNumber. This number is incremented by this method.
void GameObject::InitialiseAll( GameObject **objects, UInt8 objectCount, UInt8 *spriteNumber ) {
    GameObject *object;
    for( UInt8 i = 0; i < objectCount; ++i ) {
        object = objects[ i ];
        if( object != (GameObject*)NULL ) {
            // Use next sprite number.
            object->SpriteNumber = *spriteNumber;
            // Position object randomly.
            GameObjectLocator::Locate( object );
            // Restrict movement to arena.
            object->MovementRestricted = true;
            object->Bounds = &ArenaRectangle;
        }
        // Next sprite number.
        (*spriteNumber)++;
    }
}

/****************************/
/* MOVE AN ARRAY OF OBJECTS */
/****************************/
// Pass pointer to array of pointers to GameObjects in objects.
// Pass number of pointers in the array in objectCount.
// Returns true if any non-null objects were found in the array.
bool GameObject::MoveAll( GameObject **objects, UInt8 objectCount ) {
  if( objects != (GameObject**)NULL ) {
      GameObject *object;
      bool foundNonNull = false;
      for( UInt8 i = 0; i < objectCount; ++i ) {
        object = objects[ i ];
        if( object != (GameObject*)NULL ) {
          foundNonNull = true;
          object->Move();
        }
      }
      return foundNonNull;
   }
   else {
      // A null pointer was passed. Do nothing.
      return false;
   }
}

/****************************/
/* DRAW AN ARRAY OF OBJECTS */
/****************************/
// Pass pointer to Gameduino to draw on in gd.
// Pass pointer to array of pointers to GameObjects in objects.
// Pass number of pointers in the array in objectCount.
void GameObject::DrawAll( Gameduino *gd, GameObject **objects, UInt8 objectCount ) {
  GameObject *object;
  for( UInt8 i = 0; i < objectCount; ++i ) {
    object = objects[ i ];
    if( object != (GameObject*)NULL ) {
      // Check if object is visible.
      // If not then it wants killing off and a NULL
      // should be written to the array of pointers
      // and the sprite should be hidden.
      // If it is an enemy then it must be deleted using EnemyFactory.
      if( ! object->Visible ) {
        if( object->GetType() == EnemyObjectType ) {
            EnemyFactory::Instance.DeleteEnemy( (EnemyObject*)object );
        }
        objects[ i ] = (GameObject*)NULL;
        GDExtra::HideSprite( gd, object->SpriteNumber );
      }
      else {
        object->Draw( gd );
      }
    }
  }
}

/************************************************/
/* FIND AN UNUSED OBJECT IN AN ARRAY OF OBJECTS */
/************************************************/
// Pass pointer to array of pointers to GameObjects in objects.
// Pass number of pointers in the array in objectCount.
// Pass pointer to variable that will hold index of object found in index.
// Returns true if an unused object was found, false if not.
// An unused object is indicated by a null pointer in the array.
bool GameObject::FindUnusedObject( GameObject **objects, UInt8 objectCount, UInt8 *index ) {
  for( UInt8 i = 0; i < objectCount; ++i ) {
    if( objects[ i ] == (GameObject*)NULL ) {
      // Found a null pointer. Store index in index pointer
      // and return true.
      *index = i;
      return true;
    }
  }
  // Did not find a null pointer.
  return false;
}

/****************************************************/
/* FIND COLLISIONS WITH ALL THE OBJECTS IN AN ARRAY */
/****************************************************/
// Pass pointer to Gameduino in gd parameter.
// Pass pointer to array of pointers to GameObjects in objects.
// Pass number of pointers in the array in objectCount.
// Pass pointer to a function that takes two UInt8 parameters in func.
// The first parameter is the index of the object in the objects array that hit something.
// The second parameter is the sprite number of the sprite which it hit.
void GameObject::FindCollisions( Gameduino *gd, GameObject **objects, UInt8 objectCount, void (*func)( UInt8, UInt8 ) ) {
  GameObject *object;
  UInt8 hitSpriteNumber;
  // Repeat for each non-null object in the array.
  for( UInt8 i = 0; i < objectCount; ++i ) {
    object = objects[ i ];
    if( object != (GameObject*)NULL ) {
      // Get sprite number that has collided with the sprite number of the object.
      hitSpriteNumber = gd->rd( Gameduino::COLLISION + object->SpriteNumber );
      // If result is 0xFF then no collision was found.
      if( hitSpriteNumber != 0xFF ) {
        // Collision, so call function to deal with it.
        func( i, hitSpriteNumber );
      }
    }
  }
}

/*************************************************************************/
/* FIND AN OBJECT WITH A PARTICULAR SPRITE NUMBER IN AN ARRAY OF OBJECTS */
/*************************************************************************/
// Pass pointer to array of pointers to GameObjects in objects.
// Pass number of pointers in the array in objectCount.
// Pass sprite number to look for in spriteNumber.
// Index of object with given sprite number written to variable pointed to by index.
// Returns true if sprite number was found, false if not.
bool GameObject::FindSpriteNumber( GameObject **objects, UInt8 objectCount, UInt8 spriteNumber, UInt8 *index ) {
  GameObject *object;
  for( UInt8 i = 0; i < objectCount; ++i ) {
    object = objects[ i ];
    if( ( object != (GameObject*)NULL ) && ( object->SpriteNumber == spriteNumber ) ) {
      *index = i;
      return true;
    }
  }
  // Did not find sprite number.
  return false;
}

/**********************************************/
/* FIND NEAREST OBJECT IN AN ARRAY OF OBJECTS */
/**********************************************/
// Pass pointer to array of pointers to GameObjects in objects.
// Pass number of pointers in the array in objectCount.
// Pass x and y coordinates of point you want to check.
// Pass pointer to validation function in ValidFunc.
// This is used to establish if a particular object is to be considered
// when finding nearest object. It should return true if object should be considered
// or false to ignore it. Pass NULL if all objects are considered valid.
// Pass pointer to variable that will hold index of object found in index.
// Returns true if nearest object was found, false if not (maybe no objects in array).
bool GameObject::FindNearestObject(
    GameObject **objects, UInt8 objectCount,
    Int16 x, Int16 y,
    bool (*ValidFunc)( GameObject *object ),
    UInt8 *index
) {
  GameObject *object;
    bool found = false;
    Int16 minDistance = 0x7FFF, distance;
  for( UInt8 i = 0; i < objectCount; ++i ) {
    object = objects[ i ];
    if(
            ( object != (GameObject*)NULL ) &&
            ( ( ValidFunc == NULL ) || ValidFunc( object ) )
        ) {
            // This calculation doesn't really calculate the distance between points.
            // Should really be calculating square root of the sum of the squares of the
            // difference between coordinates. Could leave out the square root.
            // However, this is a lot quicker, has less danger of overflow and is a
            // fairly good approximation for the purposes of a game.
            distance = abs( x - object->Xco ) + abs( y - object->Yco );
            if( distance < minDistance ) {
                found = true;
                minDistance = distance;
                *index = i;
            }
    }
  }
  return found;
}

/***************************************************************************/
/* REMOVE ALL OBJECTS IN AN ARRAY THAT ARE NOT RETAINED ON A LEVEL RESTART */
/***************************************************************************/
// Pass pointer to array of pointers to GameObjects in objects.
// Pass number of pointers in the array in objectCount.
// All objects pointed to in the array that have their RetainOnLevelRestart property set
// to false are removed by writing NULL into the array.
void GameObject::RemoveUnretainedObjects( GameObject **objects, UInt8 objectCount ) {
  GameObject *object;
  for( UInt8 i = 0; i < objectCount; ++i ) {
    object = objects[ i ];
    if( ( object != (GameObject*)NULL ) && ! object->RetainOnLevelRestart ) {
            objects[ i ] = (GameObject*)NULL;
    }
  }
}

/*******************************/
/* MOVE TOWARDS ANOTHER OBJECT */
/*******************************/
// Pass object to move towards in object.
// Pass speed at which to move in speed.
void GameObject::MoveTowards( GameObject *object, Int16 speed ) {
  if( Xco <= object->Xco - speed ) {
    Xco += speed;
  }
  else if( Xco >= object->Xco + speed ) {
    Xco -= speed;
  }
  if( Yco <= object->Yco - speed ) {
    Yco += speed;
  }
  else if( Yco >= object->Yco + speed ) {
    Yco -= speed;
  }
}