After decimating the enemy forces that have attacked your ship, you are charged with taking out as many of the remaining enemy fighters as possible. 3d space fighter game was initially written while I was testing some 3d routines I was implementing for a flight simulator, but my daughter started playing it and seemed to enjoy it so I added a few sound effects, explosions etc. and so this little game was born.
main.cpp@0:01829868570e, 2015-01-03 (annotated)
- Committer:
- taylorza
- Date:
- Sat Jan 03 18:48:11 2015 +0000
- Revision:
- 0:01829868570e
- Child:
- 1:9ff7384171ec
First version with fixed point math
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
taylorza | 0:01829868570e | 1 | #include "mbed.h" |
taylorza | 0:01829868570e | 2 | #include <cstdarg> |
taylorza | 0:01829868570e | 3 | #include "LCD_ST7735.h" |
taylorza | 0:01829868570e | 4 | #include "GameInput.h" |
taylorza | 0:01829868570e | 5 | #include "font_IBM.h" |
taylorza | 0:01829868570e | 6 | #include "Canvas.h" |
taylorza | 0:01829868570e | 7 | #include "Color565.h" |
taylorza | 0:01829868570e | 8 | #include "Math.h" |
taylorza | 0:01829868570e | 9 | |
taylorza | 0:01829868570e | 10 | #define VIEW_WIDTH 160 |
taylorza | 0:01829868570e | 11 | #define VIEW_HEIGHT 104 |
taylorza | 0:01829868570e | 12 | |
taylorza | 0:01829868570e | 13 | #define NUM_STARS 10 |
taylorza | 0:01829868570e | 14 | #define NUM_TIES 5 |
taylorza | 0:01829868570e | 15 | #define NUM_TIE_VERTS 10 |
taylorza | 0:01829868570e | 16 | #define NUM_TIE_EDGES 10 |
taylorza | 0:01829868570e | 17 | #define NUM_EXPLOSIONS (NUM_TIES) |
taylorza | 0:01829868570e | 18 | |
taylorza | 0:01829868570e | 19 | #define TARGET_X (VIEW_WIDTH >> 1) |
taylorza | 0:01829868570e | 20 | #define TARGET_Y (VIEW_HEIGHT >> 1) |
taylorza | 0:01829868570e | 21 | |
taylorza | 0:01829868570e | 22 | const Fix16 NearZ(10); |
taylorza | 0:01829868570e | 23 | const Fix16 FarZ(2000); |
taylorza | 0:01829868570e | 24 | const Fix16 ViewDistance(80); |
taylorza | 0:01829868570e | 25 | const Fix16 HalfViewWidth(VIEW_WIDTH/ 2); |
taylorza | 0:01829868570e | 26 | const Fix16 HalfViewHeight(VIEW_HEIGHT/ 2); |
taylorza | 0:01829868570e | 27 | |
taylorza | 0:01829868570e | 28 | const Fix16 TenPercent = Fix16::createDirect(0x00001999); // 0.1f |
taylorza | 0:01829868570e | 29 | const Fix16 NintyPercent = Fix16::createDirect(0x0000e666); // 0.9f |
taylorza | 0:01829868570e | 30 | const Fix16 NintyFivePercent = Fix16::createDirect(0x0000f333); // 0.95f |
taylorza | 0:01829868570e | 31 | const Fix16 Ten(10); |
taylorza | 0:01829868570e | 32 | |
taylorza | 0:01829868570e | 33 | const Fix16 StarVelocity(10); |
taylorza | 0:01829868570e | 34 | |
taylorza | 0:01829868570e | 35 | Vector3d stars[NUM_STARS]; |
taylorza | 0:01829868570e | 36 | |
taylorza | 0:01829868570e | 37 | struct Line3d |
taylorza | 0:01829868570e | 38 | { |
taylorza | 0:01829868570e | 39 | uint8_t V1; |
taylorza | 0:01829868570e | 40 | uint8_t V2; |
taylorza | 0:01829868570e | 41 | |
taylorza | 0:01829868570e | 42 | Line3d(uint8_t v1, uint8_t v2) : V1(v1), V2(v2) {} |
taylorza | 0:01829868570e | 43 | }; |
taylorza | 0:01829868570e | 44 | |
taylorza | 0:01829868570e | 45 | struct TieFighter |
taylorza | 0:01829868570e | 46 | { |
taylorza | 0:01829868570e | 47 | int HitCount; |
taylorza | 0:01829868570e | 48 | |
taylorza | 0:01829868570e | 49 | Vector3d Position; |
taylorza | 0:01829868570e | 50 | Vector3d Velocity; |
taylorza | 0:01829868570e | 51 | |
taylorza | 0:01829868570e | 52 | int MinX; |
taylorza | 0:01829868570e | 53 | int MinY; |
taylorza | 0:01829868570e | 54 | int MaxX; |
taylorza | 0:01829868570e | 55 | int MaxY; |
taylorza | 0:01829868570e | 56 | }; |
taylorza | 0:01829868570e | 57 | |
taylorza | 0:01829868570e | 58 | struct Explosion |
taylorza | 0:01829868570e | 59 | { |
taylorza | 0:01829868570e | 60 | bool Active; |
taylorza | 0:01829868570e | 61 | int Counter; |
taylorza | 0:01829868570e | 62 | Vector3d P1[NUM_TIE_EDGES]; |
taylorza | 0:01829868570e | 63 | Vector3d P2[NUM_TIE_EDGES]; |
taylorza | 0:01829868570e | 64 | Vector3d Velocity[NUM_TIE_EDGES]; |
taylorza | 0:01829868570e | 65 | }; |
taylorza | 0:01829868570e | 66 | |
taylorza | 0:01829868570e | 67 | Vector3d tieVerts[NUM_TIE_VERTS] = |
taylorza | 0:01829868570e | 68 | { |
taylorza | 0:01829868570e | 69 | Vector3d(-50, 40, 0), |
taylorza | 0:01829868570e | 70 | Vector3d(-40, 0, 0), |
taylorza | 0:01829868570e | 71 | Vector3d(-50, -40, 0), |
taylorza | 0:01829868570e | 72 | Vector3d(-10, 0, 0), |
taylorza | 0:01829868570e | 73 | Vector3d(0, 20, 0), |
taylorza | 0:01829868570e | 74 | Vector3d(10, 0, 0), |
taylorza | 0:01829868570e | 75 | Vector3d(0, -20, 0), |
taylorza | 0:01829868570e | 76 | Vector3d(50, 40, 0), |
taylorza | 0:01829868570e | 77 | Vector3d(40, 0, 0), |
taylorza | 0:01829868570e | 78 | Vector3d(50, -40, 0), |
taylorza | 0:01829868570e | 79 | }; |
taylorza | 0:01829868570e | 80 | |
taylorza | 0:01829868570e | 81 | Line3d tieShape[NUM_TIE_EDGES] = |
taylorza | 0:01829868570e | 82 | { |
taylorza | 0:01829868570e | 83 | Line3d(0, 1), |
taylorza | 0:01829868570e | 84 | Line3d(1, 2), |
taylorza | 0:01829868570e | 85 | Line3d(1, 3), |
taylorza | 0:01829868570e | 86 | Line3d(3, 4), |
taylorza | 0:01829868570e | 87 | Line3d(4, 5), |
taylorza | 0:01829868570e | 88 | Line3d(5, 6), |
taylorza | 0:01829868570e | 89 | Line3d(6, 3), |
taylorza | 0:01829868570e | 90 | Line3d(5, 8), |
taylorza | 0:01829868570e | 91 | Line3d(8, 7), |
taylorza | 0:01829868570e | 92 | Line3d(8, 9), |
taylorza | 0:01829868570e | 93 | }; |
taylorza | 0:01829868570e | 94 | |
taylorza | 0:01829868570e | 95 | TieFighter ties[NUM_TIES]; |
taylorza | 0:01829868570e | 96 | Explosion explosions[NUM_EXPLOSIONS]; |
taylorza | 0:01829868570e | 97 | Vector3d steeringForce; |
taylorza | 0:01829868570e | 98 | |
taylorza | 0:01829868570e | 99 | bool updateHud = true; |
taylorza | 0:01829868570e | 100 | int hits = 0; |
taylorza | 0:01829868570e | 101 | int misses = 0; |
taylorza | 0:01829868570e | 102 | int score = 0; |
taylorza | 0:01829868570e | 103 | |
taylorza | 0:01829868570e | 104 | Bitmap1bpp image(VIEW_WIDTH, VIEW_HEIGHT); |
taylorza | 0:01829868570e | 105 | Canvas<Bitmap1bpp> canvas(&image); |
taylorza | 0:01829868570e | 106 | |
taylorza | 0:01829868570e | 107 | int cannonState = 0; |
taylorza | 0:01829868570e | 108 | int cannonCount = 0; |
taylorza | 0:01829868570e | 109 | |
taylorza | 0:01829868570e | 110 | void initStar(int index, bool initial); |
taylorza | 0:01829868570e | 111 | void initTie(int index); |
taylorza | 0:01829868570e | 112 | |
taylorza | 0:01829868570e | 113 | void startExplosion(int tieIndex); |
taylorza | 0:01829868570e | 114 | |
taylorza | 0:01829868570e | 115 | void update(); |
taylorza | 0:01829868570e | 116 | void draw(); |
taylorza | 0:01829868570e | 117 | |
taylorza | 0:01829868570e | 118 | LCD_ST7735 Surface( |
taylorza | 0:01829868570e | 119 | P0_19, |
taylorza | 0:01829868570e | 120 | P0_4, |
taylorza | 0:01829868570e | 121 | P0_5, |
taylorza | 0:01829868570e | 122 | P0_21, |
taylorza | 0:01829868570e | 123 | P0_22, |
taylorza | 0:01829868570e | 124 | P1_15, |
taylorza | 0:01829868570e | 125 | P0_2, |
taylorza | 0:01829868570e | 126 | LCD_ST7735::RGB); |
taylorza | 0:01829868570e | 127 | |
taylorza | 0:01829868570e | 128 | char buffer[20]; |
taylorza | 0:01829868570e | 129 | main() |
taylorza | 0:01829868570e | 130 | { |
taylorza | 0:01829868570e | 131 | Surface.setOrientation(LCD_ST7735::Rotate270, false); |
taylorza | 0:01829868570e | 132 | |
taylorza | 0:01829868570e | 133 | // Init stars |
taylorza | 0:01829868570e | 134 | for (int i = 0; i < NUM_STARS; ++i) |
taylorza | 0:01829868570e | 135 | { |
taylorza | 0:01829868570e | 136 | initStar(i, true); |
taylorza | 0:01829868570e | 137 | } |
taylorza | 0:01829868570e | 138 | |
taylorza | 0:01829868570e | 139 | // Init tie fighters |
taylorza | 0:01829868570e | 140 | for (int i = 0; i < NUM_TIES; ++i) |
taylorza | 0:01829868570e | 141 | { |
taylorza | 0:01829868570e | 142 | initTie(i); |
taylorza | 0:01829868570e | 143 | ties[i].HitCount = 0; |
taylorza | 0:01829868570e | 144 | } |
taylorza | 0:01829868570e | 145 | |
taylorza | 0:01829868570e | 146 | // Init explosions |
taylorza | 0:01829868570e | 147 | for (int i = 0; i < NUM_EXPLOSIONS; ++i) |
taylorza | 0:01829868570e | 148 | { |
taylorza | 0:01829868570e | 149 | explosions[i].Active = false; |
taylorza | 0:01829868570e | 150 | } |
taylorza | 0:01829868570e | 151 | |
taylorza | 0:01829868570e | 152 | Timer frameTimer; |
taylorza | 0:01829868570e | 153 | frameTimer.start(); |
taylorza | 0:01829868570e | 154 | int lastFrameTime = frameTimer.read_us(); |
taylorza | 0:01829868570e | 155 | while (true) |
taylorza | 0:01829868570e | 156 | { |
taylorza | 0:01829868570e | 157 | canvas.clear(); |
taylorza | 0:01829868570e | 158 | |
taylorza | 0:01829868570e | 159 | update(); |
taylorza | 0:01829868570e | 160 | draw(); |
taylorza | 0:01829868570e | 161 | |
taylorza | 0:01829868570e | 162 | Surface.drawBitmap(0, 16, image, 0, 0, VIEW_WIDTH, VIEW_HEIGHT, Color565::White, Color565::Black); |
taylorza | 0:01829868570e | 163 | |
taylorza | 0:01829868570e | 164 | if (updateHud) |
taylorza | 0:01829868570e | 165 | { |
taylorza | 0:01829868570e | 166 | updateHud = false; |
taylorza | 0:01829868570e | 167 | Surface.setForegroundColor(Color565::White); |
taylorza | 0:01829868570e | 168 | Surface.drawString(font_ibm, 0, 0, "Hits Score Misses"); |
taylorza | 0:01829868570e | 169 | |
taylorza | 0:01829868570e | 170 | Surface.setForegroundColor(Color565::Yellow); |
taylorza | 0:01829868570e | 171 | sprintf(buffer, "%d", hits); |
taylorza | 0:01829868570e | 172 | Surface.drawString(font_ibm, 8, 8, buffer); |
taylorza | 0:01829868570e | 173 | |
taylorza | 0:01829868570e | 174 | Surface.setForegroundColor(Color565::Lime); |
taylorza | 0:01829868570e | 175 | sprintf(buffer, "%d", score); |
taylorza | 0:01829868570e | 176 | Surface.drawString(font_ibm, 56, 8, buffer); |
taylorza | 0:01829868570e | 177 | |
taylorza | 0:01829868570e | 178 | Surface.setForegroundColor(Color565::Red); |
taylorza | 0:01829868570e | 179 | sprintf(buffer, "%d", misses); |
taylorza | 0:01829868570e | 180 | Surface.drawString(font_ibm, 128, 8, buffer); |
taylorza | 0:01829868570e | 181 | } |
taylorza | 0:01829868570e | 182 | |
taylorza | 0:01829868570e | 183 | int frameTime = frameTimer.read_us(); |
taylorza | 0:01829868570e | 184 | int duration = frameTime - lastFrameTime; |
taylorza | 0:01829868570e | 185 | lastFrameTime = frameTime; |
taylorza | 0:01829868570e | 186 | |
taylorza | 0:01829868570e | 187 | sprintf(buffer, "%d ", duration); |
taylorza | 0:01829868570e | 188 | Surface.drawString(font_ibm, 0, 120, buffer); |
taylorza | 0:01829868570e | 189 | } |
taylorza | 0:01829868570e | 190 | } |
taylorza | 0:01829868570e | 191 | |
taylorza | 0:01829868570e | 192 | void initStar(int index, bool initial) |
taylorza | 0:01829868570e | 193 | { |
taylorza | 0:01829868570e | 194 | stars[index].X = -VIEW_WIDTH / 2 + rand() % VIEW_WIDTH; |
taylorza | 0:01829868570e | 195 | stars[index].Y = -VIEW_HEIGHT / 2 + rand() % VIEW_HEIGHT; |
taylorza | 0:01829868570e | 196 | if (initial) |
taylorza | 0:01829868570e | 197 | stars[index].Z = NearZ + Fix16(rand() % (int)(FarZ - NearZ)); |
taylorza | 0:01829868570e | 198 | else |
taylorza | 0:01829868570e | 199 | stars[index].Z = 500; |
taylorza | 0:01829868570e | 200 | } |
taylorza | 0:01829868570e | 201 | |
taylorza | 0:01829868570e | 202 | void initTie(int index) |
taylorza | 0:01829868570e | 203 | { |
taylorza | 0:01829868570e | 204 | ties[index].Position.X = -VIEW_WIDTH + rand() % (2 * VIEW_WIDTH); |
taylorza | 0:01829868570e | 205 | ties[index].Position.Y = -VIEW_HEIGHT + rand() % (2 * VIEW_HEIGHT); |
taylorza | 0:01829868570e | 206 | ties[index].Position.Z = FarZ * (rand() % 3 + 1); |
taylorza | 0:01829868570e | 207 | |
taylorza | 0:01829868570e | 208 | ties[index].Velocity.X = -0.5f + rand() % 2; |
taylorza | 0:01829868570e | 209 | ties[index].Velocity.Y = -0.5f + rand() % 2; |
taylorza | 0:01829868570e | 210 | ties[index].Velocity.Z = -4 - rand() % (8 + ties[index].HitCount); |
taylorza | 0:01829868570e | 211 | } |
taylorza | 0:01829868570e | 212 | |
taylorza | 0:01829868570e | 213 | void startExplosion(int tieIndex) |
taylorza | 0:01829868570e | 214 | { |
taylorza | 0:01829868570e | 215 | TieFighter &tie = ties[tieIndex]; |
taylorza | 0:01829868570e | 216 | for (int i = 0; i < NUM_EXPLOSIONS; ++i) |
taylorza | 0:01829868570e | 217 | { |
taylorza | 0:01829868570e | 218 | Explosion &explosion = explosions[i]; |
taylorza | 0:01829868570e | 219 | if (explosion.Active == false) |
taylorza | 0:01829868570e | 220 | { |
taylorza | 0:01829868570e | 221 | explosion.Active = true; |
taylorza | 0:01829868570e | 222 | explosion.Counter = 0; |
taylorza | 0:01829868570e | 223 | |
taylorza | 0:01829868570e | 224 | for (int edge = 0; edge < NUM_TIE_EDGES; ++edge) |
taylorza | 0:01829868570e | 225 | { |
taylorza | 0:01829868570e | 226 | Line3d &shape = tieShape[edge]; |
taylorza | 0:01829868570e | 227 | |
taylorza | 0:01829868570e | 228 | // Start |
taylorza | 0:01829868570e | 229 | Vector3d &p1 = explosion.P1[edge]; |
taylorza | 0:01829868570e | 230 | Vector3d &v1 = tieVerts[shape.V1]; |
taylorza | 0:01829868570e | 231 | p1.X = tie.Position.X + v1.X; |
taylorza | 0:01829868570e | 232 | p1.Y = tie.Position.Y + v1.Y; |
taylorza | 0:01829868570e | 233 | p1.Z = tie.Position.Z + v1.Z; |
taylorza | 0:01829868570e | 234 | |
taylorza | 0:01829868570e | 235 | // End |
taylorza | 0:01829868570e | 236 | Vector3d &p2 = explosion.P2[edge]; |
taylorza | 0:01829868570e | 237 | Vector3d &v2 = tieVerts[shape.V2]; |
taylorza | 0:01829868570e | 238 | p2.X = tie.Position.X + v2.X; |
taylorza | 0:01829868570e | 239 | p2.Y = tie.Position.Y + v2.Y; |
taylorza | 0:01829868570e | 240 | p2.Z = tie.Position.Z + v2.Z; |
taylorza | 0:01829868570e | 241 | |
taylorza | 0:01829868570e | 242 | // Trajectory |
taylorza | 0:01829868570e | 243 | Vector3d &velocity = explosion.Velocity[edge]; |
taylorza | 0:01829868570e | 244 | Vector3d &tieVelocity = tie.Velocity; |
taylorza | 0:01829868570e | 245 | velocity.X = tieVelocity.X - 8 + rand() % 16; |
taylorza | 0:01829868570e | 246 | velocity.Y = tieVelocity.Y - 8 + rand() % 16; |
taylorza | 0:01829868570e | 247 | velocity.Z = tieVelocity.Z - 8 + rand() % 16; |
taylorza | 0:01829868570e | 248 | } |
taylorza | 0:01829868570e | 249 | break; |
taylorza | 0:01829868570e | 250 | } |
taylorza | 0:01829868570e | 251 | } |
taylorza | 0:01829868570e | 252 | } |
taylorza | 0:01829868570e | 253 | |
taylorza | 0:01829868570e | 254 | void update() |
taylorza | 0:01829868570e | 255 | { |
taylorza | 0:01829868570e | 256 | // Move ties |
taylorza | 0:01829868570e | 257 | for (int i = 0; i < NUM_TIES; ++i) |
taylorza | 0:01829868570e | 258 | { |
taylorza | 0:01829868570e | 259 | TieFighter &tie = ties[i]; |
taylorza | 0:01829868570e | 260 | |
taylorza | 0:01829868570e | 261 | if (cannonState == 1) |
taylorza | 0:01829868570e | 262 | { |
taylorza | 0:01829868570e | 263 | if (tie.MinX < TARGET_X && tie.MaxX > TARGET_X |
taylorza | 0:01829868570e | 264 | && tie.MinY < TARGET_Y && tie.MaxY > TARGET_Y) |
taylorza | 0:01829868570e | 265 | { |
taylorza | 0:01829868570e | 266 | startExplosion(i); |
taylorza | 0:01829868570e | 267 | ++hits; |
taylorza | 0:01829868570e | 268 | score += ((int)tie.Position.Z) / 10; |
taylorza | 0:01829868570e | 269 | updateHud = true; |
taylorza | 0:01829868570e | 270 | if (tie.HitCount < 48) ++tie.HitCount; |
taylorza | 0:01829868570e | 271 | initTie(i); |
taylorza | 0:01829868570e | 272 | continue; |
taylorza | 0:01829868570e | 273 | } |
taylorza | 0:01829868570e | 274 | } |
taylorza | 0:01829868570e | 275 | |
taylorza | 0:01829868570e | 276 | tie.Position.X += (tie.Velocity.X + steeringForce.X); |
taylorza | 0:01829868570e | 277 | tie.Position.Y += (tie.Velocity.Y + steeringForce.Y); |
taylorza | 0:01829868570e | 278 | tie.Position.Z += (tie.Velocity.Z + steeringForce.Z); |
taylorza | 0:01829868570e | 279 | |
taylorza | 0:01829868570e | 280 | if (tie.Position.Z <= NearZ) |
taylorza | 0:01829868570e | 281 | { |
taylorza | 0:01829868570e | 282 | initTie(i); |
taylorza | 0:01829868570e | 283 | ++misses; |
taylorza | 0:01829868570e | 284 | updateHud = true; |
taylorza | 0:01829868570e | 285 | } |
taylorza | 0:01829868570e | 286 | } |
taylorza | 0:01829868570e | 287 | |
taylorza | 0:01829868570e | 288 | // Move stars |
taylorza | 0:01829868570e | 289 | for (int i = 0; i < NUM_STARS; ++i) |
taylorza | 0:01829868570e | 290 | { |
taylorza | 0:01829868570e | 291 | Vector3d &star = stars[i]; |
taylorza | 0:01829868570e | 292 | star.X += (steeringForce.X * TenPercent); |
taylorza | 0:01829868570e | 293 | star.Y += (steeringForce.Y * TenPercent); |
taylorza | 0:01829868570e | 294 | star.Z -= StarVelocity; |
taylorza | 0:01829868570e | 295 | |
taylorza | 0:01829868570e | 296 | if (star.Z <= NearZ) |
taylorza | 0:01829868570e | 297 | { |
taylorza | 0:01829868570e | 298 | initStar(i, false); |
taylorza | 0:01829868570e | 299 | } |
taylorza | 0:01829868570e | 300 | } |
taylorza | 0:01829868570e | 301 | |
taylorza | 0:01829868570e | 302 | // Update explosions |
taylorza | 0:01829868570e | 303 | for (int i = 0; i < NUM_EXPLOSIONS; ++i) |
taylorza | 0:01829868570e | 304 | { |
taylorza | 0:01829868570e | 305 | Explosion &explosion = explosions[i]; |
taylorza | 0:01829868570e | 306 | if (explosion.Active == false) continue; |
taylorza | 0:01829868570e | 307 | |
taylorza | 0:01829868570e | 308 | for (int edge = 0; edge < NUM_TIE_EDGES; ++edge) |
taylorza | 0:01829868570e | 309 | { |
taylorza | 0:01829868570e | 310 | Vector3d &v = explosions[i].Velocity[edge]; |
taylorza | 0:01829868570e | 311 | |
taylorza | 0:01829868570e | 312 | Vector3d &p1 = explosions[i].P1[edge]; |
taylorza | 0:01829868570e | 313 | p1.X += v.X; |
taylorza | 0:01829868570e | 314 | p1.Y += v.Y; |
taylorza | 0:01829868570e | 315 | p1.Z += v.Z; |
taylorza | 0:01829868570e | 316 | |
taylorza | 0:01829868570e | 317 | Vector3d &p2 = explosions[i].P2[edge]; |
taylorza | 0:01829868570e | 318 | p2.X += v.X; |
taylorza | 0:01829868570e | 319 | p2.Y += v.Y; |
taylorza | 0:01829868570e | 320 | p2.Z += v.Z; |
taylorza | 0:01829868570e | 321 | } |
taylorza | 0:01829868570e | 322 | |
taylorza | 0:01829868570e | 323 | if (++explosions[i].Counter > 100) |
taylorza | 0:01829868570e | 324 | { |
taylorza | 0:01829868570e | 325 | explosions[i].Active = false; |
taylorza | 0:01829868570e | 326 | } |
taylorza | 0:01829868570e | 327 | } |
taylorza | 0:01829868570e | 328 | |
taylorza | 0:01829868570e | 329 | if (GameInput::isLeftPressed()) steeringForce.X += Fix16::One; |
taylorza | 0:01829868570e | 330 | if (GameInput::isRightPressed()) steeringForce.X -= Fix16::One; |
taylorza | 0:01829868570e | 331 | if (GameInput::isUpPressed()) steeringForce.Y -= Fix16::One; |
taylorza | 0:01829868570e | 332 | if (GameInput::isDownPressed()) steeringForce.Y += Fix16::One; |
taylorza | 0:01829868570e | 333 | |
taylorza | 0:01829868570e | 334 | if (GameInput::isCirclePressed() && cannonState == 0) |
taylorza | 0:01829868570e | 335 | { |
taylorza | 0:01829868570e | 336 | cannonState = 1; |
taylorza | 0:01829868570e | 337 | cannonCount = 0; |
taylorza | 0:01829868570e | 338 | } |
taylorza | 0:01829868570e | 339 | |
taylorza | 0:01829868570e | 340 | if (cannonState == 1) |
taylorza | 0:01829868570e | 341 | if (++cannonCount > 15) |
taylorza | 0:01829868570e | 342 | cannonState = 2; |
taylorza | 0:01829868570e | 343 | |
taylorza | 0:01829868570e | 344 | if (cannonState == 2) |
taylorza | 0:01829868570e | 345 | if (++cannonCount > 20) |
taylorza | 0:01829868570e | 346 | cannonState = 0; |
taylorza | 0:01829868570e | 347 | |
taylorza | 0:01829868570e | 348 | // Dampen thrusters |
taylorza | 0:01829868570e | 349 | steeringForce.X *= NintyFivePercent; |
taylorza | 0:01829868570e | 350 | steeringForce.Y *= NintyFivePercent; |
taylorza | 0:01829868570e | 351 | steeringForce.Z *= NintyFivePercent; |
taylorza | 0:01829868570e | 352 | } |
taylorza | 0:01829868570e | 353 | |
taylorza | 0:01829868570e | 354 | void draw() |
taylorza | 0:01829868570e | 355 | { |
taylorza | 0:01829868570e | 356 | // Draw stars |
taylorza | 0:01829868570e | 357 | for (int i = 0; i < NUM_STARS; ++i) |
taylorza | 0:01829868570e | 358 | { |
taylorza | 0:01829868570e | 359 | Vector3d &star = stars[i]; |
taylorza | 0:01829868570e | 360 | |
taylorza | 0:01829868570e | 361 | // Perspective transform |
taylorza | 0:01829868570e | 362 | Fix16 x_per = ViewDistance * (star.X / star.Z); |
taylorza | 0:01829868570e | 363 | Fix16 y_per = ViewDistance * (star.Y / star.Z); |
taylorza | 0:01829868570e | 364 | |
taylorza | 0:01829868570e | 365 | // Screen coordiante transform |
taylorza | 0:01829868570e | 366 | int x_screen = (int)(HalfViewWidth + x_per); |
taylorza | 0:01829868570e | 367 | int y_screen = (int)(HalfViewHeight + y_per); |
taylorza | 0:01829868570e | 368 | |
taylorza | 0:01829868570e | 369 | // Clip to screen |
taylorza | 0:01829868570e | 370 | if (x_screen >= VIEW_WIDTH || x_screen < 0 || |
taylorza | 0:01829868570e | 371 | y_screen >= VIEW_HEIGHT || y_screen < 0) |
taylorza | 0:01829868570e | 372 | { |
taylorza | 0:01829868570e | 373 | initStar(i, false); |
taylorza | 0:01829868570e | 374 | continue; |
taylorza | 0:01829868570e | 375 | } |
taylorza | 0:01829868570e | 376 | |
taylorza | 0:01829868570e | 377 | canvas.setPixel(x_screen, y_screen, 1); |
taylorza | 0:01829868570e | 378 | } |
taylorza | 0:01829868570e | 379 | |
taylorza | 0:01829868570e | 380 | // Draw ties |
taylorza | 0:01829868570e | 381 | for(int i = 0; i < NUM_TIES; ++i) |
taylorza | 0:01829868570e | 382 | { |
taylorza | 0:01829868570e | 383 | TieFighter &tie = ties[i]; |
taylorza | 0:01829868570e | 384 | |
taylorza | 0:01829868570e | 385 | tie.MinX = 1000000; |
taylorza | 0:01829868570e | 386 | tie.MinY = 1000000; |
taylorza | 0:01829868570e | 387 | tie.MaxX = -1000000; |
taylorza | 0:01829868570e | 388 | tie.MaxY = -1000000; |
taylorza | 0:01829868570e | 389 | |
taylorza | 0:01829868570e | 390 | for (int edge = 0; edge < NUM_TIE_EDGES; ++edge) |
taylorza | 0:01829868570e | 391 | { |
taylorza | 0:01829868570e | 392 | Vector3d p1_per, p2_per; |
taylorza | 0:01829868570e | 393 | |
taylorza | 0:01829868570e | 394 | Line3d &shape = tieShape[edge]; |
taylorza | 0:01829868570e | 395 | Vector3d &v1 = tieVerts[shape.V1]; |
taylorza | 0:01829868570e | 396 | Vector3d &v2 = tieVerts[shape.V2]; |
taylorza | 0:01829868570e | 397 | |
taylorza | 0:01829868570e | 398 | p1_per.X = ViewDistance * ((tie.Position.X + v1.X) / (tie.Position.Z + v1.Z)); |
taylorza | 0:01829868570e | 399 | p1_per.Y = ViewDistance * ((tie.Position.Y + v1.Y) / (tie.Position.Z + v1.Z)); |
taylorza | 0:01829868570e | 400 | |
taylorza | 0:01829868570e | 401 | p2_per.X = ViewDistance * ((tie.Position.X + v2.X) / (ties[i].Position.Z + v2.Z)); |
taylorza | 0:01829868570e | 402 | p2_per.Y = ViewDistance * ((tie.Position.Y + v2.Y) / (ties[i].Position.Z + v2.Z)); |
taylorza | 0:01829868570e | 403 | |
taylorza | 0:01829868570e | 404 | int p1_screen_x = (int)(HalfViewWidth + p1_per.X); |
taylorza | 0:01829868570e | 405 | int p1_screen_y = (int)(HalfViewHeight + p1_per.Y); |
taylorza | 0:01829868570e | 406 | int p2_screen_x = (int)(HalfViewWidth + p2_per.X); |
taylorza | 0:01829868570e | 407 | int p2_screen_y = (int)(HalfViewHeight + p2_per.Y); |
taylorza | 0:01829868570e | 408 | |
taylorza | 0:01829868570e | 409 | if (p1_screen_x < tie.MinX) tie.MinX = p1_screen_x; |
taylorza | 0:01829868570e | 410 | if (p2_screen_x < tie.MinX) tie.MinX = p2_screen_x; |
taylorza | 0:01829868570e | 411 | if (p1_screen_x > tie.MaxX) tie.MaxX = p1_screen_x; |
taylorza | 0:01829868570e | 412 | if (p2_screen_x > tie.MaxX) tie.MaxX = p2_screen_x; |
taylorza | 0:01829868570e | 413 | |
taylorza | 0:01829868570e | 414 | if (p1_screen_y < tie.MinY) tie.MinY = p1_screen_y; |
taylorza | 0:01829868570e | 415 | if (p2_screen_y < tie.MinY) tie.MinY = p2_screen_y; |
taylorza | 0:01829868570e | 416 | if (p1_screen_y > tie.MaxY) tie.MaxY = p1_screen_y; |
taylorza | 0:01829868570e | 417 | if (p2_screen_y > tie.MaxY) tie.MaxY = p2_screen_y; |
taylorza | 0:01829868570e | 418 | |
taylorza | 0:01829868570e | 419 | canvas.drawLine(p1_screen_x, p1_screen_y, p2_screen_x, p2_screen_y, 1); |
taylorza | 0:01829868570e | 420 | } |
taylorza | 0:01829868570e | 421 | } |
taylorza | 0:01829868570e | 422 | |
taylorza | 0:01829868570e | 423 | // Draw explosions |
taylorza | 0:01829868570e | 424 | for (int i = 0; i < NUM_EXPLOSIONS; ++i) |
taylorza | 0:01829868570e | 425 | { |
taylorza | 0:01829868570e | 426 | Explosion &explosion = explosions[i]; |
taylorza | 0:01829868570e | 427 | if (explosion.Active == false) continue; |
taylorza | 0:01829868570e | 428 | |
taylorza | 0:01829868570e | 429 | for (int edge = 0; edge < NUM_TIE_EDGES; ++edge) |
taylorza | 0:01829868570e | 430 | { |
taylorza | 0:01829868570e | 431 | Vector3d &p1 = explosion.P1[edge]; |
taylorza | 0:01829868570e | 432 | Vector3d &p2 = explosion.P2[edge]; |
taylorza | 0:01829868570e | 433 | |
taylorza | 0:01829868570e | 434 | if (p1.Z < NearZ && p2.Z < NearZ) continue; |
taylorza | 0:01829868570e | 435 | |
taylorza | 0:01829868570e | 436 | Vector3d p1_per, p2_per; |
taylorza | 0:01829868570e | 437 | |
taylorza | 0:01829868570e | 438 | p1_per.X = ViewDistance * (p1.X / p1.Z); |
taylorza | 0:01829868570e | 439 | p1_per.Y = ViewDistance * (p1.Y / p1.Z); |
taylorza | 0:01829868570e | 440 | |
taylorza | 0:01829868570e | 441 | p2_per.X = ViewDistance * (p2.X / p2.Z); |
taylorza | 0:01829868570e | 442 | p2_per.Y = ViewDistance * (p2.Y / p2.Z); |
taylorza | 0:01829868570e | 443 | |
taylorza | 0:01829868570e | 444 | int p1_screen_x = (int)(HalfViewWidth + p1_per.X); |
taylorza | 0:01829868570e | 445 | int p1_screen_y = (int)(HalfViewHeight + p1_per.Y); |
taylorza | 0:01829868570e | 446 | int p2_screen_x = (int)(HalfViewWidth + p2_per.X); |
taylorza | 0:01829868570e | 447 | int p2_screen_y = (int)(HalfViewHeight + p2_per.Y); |
taylorza | 0:01829868570e | 448 | |
taylorza | 0:01829868570e | 449 | canvas.drawLine(p1_screen_x, p1_screen_y, p2_screen_x, p2_screen_y, 1); |
taylorza | 0:01829868570e | 450 | } |
taylorza | 0:01829868570e | 451 | } |
taylorza | 0:01829868570e | 452 | |
taylorza | 0:01829868570e | 453 | // Draw laser fire |
taylorza | 0:01829868570e | 454 | if (cannonState == 1) |
taylorza | 0:01829868570e | 455 | { |
taylorza | 0:01829868570e | 456 | if (rand() % 2 == 1) |
taylorza | 0:01829868570e | 457 | { |
taylorza | 0:01829868570e | 458 | canvas.drawLine(VIEW_WIDTH - 21, VIEW_HEIGHT - 1, -4 + rand() % 8 + TARGET_X, -4 + rand() % 8 + TARGET_Y, 1); |
taylorza | 0:01829868570e | 459 | } |
taylorza | 0:01829868570e | 460 | else |
taylorza | 0:01829868570e | 461 | { |
taylorza | 0:01829868570e | 462 | canvas.drawLine(20, VIEW_HEIGHT - 1, -4 + rand() % 8 + TARGET_X, -4 + rand() % 8 + TARGET_Y, 1); |
taylorza | 0:01829868570e | 463 | } |
taylorza | 0:01829868570e | 464 | } |
taylorza | 0:01829868570e | 465 | |
taylorza | 0:01829868570e | 466 | // Draw cross-hair |
taylorza | 0:01829868570e | 467 | canvas.drawLine(VIEW_WIDTH / 2, VIEW_HEIGHT / 2 - 10, VIEW_WIDTH / 2, VIEW_HEIGHT / 2 - 5, 1); |
taylorza | 0:01829868570e | 468 | canvas.drawLine(VIEW_WIDTH / 2, VIEW_HEIGHT / 2 + 10, VIEW_WIDTH / 2, VIEW_HEIGHT / 2 + 5, 1); |
taylorza | 0:01829868570e | 469 | |
taylorza | 0:01829868570e | 470 | canvas.drawLine(VIEW_WIDTH / 2 - 10, VIEW_HEIGHT / 2, VIEW_WIDTH / 2 - 5, VIEW_HEIGHT / 2, 1); |
taylorza | 0:01829868570e | 471 | canvas.drawLine(VIEW_WIDTH / 2 + 10, VIEW_HEIGHT / 2, VIEW_WIDTH / 2 + 5, VIEW_HEIGHT / 2, 1); |
taylorza | 0:01829868570e | 472 | } |