Race around the city collecting the flags while avoiding those that stand in the way of your mission. Make no mistake you will need to be quick to outwit your opponents, they are smart and will try to box you in. I wrote this game to prove that writing a game with scrolling scenery is possible even with the limited 6kB of RAM available. I had to compromise sound effects for features, I wanted multiple opponents, I wanted to be able to drop smoke bombs to trap the opponents but all this required memory so the sound effects had to take a back seat.

Dependencies:   mbed

Committer:
taylorza
Date:
Wed Jan 28 03:26:07 2015 +0000
Revision:
0:d85c449aca6d
Child:
1:1b8125937f28
Working maze scrolling, pre-maze compression

Who changed what in which revision?

UserRevisionLine numberNew contents of line
taylorza 0:d85c449aca6d 1 #include <climits>
taylorza 0:d85c449aca6d 2 #include "RallyCar.h"
taylorza 0:d85c449aca6d 3 #include "Player.h"
taylorza 0:d85c449aca6d 4
taylorza 0:d85c449aca6d 5 #ifndef __ENEMY_H__
taylorza 0:d85c449aca6d 6 #define __ENEMY_H__
taylorza 0:d85c449aca6d 7
taylorza 0:d85c449aca6d 8 class Enemy : public RallyCar
taylorza 0:d85c449aca6d 9 {
taylorza 0:d85c449aca6d 10 private:
taylorza 0:d85c449aca6d 11 enum Action { Start, Chase, Scatter };
taylorza 0:d85c449aca6d 12
taylorza 0:d85c449aca6d 13 public:
taylorza 0:d85c449aca6d 14
taylorza 0:d85c449aca6d 15 Enemy(Point startPosition, Point homePosition, Point targetOffset, Player &player) :
taylorza 0:d85c449aca6d 16 _startPosition(startPosition),
taylorza 0:d85c449aca6d 17 _homePosition(homePosition),
taylorza 0:d85c449aca6d 18 _targetOffset(targetOffset),
taylorza 0:d85c449aca6d 19 _player(player)
taylorza 0:d85c449aca6d 20 {
taylorza 0:d85c449aca6d 21 reset();
taylorza 0:d85c449aca6d 22 }
taylorza 0:d85c449aca6d 23
taylorza 0:d85c449aca6d 24 virtual void reset()
taylorza 0:d85c449aca6d 25 {
taylorza 0:d85c449aca6d 26 setPosition(_startPosition);
taylorza 0:d85c449aca6d 27
taylorza 0:d85c449aca6d 28 setDirection(Up);
taylorza 0:d85c449aca6d 29 setDesiredDirection(Up);
taylorza 0:d85c449aca6d 30 setState(Driving);
taylorza 0:d85c449aca6d 31
taylorza 0:d85c449aca6d 32 _action = Start;
taylorza 0:d85c449aca6d 33
taylorza 0:d85c449aca6d 34 setSpriteId(0);
taylorza 0:d85c449aca6d 35
taylorza 0:d85c449aca6d 36 _actionCounter = 0;
taylorza 0:d85c449aca6d 37
taylorza 0:d85c449aca6d 38 _startCount = 90;
taylorza 0:d85c449aca6d 39 _scatterCount = 210;
taylorza 0:d85c449aca6d 40 _chaseCount = 600;
taylorza 0:d85c449aca6d 41 }
taylorza 0:d85c449aca6d 42
taylorza 0:d85c449aca6d 43 virtual void update()
taylorza 0:d85c449aca6d 44 {
taylorza 0:d85c449aca6d 45 ++_actionCounter;
taylorza 0:d85c449aca6d 46
taylorza 0:d85c449aca6d 47 Point &position = getPosition();
taylorza 0:d85c449aca6d 48
taylorza 0:d85c449aca6d 49 bool allowLeftRightTurn = position.Y % 8 == 0;
taylorza 0:d85c449aca6d 50 bool allowUpDownTurn = position.X % 8 == 0;
taylorza 0:d85c449aca6d 51
taylorza 0:d85c449aca6d 52 if (getState() == Driving)
taylorza 0:d85c449aca6d 53 {
taylorza 0:d85c449aca6d 54 switch(_action)
taylorza 0:d85c449aca6d 55 {
taylorza 0:d85c449aca6d 56 case Start:
taylorza 0:d85c449aca6d 57 if (_actionCounter == _startCount)
taylorza 0:d85c449aca6d 58 {
taylorza 0:d85c449aca6d 59 _action = Scatter;
taylorza 0:d85c449aca6d 60 _actionCounter = 0;
taylorza 0:d85c449aca6d 61 }
taylorza 0:d85c449aca6d 62 break;
taylorza 0:d85c449aca6d 63
taylorza 0:d85c449aca6d 64 case Scatter:
taylorza 0:d85c449aca6d 65 if (_actionCounter == _scatterCount)
taylorza 0:d85c449aca6d 66 {
taylorza 0:d85c449aca6d 67 _action = Chase;
taylorza 0:d85c449aca6d 68 _actionCounter = 0;
taylorza 0:d85c449aca6d 69 }
taylorza 0:d85c449aca6d 70 else
taylorza 0:d85c449aca6d 71 {
taylorza 0:d85c449aca6d 72 Direction direction = hunt(_homePosition);
taylorza 0:d85c449aca6d 73 setDesiredDirection(direction);
taylorza 0:d85c449aca6d 74 }
taylorza 0:d85c449aca6d 75 break;
taylorza 0:d85c449aca6d 76
taylorza 0:d85c449aca6d 77 case Chase:
taylorza 0:d85c449aca6d 78 if (_actionCounter == _chaseCount)
taylorza 0:d85c449aca6d 79 {
taylorza 0:d85c449aca6d 80 _action = Scatter;
taylorza 0:d85c449aca6d 81 _actionCounter = 0;
taylorza 0:d85c449aca6d 82 }
taylorza 0:d85c449aca6d 83 else
taylorza 0:d85c449aca6d 84 {
taylorza 0:d85c449aca6d 85 Point target = _player.getPosition();
taylorza 0:d85c449aca6d 86
taylorza 0:d85c449aca6d 87 if (distanceToTarget(target) > 4096)
taylorza 0:d85c449aca6d 88 {
taylorza 0:d85c449aca6d 89 switch(_player.getDirection())
taylorza 0:d85c449aca6d 90 {
taylorza 0:d85c449aca6d 91 case Left: target.X -= _targetOffset.X; break;
taylorza 0:d85c449aca6d 92 case Right: target.X += _targetOffset.X; break;
taylorza 0:d85c449aca6d 93 case Up: target.Y -= _targetOffset.Y; break;
taylorza 0:d85c449aca6d 94 case Down: target.Y += _targetOffset.Y; break;
taylorza 0:d85c449aca6d 95 }
taylorza 0:d85c449aca6d 96 }
taylorza 0:d85c449aca6d 97
taylorza 0:d85c449aca6d 98 Direction direction = hunt(target);
taylorza 0:d85c449aca6d 99 setDesiredDirection(direction);
taylorza 0:d85c449aca6d 100 }
taylorza 0:d85c449aca6d 101 break;
taylorza 0:d85c449aca6d 102
taylorza 0:d85c449aca6d 103 }
taylorza 0:d85c449aca6d 104
taylorza 0:d85c449aca6d 105 if (_action != Start)
taylorza 0:d85c449aca6d 106 {
taylorza 0:d85c449aca6d 107 if (getDirection() != getDesiredDirection())
taylorza 0:d85c449aca6d 108 {
taylorza 0:d85c449aca6d 109 if ((getDesiredDirection() == Left && allowLeftRightTurn && canGoLeft())
taylorza 0:d85c449aca6d 110 || (getDesiredDirection() == Right && allowLeftRightTurn && canGoRight())
taylorza 0:d85c449aca6d 111 || (getDesiredDirection() == Up && allowUpDownTurn && canGoUp())
taylorza 0:d85c449aca6d 112 || (getDesiredDirection() == Down && allowUpDownTurn && canGoDown()))
taylorza 0:d85c449aca6d 113 {
taylorza 0:d85c449aca6d 114 setDirection(getDesiredDirection());
taylorza 0:d85c449aca6d 115 }
taylorza 0:d85c449aca6d 116 }
taylorza 0:d85c449aca6d 117
taylorza 0:d85c449aca6d 118 switch(getDirection())
taylorza 0:d85c449aca6d 119 {
taylorza 0:d85c449aca6d 120 case Left : setSpriteId(3); moveLeft(); break;
taylorza 0:d85c449aca6d 121 case Right : setSpriteId(1); moveRight(); break;
taylorza 0:d85c449aca6d 122 case Up : setSpriteId(0); moveUp();break;
taylorza 0:d85c449aca6d 123 case Down : setSpriteId(2); moveDown(); break;
taylorza 0:d85c449aca6d 124 }
taylorza 0:d85c449aca6d 125 }
taylorza 0:d85c449aca6d 126 }
taylorza 0:d85c449aca6d 127 else
taylorza 0:d85c449aca6d 128 {
taylorza 0:d85c449aca6d 129 if (getState() == StartSpinning)
taylorza 0:d85c449aca6d 130 {
taylorza 0:d85c449aca6d 131 _actionCounter = (int)getDirection();
taylorza 0:d85c449aca6d 132 setState(Spinning);
taylorza 0:d85c449aca6d 133 }
taylorza 0:d85c449aca6d 134
taylorza 0:d85c449aca6d 135 if (getState() == Spinning)
taylorza 0:d85c449aca6d 136 {
taylorza 0:d85c449aca6d 137 setSpriteId(_actionCounter % 4);
taylorza 0:d85c449aca6d 138 }
taylorza 0:d85c449aca6d 139 }
taylorza 0:d85c449aca6d 140
taylorza 0:d85c449aca6d 141 RallyCar::update();
taylorza 0:d85c449aca6d 142 }
taylorza 0:d85c449aca6d 143
taylorza 0:d85c449aca6d 144 private:
taylorza 0:d85c449aca6d 145 Direction hunt(Point &target)
taylorza 0:d85c449aca6d 146 {
taylorza 0:d85c449aca6d 147 Direction bestDirection = None;
taylorza 0:d85c449aca6d 148 uint32_t minDistance = LONG_MAX;
taylorza 0:d85c449aca6d 149
taylorza 0:d85c449aca6d 150 uint32_t leftDistance = distanceToTarget(target, Left);
taylorza 0:d85c449aca6d 151 uint32_t rightDistance = distanceToTarget(target, Right);
taylorza 0:d85c449aca6d 152 uint32_t upDistance = distanceToTarget(target, Up);
taylorza 0:d85c449aca6d 153 uint32_t downDistance = distanceToTarget(target, Down);
taylorza 0:d85c449aca6d 154
taylorza 0:d85c449aca6d 155 if (getDirection() != Right && canGoLeft() && leftDistance < minDistance)
taylorza 0:d85c449aca6d 156 {
taylorza 0:d85c449aca6d 157 minDistance = leftDistance;
taylorza 0:d85c449aca6d 158 bestDirection = Left;
taylorza 0:d85c449aca6d 159 }
taylorza 0:d85c449aca6d 160
taylorza 0:d85c449aca6d 161 if (getDirection() != Left && canGoRight() && rightDistance < minDistance)
taylorza 0:d85c449aca6d 162 {
taylorza 0:d85c449aca6d 163 minDistance = rightDistance;
taylorza 0:d85c449aca6d 164 bestDirection = Right;
taylorza 0:d85c449aca6d 165 }
taylorza 0:d85c449aca6d 166
taylorza 0:d85c449aca6d 167 if (getDirection() != Up && canGoDown() && downDistance < minDistance)
taylorza 0:d85c449aca6d 168 {
taylorza 0:d85c449aca6d 169 minDistance = downDistance;
taylorza 0:d85c449aca6d 170 bestDirection = Down;
taylorza 0:d85c449aca6d 171 }
taylorza 0:d85c449aca6d 172
taylorza 0:d85c449aca6d 173 if (getDirection() != Down && canGoUp() && upDistance < minDistance)
taylorza 0:d85c449aca6d 174 {
taylorza 0:d85c449aca6d 175 minDistance = upDistance;
taylorza 0:d85c449aca6d 176 bestDirection = Up;
taylorza 0:d85c449aca6d 177 }
taylorza 0:d85c449aca6d 178
taylorza 0:d85c449aca6d 179 return bestDirection;
taylorza 0:d85c449aca6d 180 }
taylorza 0:d85c449aca6d 181
taylorza 0:d85c449aca6d 182 uint32_t distanceToTarget(Point &target)
taylorza 0:d85c449aca6d 183 {
taylorza 0:d85c449aca6d 184 int16_t dx = target.X - getPosition().X;
taylorza 0:d85c449aca6d 185 int16_t dy = target.Y - getPosition().Y;
taylorza 0:d85c449aca6d 186 return (dx * dx) + (dy * dy);
taylorza 0:d85c449aca6d 187 }
taylorza 0:d85c449aca6d 188
taylorza 0:d85c449aca6d 189 uint32_t distanceToTarget(Point &target, Direction direction)
taylorza 0:d85c449aca6d 190 {
taylorza 0:d85c449aca6d 191 int16_t x = getPosition().X;
taylorza 0:d85c449aca6d 192 int16_t y = getPosition().Y;
taylorza 0:d85c449aca6d 193
taylorza 0:d85c449aca6d 194 switch(direction)
taylorza 0:d85c449aca6d 195 {
taylorza 0:d85c449aca6d 196 case Left : x -= 16; break;
taylorza 0:d85c449aca6d 197 case Right : x += 16; break;
taylorza 0:d85c449aca6d 198 case Up : y -= 16; break;
taylorza 0:d85c449aca6d 199 case Down : y += 16; break;
taylorza 0:d85c449aca6d 200 }
taylorza 0:d85c449aca6d 201
taylorza 0:d85c449aca6d 202 int16_t dx = target.X - x;
taylorza 0:d85c449aca6d 203 int16_t dy = target.Y - y;
taylorza 0:d85c449aca6d 204 return (dx * dx) + (dy * dy);
taylorza 0:d85c449aca6d 205 }
taylorza 0:d85c449aca6d 206
taylorza 0:d85c449aca6d 207 private:
taylorza 0:d85c449aca6d 208 Point _startPosition;
taylorza 0:d85c449aca6d 209 Point _homePosition;
taylorza 0:d85c449aca6d 210 Point _targetOffset;
taylorza 0:d85c449aca6d 211 Player &_player;
taylorza 0:d85c449aca6d 212
taylorza 0:d85c449aca6d 213 Action _action;
taylorza 0:d85c449aca6d 214 uint16_t _actionCounter;
taylorza 0:d85c449aca6d 215 uint16_t _startCount;
taylorza 0:d85c449aca6d 216 uint16_t _scatterCount;
taylorza 0:d85c449aca6d 217 uint16_t _chaseCount;
taylorza 0:d85c449aca6d 218 };
taylorza 0:d85c449aca6d 219 #endif //__ENEMY_H__