void Engine::nextMove(int turn, Pattern patt, Graphics* graph) { // Big and ugly switch function, but much less work than using functors, for the same effect // TODO: change the values that now are magic numbers so that the destruction of the ships in a stage triggers the beginning of another one switch (patt) { case MAIN_STAGE: // FIRST ENEMY if (turn == 0) { Mix_PlayChannel(-1, graph->getPortIn(), 0); } if (turn < 20 ) { // This is an excellent porting graph->printOtherOnScreen(SHIP_PORTING, 60, 60, turn*18, static_cast<double>(turn)/20); } else if (turn == 20) { spawnEnemy(40, 40, EN_FIGHTER, 1); } else if (turn > 20 && turn < 360) { if (enemyFleet[0]) { moveEnemyOnMap(0, 2, enemyFleet[0]); } } else if (turn == 360 && enemyOnScreen) { // Here I need not use enemy1 and so on because I'm cleaning everything if (enemyFleet[0]->isAlive()) { expiredEnemy0 = true; } cleanEnemyFleet(); Mix_PlayChannel(-1, graph->getPortOut(), 0); } else if (turn > 360 && turn < 380) { if (expiredEnemy0) { // Maybe turning the lasers a little in the direction of movement helps graph->printOtherOnScreen(SHIP_PORTING, 740, 60, turn*18, static_cast<double>(380 - turn)/20); } } else if (turn == 380) { cleanEnemyFleet(); expiredEnemy0 = false; } if (turn >= 31 && turn % 15 == 1 && turn < 360) { if (enemyFleet[0]->isAlive()) { for (int i = -4; i <= 4; i++) { Laser* tmp = enemyFleet[0]->shootLaser(i*pi/24 + (pi*1.5), LASER_ENEMY); tmp->setSpeed(6); lasersOnMap.push_back(tmp); } Mix_PlayChannel(-1, graph->getZap(), 0); } } // SECOND ENEMY if (turn == 400) { Mix_PlayChannel(-1, graph->getPortIn(), 0); } if (turn > 400 && turn < 420 ) { graph->printOtherOnScreen(SHIP_PORTING, 740, 60, (turn-400)*18, static_cast<double>(turn - 400)/20); } else if (turn == 420) { spawnEnemy(720, 40, EN_FIGHTER, 1); } else if (turn > 420 && turn < 760) { if (enemyFleet[0]) { moveEnemyOnMap(pi, 2, enemyFleet[0]); } } else if (turn == 760 && enemyOnScreen) { if (enemyFleet[0]->isAlive()) { expiredEnemy0 = true; } cleanEnemyFleet(); Mix_PlayChannel(-1, graph->getPortOut(), 0); } else if (turn > 760 && turn < 780) { if (expiredEnemy0) { graph->printOtherOnScreen(SHIP_PORTING, 60, 60, turn*18, static_cast<double>(780 - turn)/20); } } else if (turn == 780) { cleanEnemyFleet(); expiredEnemy0 = false; } if (turn >= 431 && turn % 15 == 1 && turn < 760) { if (enemyFleet[0]->isAlive()) { for (int i = -4; i <= 4; i++) { Laser* tmp = enemyFleet[0]->shootLaser(i*pi/24 + (pi*1.5), LASER_ENEMY); tmp->setSpeed(6); lasersOnMap.push_back(tmp); } Mix_PlayChannel(-1, graph->getZap(), 0); } } // THIRD AND FOURTH ENEMIES // They move in sinusoids if (turn == 800) { Mix_PlayChannel(-1, graph->getPortIn(), 0); } if (turn > 800 && turn < 820 ) { graph->printOtherOnScreen(SHIP_PORTING, 60, 100, (turn-800)*18, static_cast<double>(turn - 800)/20); graph->printOtherOnScreen(SHIP_PORTING, 760, 100, (turn-800)*18, static_cast<double>(turn - 800)/20); } else if (turn == 820) { // enemy1 is the one on the right spawnEnemy(40, 80, EN_FIGHTER, 0.4); spawnEnemy(740, 80, EN_FIGHTER, 0.4); } else if (turn > 820 && turn < 1160) { if (enemyFleet[0]) { moveEnemyOnMap(0, 2, enemyFleet[0]); moveEnemyOnMap(pi/2, 5*sin((turn-800)/(2*pi)), enemyFleet[0]); } if (enemyFleet[1]) { moveEnemyOnMap(pi, 2, enemyFleet[1]); moveEnemyOnMap(pi/2, 5*sin((turn-800)/(2*pi)), enemyFleet[1]); } } else if (turn == 1160 && enemyOnScreen) { if (enemyFleet[0]->isAlive()) { expiredEnemy0 = true; } if (enemyFleet[1]->isAlive()) { expiredEnemy1 = true; } cleanEnemyFleet(); Mix_PlayChannel(-1, graph->getPortOut(), 0); } else if (turn > 1160 && turn < 1180) { if (expiredEnemy0 == true) { graph->printOtherOnScreen(SHIP_PORTING, 738, 148, turn*18, static_cast<double>(1180 - turn)/20); } if (expiredEnemy1 == true) { graph->printOtherOnScreen(SHIP_PORTING, 82, 148, turn*18, static_cast<double>(1180 - turn)/20); } } else if (turn == 1180) { cleanEnemyFleet(); expiredEnemy0 = false; expiredEnemy1 = false; } if (turn >= 831 && turn % 10 == 1 && turn < 1160) { bool laserPlayed = false; if (enemyFleet[0]->isAlive()) { // Not exactly right, now i'll think for (int i = -1; i<= 1; i++) { Laser* tmp = enemyFleet[0]->shootLaser(i*pi/6 + 1.5*pi - (pi*(turn-1000)/350), LASER_ENEMY); tmp->setSpeed(6); lasersOnMap.push_back(tmp); if (!laserPlayed) { Mix_PlayChannel(-1, graph->getZap(), 0); laserPlayed = true; } } } if (enemyFleet[1]->isAlive()) { for (int i = -1; i <= 1; i++) { Laser* tmp = enemyFleet[1]->shootLaser(i*pi/6 + 1.5*pi + (pi*(turn-1000)/350), LASER_ENEMY); tmp->setSpeed(6); lasersOnMap.push_back(tmp); if (!laserPlayed) { Mix_PlayChannel(-1, graph->getZap(), 0); laserPlayed = true; } } } } // FIFTH AND SIXTH ENEMIES // They move in circles if (turn == 1200) { Mix_PlayChannel(-1, graph->getPortIn(), 0); } if (turn > 1200 && turn < 1220 ) { graph->printOtherOnScreen(SHIP_PORTING, 160, 60, (turn-1200)*18, static_cast<double>(turn - 1200)/20); graph->printOtherOnScreen(SHIP_PORTING, 640, 60, (turn-1200)*18, static_cast<double>(turn - 1200)/20); } else if (turn == 1220) { // enemy1 is the one on the right spawnEnemy(180, 40, EN_FIGHTER, 0.8); spawnEnemy(580, 40, EN_FIGHTER, 0.8); } else if (turn > 1220 && turn < 1940) { if (enemyFleet[0]) { moveEnemyOnMap(pi + (turn-1200)*pi/180, 2, enemyFleet[0]); } if (enemyFleet[1]) { moveEnemyOnMap(-(turn-1200)*pi/180, 2, enemyFleet[1]); } } else if (turn == 1940 && enemyOnScreen) { if (enemyFleet[0]->isAlive()) { expiredEnemy0 = true; } if (enemyFleet[1]->isAlive()) { expiredEnemy1 = true; } cleanEnemyFleet(); Mix_PlayChannel(-1, graph->getPortOut(), 0); } else if (turn > 1940 && turn < 1960) { if (expiredEnemy0) { graph->printOtherOnScreen(SHIP_PORTING, 202, 59, turn*18, static_cast<double>(1960 - turn)/20); } if (expiredEnemy1) { graph->printOtherOnScreen(SHIP_PORTING, 598, 59, turn*18, static_cast<double>(1960 - turn)/20); } } else if (turn == 1940) { cleanEnemyFleet(); expiredEnemy0 = false; expiredEnemy1 = false; } if (turn >= 1231 && turn % 12 == 1 && turn < 1940) { double angleToProtagonist0 = atan2( enemyFleet[0]->getY() - protagonist->getY(), -(enemyFleet[0]->getX() - protagonist->getX())); double angleToProtagonist1 = atan2( enemyFleet[1]->getY() - protagonist->getY(), -(enemyFleet[1]->getX() - protagonist->getX())); // To use as the angle of the central laser in the burst. Redirecting the lasers will require a bunch of new atan2s bool laserPlayed = false; if (enemyFleet[0]->isAlive()) { for (int i = -2; i<=2; i++) { Laser* tmp = enemyFleet[0]->shootLaser(angleToProtagonist0 + i*pi/50, LASER_ENEMY); tmp->setSpeed(6); lasersOnMap.push_back(tmp); if (!laserPlayed) { Mix_PlayChannel(-1, graph->getZap(), 0); laserPlayed = true; } } } if (enemyFleet[1]->isAlive()) { for (int i = -2; i<=2; i++) { Laser* tmp = enemyFleet[1]->shootLaser(angleToProtagonist1 + i*pi/50, LASER_ENEMY); tmp->setSpeed(6); lasersOnMap.push_back(tmp); if (!laserPlayed) { Mix_PlayChannel(-1, graph->getZap(), 0); laserPlayed = true; } } } } // SEVENTH AND FINAL ENEMY if (turn == 1980) { Mix_PlayChannel(-1, graph->getPortIn(), 0); } if (turn > 1980 && turn < 2000 ) { graph->printOtherOnScreen(SHIP_PORTING, 400, 80, (turn-1980)*18, static_cast<double>(turn - 1980)/20); } else if (turn == 2000) { // enemy1 is the one on the right spawnEnemy(380, 60, EN_FIGHTER, 2); } if (((turn%90 == 10 && turn >= 2000) || turn == 2000) && enemyFleet[0]->isAlive()) { bool laserPlayed = false; for (int i = 0; i < 18; i++) { Laser* tmp = enemyFleet[0]->shootLaser(i*pi/9, LASER_ENEMY); tmp->setSpeed(4); lasersOnMap.push_back(tmp); if (!laserPlayed) { Mix_PlayChannel(-1, graph->getZap(), 0); laserPlayed = true; } } } if (turn >= 2000 && turn%90 >= 20) { int directionSwitch = ((turn-2000)/90)%3; moveEnemyOnMap(5*pi/3 - directionSwitch*2*pi/3, 4, enemyFleet[0]); } if (turn >= 2000) { for (int i = 0; i<lasersOnMap.size(); i++) { if (!lasersOnMap[i]->isSBA() && lasersOnMap[i]->getTurnsInLife() > 16 && lasersOnMap[i]->getTurnsInLife() <= 20) { lasersOnMap[i]->setSpeed(lasersOnMap[i]->getSpeed() - 1); } else if (!lasersOnMap[i]->isSBA() && lasersOnMap[i]->getTurnsInLife() == 40) { double angDest = atan2( lasersOnMap[i]->getCentergY() - protagonist->getCenterY(), -(lasersOnMap[i]->getCentergX() - protagonist->getCenterX())); lasersOnMap[i]->setAngle(angDest); } else if (!lasersOnMap[i]->isSBA() && lasersOnMap[i]->getTurnsInLife() == 50) { lasersOnMap[i]->setSpeed(25); } } } break; // Formerly FLOWER case BOSS_STAGE: if (turn == 0) { cleanEnemyFleet(); cleanLasers(); floweringBoss = true; bossPosition = 0; Mix_PlayChannel(-1, graph->getPortIn(), 0); } if (turn < 20 ) { // This is an excellent porting graph->printOtherOnScreen(SHIP_PORTING, 400, 60, turn*18, static_cast<double>(turn)/20); } else if (turn == 20) { if (enemyFleet.size() == 0) { spawnEnemy(380, 40, EN_CORVETTE, 1); } patternTurnsHelper = 0; // The pattern is nicer this way } else if (turn <= 30) { // TODO: Adjust values moveEnemyOnMap((pi*1.5), 10, enemyFleet[0]); } if (turn >= 31 && turn % 500 <= 400) { if (enemyFleet[0]->isAlive() && enemyFleet.size() > 0 && turn%7 == 1) { // When it's the Flowering Night, then time will stop on the Lunar Clock. Only she who possesses the Pocket Watch of Blood will be able to go against the flow in stillness and against the stillness in the flow. She is Sakuya Izayoi, the maid in the Scarlet Devil Mansion. // On unrelated news, the patterny pattern when it's not flowering is given later by manipulating the lazerbeams if (floweringBoss) { for (int i = 0; i<=20; i++) { Laser* tmp = enemyFleet[0]->shootLaser(i*pi/10 + patternTurnsHelper*pi/32, LASER_ENEMY); tmp->setSpeed(8); lasersOnMap.push_back(tmp); } } // The pattern part when you're not flowering is given by shooting harmonically else { for (int i = 0; i<=20; i++) { Laser* tmp = enemyFleet[0]->shootLaser(i*pi/10 + (pi/8)*sin((pi/100)*(turn%500)), LASER_ENEMY); tmp->setSpeed(8); lasersOnMap.push_back(tmp); } } Mix_PlayChannel(-1, graph->getZap(), 0); } } /* Possible pattern? * entry * | * (. . . .V. . . .) * (. 4 . .0. . 2 .) * (. 6 . .8. . 5 .) * (. 1 . .3. . 7 .) * (. . . . . . . .) * (. . . . . . . .) */ if (turn >= 31 && turn % 500 >= 400) { switch (bossPosition) { case 0: if (turn%500 < 429) { moveEnemyOnMap(atan2(-200, -220), 10, enemyFleet[0]); } if (turn%500 == 430) { enemyFleet[0]->teleport(160, 340); } break; case 1: if (turn%500 < 448) { moveEnemyOnMap(atan2(200, 440), 10, enemyFleet[0]); } if (turn%500 == 449) { enemyFleet[0]->teleport(600, 140); } break; case 2: if (turn%500 < 429) { moveEnemyOnMap(atan2(-200, -220), 10, enemyFleet[0]); } if (turn%500 == 430) { enemyFleet[0]->teleport(380, 340); } break; case 3: if (turn%500 < 429) { moveEnemyOnMap(atan2(200, -220), 10, enemyFleet[0]); } if (turn%500 == 430) { enemyFleet[0]->teleport(160, 140); } break; case 4: if (turn%500 < 445) { moveEnemyOnMap(atan2(-100, 440), 10, enemyFleet[0]); } if (turn%500 == 446) { enemyFleet[0]->teleport(600, 240); } break; case 5: if (turn%500 < 444) { moveEnemyOnMap(atan2(0, -220), 10, enemyFleet[0]); } if (turn%500 == 445) { enemyFleet[0]->teleport(160, 240); } break; case 6: if (turn%500 < 445) { moveEnemyOnMap(atan2(-100, 440), 10, enemyFleet[0]); } if (turn%500 == 446) { enemyFleet[0]->teleport(600, 340); } break; case 7: if (turn%500 < 424) { moveEnemyOnMap(atan2(100, -220), 10, enemyFleet[0]); } if (turn%500 == 425) { enemyFleet[0]->teleport(380, 240); } break; case 8: if (turn%500 < 410) { moveEnemyOnMap(atan2(100, 0), 10, enemyFleet[0]); } if (turn%500 == 411) { enemyFleet[0]->teleport(380, 140); } break; default: break; } } // This must be synced to the rate of fire if (turn%7 == 1) { if (floweringBoss) { for (int i = 0; i<lasersOnMap.size(); i++) { if (lasersOnMap[i]->getTurnsInLife() == 10 && !lasersOnMap[i]->isSBA()) { lasersOnMap[i]->setAngle(lasersOnMap[i]->getAngle()+(pi/2)); } if (lasersOnMap[i]->getTurnsInLife() > 10 && lasersOnMap[i]->getTurnsInLife() <= 90 && !lasersOnMap[i]->isSBA()) { lasersOnMap[i]->setAngle(lasersOnMap[i]->getAngle()+(pi/3)); } if (lasersOnMap[i]->getTurnsInLife() == 100 && !lasersOnMap[i]->isSBA()) { lasersOnMap[i]->setAngle(lasersOnMap[i]->getAngle()-(pi/2)); } } } patternTurnsHelper++; } if (turn%500 == 0 && turn != 0) { floweringBoss = !floweringBoss; bossPosition = (bossPosition+1)%9; } break; default: break; } }
void Engine::protagonistShootsSingleLaser() { Laser* tmp = protagonist->shootLaser(pi/2, LASER_ALLIED); tmp->setSpeed(20); lasersOnMap.push_back(tmp); }