Guest User

Untitled

a guest
Jan 24th, 2020
101
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <bitswap.h>
  2. #include <chipsets.h>
  3. #include <color.h>
  4. #include <colorpalettes.h>
  5. #include <colorutils.h>
  6. #include <controller.h>
  7. #include <cpp_compat.h>
  8. #include <dmx.h>
  9. #include <FastLED.h>
  10. #include <fastled_config.h>
  11. #include <fastled_delay.h>
  12. #include <fastled_progmem.h>
  13. #include <fastpin.h>
  14. #include <fastspi.h>
  15. #include <fastspi_bitbang.h>
  16. #include <fastspi_dma.h>
  17. #include <fastspi_nop.h>
  18. #include <fastspi_ref.h>
  19. #include <fastspi_types.h>
  20. #include <hsv2rgb.h>
  21. #include <led_sysdefs.h>
  22. #include <lib8tion.h>
  23. #include <noise.h>
  24. #include <pixelset.h>
  25. #include <pixeltypes.h>
  26. #include <platforms.h>
  27. #include <power_mgt.h>
  28.  
  29. // Required libs
  30. #include "FastLED.h"
  31. #include "I2Cdev.h"
  32. #include "MPU6050.h"
  33. #include "Wire.h"
  34. #include "toneAC.h"
  35. #include "iSin.h"
  36. #include "RunningMedian.h"
  37.  
  38. // Included libs
  39. #include "Enemy.h"
  40. #include "Particle.h"
  41. #include "Spawner.h"
  42. #include "Lava.h"
  43. #include "Boss.h"
  44. #include "Conveyor.h"
  45.  
  46. // MPU
  47. MPU6050 accelgyro;
  48. int16_t ax, ay, az;
  49. int16_t gx, gy, gz;
  50.  
  51. // LED setup
  52. #define NUM_LEDS             300
  53. #define DATA_PIN             3
  54. #define CLOCK_PIN            4
  55. #define LED_COLOR_ORDER      BGR//GBR
  56. #define BRIGHTNESS           150
  57. #define DIRECTION            1     // 0 = right to left, 1 = left to right
  58. #define MIN_REDRAW_INTERVAL  16    // Min redraw interval (ms) 33 = 30fps / 16 = 63fps
  59. #define USE_GRAVITY          1     // 0/1 use gravity (LED strip going up wall)
  60. #define BEND_POINT           550   // 0/1000 point at which the LED strip goes up the wall
  61.  
  62. // GAME
  63. long previousMillis = 0;           // Time of the last redraw
  64. int levelNumber = 0;
  65. long lastInputTime = 0;
  66. #define TIMEOUT              30000
  67. #define LEVEL_COUNT          9
  68. #define MAX_VOLUME           10
  69. iSin isin = iSin();
  70.  
  71. // JOYSTICK
  72. #define JOYSTICK_ORIENTATION 1     // 0, 1 or 2 to set the angle of the joystick
  73. #define JOYSTICK_DIRECTION   1     // 0/1 to flip joystick direction
  74. #define ATTACK_THRESHOLD     30000 // The threshold that triggers an attack
  75. #define JOYSTICK_DEADZONE    5     // Angle to ignore
  76. int joystickTilt = 0;              // Stores the angle of the joystick
  77. int joystickWobble = 0;            // Stores the max amount of acceleration (wobble)
  78.  
  79. // WOBBLE ATTACK
  80. #define ATTACK_WIDTH        70     // Width of the wobble attack, world is 1000 wide
  81. #define ATTACK_DURATION     500    // Duration of a wobble attack (ms)
  82. long attackMillis = 0;             // Time the attack started
  83. bool attacking = 0;                // Is the attack in progress?
  84. #define BOSS_WIDTH          40
  85.  
  86. // PLAYER
  87. #define MAX_PLAYER_SPEED    10     // Max move speed of the player
  88. char* stage;                       // what stage the game is at (PLAY/DEAD/WIN/GAMEOVER)
  89. long stageStartTime;               // Stores the time the stage changed for stages that are time based
  90. int playerPosition;                // Stores the player position
  91. int playerPositionModifier;        // +/- adjustment to player position
  92. bool playerAlive;
  93. long killTime;
  94. int lives = 3;
  95.  
  96. // POOLS
  97. int lifeLEDs[3] = {52, 50, 40};
  98. Enemy enemyPool[10] = {
  99.   Enemy(), Enemy(), Enemy(), Enemy(), Enemy(), Enemy(), Enemy(), Enemy(), Enemy(), Enemy()
  100. };
  101. int const enemyCount = 10;
  102. Particle particlePool[40] = {
  103.   Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle(), Particle()
  104. };
  105. int const particleCount = 40;
  106. Spawner spawnPool[2] = {
  107.   Spawner(), Spawner()
  108. };
  109. int const spawnCount = 2;
  110. Lava lavaPool[4] = {
  111.   Lava(), Lava(), Lava(), Lava()
  112. };
  113. int const lavaCount = 4;
  114. Conveyor conveyorPool[2] = {
  115.   Conveyor(), Conveyor()
  116. };
  117. int const conveyorCount = 2;
  118. Boss boss = Boss();
  119.  
  120. CRGB leds[NUM_LEDS];
  121. RunningMedian MPUAngleSamples = RunningMedian(5);
  122. RunningMedian MPUWobbleSamples = RunningMedian(5);
  123.  
  124. void setup() {
  125.   Serial.begin(9600);
  126.   while (!Serial);
  127.  
  128.   // MPU
  129.   Wire.begin();
  130.   accelgyro.initialize();
  131.  
  132.   // Fast LED
  133.   FastLED.addLeds<WS2812B, DATA_PIN, CLOCK_PIN, LED_COLOR_ORDER>(leds, 300);
  134.   FastLED.setBrightness(BRIGHTNESS);
  135.   FastLED.setDither(1);
  136.  
  137.   // Life LEDs
  138.   for (int i = 0; i < 3; i++) {
  139.     pinMode(lifeLEDs[i], OUTPUT);
  140.     digitalWrite(lifeLEDs[i], HIGH);
  141.   }
  142.  
  143.   loadLevel();
  144. }
  145.  
  146. void loop() {
  147.   long mm = millis();
  148.   int brightness = 0;
  149.  
  150.   if (stage == "PLAY") {
  151.     if (attacking) {
  152.       SFXattacking();
  153.     } else {
  154.       SFXtilt(joystickTilt);
  155.     }
  156.   } else if (stage == "DEAD") {
  157.     SFXdead();
  158.   }
  159.  
  160.   if (mm - previousMillis >= MIN_REDRAW_INTERVAL) {
  161.     getInput();
  162.     long frameTimer = mm;
  163.     previousMillis = mm;
  164.  
  165.     if (abs(joystickTilt) > JOYSTICK_DEADZONE) {
  166.       lastInputTime = mm;
  167.       if (stage == "SCREENSAVER") {
  168.         levelNumber = -1;
  169.         stageStartTime = mm;
  170.         stage = "WIN";
  171.       }
  172.     } else {
  173.       if (lastInputTime + TIMEOUT < mm) {
  174.         stage = "SCREENSAVER";
  175.       }
  176.     }
  177.     if (stage == "SCREENSAVER") {
  178.       screenSaverTick();
  179.     } else if (stage == "PLAY") {
  180.       // PLAYING
  181.       if (attacking && attackMillis + ATTACK_DURATION < mm) attacking = 0;
  182.  
  183.       // If not attacking, check if they should be
  184.       if (!attacking && joystickWobble > ATTACK_THRESHOLD) {
  185.         attackMillis = mm;
  186.         attacking = 1;
  187.       }
  188.  
  189.       // If still not attacking, move!
  190.       playerPosition += playerPositionModifier;
  191.       if (!attacking) {
  192.         int moveAmount = (joystickTilt / 6.0);
  193.         if (DIRECTION) moveAmount = -moveAmount;
  194.         moveAmount = constrain(moveAmount, -MAX_PLAYER_SPEED, MAX_PLAYER_SPEED);
  195.         playerPosition -= moveAmount;
  196.         if (playerPosition < 0) playerPosition = 0;
  197.         if (playerPosition >= 1000 && !boss.Alive()) {
  198.           // Reached exit!
  199.           levelComplete();
  200.           return;
  201.         }
  202.       }
  203.  
  204.       if (inLava(playerPosition)) {
  205.         die();
  206.       }
  207.  
  208.       // Ticks and draw calls
  209.       FastLED.clear();
  210.       tickConveyors();
  211.       tickSpawners();
  212.       tickBoss();
  213.       tickLava();
  214.       tickEnemies();
  215.       drawPlayer();
  216.       drawAttack();
  217.       drawExit();
  218.     } else if (stage == "DEAD") {
  219.       // DEAD
  220.       FastLED.clear();
  221.       if (!tickParticles()) {
  222.         loadLevel();
  223.       }
  224.     } else if (stage == "WIN") {
  225.       // LEVEL COMPLETE
  226.       FastLED.clear();
  227.       if (stageStartTime + 500 > mm) {
  228.         int n = max(map(((mm - stageStartTime)), 0, 500, NUM_LEDS, 0), 0);
  229.         for (int i = NUM_LEDS; i >= n; i--) {
  230.           brightness = 255;
  231.           leds[i] = CRGB(0, brightness, 0);
  232.         }
  233.         SFXwin();
  234.       } else if (stageStartTime + 1000 > mm) {
  235.         int n = max(map(((mm - stageStartTime)), 500, 1000, NUM_LEDS, 0), 0);
  236.         for (int i = 0; i < n; i++) {
  237.           brightness = 255;
  238.           leds[i] = CRGB(0, brightness, 0);
  239.         }
  240.         SFXwin();
  241.       } else if (stageStartTime + 1200 > mm) {
  242.         leds[0] = CRGB(0, 255, 0);
  243.       } else {
  244.         nextLevel();
  245.       }
  246.     } else if (stage == "COMPLETE") {
  247.       FastLED.clear();
  248.       SFXcomplete();
  249.       if (stageStartTime + 500 > mm) {
  250.         int n = max(map(((mm - stageStartTime)), 0, 500, NUM_LEDS, 0), 0);
  251.         for (int i = NUM_LEDS; i >= n; i--) {
  252.           brightness = (sin(((i * 10) + mm) / 500.0) + 1) * 255;
  253.           leds[i].setHSV(brightness, 255, 50);
  254.         }
  255.       } else if (stageStartTime + 5000 > mm) {
  256.         for (int i = NUM_LEDS; i >= 0; i--) {
  257.           brightness = (sin(((i * 10) + mm) / 500.0) + 1) * 255;
  258.           leds[i].setHSV(brightness, 255, 50);
  259.         }
  260.       } else if (stageStartTime + 5500 > mm) {
  261.         int n = max(map(((mm - stageStartTime)), 5000, 5500, NUM_LEDS, 0), 0);
  262.         for (int i = 0; i < n; i++) {
  263.           brightness = (sin(((i * 10) + mm) / 500.0) + 1) * 255;
  264.           leds[i].setHSV(brightness, 255, 50);
  265.         }
  266.       } else {
  267.         nextLevel();
  268.       }
  269.     } else if (stage == "GAMEOVER") {
  270.       // GAME OVER!
  271.       FastLED.clear();
  272.       stageStartTime = 0;
  273.     }
  274.  
  275.     Serial.print(millis() - mm);
  276.     Serial.print(" - ");
  277.     FastLED.show();
  278.     Serial.println(millis() - mm);
  279.   }
  280. }
  281.  
  282.  
  283. // ---------------------------------
  284. // ------------ LEVELS -------------
  285. // ---------------------------------
  286. void loadLevel() {
  287.   updateLives();
  288.   cleanupLevel();
  289.   playerPosition = 0;
  290.   playerAlive = 1;
  291.   switch (levelNumber) {
  292.     case 0:
  293.       // Left or right?
  294.       playerPosition = 200;
  295.       spawnEnemy(1, 0, 0, 0);
  296.       break;
  297.     case 1:
  298.       // Slow moving enemy
  299.       spawnEnemy(900, 0, 1, 0);
  300.       break;
  301.     case 2:
  302.       // Spawning enemies at exit every 2 seconds
  303.       spawnPool[0].Spawn(1000, 3000, 2, 0, 0);
  304.       break;
  305.     case 3:
  306.       // Lava intro
  307.       spawnLava(400, 490, 2000, 2000, 0, "OFF");
  308.       spawnPool[0].Spawn(1000, 5500, 3, 0, 0);
  309.       break;
  310.     case 4:
  311.       // Sin enemy
  312.       spawnEnemy(700, 1, 7, 275);
  313.       spawnEnemy(500, 1, 5, 250);
  314.       break;
  315.     case 5:
  316.       // Conveyor
  317.       spawnConveyor(100, 600, -1);
  318.       spawnEnemy(800, 0, 0, 0);
  319.       break;
  320.     case 6:
  321.       // Conveyor of enemies
  322.       spawnConveyor(50, 1000, 1);
  323.       spawnEnemy(300, 0, 0, 0);
  324.       spawnEnemy(400, 0, 0, 0);
  325.       spawnEnemy(500, 0, 0, 0);
  326.       spawnEnemy(600, 0, 0, 0);
  327.       spawnEnemy(700, 0, 0, 0);
  328.       spawnEnemy(800, 0, 0, 0);
  329.       spawnEnemy(900, 0, 0, 0);
  330.       break;
  331.     case 7:
  332.       // Lava run
  333.       spawnLava(195, 300, 2000, 2000, 0, "OFF");
  334.       spawnLava(350, 455, 2000, 2000, 0, "OFF");
  335.       spawnLava(510, 610, 2000, 2000, 0, "OFF");
  336.       spawnLava(660, 760, 2000, 2000, 0, "OFF");
  337.       spawnPool[0].Spawn(1000, 3800, 4, 0, 0);
  338.       break;
  339.     case 8:
  340.       // Sin enemy #2
  341.       spawnEnemy(700, 1, 7, 275);
  342.       spawnEnemy(500, 1, 5, 250);
  343.       spawnPool[0].Spawn(1000, 5500, 4, 0, 3000);
  344.       spawnPool[1].Spawn(0, 5500, 5, 1, 10000);
  345.       spawnConveyor(100, 900, -1);
  346.       break;
  347.     case 9:
  348.       // Boss
  349.       spawnBoss();
  350.       break;
  351.   }
  352.   stageStartTime = millis();
  353.   stage = "PLAY";
  354. }
  355.  
  356. void spawnBoss() {
  357.   boss.Spawn();
  358.   moveBoss();
  359. }
  360.  
  361. void moveBoss() {
  362.   int spawnSpeed = 2500;
  363.   if (boss._lives == 2) spawnSpeed = 2000;
  364.   if (boss._lives == 1) spawnSpeed = 1500;
  365.   spawnPool[0].Spawn(boss._pos, spawnSpeed, 3, 0, 0);
  366.   spawnPool[1].Spawn(boss._pos, spawnSpeed, 3, 1, 0);
  367. }
  368.  
  369. void spawnEnemy(int pos, int dir, int sp, int wobble) {
  370.   for (int e = 0; e < enemyCount; e++) {
  371.     if (!enemyPool[e].Alive()) {
  372.       enemyPool[e].Spawn(pos, dir, sp, wobble);
  373.       enemyPool[e].playerSide = pos > playerPosition ? 1 : -1;
  374.       return;
  375.     }
  376.   }
  377. }
  378.  
  379. void spawnLava(int left, int right, int ontime, int offtime, int offset, char* state) {
  380.   for (int i = 0; i < lavaCount; i++) {
  381.     if (!lavaPool[i].Alive()) {
  382.       lavaPool[i].Spawn(left, right, ontime, offtime, offset, state);
  383.       return;
  384.     }
  385.   }
  386. }
  387.  
  388. void spawnConveyor(int startPoint, int endPoint, int dir) {
  389.   for (int i = 0; i < conveyorCount; i++) {
  390.     if (!conveyorPool[i]._alive) {
  391.       conveyorPool[i].Spawn(startPoint, endPoint, dir);
  392.       return;
  393.     }
  394.   }
  395. }
  396.  
  397. void cleanupLevel() {
  398.   for (int i = 0; i < enemyCount; i++) {
  399.     enemyPool[i].Kill();
  400.   }
  401.   for (int i = 0; i < particleCount; i++) {
  402.     particlePool[i].Kill();
  403.   }
  404.   for (int i = 0; i < spawnCount; i++) {
  405.     spawnPool[i].Kill();
  406.   }
  407.   for (int i = 0; i < lavaCount; i++) {
  408.     lavaPool[i].Kill();
  409.   }
  410.   for (int i = 0; i < conveyorCount; i++) {
  411.     conveyorPool[i].Kill();
  412.   }
  413.   boss.Kill();
  414. }
  415.  
  416. void levelComplete() {
  417.   stageStartTime = millis();
  418.   stage = "WIN";
  419.   if (levelNumber == LEVEL_COUNT) stage = "COMPLETE";
  420.   lives = 3;
  421.   updateLives();
  422. }
  423.  
  424. void nextLevel() {
  425.   levelNumber ++;
  426.   if (levelNumber > LEVEL_COUNT) levelNumber = 0;
  427.   loadLevel();
  428. }
  429.  
  430. void gameOver() {
  431.   levelNumber = 0;
  432.   loadLevel();
  433. }
  434.  
  435. void die() {
  436.   playerAlive = 0;
  437.   if (levelNumber > 0) lives --;
  438.   updateLives();
  439.   if (lives == 0) {
  440.     levelNumber = 0;
  441.     lives = 3;
  442.   }
  443.   for (int p = 0; p < particleCount; p++) {
  444.     particlePool[p].Spawn(playerPosition);
  445.   }
  446.   stageStartTime = millis();
  447.   stage = "DEAD";
  448.   killTime = millis();
  449. }
  450.  
  451. // ----------------------------------
  452. // -------- TICKS & RENDERS ---------
  453. // ----------------------------------
  454. void tickEnemies() {
  455.   for (int i = 0; i < enemyCount; i++) {
  456.     if (enemyPool[i].Alive()) {
  457.       enemyPool[i].Tick();
  458.       // Hit attack?
  459.       if (attacking) {
  460.         if (enemyPool[i]._pos > playerPosition - (ATTACK_WIDTH / 2) && enemyPool[i]._pos < playerPosition + (ATTACK_WIDTH / 2)) {
  461.           enemyPool[i].Kill();
  462.           SFXkill();
  463.         }
  464.       }
  465.       if (inLava(enemyPool[i]._pos)) {
  466.         enemyPool[i].Kill();
  467.         SFXkill();
  468.       }
  469.       // Draw (if still alive)
  470.       if (enemyPool[i].Alive()) {
  471.         leds[getLED(enemyPool[i]._pos)] = CRGB(255, 0, 0);
  472.       }
  473.       // Hit player?
  474.       if (
  475.         (enemyPool[i].playerSide == 1 && enemyPool[i]._pos <= playerPosition) ||
  476.         (enemyPool[i].playerSide == -1 && enemyPool[i]._pos >= playerPosition)
  477.       ) {
  478.         die();
  479.         return;
  480.       }
  481.     }
  482.   }
  483. }
  484.  
  485. void tickBoss() {
  486.   // DRAW
  487.   if (boss.Alive()) {
  488.     boss._ticks ++;
  489.     for (int i = getLED(boss._pos - BOSS_WIDTH / 2); i <= getLED(boss._pos + BOSS_WIDTH / 2); i++) {
  490.       leds[i] = CRGB::DarkRed;
  491.       leds[i] %= 100;
  492.     }
  493.     // CHECK COLLISION
  494.     if (getLED(playerPosition) > getLED(boss._pos - BOSS_WIDTH / 2) && getLED(playerPosition) < getLED(boss._pos + BOSS_WIDTH)) {
  495.       die();
  496.       return;
  497.     }
  498.     // CHECK FOR ATTACK
  499.     if (attacking) {
  500.       if (
  501.         (getLED(playerPosition + (ATTACK_WIDTH / 2)) >= getLED(boss._pos - BOSS_WIDTH / 2) && getLED(playerPosition + (ATTACK_WIDTH / 2)) <= getLED(boss._pos + BOSS_WIDTH / 2)) ||
  502.         (getLED(playerPosition - (ATTACK_WIDTH / 2)) <= getLED(boss._pos + BOSS_WIDTH / 2) && getLED(playerPosition - (ATTACK_WIDTH / 2)) >= getLED(boss._pos - BOSS_WIDTH / 2))
  503.       ) {
  504.         boss.Hit();
  505.         if (boss.Alive()) {
  506.           moveBoss();
  507.         } else {
  508.           spawnPool[0].Kill();
  509.           spawnPool[1].Kill();
  510.         }
  511.       }
  512.     }
  513.   }
  514. }
  515.  
  516. void drawPlayer() {
  517.   leds[getLED(playerPosition)] = CRGB(0, 255, 0);
  518. }
  519.  
  520. void drawExit() {
  521.   if (!boss.Alive()) {
  522.     leds[NUM_LEDS - 1] = CRGB(0, 0, 255);
  523.   }
  524. }
  525.  
  526. void tickSpawners() {
  527.   long mm = millis();
  528.   for (int s = 0; s < spawnCount; s++) {
  529.     if (spawnPool[s].Alive() && spawnPool[s]._activate < mm) {
  530.       if (spawnPool[s]._lastSpawned + spawnPool[s]._rate < mm || spawnPool[s]._lastSpawned == 0) {
  531.         spawnEnemy(spawnPool[s]._pos, spawnPool[s]._dir, spawnPool[s]._sp, 0);
  532.         spawnPool[s]._lastSpawned = mm;
  533.       }
  534.     }
  535.   }
  536. }
  537.  
  538. void tickLava() {
  539.   int A, B, p, i, brightness, flicker;
  540.   long mm = millis();
  541.   Lava LP;
  542.   for (i = 0; i < lavaCount; i++) {
  543.     flicker = random8(5);
  544.     LP = lavaPool[i];
  545.     if (LP.Alive()) {
  546.       A = getLED(LP._left);
  547.       B = getLED(LP._right);
  548.       if (LP._state == "OFF") {
  549.         if (LP._lastOn + LP._offtime < mm) {
  550.           LP._state = "ON";
  551.           LP._lastOn = mm;
  552.         }
  553.         for (p = A; p <= B; p++) {
  554.           leds[p] = CRGB(3 + flicker, (3 + flicker) / 1.5, 0);
  555.         }
  556.       } else if (LP._state == "ON") {
  557.         if (LP._lastOn + LP._ontime < mm) {
  558.           LP._state = "OFF";
  559.           LP._lastOn = mm;
  560.         }
  561.         for (p = A; p <= B; p++) {
  562.           leds[p] = CRGB(150 + flicker, 100 + flicker, 0);
  563.         }
  564.       }
  565.     }
  566.     lavaPool[i] = LP;
  567.   }
  568. }
  569.  
  570. bool tickParticles() {
  571.   bool stillActive = false;
  572.   for (int p = 0; p < particleCount; p++) {
  573.     if (particlePool[p].Alive()) {
  574.       particlePool[p].Tick(USE_GRAVITY);
  575.       leds[getLED(particlePool[p]._pos)] += CRGB(particlePool[p]._power, 0, 0);
  576.       stillActive = true;
  577.     }
  578.   }
  579.   return stillActive;
  580. }
  581.  
  582. void tickConveyors() {
  583.   int b, dir, n, i, ss, ee, led;
  584.   long m = 10000 + millis();
  585.   playerPositionModifier = 0;
  586.  
  587.   for (i = 0; i < conveyorCount; i++) {
  588.     if (conveyorPool[i]._alive) {
  589.       dir = conveyorPool[i]._dir;
  590.       ss = getLED(conveyorPool[i]._startPoint);
  591.       ee = getLED(conveyorPool[i]._endPoint);
  592.       for (led = ss; led < ee; led++) {
  593.         b = 5;
  594.         n = (-led + (m / 100)) % 5;
  595.         if (dir == -1) n = (led + (m / 100)) % 5;
  596.         b = (5 - n) / 2.0;
  597.         if (b > 0) leds[led] = CRGB(0, 0, b);
  598.       }
  599.  
  600.       if (playerPosition > conveyorPool[i]._startPoint && playerPosition < conveyorPool[i]._endPoint) {
  601.         if (dir == -1) {
  602.           playerPositionModifier = -(MAX_PLAYER_SPEED - 4);
  603.         } else {
  604.           playerPositionModifier = (MAX_PLAYER_SPEED - 4);
  605.         }
  606.       }
  607.     }
  608.   }
  609. }
  610.  
  611. void drawAttack() {
  612.   if (!attacking) return;
  613.   int n = map(millis() - attackMillis, 0, ATTACK_DURATION, 100, 5);
  614.   for (int i = getLED(playerPosition - (ATTACK_WIDTH / 2)) + 1; i <= getLED(playerPosition + (ATTACK_WIDTH / 2)) - 1; i++) {
  615.     leds[i] = CRGB(0, 0, n);
  616.   }
  617.   if (n > 90) {
  618.     n = 255;
  619.     leds[getLED(playerPosition)] = CRGB(255, 255, 255);
  620.   } else {
  621.     n = 0;
  622.     leds[getLED(playerPosition)] = CRGB(0, 255, 0);
  623.   }
  624.   leds[getLED(playerPosition - (ATTACK_WIDTH / 2))] = CRGB(n, n, 255);
  625.   leds[getLED(playerPosition + (ATTACK_WIDTH / 2))] = CRGB(n, n, 255);
  626. }
  627.  
  628. int getLED(int pos) {
  629.   // The world is 1000 pixels wide, this converts world units into an LED number
  630.   return constrain((int)map(pos, 0, 1000, 0, NUM_LEDS - 1), 0, NUM_LEDS - 1);
  631. }
  632.  
  633. bool inLava(int pos) {
  634.   // Returns if the player is in active lava
  635.   int i;
  636.   Lava LP;
  637.   for (i = 0; i < lavaCount; i++) {
  638.     LP = lavaPool[i];
  639.     if (LP.Alive() && LP._state == "ON") {
  640.       if (LP._left < pos && LP._right > pos) return true;
  641.     }
  642.   }
  643.   return false;
  644. }
  645.  
  646. void updateLives() {
  647.   // Updates the life LEDs to show how many lives the player has left
  648.   for (int i = 0; i < 3; i++) {
  649.     digitalWrite(lifeLEDs[i], lives > i ? HIGH : LOW);
  650.   }
  651. }
  652.  
  653.  
  654. // ---------------------------------
  655. // --------- SCREENSAVER -----------
  656. // ---------------------------------
  657. void screenSaverTick() {
  658.   int n, b, c, i;
  659.   long mm = millis();
  660.   int mode = (mm / 20000) % 2;
  661.  
  662.   for (i = 0; i < NUM_LEDS; i++) {
  663.     leds[i].nscale8(250);
  664.   }
  665.   if (mode == 0) {
  666.     // Marching green <> orange
  667.     n = (mm / 250) % 10;
  668.     b = 10 + ((sin(mm / 500.00) + 1) * 20.00);
  669.     c = 20 + ((sin(mm / 5000.00) + 1) * 33);
  670.     for (i = 0; i < NUM_LEDS; i++) {
  671.       if (i % 10 == n) {
  672.         leds[i] = CHSV( c, 255, 150);
  673.       }
  674.     }
  675.   } else if (mode == 1) {
  676.     // Random flashes
  677.     randomSeed(mm);
  678.     for (i = 0; i < NUM_LEDS; i++) {
  679.       if (random8(200) == 0) {
  680.         leds[i] = CHSV( 25, 255, 100);
  681.       }
  682.     }
  683.   }
  684. }
  685.  
  686. // ---------------------------------
  687. // ----------- JOYSTICK ------------
  688. // ---------------------------------
  689. void getInput() {
  690.   // This is responsible for the player movement speed and attacking.
  691.   // You can replace it with anything you want that passes a -90>+90 value to joystickTilt
  692.   // and any value to joystickWobble that is greater than ATTACK_THRESHOLD (defined at start)
  693.   // For example you could use 3 momentery buttons:
  694.   // if(digitalRead(leftButtonPinNumber) == HIGH) joystickTilt = -90;
  695.   // if(digitalRead(rightButtonPinNumber) == HIGH) joystickTilt = 90;
  696.   // if(digitalRead(attackButtonPinNumber) == HIGH) joystickWobble = ATTACK_THRESHOLD;
  697.  
  698.   accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  699.   int a = (JOYSTICK_ORIENTATION == 0 ? ax : (JOYSTICK_ORIENTATION == 1 ? ay : az)) / 166;
  700.   int g = (JOYSTICK_ORIENTATION == 0 ? gx : (JOYSTICK_ORIENTATION == 1 ? gy : gz));
  701.   if (abs(a) < JOYSTICK_DEADZONE) a = 0;
  702.   if (a > 0) a -= JOYSTICK_DEADZONE;
  703.   if (a < 0) a += JOYSTICK_DEADZONE;
  704.   MPUAngleSamples.add(a);
  705.   MPUWobbleSamples.add(g);
  706.  
  707.   joystickTilt = MPUAngleSamples.getMedian();
  708.   if (JOYSTICK_DIRECTION == 1) {
  709.     joystickTilt = 0 - joystickTilt;
  710.   }
  711.   joystickWobble = abs(MPUWobbleSamples.getHighest());
  712. }
  713.  
  714.  
  715. // ---------------------------------
  716. // -------------- SFX --------------
  717. // ---------------------------------
  718. void SFXtilt(int amount) {
  719.   int f = map(abs(amount), 0, 90, 80, 900) + random8(100);
  720.   if (playerPositionModifier < 0) f -= 500;
  721.   if (playerPositionModifier > 0) f += 200;
  722.   toneAC(f, min(min(abs(amount) / 9, 5), MAX_VOLUME));
  723.  
  724. }
  725. void SFXattacking() {
  726.   int freq = map(sin(millis() / 2.0) * 1000.0, -1000, 1000, 500, 600);
  727.   if (random8(5) == 0) {
  728.     freq *= 3;
  729.   }
  730.   toneAC(freq, MAX_VOLUME);
  731. }
  732. void SFXdead() {
  733.   int freq = max(1000 - (millis() - killTime), 10);
  734.   freq += random8(200);
  735.   int vol = max(10 - (millis() - killTime) / 200, 0);
  736.   toneAC(freq, MAX_VOLUME);
  737. }
  738. void SFXkill() {
  739.   toneAC(2000, MAX_VOLUME, 1000, true);
  740. }
  741. void SFXwin() {
  742.   int freq = (millis() - stageStartTime) / 3.0;
  743.   freq += map(sin(millis() / 20.0) * 1000.0, -1000, 1000, 0, 20);
  744.   int vol = 10;//max(10 - (millis()-stageStartTime)/200, 0);
  745.   toneAC(freq, MAX_VOLUME);
  746. }
  747.  
  748. void SFXcomplete() {
  749.   noToneAC();
  750. }
RAW Paste Data