Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Enemy.h
00001 #include <climits> 00002 #include "RallyCar.h" 00003 #include "Player.h" 00004 00005 #ifndef __ENEMY_H__ 00006 #define __ENEMY_H__ 00007 00008 class Enemy : public RallyCar 00009 { 00010 private: 00011 enum Action { Start, Chase, Scatter }; 00012 00013 public: 00014 00015 Enemy(Point startPosition, Point homePosition, Point targetOffset, Player &player) : 00016 _startPosition(startPosition), 00017 _homePosition(homePosition), 00018 _targetOffset(targetOffset), 00019 _player(player) 00020 { 00021 reset(); 00022 } 00023 00024 virtual void reset() 00025 { 00026 setPosition(_startPosition); 00027 00028 setDirection(Up); 00029 setDesiredDirection(Up); 00030 setState(Driving); 00031 00032 _action = Start; 00033 00034 setSpriteId(0); 00035 00036 _actionCounter = 0; 00037 00038 _startCount = 120; 00039 _scatterCount = 210; 00040 _chaseCount = 600; 00041 } 00042 00043 virtual void update() 00044 { 00045 ++_actionCounter; 00046 00047 Point &position = getPosition(); 00048 00049 bool allowLeftRightTurn = position.Y % 8 == 0; 00050 bool allowUpDownTurn = position.X % 8 == 0; 00051 00052 if (getState() == Driving) 00053 { 00054 switch(_action) 00055 { 00056 case Start: 00057 if (_actionCounter == _startCount) 00058 { 00059 _action = Scatter; 00060 _actionCounter = 0; 00061 } 00062 break; 00063 00064 case Scatter: 00065 if (_actionCounter == _scatterCount) 00066 { 00067 _action = Chase; 00068 _actionCounter = 0; 00069 } 00070 else 00071 { 00072 Direction direction = hunt(_homePosition); 00073 setDesiredDirection(direction); 00074 } 00075 break; 00076 00077 case Chase: 00078 if (_actionCounter == _chaseCount) 00079 { 00080 _action = Scatter; 00081 _actionCounter = 0; 00082 } 00083 else 00084 { 00085 Point target = _player.getPosition(); 00086 00087 if (distanceToTarget(target) > 4096) 00088 { 00089 switch(_player.getDirection()) 00090 { 00091 case Left: target.X -= _targetOffset.X; break; 00092 case Right: target.X += _targetOffset.X; break; 00093 case Up: target.Y -= _targetOffset.Y; break; 00094 case Down: target.Y += _targetOffset.Y; break; 00095 } 00096 } 00097 00098 Direction direction = hunt(target); 00099 if (getDesiredDirection() != direction) 00100 { 00101 setDesiredDirection(direction); 00102 // Slow enemy down when they change direction 00103 return; 00104 } 00105 } 00106 break; 00107 00108 } 00109 00110 if (_action != Start) 00111 { 00112 if (getDirection() != getDesiredDirection()) 00113 { 00114 if ((getDesiredDirection() == Left && allowLeftRightTurn && canGoLeft()) 00115 || (getDesiredDirection() == Right && allowLeftRightTurn && canGoRight()) 00116 || (getDesiredDirection() == Up && allowUpDownTurn && canGoUp()) 00117 || (getDesiredDirection() == Down && allowUpDownTurn && canGoDown())) 00118 { 00119 setDirection(getDesiredDirection()); 00120 } 00121 } 00122 00123 switch(getDirection()) 00124 { 00125 case Left : setSpriteId(3); moveLeft(); break; 00126 case Right : setSpriteId(1); moveRight(); break; 00127 case Up : setSpriteId(0); moveUp();break; 00128 case Down : setSpriteId(2); moveDown(); break; 00129 } 00130 } 00131 } 00132 else 00133 { 00134 if (getState() == StartSpinning) 00135 { 00136 _actionCounter = (int)getDirection(); 00137 setState(Spinning); 00138 } 00139 00140 if (getState() == Spinning) 00141 { 00142 setSpriteId(_actionCounter % 4); 00143 } 00144 } 00145 00146 RallyCar::update(); 00147 } 00148 00149 private: 00150 Direction hunt(Point &target) 00151 { 00152 Direction bestDirection = None; 00153 uint32_t minDistance = LONG_MAX; 00154 00155 uint32_t leftDistance = distanceToTarget(target, Left); 00156 uint32_t rightDistance = distanceToTarget(target, Right); 00157 uint32_t upDistance = distanceToTarget(target, Up); 00158 uint32_t downDistance = distanceToTarget(target, Down); 00159 00160 if (getDirection() != Right && canGoLeft() && leftDistance < minDistance) 00161 { 00162 minDistance = leftDistance; 00163 bestDirection = Left; 00164 } 00165 00166 if (getDirection() != Left && canGoRight() && rightDistance < minDistance) 00167 { 00168 minDistance = rightDistance; 00169 bestDirection = Right; 00170 } 00171 00172 if (getDirection() != Up && canGoDown() && downDistance < minDistance) 00173 { 00174 minDistance = downDistance; 00175 bestDirection = Down; 00176 } 00177 00178 if (getDirection() != Down && canGoUp() && upDistance < minDistance) 00179 { 00180 minDistance = upDistance; 00181 bestDirection = Up; 00182 } 00183 00184 return bestDirection; 00185 } 00186 00187 uint32_t distanceToTarget(Point &target) 00188 { 00189 int16_t dx = target.X - getPosition().X; 00190 int16_t dy = target.Y - getPosition().Y; 00191 return (dx * dx) + (dy * dy); 00192 } 00193 00194 uint32_t distanceToTarget(Point &target, Direction direction) 00195 { 00196 int16_t x = getPosition().X; 00197 int16_t y = getPosition().Y; 00198 00199 switch(direction) 00200 { 00201 case Left : x -= 16; break; 00202 case Right : x += 16; break; 00203 case Up : y -= 16; break; 00204 case Down : y += 16; break; 00205 } 00206 00207 int16_t dx = target.X - x; 00208 int16_t dy = target.Y - y; 00209 return (dx * dx) + (dy * dy); 00210 } 00211 00212 private: 00213 Point _startPosition; 00214 Point _homePosition; 00215 Point _targetOffset; 00216 Player &_player; 00217 00218 Action _action; 00219 uint16_t _actionCounter; 00220 uint16_t _startCount; 00221 uint16_t _scatterCount; 00222 uint16_t _chaseCount; 00223 }; 00224 #endif //__ENEMY_H__
Generated on Tue Jul 12 2022 21:15:25 by
