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@4:b857db213f10, 2015-02-08 (annotated)
- Committer:
- taylorza
- Date:
- Sun Feb 08 01:38:18 2015 +0000
- Revision:
- 4:b857db213f10
- Parent:
- 2:db53af3d2e0f
Removed duty lookup table
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 | 1:9ff7384171ec | 9 | #include "SpriteSheet.h" |
taylorza | 1:9ff7384171ec | 10 | |
taylorza | 1:9ff7384171ec | 11 | #include "SoundBlock.h" |
taylorza | 1:9ff7384171ec | 12 | #include "SoundChannel.h" |
taylorza | 1:9ff7384171ec | 13 | #include "OneBitSound.h" |
taylorza | 0:01829868570e | 14 | |
taylorza | 0:01829868570e | 15 | #define VIEW_WIDTH 160 |
taylorza | 0:01829868570e | 16 | #define VIEW_HEIGHT 104 |
taylorza | 0:01829868570e | 17 | |
taylorza | 0:01829868570e | 18 | #define NUM_STARS 10 |
taylorza | 0:01829868570e | 19 | #define NUM_TIES 5 |
taylorza | 0:01829868570e | 20 | #define NUM_TIE_VERTS 10 |
taylorza | 0:01829868570e | 21 | #define NUM_TIE_EDGES 10 |
taylorza | 0:01829868570e | 22 | #define NUM_EXPLOSIONS (NUM_TIES) |
taylorza | 0:01829868570e | 23 | |
taylorza | 0:01829868570e | 24 | #define TARGET_X (VIEW_WIDTH >> 1) |
taylorza | 0:01829868570e | 25 | #define TARGET_Y (VIEW_HEIGHT >> 1) |
taylorza | 0:01829868570e | 26 | |
taylorza | 1:9ff7384171ec | 27 | const float NearZ = 10; |
taylorza | 1:9ff7384171ec | 28 | const float FarZ = 2000; |
taylorza | 1:9ff7384171ec | 29 | const float ViewDistance = 80; |
taylorza | 1:9ff7384171ec | 30 | const float HalfViewWidth = VIEW_WIDTH/ 2; |
taylorza | 1:9ff7384171ec | 31 | const float HalfViewHeight = VIEW_HEIGHT/ 2; |
taylorza | 0:01829868570e | 32 | |
taylorza | 1:9ff7384171ec | 33 | const float TenPercent = 0.1f; |
taylorza | 1:9ff7384171ec | 34 | const float NintyFivePercent = 0.95f; |
taylorza | 0:01829868570e | 35 | |
taylorza | 1:9ff7384171ec | 36 | const float StarVelocity = 10; |
taylorza | 0:01829868570e | 37 | |
taylorza | 0:01829868570e | 38 | Vector3d stars[NUM_STARS]; |
taylorza | 0:01829868570e | 39 | |
taylorza | 0:01829868570e | 40 | struct Line3d |
taylorza | 0:01829868570e | 41 | { |
taylorza | 0:01829868570e | 42 | uint8_t V1; |
taylorza | 0:01829868570e | 43 | uint8_t V2; |
taylorza | 0:01829868570e | 44 | |
taylorza | 0:01829868570e | 45 | Line3d(uint8_t v1, uint8_t v2) : V1(v1), V2(v2) {} |
taylorza | 0:01829868570e | 46 | }; |
taylorza | 0:01829868570e | 47 | |
taylorza | 0:01829868570e | 48 | struct TieFighter |
taylorza | 0:01829868570e | 49 | { |
taylorza | 0:01829868570e | 50 | |
taylorza | 0:01829868570e | 51 | Vector3d Position; |
taylorza | 0:01829868570e | 52 | Vector3d Velocity; |
taylorza | 0:01829868570e | 53 | |
taylorza | 0:01829868570e | 54 | int MinX; |
taylorza | 0:01829868570e | 55 | int MinY; |
taylorza | 0:01829868570e | 56 | int MaxX; |
taylorza | 0:01829868570e | 57 | int MaxY; |
taylorza | 0:01829868570e | 58 | }; |
taylorza | 0:01829868570e | 59 | |
taylorza | 0:01829868570e | 60 | struct Explosion |
taylorza | 0:01829868570e | 61 | { |
taylorza | 0:01829868570e | 62 | bool Active; |
taylorza | 0:01829868570e | 63 | int Counter; |
taylorza | 0:01829868570e | 64 | Vector3d P1[NUM_TIE_EDGES]; |
taylorza | 0:01829868570e | 65 | Vector3d P2[NUM_TIE_EDGES]; |
taylorza | 0:01829868570e | 66 | Vector3d Velocity[NUM_TIE_EDGES]; |
taylorza | 0:01829868570e | 67 | }; |
taylorza | 0:01829868570e | 68 | |
taylorza | 0:01829868570e | 69 | Vector3d tieVerts[NUM_TIE_VERTS] = |
taylorza | 0:01829868570e | 70 | { |
taylorza | 0:01829868570e | 71 | Vector3d(-50, 40, 0), |
taylorza | 0:01829868570e | 72 | Vector3d(-40, 0, 0), |
taylorza | 0:01829868570e | 73 | Vector3d(-50, -40, 0), |
taylorza | 0:01829868570e | 74 | Vector3d(-10, 0, 0), |
taylorza | 0:01829868570e | 75 | Vector3d(0, 20, 0), |
taylorza | 0:01829868570e | 76 | Vector3d(10, 0, 0), |
taylorza | 0:01829868570e | 77 | Vector3d(0, -20, 0), |
taylorza | 0:01829868570e | 78 | Vector3d(50, 40, 0), |
taylorza | 0:01829868570e | 79 | Vector3d(40, 0, 0), |
taylorza | 0:01829868570e | 80 | Vector3d(50, -40, 0), |
taylorza | 0:01829868570e | 81 | }; |
taylorza | 0:01829868570e | 82 | |
taylorza | 0:01829868570e | 83 | Line3d tieShape[NUM_TIE_EDGES] = |
taylorza | 0:01829868570e | 84 | { |
taylorza | 0:01829868570e | 85 | Line3d(0, 1), |
taylorza | 0:01829868570e | 86 | Line3d(1, 2), |
taylorza | 0:01829868570e | 87 | Line3d(1, 3), |
taylorza | 0:01829868570e | 88 | Line3d(3, 4), |
taylorza | 0:01829868570e | 89 | Line3d(4, 5), |
taylorza | 0:01829868570e | 90 | Line3d(5, 6), |
taylorza | 0:01829868570e | 91 | Line3d(6, 3), |
taylorza | 0:01829868570e | 92 | Line3d(5, 8), |
taylorza | 0:01829868570e | 93 | Line3d(8, 7), |
taylorza | 0:01829868570e | 94 | Line3d(8, 9), |
taylorza | 0:01829868570e | 95 | }; |
taylorza | 0:01829868570e | 96 | |
taylorza | 0:01829868570e | 97 | TieFighter ties[NUM_TIES]; |
taylorza | 0:01829868570e | 98 | Explosion explosions[NUM_EXPLOSIONS]; |
taylorza | 0:01829868570e | 99 | Vector3d steeringForce; |
taylorza | 0:01829868570e | 100 | |
taylorza | 0:01829868570e | 101 | bool updateHud = true; |
taylorza | 0:01829868570e | 102 | int hits = 0; |
taylorza | 0:01829868570e | 103 | int misses = 0; |
taylorza | 0:01829868570e | 104 | int score = 0; |
taylorza | 0:01829868570e | 105 | |
taylorza | 0:01829868570e | 106 | Bitmap1bpp image(VIEW_WIDTH, VIEW_HEIGHT); |
taylorza | 0:01829868570e | 107 | Canvas<Bitmap1bpp> canvas(&image); |
taylorza | 0:01829868570e | 108 | |
taylorza | 0:01829868570e | 109 | int cannonState = 0; |
taylorza | 0:01829868570e | 110 | int cannonCount = 0; |
taylorza | 0:01829868570e | 111 | |
taylorza | 0:01829868570e | 112 | void initStar(int index, bool initial); |
taylorza | 0:01829868570e | 113 | void initTie(int index); |
taylorza | 0:01829868570e | 114 | |
taylorza | 0:01829868570e | 115 | void startExplosion(int tieIndex); |
taylorza | 0:01829868570e | 116 | |
taylorza | 1:9ff7384171ec | 117 | void showIntro(); |
taylorza | 1:9ff7384171ec | 118 | void playGame(); |
taylorza | 1:9ff7384171ec | 119 | |
taylorza | 0:01829868570e | 120 | void update(); |
taylorza | 0:01829868570e | 121 | void draw(); |
taylorza | 0:01829868570e | 122 | |
taylorza | 1:9ff7384171ec | 123 | char buffer[20]; |
taylorza | 1:9ff7384171ec | 124 | |
taylorza | 1:9ff7384171ec | 125 | OneBitSound soundEngine(P0_18); |
taylorza | 1:9ff7384171ec | 126 | |
taylorza | 1:9ff7384171ec | 127 | CREATE_EFFECT(Sound_FireLaser) |
taylorza | 1:9ff7384171ec | 128 | TONE(20, 50, 2000, -50, 128, 0) |
taylorza | 1:9ff7384171ec | 129 | END_EFFECT |
taylorza | 1:9ff7384171ec | 130 | |
taylorza | 1:9ff7384171ec | 131 | CREATE_EFFECT(Sound_Explosion) |
taylorza | 1:9ff7384171ec | 132 | NOISE(20, 1000, 10, 5) |
taylorza | 1:9ff7384171ec | 133 | END_EFFECT |
taylorza | 1:9ff7384171ec | 134 | |
taylorza | 0:01829868570e | 135 | LCD_ST7735 Surface( |
taylorza | 0:01829868570e | 136 | P0_19, |
taylorza | 2:db53af3d2e0f | 137 | P0_20, |
taylorza | 2:db53af3d2e0f | 138 | P0_7, |
taylorza | 0:01829868570e | 139 | P0_21, |
taylorza | 0:01829868570e | 140 | P0_22, |
taylorza | 0:01829868570e | 141 | P1_15, |
taylorza | 0:01829868570e | 142 | P0_2, |
taylorza | 0:01829868570e | 143 | LCD_ST7735::RGB); |
taylorza | 0:01829868570e | 144 | |
taylorza | 0:01829868570e | 145 | main() |
taylorza | 0:01829868570e | 146 | { |
taylorza | 0:01829868570e | 147 | Surface.setOrientation(LCD_ST7735::Rotate270, false); |
taylorza | 1:9ff7384171ec | 148 | |
taylorza | 1:9ff7384171ec | 149 | showIntro(); |
taylorza | 1:9ff7384171ec | 150 | playGame(); |
taylorza | 1:9ff7384171ec | 151 | } |
taylorza | 1:9ff7384171ec | 152 | |
taylorza | 1:9ff7384171ec | 153 | void showIntro() |
taylorza | 1:9ff7384171ec | 154 | { |
taylorza | 1:9ff7384171ec | 155 | // Title - Space Raiders |
taylorza | 1:9ff7384171ec | 156 | Surface.drawBitmap(13, 0, bmp, 0, 0, 133, 13, Color565::Aqua, Color565::Black); |
taylorza | 1:9ff7384171ec | 157 | |
taylorza | 1:9ff7384171ec | 158 | // Image |
taylorza | 1:9ff7384171ec | 159 | Surface.drawBitmap(45, 16, bmp, 0, 16, 69, 83, Color565::Green, Color565::Black); |
taylorza | 1:9ff7384171ec | 160 | |
taylorza | 1:9ff7384171ec | 161 | // Press [] to start |
taylorza | 1:9ff7384171ec | 162 | Surface.drawBitmap(43, 102, bmp, 72, 16, 73, 8, Color565::White, Color565::Black); |
taylorza | 1:9ff7384171ec | 163 | |
taylorza | 1:9ff7384171ec | 164 | // (c)2015 |
taylorza | 1:9ff7384171ec | 165 | Surface.drawBitmap(44, 120, bmp, 72, 32, 71, 8, Color565::White, Color565::Black); |
taylorza | 1:9ff7384171ec | 166 | |
taylorza | 1:9ff7384171ec | 167 | while (!GameInput::isSquarePressed()); |
taylorza | 1:9ff7384171ec | 168 | } |
taylorza | 1:9ff7384171ec | 169 | |
taylorza | 1:9ff7384171ec | 170 | void playGame() |
taylorza | 1:9ff7384171ec | 171 | { |
taylorza | 1:9ff7384171ec | 172 | Surface.clearScreen(); |
taylorza | 0:01829868570e | 173 | |
taylorza | 0:01829868570e | 174 | // Init stars |
taylorza | 0:01829868570e | 175 | for (int i = 0; i < NUM_STARS; ++i) |
taylorza | 0:01829868570e | 176 | { |
taylorza | 0:01829868570e | 177 | initStar(i, true); |
taylorza | 0:01829868570e | 178 | } |
taylorza | 0:01829868570e | 179 | |
taylorza | 0:01829868570e | 180 | // Init tie fighters |
taylorza | 0:01829868570e | 181 | for (int i = 0; i < NUM_TIES; ++i) |
taylorza | 0:01829868570e | 182 | { |
taylorza | 1:9ff7384171ec | 183 | initTie(i); |
taylorza | 0:01829868570e | 184 | } |
taylorza | 0:01829868570e | 185 | |
taylorza | 0:01829868570e | 186 | // Init explosions |
taylorza | 0:01829868570e | 187 | for (int i = 0; i < NUM_EXPLOSIONS; ++i) |
taylorza | 0:01829868570e | 188 | { |
taylorza | 0:01829868570e | 189 | explosions[i].Active = false; |
taylorza | 0:01829868570e | 190 | } |
taylorza | 0:01829868570e | 191 | |
taylorza | 0:01829868570e | 192 | while (true) |
taylorza | 0:01829868570e | 193 | { |
taylorza | 0:01829868570e | 194 | canvas.clear(); |
taylorza | 0:01829868570e | 195 | |
taylorza | 0:01829868570e | 196 | update(); |
taylorza | 0:01829868570e | 197 | draw(); |
taylorza | 0:01829868570e | 198 | |
taylorza | 0:01829868570e | 199 | Surface.drawBitmap(0, 16, image, 0, 0, VIEW_WIDTH, VIEW_HEIGHT, Color565::White, Color565::Black); |
taylorza | 0:01829868570e | 200 | |
taylorza | 0:01829868570e | 201 | if (updateHud) |
taylorza | 0:01829868570e | 202 | { |
taylorza | 0:01829868570e | 203 | updateHud = false; |
taylorza | 0:01829868570e | 204 | Surface.setForegroundColor(Color565::White); |
taylorza | 0:01829868570e | 205 | Surface.drawString(font_ibm, 0, 0, "Hits Score Misses"); |
taylorza | 0:01829868570e | 206 | |
taylorza | 0:01829868570e | 207 | Surface.setForegroundColor(Color565::Yellow); |
taylorza | 0:01829868570e | 208 | sprintf(buffer, "%d", hits); |
taylorza | 0:01829868570e | 209 | Surface.drawString(font_ibm, 8, 8, buffer); |
taylorza | 0:01829868570e | 210 | |
taylorza | 0:01829868570e | 211 | Surface.setForegroundColor(Color565::Lime); |
taylorza | 0:01829868570e | 212 | sprintf(buffer, "%d", score); |
taylorza | 0:01829868570e | 213 | Surface.drawString(font_ibm, 56, 8, buffer); |
taylorza | 0:01829868570e | 214 | |
taylorza | 0:01829868570e | 215 | Surface.setForegroundColor(Color565::Red); |
taylorza | 0:01829868570e | 216 | sprintf(buffer, "%d", misses); |
taylorza | 0:01829868570e | 217 | Surface.drawString(font_ibm, 128, 8, buffer); |
taylorza | 0:01829868570e | 218 | } |
taylorza | 0:01829868570e | 219 | |
taylorza | 1:9ff7384171ec | 220 | if (misses == 50) break; |
taylorza | 1:9ff7384171ec | 221 | } |
taylorza | 1:9ff7384171ec | 222 | |
taylorza | 1:9ff7384171ec | 223 | Surface.setForegroundColor(Color565::Red); |
taylorza | 1:9ff7384171ec | 224 | Surface.drawString(font_ibm, 44, 60, "GAME OVER"); |
taylorza | 0:01829868570e | 225 | } |
taylorza | 0:01829868570e | 226 | |
taylorza | 0:01829868570e | 227 | void initStar(int index, bool initial) |
taylorza | 0:01829868570e | 228 | { |
taylorza | 1:9ff7384171ec | 229 | stars[index].X = -VIEW_WIDTH + rand() % (2 * VIEW_WIDTH); |
taylorza | 1:9ff7384171ec | 230 | stars[index].Y = -VIEW_HEIGHT + rand() % (2 * VIEW_HEIGHT); |
taylorza | 0:01829868570e | 231 | if (initial) |
taylorza | 1:9ff7384171ec | 232 | stars[index].Z = NearZ + rand() % (int)(FarZ - NearZ); |
taylorza | 0:01829868570e | 233 | else |
taylorza | 0:01829868570e | 234 | stars[index].Z = 500; |
taylorza | 0:01829868570e | 235 | } |
taylorza | 0:01829868570e | 236 | |
taylorza | 0:01829868570e | 237 | void initTie(int index) |
taylorza | 0:01829868570e | 238 | { |
taylorza | 0:01829868570e | 239 | ties[index].Position.X = -VIEW_WIDTH + rand() % (2 * VIEW_WIDTH); |
taylorza | 0:01829868570e | 240 | ties[index].Position.Y = -VIEW_HEIGHT + rand() % (2 * VIEW_HEIGHT); |
taylorza | 0:01829868570e | 241 | ties[index].Position.Z = FarZ * (rand() % 3 + 1); |
taylorza | 0:01829868570e | 242 | |
taylorza | 0:01829868570e | 243 | ties[index].Velocity.X = -0.5f + rand() % 2; |
taylorza | 0:01829868570e | 244 | ties[index].Velocity.Y = -0.5f + rand() % 2; |
taylorza | 1:9ff7384171ec | 245 | int difficulty = hits > 48 ? 48 : hits; |
taylorza | 1:9ff7384171ec | 246 | ties[index].Velocity.Z = -4 - rand() % (8 + difficulty); |
taylorza | 0:01829868570e | 247 | } |
taylorza | 0:01829868570e | 248 | |
taylorza | 0:01829868570e | 249 | void startExplosion(int tieIndex) |
taylorza | 0:01829868570e | 250 | { |
taylorza | 0:01829868570e | 251 | TieFighter &tie = ties[tieIndex]; |
taylorza | 0:01829868570e | 252 | for (int i = 0; i < NUM_EXPLOSIONS; ++i) |
taylorza | 0:01829868570e | 253 | { |
taylorza | 0:01829868570e | 254 | Explosion &explosion = explosions[i]; |
taylorza | 0:01829868570e | 255 | if (explosion.Active == false) |
taylorza | 0:01829868570e | 256 | { |
taylorza | 0:01829868570e | 257 | explosion.Active = true; |
taylorza | 0:01829868570e | 258 | explosion.Counter = 0; |
taylorza | 0:01829868570e | 259 | |
taylorza | 0:01829868570e | 260 | for (int edge = 0; edge < NUM_TIE_EDGES; ++edge) |
taylorza | 0:01829868570e | 261 | { |
taylorza | 0:01829868570e | 262 | Line3d &shape = tieShape[edge]; |
taylorza | 0:01829868570e | 263 | |
taylorza | 0:01829868570e | 264 | // Start |
taylorza | 0:01829868570e | 265 | Vector3d &p1 = explosion.P1[edge]; |
taylorza | 0:01829868570e | 266 | Vector3d &v1 = tieVerts[shape.V1]; |
taylorza | 0:01829868570e | 267 | p1.X = tie.Position.X + v1.X; |
taylorza | 0:01829868570e | 268 | p1.Y = tie.Position.Y + v1.Y; |
taylorza | 0:01829868570e | 269 | p1.Z = tie.Position.Z + v1.Z; |
taylorza | 0:01829868570e | 270 | |
taylorza | 0:01829868570e | 271 | // End |
taylorza | 0:01829868570e | 272 | Vector3d &p2 = explosion.P2[edge]; |
taylorza | 0:01829868570e | 273 | Vector3d &v2 = tieVerts[shape.V2]; |
taylorza | 0:01829868570e | 274 | p2.X = tie.Position.X + v2.X; |
taylorza | 0:01829868570e | 275 | p2.Y = tie.Position.Y + v2.Y; |
taylorza | 0:01829868570e | 276 | p2.Z = tie.Position.Z + v2.Z; |
taylorza | 0:01829868570e | 277 | |
taylorza | 0:01829868570e | 278 | // Trajectory |
taylorza | 0:01829868570e | 279 | Vector3d &velocity = explosion.Velocity[edge]; |
taylorza | 0:01829868570e | 280 | Vector3d &tieVelocity = tie.Velocity; |
taylorza | 0:01829868570e | 281 | velocity.X = tieVelocity.X - 8 + rand() % 16; |
taylorza | 0:01829868570e | 282 | velocity.Y = tieVelocity.Y - 8 + rand() % 16; |
taylorza | 0:01829868570e | 283 | velocity.Z = tieVelocity.Z - 8 + rand() % 16; |
taylorza | 0:01829868570e | 284 | } |
taylorza | 1:9ff7384171ec | 285 | soundEngine.play(2, EFFECT(Sound_Explosion)); |
taylorza | 0:01829868570e | 286 | break; |
taylorza | 0:01829868570e | 287 | } |
taylorza | 0:01829868570e | 288 | } |
taylorza | 0:01829868570e | 289 | } |
taylorza | 0:01829868570e | 290 | |
taylorza | 0:01829868570e | 291 | void update() |
taylorza | 0:01829868570e | 292 | { |
taylorza | 0:01829868570e | 293 | // Move ties |
taylorza | 0:01829868570e | 294 | for (int i = 0; i < NUM_TIES; ++i) |
taylorza | 0:01829868570e | 295 | { |
taylorza | 0:01829868570e | 296 | TieFighter &tie = ties[i]; |
taylorza | 0:01829868570e | 297 | |
taylorza | 0:01829868570e | 298 | if (cannonState == 1) |
taylorza | 0:01829868570e | 299 | { |
taylorza | 0:01829868570e | 300 | if (tie.MinX < TARGET_X && tie.MaxX > TARGET_X |
taylorza | 0:01829868570e | 301 | && tie.MinY < TARGET_Y && tie.MaxY > TARGET_Y) |
taylorza | 0:01829868570e | 302 | { |
taylorza | 0:01829868570e | 303 | startExplosion(i); |
taylorza | 0:01829868570e | 304 | ++hits; |
taylorza | 0:01829868570e | 305 | score += ((int)tie.Position.Z) / 10; |
taylorza | 1:9ff7384171ec | 306 | updateHud = true; |
taylorza | 0:01829868570e | 307 | initTie(i); |
taylorza | 0:01829868570e | 308 | continue; |
taylorza | 0:01829868570e | 309 | } |
taylorza | 0:01829868570e | 310 | } |
taylorza | 0:01829868570e | 311 | |
taylorza | 0:01829868570e | 312 | tie.Position.X += (tie.Velocity.X + steeringForce.X); |
taylorza | 0:01829868570e | 313 | tie.Position.Y += (tie.Velocity.Y + steeringForce.Y); |
taylorza | 0:01829868570e | 314 | tie.Position.Z += (tie.Velocity.Z + steeringForce.Z); |
taylorza | 0:01829868570e | 315 | |
taylorza | 0:01829868570e | 316 | if (tie.Position.Z <= NearZ) |
taylorza | 0:01829868570e | 317 | { |
taylorza | 0:01829868570e | 318 | initTie(i); |
taylorza | 0:01829868570e | 319 | ++misses; |
taylorza | 0:01829868570e | 320 | updateHud = true; |
taylorza | 0:01829868570e | 321 | } |
taylorza | 0:01829868570e | 322 | } |
taylorza | 0:01829868570e | 323 | |
taylorza | 0:01829868570e | 324 | // Move stars |
taylorza | 0:01829868570e | 325 | for (int i = 0; i < NUM_STARS; ++i) |
taylorza | 0:01829868570e | 326 | { |
taylorza | 0:01829868570e | 327 | Vector3d &star = stars[i]; |
taylorza | 0:01829868570e | 328 | star.X += (steeringForce.X * TenPercent); |
taylorza | 0:01829868570e | 329 | star.Y += (steeringForce.Y * TenPercent); |
taylorza | 0:01829868570e | 330 | star.Z -= StarVelocity; |
taylorza | 0:01829868570e | 331 | |
taylorza | 0:01829868570e | 332 | if (star.Z <= NearZ) |
taylorza | 0:01829868570e | 333 | { |
taylorza | 0:01829868570e | 334 | initStar(i, false); |
taylorza | 0:01829868570e | 335 | } |
taylorza | 0:01829868570e | 336 | } |
taylorza | 0:01829868570e | 337 | |
taylorza | 0:01829868570e | 338 | // Update explosions |
taylorza | 0:01829868570e | 339 | for (int i = 0; i < NUM_EXPLOSIONS; ++i) |
taylorza | 0:01829868570e | 340 | { |
taylorza | 0:01829868570e | 341 | Explosion &explosion = explosions[i]; |
taylorza | 0:01829868570e | 342 | if (explosion.Active == false) continue; |
taylorza | 0:01829868570e | 343 | |
taylorza | 0:01829868570e | 344 | for (int edge = 0; edge < NUM_TIE_EDGES; ++edge) |
taylorza | 0:01829868570e | 345 | { |
taylorza | 0:01829868570e | 346 | Vector3d &v = explosions[i].Velocity[edge]; |
taylorza | 0:01829868570e | 347 | |
taylorza | 0:01829868570e | 348 | Vector3d &p1 = explosions[i].P1[edge]; |
taylorza | 0:01829868570e | 349 | p1.X += v.X; |
taylorza | 0:01829868570e | 350 | p1.Y += v.Y; |
taylorza | 0:01829868570e | 351 | p1.Z += v.Z; |
taylorza | 0:01829868570e | 352 | |
taylorza | 0:01829868570e | 353 | Vector3d &p2 = explosions[i].P2[edge]; |
taylorza | 0:01829868570e | 354 | p2.X += v.X; |
taylorza | 0:01829868570e | 355 | p2.Y += v.Y; |
taylorza | 0:01829868570e | 356 | p2.Z += v.Z; |
taylorza | 0:01829868570e | 357 | } |
taylorza | 0:01829868570e | 358 | |
taylorza | 0:01829868570e | 359 | if (++explosions[i].Counter > 100) |
taylorza | 0:01829868570e | 360 | { |
taylorza | 0:01829868570e | 361 | explosions[i].Active = false; |
taylorza | 0:01829868570e | 362 | } |
taylorza | 0:01829868570e | 363 | } |
taylorza | 0:01829868570e | 364 | |
taylorza | 1:9ff7384171ec | 365 | if (GameInput::isLeftPressed()) steeringForce.X += 1.5; |
taylorza | 1:9ff7384171ec | 366 | if (GameInput::isRightPressed()) steeringForce.X -= 1.5; |
taylorza | 1:9ff7384171ec | 367 | if (GameInput::isUpPressed()) steeringForce.Y -= 1.5; |
taylorza | 1:9ff7384171ec | 368 | if (GameInput::isDownPressed()) steeringForce.Y += 1.5; |
taylorza | 0:01829868570e | 369 | |
taylorza | 0:01829868570e | 370 | if (GameInput::isCirclePressed() && cannonState == 0) |
taylorza | 0:01829868570e | 371 | { |
taylorza | 0:01829868570e | 372 | cannonState = 1; |
taylorza | 1:9ff7384171ec | 373 | cannonCount = 0; |
taylorza | 0:01829868570e | 374 | } |
taylorza | 0:01829868570e | 375 | |
taylorza | 0:01829868570e | 376 | if (cannonState == 1) |
taylorza | 1:9ff7384171ec | 377 | if (++cannonCount > 10) |
taylorza | 0:01829868570e | 378 | cannonState = 2; |
taylorza | 0:01829868570e | 379 | |
taylorza | 0:01829868570e | 380 | if (cannonState == 2) |
taylorza | 0:01829868570e | 381 | if (++cannonCount > 20) |
taylorza | 0:01829868570e | 382 | cannonState = 0; |
taylorza | 0:01829868570e | 383 | |
taylorza | 0:01829868570e | 384 | // Dampen thrusters |
taylorza | 0:01829868570e | 385 | steeringForce.X *= NintyFivePercent; |
taylorza | 0:01829868570e | 386 | steeringForce.Y *= NintyFivePercent; |
taylorza | 0:01829868570e | 387 | steeringForce.Z *= NintyFivePercent; |
taylorza | 0:01829868570e | 388 | } |
taylorza | 0:01829868570e | 389 | |
taylorza | 0:01829868570e | 390 | void draw() |
taylorza | 0:01829868570e | 391 | { |
taylorza | 0:01829868570e | 392 | // Draw stars |
taylorza | 0:01829868570e | 393 | for (int i = 0; i < NUM_STARS; ++i) |
taylorza | 0:01829868570e | 394 | { |
taylorza | 0:01829868570e | 395 | Vector3d &star = stars[i]; |
taylorza | 0:01829868570e | 396 | |
taylorza | 0:01829868570e | 397 | // Perspective transform |
taylorza | 1:9ff7384171ec | 398 | float x_per = ViewDistance * (star.X / star.Z); |
taylorza | 1:9ff7384171ec | 399 | float y_per = ViewDistance * (star.Y / star.Z); |
taylorza | 0:01829868570e | 400 | |
taylorza | 0:01829868570e | 401 | // Screen coordiante transform |
taylorza | 0:01829868570e | 402 | int x_screen = (int)(HalfViewWidth + x_per); |
taylorza | 0:01829868570e | 403 | int y_screen = (int)(HalfViewHeight + y_per); |
taylorza | 0:01829868570e | 404 | |
taylorza | 0:01829868570e | 405 | // Clip to screen |
taylorza | 0:01829868570e | 406 | if (x_screen >= VIEW_WIDTH || x_screen < 0 || |
taylorza | 0:01829868570e | 407 | y_screen >= VIEW_HEIGHT || y_screen < 0) |
taylorza | 0:01829868570e | 408 | { |
taylorza | 0:01829868570e | 409 | initStar(i, false); |
taylorza | 0:01829868570e | 410 | continue; |
taylorza | 0:01829868570e | 411 | } |
taylorza | 0:01829868570e | 412 | |
taylorza | 0:01829868570e | 413 | canvas.setPixel(x_screen, y_screen, 1); |
taylorza | 0:01829868570e | 414 | } |
taylorza | 0:01829868570e | 415 | |
taylorza | 0:01829868570e | 416 | // Draw ties |
taylorza | 0:01829868570e | 417 | for(int i = 0; i < NUM_TIES; ++i) |
taylorza | 0:01829868570e | 418 | { |
taylorza | 0:01829868570e | 419 | TieFighter &tie = ties[i]; |
taylorza | 0:01829868570e | 420 | |
taylorza | 0:01829868570e | 421 | tie.MinX = 1000000; |
taylorza | 0:01829868570e | 422 | tie.MinY = 1000000; |
taylorza | 0:01829868570e | 423 | tie.MaxX = -1000000; |
taylorza | 0:01829868570e | 424 | tie.MaxY = -1000000; |
taylorza | 0:01829868570e | 425 | |
taylorza | 0:01829868570e | 426 | for (int edge = 0; edge < NUM_TIE_EDGES; ++edge) |
taylorza | 0:01829868570e | 427 | { |
taylorza | 0:01829868570e | 428 | Vector3d p1_per, p2_per; |
taylorza | 0:01829868570e | 429 | |
taylorza | 0:01829868570e | 430 | Line3d &shape = tieShape[edge]; |
taylorza | 0:01829868570e | 431 | Vector3d &v1 = tieVerts[shape.V1]; |
taylorza | 0:01829868570e | 432 | Vector3d &v2 = tieVerts[shape.V2]; |
taylorza | 0:01829868570e | 433 | |
taylorza | 0:01829868570e | 434 | p1_per.X = ViewDistance * ((tie.Position.X + v1.X) / (tie.Position.Z + v1.Z)); |
taylorza | 0:01829868570e | 435 | p1_per.Y = ViewDistance * ((tie.Position.Y + v1.Y) / (tie.Position.Z + v1.Z)); |
taylorza | 0:01829868570e | 436 | |
taylorza | 0:01829868570e | 437 | p2_per.X = ViewDistance * ((tie.Position.X + v2.X) / (ties[i].Position.Z + v2.Z)); |
taylorza | 0:01829868570e | 438 | p2_per.Y = ViewDistance * ((tie.Position.Y + v2.Y) / (ties[i].Position.Z + v2.Z)); |
taylorza | 0:01829868570e | 439 | |
taylorza | 0:01829868570e | 440 | int p1_screen_x = (int)(HalfViewWidth + p1_per.X); |
taylorza | 0:01829868570e | 441 | int p1_screen_y = (int)(HalfViewHeight + p1_per.Y); |
taylorza | 0:01829868570e | 442 | int p2_screen_x = (int)(HalfViewWidth + p2_per.X); |
taylorza | 0:01829868570e | 443 | int p2_screen_y = (int)(HalfViewHeight + p2_per.Y); |
taylorza | 0:01829868570e | 444 | |
taylorza | 0:01829868570e | 445 | if (p1_screen_x < tie.MinX) tie.MinX = p1_screen_x; |
taylorza | 0:01829868570e | 446 | if (p2_screen_x < tie.MinX) tie.MinX = p2_screen_x; |
taylorza | 0:01829868570e | 447 | if (p1_screen_x > tie.MaxX) tie.MaxX = p1_screen_x; |
taylorza | 0:01829868570e | 448 | if (p2_screen_x > tie.MaxX) tie.MaxX = p2_screen_x; |
taylorza | 0:01829868570e | 449 | |
taylorza | 0:01829868570e | 450 | if (p1_screen_y < tie.MinY) tie.MinY = p1_screen_y; |
taylorza | 0:01829868570e | 451 | if (p2_screen_y < tie.MinY) tie.MinY = p2_screen_y; |
taylorza | 0:01829868570e | 452 | if (p1_screen_y > tie.MaxY) tie.MaxY = p1_screen_y; |
taylorza | 0:01829868570e | 453 | if (p2_screen_y > tie.MaxY) tie.MaxY = p2_screen_y; |
taylorza | 0:01829868570e | 454 | |
taylorza | 0:01829868570e | 455 | canvas.drawLine(p1_screen_x, p1_screen_y, p2_screen_x, p2_screen_y, 1); |
taylorza | 0:01829868570e | 456 | } |
taylorza | 0:01829868570e | 457 | } |
taylorza | 0:01829868570e | 458 | |
taylorza | 0:01829868570e | 459 | // Draw explosions |
taylorza | 0:01829868570e | 460 | for (int i = 0; i < NUM_EXPLOSIONS; ++i) |
taylorza | 0:01829868570e | 461 | { |
taylorza | 0:01829868570e | 462 | Explosion &explosion = explosions[i]; |
taylorza | 0:01829868570e | 463 | if (explosion.Active == false) continue; |
taylorza | 0:01829868570e | 464 | |
taylorza | 0:01829868570e | 465 | for (int edge = 0; edge < NUM_TIE_EDGES; ++edge) |
taylorza | 0:01829868570e | 466 | { |
taylorza | 0:01829868570e | 467 | Vector3d &p1 = explosion.P1[edge]; |
taylorza | 0:01829868570e | 468 | Vector3d &p2 = explosion.P2[edge]; |
taylorza | 0:01829868570e | 469 | |
taylorza | 0:01829868570e | 470 | if (p1.Z < NearZ && p2.Z < NearZ) continue; |
taylorza | 0:01829868570e | 471 | |
taylorza | 0:01829868570e | 472 | Vector3d p1_per, p2_per; |
taylorza | 0:01829868570e | 473 | |
taylorza | 0:01829868570e | 474 | p1_per.X = ViewDistance * (p1.X / p1.Z); |
taylorza | 0:01829868570e | 475 | p1_per.Y = ViewDistance * (p1.Y / p1.Z); |
taylorza | 0:01829868570e | 476 | |
taylorza | 0:01829868570e | 477 | p2_per.X = ViewDistance * (p2.X / p2.Z); |
taylorza | 0:01829868570e | 478 | p2_per.Y = ViewDistance * (p2.Y / p2.Z); |
taylorza | 0:01829868570e | 479 | |
taylorza | 0:01829868570e | 480 | int p1_screen_x = (int)(HalfViewWidth + p1_per.X); |
taylorza | 0:01829868570e | 481 | int p1_screen_y = (int)(HalfViewHeight + p1_per.Y); |
taylorza | 0:01829868570e | 482 | int p2_screen_x = (int)(HalfViewWidth + p2_per.X); |
taylorza | 0:01829868570e | 483 | int p2_screen_y = (int)(HalfViewHeight + p2_per.Y); |
taylorza | 0:01829868570e | 484 | |
taylorza | 0:01829868570e | 485 | canvas.drawLine(p1_screen_x, p1_screen_y, p2_screen_x, p2_screen_y, 1); |
taylorza | 0:01829868570e | 486 | } |
taylorza | 0:01829868570e | 487 | } |
taylorza | 0:01829868570e | 488 | |
taylorza | 0:01829868570e | 489 | // Draw laser fire |
taylorza | 0:01829868570e | 490 | if (cannonState == 1) |
taylorza | 0:01829868570e | 491 | { |
taylorza | 0:01829868570e | 492 | if (rand() % 2 == 1) |
taylorza | 0:01829868570e | 493 | { |
taylorza | 0:01829868570e | 494 | canvas.drawLine(VIEW_WIDTH - 21, VIEW_HEIGHT - 1, -4 + rand() % 8 + TARGET_X, -4 + rand() % 8 + TARGET_Y, 1); |
taylorza | 1:9ff7384171ec | 495 | soundEngine.play(0, EFFECT(Sound_FireLaser)); |
taylorza | 0:01829868570e | 496 | } |
taylorza | 0:01829868570e | 497 | else |
taylorza | 0:01829868570e | 498 | { |
taylorza | 0:01829868570e | 499 | canvas.drawLine(20, VIEW_HEIGHT - 1, -4 + rand() % 8 + TARGET_X, -4 + rand() % 8 + TARGET_Y, 1); |
taylorza | 1:9ff7384171ec | 500 | soundEngine.play(1, EFFECT(Sound_FireLaser)); |
taylorza | 0:01829868570e | 501 | } |
taylorza | 0:01829868570e | 502 | } |
taylorza | 0:01829868570e | 503 | |
taylorza | 0:01829868570e | 504 | // Draw cross-hair |
taylorza | 0:01829868570e | 505 | canvas.drawLine(VIEW_WIDTH / 2, VIEW_HEIGHT / 2 - 10, VIEW_WIDTH / 2, VIEW_HEIGHT / 2 - 5, 1); |
taylorza | 0:01829868570e | 506 | canvas.drawLine(VIEW_WIDTH / 2, VIEW_HEIGHT / 2 + 10, VIEW_WIDTH / 2, VIEW_HEIGHT / 2 + 5, 1); |
taylorza | 0:01829868570e | 507 | |
taylorza | 0:01829868570e | 508 | canvas.drawLine(VIEW_WIDTH / 2 - 10, VIEW_HEIGHT / 2, VIEW_WIDTH / 2 - 5, VIEW_HEIGHT / 2, 1); |
taylorza | 0:01829868570e | 509 | canvas.drawLine(VIEW_WIDTH / 2 + 10, VIEW_HEIGHT / 2, VIEW_WIDTH / 2 + 5, VIEW_HEIGHT / 2, 1); |
taylorza | 0:01829868570e | 510 | } |