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
Revision 4:673eb9735d44, committed 2013-06-08
- Comitter:
- RichardE
- Date:
- Sat Jun 08 11:24:05 2013 +0000
- Parent:
- 3:a6a0cd726ca0
- Child:
- 5:0b0651ac7832
- Commit message:
- Pulled in more code. Now panel controls are working. Level 0 (attract mode) now goes round an endless loop sending state of panel controls up serial port to PC.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ArenaConst.cpp Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,11 @@ +#include "ArenaConst.h" +#include "GameObject.h" + +// Rectangle defining boundaries of arena. +Rectangle ArenaRectangle( + GameObject::FromPixel( ARENA_MIN_X ), + GameObject::FromPixel( ARENA_MIN_Y ), + GameObject::FromPixel( ARENA_MIN_X + ARENA_WIDTH - 1 ), + GameObject::FromPixel( ARENA_MIN_Y + ARENA_HEIGHT - 1 ) +); +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ArenaConst.h Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,38 @@ +/* + * SOURCE FILE : ArenaConst.h + * + * A few more constants associated with screen coordinates for gameplay arena. + * + */ + +#ifndef ArenaConstIncluded + + #define ArenaConstIncluded + + #include "GameObject.h" + #include "GDConst.h" + #include "Rectangle.h" + + // Pixel coordinates and dimensions. + #define ARENA_MIN_X 8 + #define ARENA_WIDTH 384 + #define ARENA_MIN_Y 16 + #define ARENA_HEIGHT 272 + + // Character coordinates and dimensions. + #define ARENA_BORDER_X 0 + #define ARENA_BORDER_Y 1 + #define ARENA_BORDER_WIDTH 50 + #define ARENA_BORDER_HEIGHT 36 + + // Rectangle defining boundaries of arena. + extern Rectangle ArenaRectangle; + + // Start coordinates for player. NOT pixel coordinates. + #define PLAYER_START_X GameObject::FromPixel( ( ARENA_MIN_X + ( ( ARENA_WIDTH - SPRITE_PIXEL_WIDTH ) >> 1 ) ) ) + #define PLAYER_START_Y GameObject::FromPixel( ( ARENA_MIN_Y + ( ( ARENA_HEIGHT - SPRITE_PIXEL_HEIGHT ) >> 1 ) ) ) + +#endif + +/* END of ArenaConst.h */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BCDNumber.cpp Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,60 @@ +/* + * SOURCE FILE : BCDNumber.cpp + * + * A 4 byte unsigned BCD integer. + * + */ + +#include "BCDNumber.h" + +/***********************/ +/* ADD TWO BCD NUMBERS */ +/***********************/ +// Pass first number in A. +// Pass second number in B. +// Pass pointer to result in result. +// Pass carry flag in carry. +// Remember numbers are BCD coded so 0x99999999 means 9 million, +// 9 hundred and 99 thousand, 9 hundred and 99. +// Returns carry flag. If this is set then overflow occurred. +bool BCDNumber::Add( UInt32 numA, UInt32 numB, UInt32 *result, bool carry ) { + const UInt8 *ptrA = (const UInt8*)&numA; + const UInt8 *ptrB = (const UInt8*)&numB; + UInt8 *ptrR = (UInt8*)result; + UInt8 sum, digits; + for( UInt8 b = 0; b < ByteCount; ++b ) { + digits = 0; + // Add together lower 4 bits. + sum = ( *ptrA & 0xF ) + ( *ptrB & 0xF ); + // If carry flag set then add one. + if( carry ) { + sum++; + } + // If result is >= 10 then set carry and subtract 10 from sum. + carry = ( sum >= 10 ); + if( carry ) { + sum -= 10; + } + // Write lower 4 bits. + digits |= sum; + // Add together upper 4 bits and carry. + sum = ( ( *ptrA & 0xF0 ) >> 4 ) + ( ( *ptrB & 0xF0 ) >> 4 ); + // If carry flag set then add one. + if( carry ) { + sum++; + } + // If result is >= 10 then set carry and subtract 10 from sum. + carry = ( sum >= 10 ); + if( carry ) { + sum -= 10; + } + // Write upper 4 bits. + digits |= ( sum << 4 ); + // Store digits in result and skip to next byte. + *ptrR++ = digits; + ptrA++; + ptrB++; + } + return carry; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BCDNumber.h Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,39 @@ +/* + * SOURCE FILE : BCDNumber.h + * + * A 4 byte unsigned BCD integer. + * + */ + +#ifndef BCDNumberIncluded + + #define BCDNumberIncluded + + #include "Types.h" + + class BCDNumber { + + public : + + enum { + ByteCount = 4, // Number of bytes used to store number. + }; + + /***********************/ + /* ADD TWO BCD NUMBERS */ + /***********************/ + // Pass first number in A. + // Pass second number in B. + // Pass pointer to result in result. + // Pass carry flag in carry. + // Remember numbers are BCD coded so 0x99999999 means 9 million, + // 9 hundred and 99 thousand, 9 hundred and 99. + // Returns carry flag. If this is set then overflow occurred. + static bool Add( UInt32 numA, UInt32 numB, UInt32 *result, bool carry = false ); + + }; + +#endif + +/* END of BCDNumber.h */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BulletManager.cpp Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,81 @@ +/* + * SOURCE FILE : BulletManager.cpp + * + * Responsible for managing a collection of bullets. + * + */ + +#include "BulletManager.h" +// #include "BulletObject.h" +// #include "ArenaConst.h" +#include "GDExtra.h" + +/***************/ +/* CONSTRUCTOR */ +/***************/ +// Pass number of sprite to use for first bullet. +// MaxBullets consequtive sprites will be used for bullets. +BulletManager::BulletManager( UInt8 firstSpriteNumber ) { +#if 0 + // Initialise aspects of bullets that never change. + BulletObject *bullet; + for( UInt8 b = 0; b < MaxBullets; ++b ) { + bullet = bullets + b; + bullet->SpriteNumber = firstSpriteNumber + b; + bullet->PixelWidth = 6; + bullet->PixelHeight = 6; + bullet->Bounds = &ArenaRectangle; + } +#endif +} + +/**********************/ +/* START A BULLET OFF */ +/**********************/ +// Pass start coordinates in x and y (NOT pixel coordinates). +// Pass bullet velocities in hv and vv (NOT pixel velocities). +// Returns true if bullet was started successfully. +bool BulletManager::StartBullet( Int16 x, Int16 y, Int16 hv, Int16 vv ) { +#if 0 + // Try and find an unused bullet slot. + UInt8 index; + if( GameObject::FindUnusedObject( bulletPointers, MaxBullets, &index ) ) { + // Found a free bullet slot. Point to entry in bullets array. + BulletObject *bullet = bullets + index; + bulletPointers[ index ] = bullet; + bullet->Start( x, y, hv, vv ); + return true; + } + else { + // No free bullet slots. + return false; + } +#else +return false; +#endif +} + +/************************/ +/* KILL A SINGLE BULLET */ +/************************/ +// Pass index of bullet in b. +void BulletManager::KillBullet( UInt8 b ) { +#if 0 + GameObject *bullet = bulletPointers[ b ]; + if( bullet != (GameObject*)NULL ) { + bulletPointers[ b ] = (BulletObject*)NULL; + // Hide bullet sprite by setting y coordinate to 400. + GDExtra::HideSprite( bullet->SpriteNumber ); + } +#endif +} + +/********************/ +/* KILL ALL BULLETS */ +/********************/ +void BulletManager::KillAllBullets( void ) { + for( UInt8 b = 0; b < MaxBullets; ++b ) { + KillBullet( b ); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BulletManager.h Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,73 @@ +/* + * SOURCE FILE : BulletManager.h + * + * Responsible for managing a collection of bullets. + * + */ + +#ifndef BulletManagerIncluded + + #define BulletManagerIncluded + + #include "Types.h" + #include "BulletObject.h" + + class BulletManager { + + public : + + enum { + MaxBullets = 20, // maximum number of bullets on the go at one tine. + }; + + /***************/ + /* CONSTRUCTOR */ + /***************/ + // Pass number of sprite to use for first bullet. + // MaxBullets consequtive sprites will be used for bullets. + BulletManager( UInt8 firstSpriteNumber ); + + /**********************/ + /* START A BULLET OFF */ + /**********************/ + // Pass start coordinates in x and y (NOT pixel coordinates). + // Pass bullet velocities in hv and vv (NOT pixel velocities). + // Returns true if bullet was started successfully. + bool StartBullet( Int16 x, Int16 y, Int16 hv, Int16 vv ); + + /************************/ + /* KILL A SINGLE BULLET */ + /************************/ + // Pass index of bullet in b. + void KillBullet( UInt8 b ); + + /********************/ + /* KILL ALL BULLETS */ + /********************/ + void KillAllBullets( void ); + + /************************************************/ + /* GET ARRAY CONTAINING POINTERS TO ALL BULLETS */ + /************************************************/ + // Returns pointer to array of GameObject pointers. + // The array has BulletManager::MaxBullets pointers in it. + GameObject **GetBullets( void ) { + return bulletPointers; + } + + private : + + // All the bullets. + BulletObject bullets[ MaxBullets ]; + + // Pointers to all the bullets. + // Entries in this array will be NULL for bullets that are not active. + // When bullet is active it will point to the corresponding entry in the bullets array. + GameObject *bulletPointers[ MaxBullets ]; + + }; + +#endif + +/* END of BulletManager.h */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BulletObject.h Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,90 @@ +/* + * SOURCE FILE : BulletObject.h + * + * Represents a bullet type objects with horizontal and vertical velocities. + * + */ + +#ifndef BulletObjectIncluded + + #define BulletObjectIncluded + + #include "Gameduino.h" + #include "GameObject.h" + #include "SpriteImageId.h" + #include "SpriteGroup.h" + + class BulletObject : public GameObject { + + public : + + /***************/ + /* CONSTRUCTOR */ + /***************/ + BulletObject() : + imageNumber( PlayerBulletImage ), + spriteGroup( GoodGuy ) + { + DeleteWhenRestricted = true; + } + + /**************/ + /* DESTRUCTOR */ + /**************/ + virtual ~BulletObject() { + } + + /************************/ + /* GET GAME OBJECT TYPE */ + /************************/ + // Returns type of game object. + virtual GameObjectTypes GetType( void ) { + return BulletObjectType; + } + + /****************/ + /* START BULLET */ + /****************/ + void Start( Int16 x, Int16 y, Int16 hv, Int16 vv ) { + Xco = x; + Yco = y; + hSpeed = hv; + vSpeed = vv; + Visible = true; + } + + /************************/ + /* MOVE THE GAME OBJECT */ + /************************/ + virtual void ProtectedMove( void ) { + Xco += hSpeed; + Yco += vSpeed; + } + + /************************/ + /* DRAW THE GAME OBJECT */ + /************************/ + // This is only called after it has been established that the + // game object is visible. + virtual void Draw( void ) { + // GD.sprite( SpriteNumber, ToPixel( Xco ), ToPixel( Yco ), imageNumber, 0, 0, spriteGroup ); + } + + private : + + // Number of sprite image used for bullet. + SpriteImageId imageNumber; + + // Indicates whether these are good or bad bullets for + // purposes of collision detection. + SpriteGroup spriteGroup; + + // Horizontal and vertical velocities. + Int16 hSpeed, vSpeed; + + }; + +#endif + +/* END of BulletObject.h */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BulletVelocities.h Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,121 @@ +/* + * SOURCE FILE : BulletVelocities.h + * + * Converts from set of joystick inputs to horizontal and vertical velocities. + * + */ + +#ifndef BulletVelocitiesIncluded + + #define BulletVelocitiesIncluded + + #include "Int16Pair.h" + + class BulletVelocities { + + public : + + /***************/ + /* CONSTRUCTOR */ + /***************/ + // Pass velocity for a horizontally moving bullet in h. + // Pass velocity for a vertically moving bullet in v. + BulletVelocities( Int16 h, Int16 v ) { + // Calculate velocities used on the diagonal. + // This is really doing hd = h * cos( 45 degrees ) and + // vd = v * sin( 45 degrees ). + Int16 hd = (Int16)floor( (double)h * 0.707 + 0.5 ); + Int16 vd = (Int16)floor( (double)v * 0.707 + 0.5 ); + // Initialise the table of velocities. + Int16Pair *ptr = pairs; + // No joystick contacts closed. Index 0. + ptr->X = 0; + ptr->Y = 0; + ptr++; + // Joystick up. Index 1 + ptr->X = 0; + ptr->Y = -v; + ptr++; + // Joystick down. Index 2. + ptr->X = 0; + ptr->Y = v; + ptr++; + // Joystick up and down (impossible). Index 3. + ptr->X = 0; + ptr->Y = v; + ptr++; + // Joystick left. Index 4. + ptr->X = -h; + ptr->Y = 0; + ptr++; + // Joystick left and up. Index 5. + ptr->X = -hd; + ptr->Y = -vd; + ptr++; + // Joystick left and down. Index 6. + ptr->X = -hd; + ptr->Y = vd; + ptr++; + // Joystick up, down and left (impossible). Index 7. + ptr->X = 0; + ptr->Y = v; + ptr++; + // Joystick right. Index 8. + ptr->X = h; + ptr->Y = 0; + ptr++; + // Joystick right and up. Index 9. + ptr->X = hd; + ptr->Y = -vd; + ptr++; + // Joystick right and down. Index 10. + ptr->X = hd; + ptr->Y = vd; + ptr++; + // Joystick up, down and right (impossible). Index 11. + ptr->X = 0; + ptr->Y = v; + ptr++; + // Joystick left and right (impossible). Index 12. + ptr->X = 0; + ptr->Y = v; + ptr++; + // Joystick up, left and right (impossible). Index 13. + ptr->X = 0; + ptr->Y = v; + ptr++; + // Joystick down, left and right (impossible) Index 14. + ptr->X = 0; + ptr->Y = v; + ptr++; + // Joystick up, down, left and right (impossible). Index 15. + ptr->X = 0; + ptr->Y = v; + ptr++; + } + + /*******************************************************/ + /* GET VELOCITIES FOR A COMBINATION OF JOYSTICK INPUTS */ + /*******************************************************/ + // Pass a map containing joystick inputs where a set bit indicates a closed contact. + // Bits must be ordered as follows : + // Bit 0 = Up. + // Bit 1 = Down. + // Bit 2 = Left. + // Bit 3 = Right. + // Remaining bits are ignored. + const Int16Pair *GetVelocities( UInt8 joyMap ) const { + return pairs + ( joyMap & 0x0F ); + } + + private : + + // Horizontal and vertical velocities for each combination of joystick inputs. + Int16Pair pairs[ 16 ]; + + }; + +#endif + +/* END of BulletVelocities.h */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FrameCounter.cpp Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,11 @@ +/* + * SOURCE FILE : FrameCounter.h + * + * A counter updated on every vertical fram flyback. + * + */ + +#include "Types.h" + +UInt8 FrameCounter = 0; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FrameCounter.h Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,17 @@ +/* + * SOURCE FILE : FrameCounter.h + * + * A counter updated on every vertical frame flyback. + * + */ + +#ifndef FrameCounterIncluded + + #include "Types.h" + + extern UInt8 FrameCounter; + +#endif + +/* END of FrameCounter.h */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GameObject.cpp Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,236 @@ +/* + * 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" + +/**********************************/ +/* 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 ) { +#if 0 + 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)++; + } +#endif +} + +/****************************/ +/* 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 ) { + 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; +} + +/****************************/ +/* DRAW AN ARRAY OF OBJECTS */ +/****************************/ +// Pass pointer to array of pointers to GameObjects in objects. +// Pass number of pointers in the array in objectCount. +void GameObject::DrawAll( GameObject **objects, UInt8 objectCount ) { +#if 0 + 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( ! object->Visible ) { + objects[ i ] = (GameObject*)NULL; + GDExtra::HideSprite( object->SpriteNumber ); + } + else { + object->Draw(); + } + } + } +#endif +} + +/************************************************/ +/* 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 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( GameObject **objects, UInt8 objectCount, void (*func)( UInt8, UInt8 ) ) { +#if 0 + 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( 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 ); + } + } + } +#endif +} + +/*************************************************************************/ +/* 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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GameObject.h Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,285 @@ +/* + * SOURCE FILE : GameObject.h + * + * The abstract base class for all graphical game objects. + * + */ + +#ifndef GameObjectIncluded + + #define GameObjectIncluded + + #include "Gameduino.h" // Gameduino stuff + #include "Types.h" + #include "GDConst.h" + #include "SpriteImageId.h" + #include "SpriteGroup.h" + #include "GameObjectTypes.h" + #include "Rectangle.h" + + class GameObject { + + public : + + // Bitmasks to use with RestrictionFlags. + enum RestrictionMask { + UpRestriction = 1, + DownRestriction = 2, + LeftRestriction = 4, + RightRestriction = 8, + }; + + // X coordinate (NOT pixel coordinate). + Int16 Xco; + + // Y coordinate (NOT pixel coordinate). + Int16 Yco; + + // Pixel width. + UInt8 PixelWidth; + + // Pixel height. + UInt8 PixelHeight; + + // Visibility flag. + bool Visible; + + // Limits for object movement. + Rectangle *Bounds; + + // Indicates if movement is restricted. + bool MovementRestricted; + + // Indicates object should be deleted when moves outside restricted area. + bool DeleteWhenRestricted; + + // Flags which are set when object is being restricted. + // Only works when MovementRestricted is true. + // If MovementRestricted is false RestrictionFlags are always all zero. + // Use RestrictionMask enumeration with this field. + UInt8 RestrictionFlags; + + // Indicates which Gameduino sprite is being used for this object. + UInt8 SpriteNumber; + + // Determines if object is retained on a level restart. + // Most enemy objects are retained on a level restart, although their positions change. + // However, enemy bullets (for example) are killed off on a level restart. + bool RetainOnLevelRestart; + + /***************/ + /* CONSTRUCTOR */ + /***************/ + GameObject() : + Xco( FromPixel( 100 ) ), + Yco( FromPixel( 100 ) ), + PixelWidth( SPRITE_PIXEL_WIDTH ), + PixelHeight( SPRITE_PIXEL_HEIGHT ), + Visible( true ), + Bounds( NULL ), + MovementRestricted( true ), + DeleteWhenRestricted( false ), + RestrictionFlags( 0 ), + SpriteNumber( 0 ), + RetainOnLevelRestart( true ) + { + } + + /**************/ + /* DESTRUCTOR */ + /**************/ + // Must be virtual! + // If not then could end up calling the base class + // destructor for a derived class. Not pretty. + virtual ~GameObject() { + } + + /************************/ + /* GET GAME OBJECT TYPE */ + /************************/ + // Returns type of game object. + virtual GameObjectTypes GetType( void ) = 0; + + // Note that coordinates for all game objects are NOT screen pixel coordinates. + // The coordinate system used has a much higher resolution that the screen. + // This allows objects to move at a speed of less than one pixel per screen update. + // Use the methods ToPixel and FromPixel to convert between game object coordinates + // and pixel coordinates. + + /********************************/ + /* CONVERT TO PIXEL COORDINATES */ + /********************************/ + // Returns pixel equivalent of coordinate. + static Int16 ToPixel( Int16 x ) { + return ( x >> 6 ); + } + + /**********************************/ + /* CONVERT FROM PIXEL COORDINATES */ + /**********************************/ + // Returns pixel equivalent of coordinate. + static Int16 FromPixel( Int16 x ) { + return ( x << 6 ); + } + + /************************/ + /* MOVE THE GAME OBJECT */ + /************************/ + void Move( void ) { + ProtectedMove(); + // Calculate coordinates for edges of object. + Int16 dx = FromPixel( ( SPRITE_PIXEL_WIDTH - PixelWidth ) >> 1 ); + Int16 dy = FromPixel( ( SPRITE_PIXEL_HEIGHT - PixelHeight ) >> 1 ); + Int16 left = Xco + dx; + Int16 top = Yco + dy; + Int16 right = left + FromPixel( PixelWidth - 1 ); + Int16 bottom = top + FromPixel( PixelHeight - 1 ); + RestrictionFlags = 0; + // Kill off or restrict movement if moved outside restricted area. + // Do nothing if Bounds is NULL. + if( Bounds != NULL ) { + if( DeleteWhenRestricted ) { + if( + left < Bounds->X1 || + right > Bounds->X2 || + top < Bounds->Y1 || + bottom > Bounds->Y2 + ) { + Visible = false; + } + } + else if( MovementRestricted ) { + if( left < Bounds->X1 ) { + Xco = Bounds->X1 - dx; + RestrictionFlags |= (UInt8)LeftRestriction; + } + else if( right > Bounds->X2 ) { + Xco = Bounds->X2 - FromPixel( PixelWidth - 1 ); + RestrictionFlags |= (UInt8)RightRestriction; + } + if( top < Bounds->Y1 ) { + Yco = Bounds->Y1 - dy; + RestrictionFlags |= (UInt8)UpRestriction; + } + else if( bottom > Bounds->Y2 ) { + Yco = Bounds->Y2 - FromPixel( PixelHeight - 1 ); + RestrictionFlags |= (UInt8)DownRestriction; + } + } + } + } + + /************************/ + /* DRAW THE GAME OBJECT */ + /************************/ + // Note if Visible is false this should not draw anything + // and/or hide the visible object. + virtual void Draw( void ) = 0; + + /**********************************/ + /* 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. + static void InitialiseAll( GameObject **objects, UInt8 objectCount, UInt8 *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. + static bool MoveAll( GameObject **objects, UInt8 objectCount ); + + /****************************/ + /* DRAW AN ARRAY OF OBJECTS */ + /****************************/ + // Pass pointer to array of pointers to GameObjects in objects. + // Pass number of pointers in the array in objectCount. + static void DrawAll( GameObject **objects, UInt8 objectCount ); + + /************************************************/ + /* 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. + static bool FindUnusedObject( GameObject **objects, UInt8 objectCount, UInt8 *index ); + + /****************************************************/ + /* FIND COLLISIONS WITH ALL THE OBJECTS IN AN ARRAY */ + /****************************************************/ + // 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. + static void FindCollisions( GameObject **objects, UInt8 objectCount, void (*func)( UInt8, UInt8 ) ); + + /*************************************************************************/ + /* 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. + static bool FindSpriteNumber( GameObject **objects, UInt8 objectCount, UInt8 spriteNumber, UInt8 *index ); + + /**********************************************/ + /* 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). + static bool FindNearestObject( + GameObject **objects, UInt8 objectCount, + Int16 x, Int16 y, + bool (*ValidFunc)( GameObject *object ), + UInt8 *index + ); + + /***************************************************************************/ + /* 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. + static void RemoveUnretainedObjects( GameObject **objects, UInt8 objectCount ); + + /*******************************/ + /* MOVE TOWARDS ANOTHER OBJECT */ + /*******************************/ + // Pass object to move towards in object. + // Pass speed at which to move in speed. + void MoveTowards( GameObject *object, Int16 speed ); + + protected : + + /************************/ + /* MOVE THE GAME OBJECT */ + /************************/ + virtual void ProtectedMove( void ) = 0; + + private : + + }; + +#endif + +/* END of GameObject.h */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GameObjectLocator.cpp Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,71 @@ +/* + * SOURCE FILE : GameObjectLocator.cpp + * + * Code for randomly positioning objects. + * + */ + +#include "GameObjectLocator.h" +#include "ArenaConst.h" +#include "Random.h" + +// Indicates which quadrant to put next object in. +UInt8 GameObjectLocator::quad = 0; + +/*************************************/ +/* POSITION OBJECT RANDOMLY IN ARENA */ +/*************************************/ +// Pass object to locate in obj. +void GameObjectLocator::Locate( GameObject *obj ) { + Int16 x, y; + + // Calculate start pixel coordinates for player. + Int16 ppx = GameObject::ToPixel( PLAYER_START_X ); + Int16 ppy = GameObject::ToPixel( PLAYER_START_Y ); + + // Keep calculating random coordinates until coordinates chosen + // are some distance away from chase object. + do { + + x = Random::Get( ( ARENA_WIDTH >> 1 ) - SPRITE_PIXEL_WIDTH - 4 ); + y = Random::Get( ( ARENA_HEIGHT >> 1 ) - SPRITE_PIXEL_HEIGHT - 4 ); + + switch( quad ) { + + case 0 : + x += ARENA_MIN_X; + y += ARENA_MIN_Y; + break; + + case 1 : + x = ARENA_MIN_X + ARENA_WIDTH - SPRITE_PIXEL_WIDTH - x; + y += ARENA_MIN_Y; + break; + + case 2 : + x += ARENA_MIN_X; + y = ARENA_MIN_Y + ARENA_HEIGHT - SPRITE_PIXEL_HEIGHT - y; + break; + + case 3 : + x = ARENA_MIN_X + ARENA_WIDTH - SPRITE_PIXEL_WIDTH - x; + y = ARENA_MIN_Y + ARENA_HEIGHT - SPRITE_PIXEL_HEIGHT - y; + break; + + } + + } while( + ( abs( x - ppx ) < ( SPRITE_PIXEL_WIDTH << 1 ) ) && + ( abs( y - ppy ) < ( SPRITE_PIXEL_HEIGHT << 1 ) ) + ); + + obj->Xco = GameObject::FromPixel( x ); + obj->Yco = GameObject::FromPixel( y ); + + // Use next quadrant on next call. + quad++; + quad &= 3; + +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GameObjectLocator.h Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,34 @@ +/* + * SOURCE FILE : GameObjectLocator.h + * + * Code for randomly positioning objects. + * + */ + +#ifndef GameObjectLocatorIncluded + + #define GameObjectLocatorIncluded + + #include "GameObject.h" + + class GameObjectLocator { + + public : + + /*************************************/ + /* POSITION OBJECT RANDOMLY IN ARENA */ + /*************************************/ + // Pass object to locate in obj. + static void Locate( GameObject *obj ); + + private : + + // Indicates which quadrant to put next object in. + static UInt8 quad; + + }; + +#endif + +/* END of GameObjectLocator.h */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GameObjectTypes.h Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,27 @@ +/* + * SOURCE FILE : GameObjectTypes.h + * + * Enumeration of all the game object types. + * + */ + +#ifndef GameObjectTypesIncluded + + #define GameObjectTypesIncluded + + // Note that different kinds of enemies can be distinguished using the EnemyType enumeration. + + enum GameObjectTypes { + PlayerObjectType, + BulletObjectType, + ExplosionObjectType, + EnemyObjectType, + HumanObjectType, + FiftyObjectType, + StarObjectType, + }; + +#endif + +/* END of GameObjectTypes.h */ +
--- a/GameRobotRic.cpp Fri Jun 07 20:29:59 2013 +0000 +++ b/GameRobotRic.cpp Sat Jun 08 11:24:05 2013 +0000 @@ -10,13 +10,10 @@ #include "LevelCollection.h" // all the levels #include "sprite.h" // sprite data #include "RobotRicCharacterSet.h" // character set used in this game -#if 0 - #include "GDExtra.h" // extra Gameduino functions - #include "GDConst.h" // a few more Gameduino constants - #include "ArenaConst.h" // gameplay arena constants - #include "I2CEEPROM.h" // for access to serial EEPROM - #include "HighScoreEntry.h" // for getting player's name for high score table -#endif +#include "HighScoreEntry.h" // for getting player's name for high score table +#include "GDExtra.h" // extra Gameduino functions +#include "GDConst.h" // a few more Gameduino constants +#include "ArenaConst.h" // gameplay arena constants // Define following for debugging messages to serial port. #define CHATTY @@ -24,24 +21,16 @@ // Number of lives player starts with. #define START_LIVES 5 -// Pin allocations for I2C communications link. -#define EEPROM_SCL 5 -#define EEPROM_SDA 7 -#define EEPROM_WP 8 - -// Address of EEPROM set using A0, A1 and A2 pins. -#define ADDRESS_OF_EEPROM 0 - // Serial link to PC over USB cable. Globally accessible. Serial pc( USBTX, USBRX ); /**************************/ /* CHECK FOR A HIGH SCORE */ /**************************/ +// Pass pointer to a Gameduino to display on in gd. // Pass pointer to high score table in highScores. // Pass score that was achieved in score. -void GameRobotRic::CheckForHighScore( HighScoreTable *highScores, UInt32 score ) { -#if 0 +void GameRobotRic::CheckForHighScore( Gameduino *gd, HighScoreTable *highScores, UInt32 score ) { UInt8 tablePos; // Enter name into high score table if score is high enough. if( ( tablePos = highScores->GetPositionInTable( player.Score ) ) < highScores->GetCapacity() ) { @@ -49,11 +38,10 @@ // Get player to input name. HighScoreEntry nameGetter; PlayerName name; - nameGetter.GetName( &name, &controls ); + nameGetter.GetName( &name, &controls, gd ); // Add name and score to table. highScores->Add( tablePos, &name, score ); } -#endif } /*****************/ @@ -61,9 +49,9 @@ /*****************/ // This NEVER exits. void GameRobotRic::Play( void ) { - #ifdef CHATTY - pc.puts( "Program has restarted!\r\n" ); - #endif +#ifdef CHATTY + pc.puts( "Program has restarted!\r\n" ); +#endif // Make a digital output for use as the Gameduino chip select pin. Deselect it. DigitalOut gameduinoCS( p8 ); gameduinoCS = 1; @@ -105,63 +93,55 @@ HighScoreTable highScores( &eeprom ); // Start on the attract level. UInt8 levelNumber = LevelCollection::AttractLevel; -#if 0 - player.Lives = START_LIVES; -#endif - LevelCollection levels; - Level *level; - Level::LevelExitCode exitCode; -#if 0 - // Initialise panel controls. - controls.InitialisePins(); - // Specify controls player should use. - player.SetControls( &controls ); - // Restrict players movement. - player.MovementRestricted = true; - player.Bounds = &ArenaRectangle; -#endif - // Repeat forever. - while( true ) { - // Get level specified by level number. - level = levels.GetLevel( levelNumber ); - // If failed to get level with that number go back to first normal level. - // This will happen if player completes last level. - if( level == NULL ) { - levelNumber = LevelCollection::FirstNormalLevel; - // Refetch level. - level = levels.GetLevel( levelNumber ); + player.Lives = START_LIVES; + LevelCollection levels; + Level *level; + Level::LevelExitCode exitCode; + // Initialise panel controls. + controls.InitialisePins(); + // Specify controls player should use. + player.SetControls( &controls ); + // Restrict players movement. + player.MovementRestricted = true; + player.Bounds = &ArenaRectangle; + // Repeat forever. + while( true ) { + // Get level specified by level number. + level = levels.GetLevel( levelNumber ); + // If failed to get level with that number go back to first normal level. + // This will happen if player completes last level. + if( level == NULL ) { + levelNumber = LevelCollection::FirstNormalLevel; + // Refetch level. + level = levels.GetLevel( levelNumber ); + } + // Pass reference to high score table. + level->SetHighScores( &highScores ); + // Set player that is playing the level. + level->SetPlayer( &player ); + // Set Gameduino to use. + level->SetGameduino( &gd ); + // Play the level. + exitCode = level->Play(); + // If player was killed then decrement lives otherwise + // advance to next level. + switch( exitCode ) { + case Level::GameOver : + // TODO : Do some sort of game over fuss. + CheckForHighScore( &gd, &highScores, player.Score ); + // Go back to attract level and reset player lives and score. + levelNumber = LevelCollection::AttractLevel; + player.Lives = START_LIVES; + player.Score = 0; + break; + case Level::Completed : + levelNumber++; + break; + } + // Wait a bit. + wait( (float)2 ); } - // Pass reference to high score table. - level->SetHighScores( &highScores ); -#if 0 - // Set player that is playing the level. - level->SetPlayer( &player ); -#endif - // Set Gameduino to use. - level->SetGameduino( &gd ); - // Play the level. - exitCode = level->Play(); - // If player was killed then decrement lives otherwise - // advance to next level. - switch( exitCode ) { - case Level::GameOver : -#if 0 - // TODO : Do some sort of game over fuss. - CheckForHighScore( &highScores, player.Score ); -#endif - // Go back to attract level and reset player lives and score. - levelNumber = LevelCollection::AttractLevel; -#if 0 - player.Lives = START_LIVES; - player.Score = 0; -#endif - break; - case Level::Completed : - levelNumber++; - break; - } - // Wait a bit. - wait( (float)2 ); - } } + +
--- a/GameRobotRic.h Fri Jun 07 20:29:59 2013 +0000 +++ b/GameRobotRic.h Sat Jun 08 11:24:05 2013 +0000 @@ -11,7 +11,8 @@ #include "Gameduino.h" // Gameduino stuff #include "Game.h" // base class for all games - // #include "PlayerObject.h" + #include "PanelControls.h" // for joysticks and buttons + #include "PlayerObject.h" #include "HighScoreTable.h" // for high score table stored in external EEPROM class GameRobotRic : public Game { @@ -27,17 +28,18 @@ private : // The one and only player. - // PlayerObject player; + PlayerObject player; // Controls used by player. - // PanelControls controls; + PanelControls controls; /**************************/ /* CHECK FOR A HIGH SCORE */ /**************************/ + // Pass pointer to a Gameduino to display on in gd. // Pass pointer to high score table in highScores. // Pass score that was achieved in score. - void CheckForHighScore( HighScoreTable *highScores, UInt32 score ); + void CheckForHighScore( Gameduino *gd, HighScoreTable *highScores, UInt32 score ); };
--- a/HighScoreEntry.cpp Fri Jun 07 20:29:59 2013 +0000 +++ b/HighScoreEntry.cpp Sat Jun 08 11:24:05 2013 +0000 @@ -8,14 +8,12 @@ #include "HighScoreEntry.h" #include "Gameduino.h" // Gameduino stuff -#if 0 - #include "GDExtra.h" // more Gameduino stuff - #include "GDConst.h" // Gameduino constants - #include "CharBlocks.h" // blocks of characters in program memory - #include "CharFrame.h" // for drawing frames made of characters - #include "CharCodes.h" // character codes - #include "FrameCounter.h" // counter updated every vertical flyback -#endif +#include "GDExtra.h" // more Gameduino stuff +#include "GDConst.h" // Gameduino constants +#include "FrameCounter.h" // counter updated every vertical flyback +#include "CharBlocks.h" // blocks of characters in program memory +#include "CharFrame.h" // for drawing frames made of characters +#include "CharCodes.h" // character codes /***************/ /* CONSTRUCTOR */ @@ -36,8 +34,8 @@ /*********************/ // Pass pointer to place to store name in name. // Pass pointer to controls to read in controls. -#if 0 -void HighScoreEntry::GetName( PlayerName *name, PanelControls *controls ) { +// Pass pointer to Gameduino to display on in gd. +void HighScoreEntry::GetName( PlayerName *name, PanelControls *controls, Gameduino *gd ) { UInt16 inputs; UInt8 countdown = 0; char *curPtr; @@ -46,9 +44,9 @@ name->Name[ i ] = 'A'; } // Draw screen. - DrawScreen(); + DrawScreen( gd ); // Wait until player releases all controls. - WaitControls( controls, false ); + WaitControls( gd, controls, false ); // Start at leftmost character. cursorPos = 0; // Loop until cursor moves beyond rightmost character. @@ -84,90 +82,86 @@ if( cursorPos > 0 ) { cursorPos--; // Wait until all controls released. - WaitControls( controls, false ); + WaitControls( gd, controls, false ); } } else if( inputs & PanelControls::Right1 ) { // Joystick right moves cursor forwards. cursorPos++; // Wait until all controls released. - WaitControls( controls, false ); + WaitControls( gd, controls, false ); } } else { countdown--; } // Wait for vertical flyback. Then draw name and do animation. - GD.waitvblank(); + gd->waitvblank(); FrameCounter++; - DrawName( name ); - Animate(); + DrawName( gd, name ); + Animate( gd ); } // Wait until player releases all controls before returning. - WaitControls( controls, false ); + WaitControls( gd, controls, false ); } -#endif /*********************/ /* WAIT FOR CONTROLS */ /*********************/ +// Pass pointer to Gameduino to display on in gd. // Pass pointer to controls to read in controls. // Pass true in waitActivate to wait for a control to be used. // Pass false to wait for release. -#if 0 -void HighScoreEntry::WaitControls( PanelControls *controls, bool waitActivate ) { - boolean released = false; +void HighScoreEntry::WaitControls( Gameduino *gd, PanelControls *controls, bool waitActivate ) { + bool released = false; UInt16 inputs; while( ! released ) { controls->Read(); inputs = controls->GetInputs(); released = ( waitActivate ? ( inputs != 0 ) : ( inputs == 0 ) ); if( ! released ) { - GD.waitvblank(); + gd->waitvblank(); FrameCounter++; - Animate(); + Animate( gd ); } } } -#endif /*******************/ /* DRAW THE SCREEN */ /*******************/ -void HighScoreEntry::DrawScreen( void ) { -#if 0 - GD.waitvblank(); +// Pass pointer to Gameduino to draw on in gd. +void HighScoreEntry::DrawScreen( Gameduino *gd ) { + gd->waitvblank(); // Clear the screen to zero characters. - GD.fill( RAM_PIC, 0, RAM_PIC_SIZE ); + gd->fill( Gameduino::RAM_PIC, 0, RAM_PIC_SIZE ); // Turn off all the sprites. for( UInt16 s = 0; s < SPRITE_COUNT; ++s ) { - GD.sprite( s, 0, 400, 0, 0 ); + gd->sprite( s, 0, 400, 0, 0 ); } // Draw border around screen. - CharFrame::Draw( 0, 0, VISIBLE_CHAR_WIDTH, VISIBLE_CHAR_HEIGHT ); + CharFrame::Draw( gd, 0, 0, VISIBLE_CHAR_WIDTH, VISIBLE_CHAR_HEIGHT ); // Draw logo. - GDExtra::WriteProgCharBlock( 2, 2, CharBlocks::EnterNameInstructionText ); -#endif + GDExtra::WriteProgCharBlock( gd, 2, 2, CharBlocks::EnterNameInstructionText ); } /********************************/ /* DRAW THE NAME AND THE CURSOR */ /********************************/ +// Pass pointer to Gameduino to draw on in gd. // Pass player name in name. -void HighScoreEntry::DrawName( PlayerName *name ) { -#if 0 - GD.putstr( 21, 11, name->Name ); - UInt16 address = RAM_PIC + 12 * SCREEN_CHAR_WIDTH + 21; +void HighScoreEntry::DrawName( Gameduino *gd, PlayerName *name ) { + gd->putstr( 21, 11, name->Name ); + UInt16 address = Gameduino::RAM_PIC + 12 * SCREEN_CHAR_WIDTH + 21; for( UInt8 i = 0; i < PlayerName::Length; ++i ) { - GD.wr( address, ( i == cursorPos ) ? ArrowUp : ' ' ); + gd->wr( address, ( i == cursorPos ) ? ArrowUp : ' ' ); address++; } -#endif } /********************/ /* UPDATE ANIMATION */ /********************/ -void HighScoreEntry::Animate( void ) { +// Pass pointer to Gameduino to display on in gd. +void HighScoreEntry::Animate( Gameduino *gd ) { } -
--- a/HighScoreEntry.h Fri Jun 07 20:29:59 2013 +0000 +++ b/HighScoreEntry.h Sat Jun 08 11:24:05 2013 +0000 @@ -11,8 +11,9 @@ #define HighScoreEntryDefined #include "Types.h" - // #include "PanelControls.h" // for reading panel controls. + #include "PanelControls.h" // for reading panel controls. #include "PlayerName.h" + #include "Gameduino.h" class HighScoreEntry { @@ -33,7 +34,8 @@ /*********************/ // Pass pointer to place to store name in name. // Pass pointer to controls to read in controls. - // void GetName( PlayerName *name, PanelControls *controls ); + // Pass pointer to Gameduino to display on in gd. + void GetName( PlayerName *name, PanelControls *controls, Gameduino *gd ); private : @@ -43,26 +45,30 @@ /*********************/ /* WAIT FOR CONTROLS */ /*********************/ + // Pass pointer to Gameduino to display on in gd. // Pass pointer to controls to read in controls. // Pass true in waitActivate to wait for a control to be used. // Pass false to wait for release. - // void WaitControls( PanelControls *controls, bool waitActivate ); + void WaitControls( Gameduino *gd, PanelControls *controls, bool waitActivate ); /*******************/ /* DRAW THE SCREEN */ /*******************/ - void DrawScreen( void ); + // Pass pointer to Gameduino to display on in gd. + void DrawScreen( Gameduino *gd ); /********************************/ /* DRAW THE NAME AND THE CURSOR */ /********************************/ + // Pass pointer to Gameduino to display on in gd. // Pass player name in name. - void DrawName( PlayerName *name ); + void DrawName( Gameduino *gd, PlayerName *name ); /********************/ /* UPDATE ANIMATION */ /********************/ - void Animate( void ); + // Pass pointer to Gameduino to display on in gd. + void Animate( Gameduino *gd ); };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Int16Pair.h Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,45 @@ +/* + * SOURCE FILE : Int16Pair.h + * + * Pair of Int16s in a class. + * + */ + +#ifndef Int16PairIncluded + + #define Int16PairIncluded + + #include "Types.h" + + class Int16Pair { + + public : + + // X and Y components. + Int16 X, Y; + + /***************/ + /* CONSTRUCTOR */ + /***************/ + Int16Pair() : + X( 0 ), + Y( 0 ) + { + } + + /***************/ + /* CONSTRUCTOR */ + /***************/ + // Pass X and Y components in x and y. + Int16Pair( Int16 x, Int16 y ) : + X( x ), + Y( y ) + { + } + + }; + +#endif + +/* END of Int16Pair.h */ +
--- a/Level.h Fri Jun 07 20:29:59 2013 +0000 +++ b/Level.h Sat Jun 08 11:24:05 2013 +0000 @@ -19,6 +19,8 @@ #include "StringData.h" #include "HighScoreTable.h" #include "CharFrame.h" + #include "PanelControls.h" + #include "PlayerObject.h" #if 0 #include "ArenaConst.h" #include "SpriteImageId.h" @@ -68,11 +70,9 @@ /* SET PLAYER WHO IS PLAYING THE LEVEL */ /***************************************/ // Pass pointer to player in p. -#if 0 void SetPlayer( PlayerObject *p ) { player = p; } -#endif // Enumeration of reasons why level ended. enum LevelExitCode { @@ -95,7 +95,7 @@ Gameduino *gd; // Player playing the level. - // PlayerObject *player; + PlayerObject *player; /*************/ /* PLAY LOOP */
--- a/Level0.cpp Fri Jun 07 20:29:59 2013 +0000 +++ b/Level0.cpp Sat Jun 08 11:24:05 2013 +0000 @@ -6,10 +6,10 @@ */ #include "Level0.h" -#if 0 - #include "CharBlocks.h" - #include "EEPROMDump.h" -#endif +#include "CharBlocks.h" + +// REMOVE THIS! +extern Serial pc; /***************/ /* CONSTRUCTOR */ @@ -82,7 +82,6 @@ DrawHighScores(); } } - #if 0 // Must have a player with non-NULL controls. PanelControls *controls; if( @@ -99,9 +98,9 @@ do { controls->Read(); inputs = controls->GetInputs(); - } while( inputs == 0 ); + pc.printf( "Inputs = %04X\r\n", (int)inputs ); + } while( true /* inputs == 0 */ ); } - #endif } return Completed; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PanelControls.h Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,107 @@ +/* + * SOURCE FILE : PanelControls.h + * + * Responsible for reading joysticks and buttons. + * This is the version for mbed LPC1768. + * There is a version kicking around for the LPC11U24 that uses different inputs for joystick 2. + * + */ + +#ifndef PanelControlsIncluded + + #define PanelControlsIncluded + + #include "mbed.h" + #include "Types.h" + + class PanelControls { + + public : + + /***************/ + /* CONSTRUCTOR */ + /***************/ + PanelControls() : + inputs( 0 ), + bus( (BusIn*)NULL ) + { + } + + /**************/ + /* DESTRUCTOR */ + /**************/ + ~PanelControls() { + delete bus; + } + + /*************************/ + /* INITIALISE INPUT PINS */ + /*************************/ + void InitialisePins( void ) { + // Create an input bus. + bus = new BusIn( + p23, p24, p25, p26, // joystick 1 up, down, left, right + p21, p22, p27, p28, // joystick 2 up, down, left, right + p29, p30 // button 1, button 2 + ); + } + + /*****************************/ + /* READ ALL THE PANEL INPUTS */ + /*****************************/ + // Returns a bitmap of all the inputs. + void Read( void ) { + if( bus == (BusIn*)NULL ) { + inputs = 0; + } + else { + // Note that a closed contact registers as a zero + // which is why the bitwise not operator (~) is used. + inputs = ~*bus & 0x3FF; + } + } + + // Masks to use with GetInputs method. + enum Mask { + Up1 = 1, + Down1 = 2, + Left1 = 4, + Right1 = 8, + Up2 = 16, + Down2 = 32, + Left2 = 64, + Right2 = 128, + Button1 = 256, + Button2 = 512, + }; + + // Bit numbers indicating where readings for each joystick start in the map. + // Can use these with right shift operator. + enum Bits { + Joy1 = 0, // joystick 1 readings start at bit 0 + Joy2 = 4, // joystick 2 readings start at bit 4 + Buttons = 8, // button readings start at bit 8 + }; + + /***************************/ + /* GET STATE OF THE INPUTS */ + /***************************/ + // Returns a bitmap of the state of the inputs + // last time Read was called. + UInt16 GetInputs( void ) { + return inputs; + } + + private : + + // Stored state of inputs. + UInt16 inputs; + + // Input bus used to read inputs. + BusIn *bus; + + }; + +#endif + +/* END of PanelControls.h */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PlayerObject.cpp Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,163 @@ +/* + * SOURCE FILE : PlayerObject.cpp + * + * Represents the player objects. + * + */ + +#include "PlayerObject.h" +// #include "SoundManager.h" +// #include "Sounds.h" +// #include "FrameCounter.h" + +// Bullet velocity information. +BulletVelocities PlayerObject::bulletVelocities( FromPixel( 2 ), FromPixel( 2 ) ); + +// Player velocity information. +BulletVelocities PlayerObject::playerVelocities( FromPixel( 1 ), FromPixel( 1 ) ); + +/***************/ +/* CONSTRUCTOR */ +/***************/ +PlayerObject::PlayerObject() : + Lives( 5 ), + Score( 0 ), + controls( (PanelControls*)NULL ), + playerBullets( 200 ), // parameter is first sprite number used for bullets + bulletCountdown( 0 ) +{ +} + +/**************/ +/* DESTRUCTOR */ +/**************/ +PlayerObject::~PlayerObject() { +} + +/************************/ +/* MOVE THE GAME OBJECT */ +/************************/ +void PlayerObject::ProtectedMove( void ) { +#if 0 + // Do nothing if controls are not specified. + if( controls != (PanelControls*)NULL ) { + // Read joysticks and buttons. Buttons are not used. + UInt16 map = controls->GetInputs(); + // Extract bits relating to joystick 1 (player movement). + UInt16 joy1Map = ( map >> PanelControls::Joy1 ) & 0x0F; + // Fetch velocities associated with this combination of joystick inputs. + const Int16Pair *pair = playerVelocities.GetVelocities( joy1Map ); + // Add on velocities to player coordinates. + Xco += pair->X; + Yco += pair->Y; + // Deal with starting a new bullet. + if( bulletCountdown > 0 ) { + bulletCountdown--; + } + else { + // Extract bits relating to joystick 2 (bullet firing). + UInt16 joy2Map = ( map >> PanelControls::Joy2 ) & 0x0F; + // Only start a bullet if at least one joystick contact is closed. + if( joy2Map != 0 ) { + // Fetch velocities associated with this combination of joystick inputs. + pair = bulletVelocities.GetVelocities( joy2Map ); + // Try and start a new bullet. + if( playerBullets.StartBullet( Xco, Yco, pair->X, pair->Y ) ) { + // If bullet was started then make a bullet sound. + SoundManager::Instance.PlaySound( Sounds::FireGun, 0, 0 ); + } + // Reset countdown until another bullet can start. + bulletCountdown = 8; + } + } + } +#endif +} + +/************************/ +/* DRAW THE GAME OBJECT */ +/************************/ +// This is only called after it has been established that the +// game object is visible. +void PlayerObject::Draw( void ) { +#if 0 + SpriteTransform transform; + SpriteImageId imageId; + // Check controls have been specified. + if( controls != (PanelControls*)NULL ) { + // Read joysticks and buttons. Buttons are not used. + UInt16 map = controls->GetInputs(); + // Work out which sprite image to use and how to transform it. + // Player shifts from left to right foot every 4 frames. + bool leftFootUp = ( ( FrameCounter & 4 ) != 0 ); + if( map & PanelControls::Left2 ) { + // Firing to the left. + transform = STNormal; + if( map & PanelControls::Up2 ) { + // Firing left and up. + imageId = leftFootUp ? PlayerGunUpLeftFootUpImage : PlayerGunUpRightFootUpImage; + } + else if( map & PanelControls::Down2 ) { + // Firing left and down. + imageId = leftFootUp ? PlayerGunDownLeftFootUpImage : PlayerGunDownRightFootUpImage; + } + else { + // Firing left and level. + imageId = leftFootUp ? PlayerGunLevelLeftFootUpImage : PlayerGunLevelRightFootUpImage; + } + } + else if( map & PanelControls::Right2 ) { + // Firing to the right. + transform = STFlipX; + if( map & PanelControls::Up2 ) { + // Firing right and up. Image is flipped so left foot becomes right foot. + imageId = leftFootUp ? PlayerGunUpRightFootUpImage : PlayerGunUpLeftFootUpImage; + } + else if( map & PanelControls::Down2 ) { + // Firing right and down. Image is flipped so left foot becomes right foot. + imageId = leftFootUp ? PlayerGunDownRightFootUpImage : PlayerGunDownLeftFootUpImage; + } + else { + // Firing right and level. Image is flipped so left foot becomes right foot. + imageId = leftFootUp ? PlayerGunLevelRightFootUpImage : PlayerGunLevelLeftFootUpImage; + } + } + else { + // Firing up, down or not firing. + transform = leftFootUp ? STNormal : STFlipX; + // Use a different image if firing up. + imageId = ( map & PanelControls::Up2 ) ? PlayerBothGunsUpImage : PlayerImage; + } + } + else { + // Controls have not been specified so use standing still image. + transform = STNormal; + imageId = PlayerImage; + } + GD.sprite( SpriteNumber, ToPixel( Xco ), ToPixel( Yco ), imageId, 0, transform, GoodGuy ); +#endif +} + +/*************************/ +/* ADD TO PLAYER'S SCORE */ +/*************************/ +// Pass number of points to add in points (THIS IS BCD CODED!). +void PlayerObject::AddToScore( UInt16 points ) { + // Get fourth digit from the right of the score. + UInt8 digit = (UInt8)( ( Score & 0xF000 ) >> 12 ); + // Add on points. + if( BCDNumber::Add( Score, points, &Score ) ) { + // If score overflows then stick at maximum. + Score = 0x99999999UL; + } + // Check if the fourth digit from the right has changed. + // If it has then you must have passed through a thousand point + // boundary so award an extra life but don't let it overflow. +#if 0 + if( ( digit != (UInt8)( ( Score & 0xF000 ) >> 12 ) ) && ( Lives < 255 ) ) { + SoundManager::Instance.PlaySound( Sounds::ExtraLife, 0, 0 ); + Lives++; + } +#endif +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PlayerObject.h Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,136 @@ +/* + * SOURCE FILE : PlayerObject.h + * + * Represents the player objects. + * + */ + +#ifndef PlayerObjectIncluded + + #define PlayerObjectIncluded + + #include "Gameduino.h" + #include "GameObject.h" + #include "BulletManager.h" + #include "PanelControls.h" + #include "BulletVelocities.h" + #include "SpriteImageId.h" + #include "BCDNumber.h" + + class PlayerObject : public GameObject { + + public : + + // Lives remaining. + UInt8 Lives; + + // Score as a BCD number. + UInt32 Score; + + /***************/ + /* CONSTRUCTOR */ + /***************/ + PlayerObject(); + + /**************/ + /* DESTRUCTOR */ + /**************/ + virtual ~PlayerObject(); + + /**************************************/ + /* SET CONTROLS FOR THE PLAYER TO USE */ + /**************************************/ + // Pass controls to use in pc. + void SetControls( PanelControls *pc ) { + controls = pc; + } + + /*****************************************/ + /* GET CONTROLS BEING USED BY THE PLAYER */ + /*****************************************/ + PanelControls *GetControls( void ) const { + return controls; + } + + /******************************/ + /* READ THE PLAYER'S CONTROLS */ + /******************************/ + void ReadControls( void ) { + if( controls != (PanelControls*)NULL ) { + controls->Read(); + } + } + + /************************/ + /* GET GAME OBJECT TYPE */ + /************************/ + // Returns type of game object. + virtual GameObjectTypes GetType( void ) { + return PlayerObjectType; + } + + /************************/ + /* MOVE THE GAME OBJECT */ + /************************/ + virtual void ProtectedMove( void ); + + /************************/ + /* DRAW THE GAME OBJECT */ + /************************/ + // This is only called after it has been established that the + // game object is visible. + virtual void Draw( void ); + + /*********************************/ + /* KILL A SINGLE PLAYER'S BULLET */ + /*********************************/ + // Pass index of bullet in b. + void KillBullet( UInt8 b ) { + playerBullets.KillBullet( b ); + } + + /*****************************/ + /* KILL ALL PLAYER'S BULLETS */ + /*****************************/ + void KillAllBullets( void ) { + playerBullets.KillAllBullets(); + } + + /*********************************************************/ + /* GET ARRAY CONTAINING POINTERS TO ALL PLAYER'S BULLETS */ + /*********************************************************/ + // Returns pointer to array of GameObject pointers. + // The array has BulletManager::MaxBullets pointers in it. + GameObject **GetBullets( void ) { + return playerBullets.GetBullets(); + } + + /*************************/ + /* ADD TO PLAYER'S SCORE */ + /*************************/ + // Pass number of points to add in points (THIS IS BCD CODED!). + void AddToScore( UInt16 points ); + + private : + + // Pointer to object used to read joysticks and buttons. + PanelControls *controls; + + // Manages player's bullets. + BulletManager playerBullets; + + // Countdown until next bullet available. + UInt8 bulletCountdown; + + // Bullet velocity information. + static BulletVelocities bulletVelocities; + + // Player movement velocities. + static BulletVelocities playerVelocities; + + }; + +#endif + +/* END of PlayerObject.h */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Random.h Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,40 @@ +/* + * SOURCE FILE : Random.h + * + * Definition of class Random. + * Generates random numbers a bit like the random function used by Arduino and Maple and so on. + * + */ + +#ifndef RandomDefined + + #define RandomDefined + + #include <stdlib.h> + + class Random { + + public : + + /***********************/ + /* GET A RANDOM NUMBER */ + /***********************/ + // Get a random number between min and max. + // Result may be equal to min but is always less than max. + static long Get( long min, long max ) { + return min + ( rand() % ( max - min ) ); + } + + /***********************/ + /* GET A RANDOM NUMBER */ + /***********************/ + static long Get( long max ) { + return Get( 0L, max ); + } + + }; + +#endif + +/* END of Random.h */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Rectangle.cpp Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,40 @@ +/* + * SOURCE FILE : Rectangle.cpp + * + * Definition of class Rectangle. + * Represents a rectangular area. + * + */ + +#include "Rectangle.h" + +/***************/ +/* CONSTRUCTOR */ +/***************/ +Rectangle::Rectangle() : + X1( 0 ), + Y1( 0 ), + X2( 9 ), + Y2( 9 ) +{ +} + +/***************/ +/* CONSTRUCTOR */ +/***************/ +// Pass coordinates of top left in x1 and y1. +// Pass coordinates of bottom right in x2 and y2. +Rectangle::Rectangle( Int16 x1, Int16 y1, Int16 x2, Int16 y2 ) : + X1( x1 ), + Y1( y1 ), + X2( x2 ), + Y2( y2 ) +{ +} + +/**************/ +/* DESTRUCTOR */ +/**************/ +Rectangle::~Rectangle() { +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Rectangle.h Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,63 @@ +/* + * SOURCE FILE : Rectangle.h + * + * Definition of class Rectangle. + * Represents a rectangular area. + * + */ + +#ifndef RectangleDefined + + #define RectangleDefined + + #include "Types.h" + + class Rectangle { + + public : + + // Coordinates of top left. + Int16 X1, Y1; + + // Coordinates of bottom right. + Int16 X2, Y2; + + /***************/ + /* CONSTRUCTOR */ + /***************/ + Rectangle(); + + /***************/ + /* CONSTRUCTOR */ + /***************/ + // Pass coordinates of top left in x1 and y1. + // Pass coordinates of bottom right in x2 and y2. + Rectangle( Int16 x1, Int16 y1, Int16 x2, Int16 y2 ); + + /**************/ + /* DESTRUCTOR */ + /**************/ + virtual ~Rectangle(); + + /*******************/ + /* CALCULATE WIDTH */ + /*******************/ + // Returns width of rectangle. + Int16 GetWidth( void ) const { + return X2 - X1 + 1; + } + + /********************/ + /* CALCULATE HEIGHT */ + /********************/ + // Returns height of rectangle. + Int16 GetHeight( void ) const { + return Y2 - Y1 + 1; + } + + }; + +#endif + +/* END of Rectangle.h */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SpriteGroup.h Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,21 @@ +/* + * SOURCE FILE : SpriteGroup.h + * + * Enumeration of the two groups of sprites. + * Mainly of use for sprite collision detection. + * + */ + +#ifndef SpriteGroupIncluded + + #define SpriteGroupIncluded + + enum SpriteGroup { + GoodGuy = 0, // J collision class + BadGuy = 1, // K collision class + }; + +#endif + +/* END of SpriteGroup.h */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SpriteImageId.h Sat Jun 08 11:24:05 2013 +0000 @@ -0,0 +1,57 @@ +/* + * SOURCE FILE : SpriteImageId.h + * + * Image ID numbers for sprites. Ordering is important. + * These are ordered the same way as the sprite images in the sprite RAM of the Gameduino. + * + */ + +#ifndef SpriteImageIdIncluded + + #define SpriteImageIdIncluded + + enum SpriteImageId { + PlayerImage = 0, + PlayerBulletImage = 1, + GruntImage = 2, + Explosion0Image = 3, + Explosion1Image = 4, + Explosion2Image = 5, + Explosion3Image = 6, + Explosion4Image = 7, + Explosion5Image = 8, + Explosion6Image = 9, + Explosion7Image = 10, + Explosion8Image = 11, + Explosion9Image = 12, + BlueMeanyImage = 13, + SkullImage = 14, + Woman0Image = 15, + Woman1Image = 16, + Woman2Image = 17, + FiftyImage = 18, + PlayerGunUpLeftFootUpImage = 19, + PlayerGunUpRightFootUpImage = 20, + PlayerGunLevelLeftFootUpImage = 21, + PlayerGunLevelRightFootUpImage = 22, + PlayerGunDownLeftFootUpImage = 23, + PlayerGunDownRightFootUpImage = 24, + PlayerBothGunsUpImage = 25, + Man0Image = 26, + Man1Image = 27, + Man2Image = 28, + Star0Image = 29, + Star1Image = 30, + Crusher0Image = 31, + Crusher1Image = 32, + Crusher2Image = 33, + BrainImage = 34, + MutantWomanImage = 35, + MutantManImage = 36, + BrainBulletImage = 37, + }; + +#endif + +/* END of SpriteImageId.h */ +