This repository has been archived on 2022-09-26. You can view files and clone it, but cannot push or open issues or pull requests.
2022-09-25 12:23:49 -04:00

943 lines
23 KiB
C

// stage
s16 stageClock,
nextClock;
// groups
static void waveSine(bool right){
struct enemySpawner spawner = {
.angle = 256,
.speed = FIX16(1),
.x = GAME_W / 5 * (right ? 3 : 2),
.y = -16,
.image = right ? &fairyRed : &fairyBlue,
.offX = 16,
.offY = 16,
.health = 2
};
spawner.fixes[0] = FIX16(spawner.x);
spawner.fixes[1] = FIX16(32);
spawner.fixes[2] = FIX16(64);
spawner.fixes[3] = FIX16(0.08);
spawner.bools[0] = right;
void updater(s16 i){
enemies[i].pos.x = fix16Sub(enemies[i].fixes[0], fix16Mul(sinFix16(enemies[i].fixes[1]), enemies[i].fixes[2]));
enemies[i].fixes[1] = enemies[i].bools[0] ? fix16Add(enemies[i].fixes[1], enemies[i].fixes[3]) : fix16Sub(enemies[i].fixes[1], enemies[i].fixes[3]);
}
for(u8 i = 0; i < 6; i++){
spawnEnemy(spawner, updater, EMPTY);
spawner.y -= 32;
}
}
static void waveBig1(){
struct enemySpawner spawner = {
.angle = 256,
.speed = FIX16(0.75),
.x = GAME_W / 2,
.y = -16,
.image = &fairyGreen,
.offX = 16,
.offY = 16,
.health = 8
};
void updater(s16 i){
if(enemies[i].clock == 40){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.image = &bigBullet,
.angle = 128,
.speed = FIX16(1.5),
.big = TRUE
};
for(u8 j = 0; j < 5; j++){
spawnBullet(spawner, EMPTY);
spawner.angle += 64;
}
}
else if(enemies[i].clock == 120){
enemies[i].speed = FIX16(0.5);
updateEnemyVel(i);
}
}
spawnEnemy(spawner, updater, EMPTY);
}
static void waveBig2(bool left){
struct enemySpawner spawner = {
.angle = 256,
.speed = FIX16(0.5),
.x = left ? GAME_W / 5 - 16 : GAME_W / 5 * 4 + 16,
.y = -16,
.image = left ? &fairyGreen : &fairyYellow,
.offX = 16,
.offY = 16,
.health = 6
};
spawner.bools[0] = left;
void updater(s16 i){
if(enemies[i].clock >= 60 && enemies[i].clock < 180 && enemies[i].clock % 15 == 0){
if(enemies[i].clock == 60){
velPos.x = player.pos.x;
velPos.y = player.pos.y;
}
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.speed = FIX16(1.5),
.image = &smallBullet,
.light = enemies[i].clock % 30 == 0,
.top = TRUE
};
spawner.vel = hone(enemies[i].pos, velPos, spawner.speed, 48);
spawnBullet(spawner, EMPTY);
} else if(enemies[i].bools[0] && enemies[i].clock == 61){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.image = &bigBullet,
.angle = 64,
.speed = FIX16(1.25),
.big = TRUE
};
for(u8 j = 0; j < 4; j++){
spawnBullet(spawner, EMPTY);
spawner.angle += 64;
}
}
}
spawnEnemy(spawner, updater, EMPTY);
}
static void waveBig3(){
struct enemySpawner spawner = {
.angle = 256,
.speed = FIX16(0.75),
.x = GAME_W / 2,
.y = -16,
.image = &fairyGreen,
.offX = 16,
.offY = 16,
.health = 8
};
void updater(s16 i){
if(enemies[i].clock > 0 && enemies[i].clock < 120 && enemies[i].clock % 40 == 20){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.speed = FIX16(1.5)
};
if(enemies[i].clock == 60){
spawner.image = &smallBullet;
spawner.angle = 96;
} else {
spawner.image = &bigBullet;
spawner.big = TRUE;
spawner.angle = 128;
}
for(u8 j = 0; j < (enemies[i].clock == 60 ? 6 : 5); j++){
spawnBullet(spawner, EMPTY);
spawner.angle += 64;
}
}
else if(enemies[i].clock == 120){
enemies[i].speed = FIX16(0.5);
updateEnemyVel(i);
}
}
spawnEnemy(spawner, updater, EMPTY);
}
static void waveSwarm(u8 count){
struct enemySpawner spawner = {
.angle = 256,
.speed = FIX16(1.25),
.y = -16,
.offX = 16,
.offY = 16,
.health = 2
};
for(u8 i = 0; i < count; i++){
spawner.x = random() % (GAME_W / 2 - 48);
spawner.x += (i % 2 == 0) ? (GAME_W / 2) : 48;
spawner.image = i % 4 < 2 ? &fairyRed : &fairyBlue;
spawner.y -= 32;
spawnEnemy(spawner, EMPTY, EMPTY);
}
}
static void waveBig4(bool right, bool second){
struct enemySpawner spawner = {
.angle = 256,
.speed = FIX16(0.6),
.x = right ? (GAME_W / 4 * 3 + 24) : (GAME_W / 4 - 24),
.y = -16,
.image = right ? &fairyYellow : &fairyGreen,
.offX = 16,
.offY = 16,
.health = 4
};
if(right) spawner.y -= 24;
spawner.bools[0] = right;
spawner.bools[1] = second;
void updater(s16 i){
if(enemies[i].clock == 40){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.image = &bigBullet,
.big = TRUE,
.speed = FIX16(1.25),
.angle = 32,
.light = enemies[i].bools[0]
};
if(enemies[i].bools[0]) spawner.angle = 512 - spawner.angle;
for(u8 j = 0; j < 5; j++){
spawnBullet(spawner, EMPTY);
spawner.angle += enemies[i].bools[0] ? -64 : 64;
}
} else if(enemies[i].clock >= 60 && enemies[i].clock < 150 && enemies[i].clock % 10 == 0 && enemies[i].bools[1]){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.image = &smallBullet,
.speed = FIX16(2),
.light = !enemies[i].bools[0]
};
if(enemies[i].clock == 60){
velPos = hone(enemies[i].pos, player.pos, spawner.speed, 0);
enemies[i].fixes[0] = velPos.x;
enemies[i].fixes[1] = velPos.y;
}
spawner.vel.x = enemies[i].fixes[0];
spawner.vel.y = enemies[i].fixes[1];
// spawner.vel = velPos;
spawnBullet(spawner, EMPTY);
}
}
spawnEnemy(spawner, updater, EMPTY);
}
static void waveBig5(bool right){
struct enemySpawner spawner = {
.angle = 256,
.speed = FIX16(0.75),
.x = 80,
.y = -16,
.image = &fairyRed,
.offX = 16,
.offY = 16,
.health = 6
};
if(right){
spawner.x = GAME_W - spawner.x;
spawner.y -= 32;
}
spawner.bools[0] = right;
void updater(s16 i){
if(enemies[i].clock > 0 && enemies[i].clock % 60 == 30 && enemies[i].clock < 240){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.image = &bigBullet,
.big = TRUE,
.angle = enemies[i].bools[0] ? 512 : 0,
.speed = FIX16(1.5)
};
spawner.angle += enemies[i].bools[0] ? enemies[i].ints[0] : -enemies[i].ints[0];
spawner.bools[0] = enemies[i].bools[0];
void updater(s16 j){
if(bullets[j].clock > 30 && bullets[j].clock % 16 == 0){
bullets[j].angle += bullets[j].bools[0] ? -32 : 32;
updateBulletVel(j);
}
}
for(u8 j = 0; j < 5; j++){
if(j > 0) spawnBullet(spawner, updater);
spawner.angle += enemies[i].bools[0] ? -64 : 64;
}
enemies[i].ints[0] += 56;
}
if(enemies[i].clock == 120){
enemies[i].speed = FIX16(0.5);
updateEnemyVel(i);
}
}
spawnEnemy(spawner, updater, EMPTY);
}
static void waveBig6(bool right){
struct enemySpawner spawner = {
.angle = right ? 512 : 0,
.speed = FIX16(1),
.x = right ? (GAME_W + 16) : -32,
.y = 40,
.image = right ? &fairyGreen : &fairyYellow,
.offX = 16,
.offY = 16,
.health = 4
};
spawner.bools[0] = right;
void updater(s16 i){
if(enemies[i].clock % 10 == 0 && enemies[i].clock >= 60 && enemies[i].clock < 180){
enemies[i].angle += enemies[i].bools[0] ? -24 : 24;
updateEnemyVel(i);
}
if(enemies[i].clock % 35 == 0 && enemies[i].clock > 0 && enemies[i].clock < 180){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y
};
for(u8 j = 0; j < 4; j++){
spawner.angle = random() % 256;
if(enemies[i].bools[0]) spawner.angle += 256;
if(j < 2){
spawner.speed = FIX16(1.25);
spawner.big = TRUE;
spawner.image = &bigBullet;
} else {
spawner.speed = FIX16(1.75);
spawner.image = &smallBullet;
spawner.top = TRUE;
}
spawnBullet(spawner, EMPTY);
}
}
}
spawnEnemy(spawner, updater, EMPTY);
}
static void waveFormation(bool right){
struct enemySpawner spawner = {
.angle = 256,
.speed = FIX16(1),
.x = right ? (GAME_W - 48) : 48,
.y = -16,
.image = right ? &fairyRed : &fairyBlue,
.offX = 16,
.offY = 16,
.health = 2
};
void updater(s16 i){
if(enemies[i].clock > 0 && enemies[i].clock % 60 == 0 && enemies[i].clock <= 180){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.image = &smallBullet,
.light = TRUE,
.speed = FIX16(1.5)
};
spawner.vel = hone(enemies[i].pos, player.pos, spawner.speed, 16);
spawnBullet(spawner, updater);
}
if(enemies[i].clock == 90){
enemies[i].speed = FIX16(0.75);
updateEnemyVel(i);
}
}
for(u8 i = 0; i < 4; i++){
spawnEnemy(spawner, updater, EMPTY);
spawner.x += right ? -32 : 32;
spawner.y -= 32;
}
}
// bosses
#define BOSS_MOD_Y FIX16(8)
#define BOSS_MOD_X FIX16(64)
fix16 bossLimitY, bossLimitH, bossLimitX, bossLimitW;
static void bossIntro(s16 i){
enemies[i].last.x = enemies[i].pos.x;
enemies[i].clock = -1;
if(clock % 32 == 0){
enemies[i].speed = fix16Sub(enemies[i].speed, FIX16(0.25));
if(enemies[i].speed <= 0){
bossLimitY = fix16Sub(enemies[i].pos.y, BOSS_MOD_Y);
bossLimitH = fix16Add(enemies[i].pos.y, BOSS_MOD_Y);
bossLimitX = fix16Sub(enemies[i].pos.x, BOSS_MOD_X);
bossLimitW = fix16Add(enemies[i].pos.x, BOSS_MOD_X);
// enemies[i].speed = FIX16(0.5);
enemies[i].angle = 32;
enemies[i].bools[0] = TRUE;
enemies[i].clock = -1;
}
updateEnemyVel(i);
}
}
#define BOSS_FLIP_MOD 15
s16 bossAnimateClock, bossFlipClock;
static void bossAnimate(s16 i){
if(enemies[i].flipClock == 0){
if(enemies[i].last.x > enemies[i].pos.x){
enemies[i].flipClock = BOSS_FLIP_MOD;
SPR_setAnim(enemies[i].image, 1);
SPR_setFrame(enemies[i].image, 0);
SPR_setHFlip(enemies[i].image, 0);
} else if(enemies[i].last.x < enemies[i].pos.x){
enemies[i].flipClock = BOSS_FLIP_MOD;
SPR_setAnim(enemies[i].image, 1);
SPR_setFrame(enemies[i].image, 0);
SPR_setHFlip(enemies[i].image, 1);
} else {
enemies[i].flipClock = BOSS_FLIP_MOD;
bossFlipClock = 0;
SPR_setAnim(enemies[i].image, 0);
SPR_setHFlip(enemies[i].image, 0);
}
}
if(enemies[i].flipClock > 0)
enemies[i].flipClock--;
if(enemies[i].last.x == enemies[i].pos.x){
if(bossAnimateClock % 10 == 0) SPR_nextFrame(enemies[i].image);
} else {
if(bossFlipClock >= 90) SPR_setFrame(enemies[i].image, 0);
else if(bossFlipClock >= 30) SPR_setFrame(enemies[i].image, 1);
else SPR_setFrame(enemies[i].image, 0);
bossFlipClock++;
}
bossAnimateClock++;
}
static void bossMove(s16 i){
if(enemies[i].pos.x > bossLimitW || enemies[i].pos.x < bossLimitX){
enemies[i].pos.x = enemies[i].pos.x > bossLimitW ? bossLimitW : bossLimitX;
enemies[i].angle = 512 - enemies[i].angle;
updateEnemyVel(i);
}
if(enemies[i].pos.y > bossLimitH || enemies[i].pos.y < bossLimitY){
enemies[i].pos.y = enemies[i].pos.y > bossLimitH ? bossLimitH : bossLimitY;
enemies[i].angle = 1024 - enemies[i].angle;
updateEnemyVel(i);
}
if(enemies[i].clock % 120 == 119){
enemies[i].speed = enemies[i].speed == 0 ? FIX16(0.5) : 0;
updateEnemyVel(i);
}
}
static void waveMidboss1(){
bossAnimateClock = 0;
struct enemySpawner spawner = {
.angle = 256,
.speed = FIX16(1),
.x = GAME_W / 2,
.y = -16,
.image = &cirno,
.offX = 24,
.offY = 28,
.boss = TRUE,
.health = 40
};
bossMax = spawner.health;
void updater(s16 i){
bossAnimate(i);
if(enemies[i].bools[0]){
bossHealth = enemies[i].health;
bossMove(i);
if(enemies[i].health > 20){
// ring
if(enemies[i].clock % 90 == 0){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.image = &bigBullet,
.big = TRUE,
.speed = FIX16(1.5),
.angle = 80 + random() % 32,
.light = TRUE
};
for(u8 j = 3; j < 15; j++){
if(j % 3 < 2) spawnBullet(spawner, EMPTY);
spawner.angle += 32;
}
}
// puke
else if(enemies[i].clock % 20 == 0){
struct bulletSpawner spawner = {
.x = FIX16(enemies[i].clock % 180 < 90 ? 32 : GAME_W - 32),
.y = FIX16(48),
.image = &bigBullet,
.big = TRUE,
.top = TRUE,
.speed = FIX16(2)
};
velPos.x = spawner.x;
velPos.y = spawner.y;
spawner.vel = hone(velPos, player.pos, spawner.speed, 32);
spawnBullet(spawner, EMPTY);
spawnExplosion(spawner.x, spawner.y, 3);
}
} else {
if(!enemies[i].bools[7]){
killBullets = TRUE;
enemies[i].bools[7] = TRUE;
enemies[i].clock = -60;
}
if(enemies[i].clock >= 0){
// swash
if(enemies[i].clock % 8 == 0){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.image = &smallBullet,
.speed = FIX16(1.75),
.light = TRUE,
.top = TRUE,
.angle = enemies[i].ints[0]
};
if(enemies[i].clock % 16 == 8){
spawner.image = &bigBullet;
spawner.big = TRUE;
}
void updater(s16 j){
if(bullets[j].bools[0] && bullets[j].clock == 15){
bullets[j].angle = 64 + random() % 384;
bullets[j].speed = FIX16(1.75);
updateBulletVel(j);
} else if(!bullets[j].bools[0] && bullets[j].clock >= 0 && bullets[j].clock % 10 == 0){
bullets[j].speed = fix16Sub(bullets[j].speed, FIX16(0.25));
if(bullets[j].speed <= 0){
bullets[j].speed = 0;
bullets[j].clock = -1;
bullets[j].bools[0] = TRUE;
}
updateBulletVel(j);
}
}
spawnBullet(spawner, updater);
enemies[i].ints[0] += enemies[i].bools[4] ? -64 : 56;
if(enemies[i].ints[0] > 512 || enemies[i].ints[0] < 0) enemies[i].bools[4] = !enemies[i].bools[4];
}
// balls
if(enemies[i].clock % 45 == 0 && enemies[i].clock > 0){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.image = &hugeBullet,
.speed = FIX16(1.75),
.huge = TRUE
};
spawner.vel = hone(enemies[i].pos, player.pos, spawner.speed, 16);
spawnBullet(spawner, EMPTY);
}
}
}
} else bossIntro(i);
}
void suicide(s16 i){
bossHealth = 0;
killBullets = TRUE;
}
spawnEnemy(spawner, updater, suicide);
}
static void waveMidboss2(){
bossAnimateClock = 0;
struct enemySpawner spawner = {
.angle = 256,
.speed = FIX16(1),
.x = GAME_W / 2,
.y = -16,
.image = &cirno,
.offX = 24,
.offY = 28,
.boss = TRUE,
.health = 60
};
bossMax = spawner.health;
void updater(s16 i){
bossAnimate(i);
if(enemies[i].bools[0]){
bossHealth = enemies[i].health;
bossMove(i);
if(enemies[i].health > 40){
// laser
if(enemies[i].clock % 30 == 0){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.image = &hugeBullet,
.huge = TRUE,
.speed = FIX16(2),
.angle = 256,
.light = TRUE
};
spawnBullet(spawner, EMPTY);
}
// homing
if(enemies[i].clock > 0 && enemies[i].clock % 15 == 10){
struct bulletSpawner spawner = {
.x = FIX16(random() % (GAME_W - 64) + 32),
.y = FIX16(32 + random() % 32),
.image = &bigBullet,
.speed = FIX16(1.25),
.angle = 256
};
spawner.fixes[0] = spawner.speed;
void updater(s16 j){
if(bullets[j].clock == 10){
bullets[j].speed = 0;
updateBulletVel(j);
}
else if(bullets[j].clock >= 20 && bullets[j].clock % 20 == 0 && bullets[j].clock < 60)
bullets[j].vel = hone(bullets[j].pos, player.pos, bullets[j].fixes[0], 8);
}
spawnBullet(spawner, updater);
spawnExplosion(spawner.x, spawner.y, 3);
}
} else if(enemies[i].health > 20){
if(!enemies[i].bools[7]){
killBullets = TRUE;
enemies[i].bools[7] = TRUE;
enemies[i].clock = -60;
}
// ring
if(enemies[i].clock % 5 == 0){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.image = &bigBullet,
.light = TRUE,
.speed = FIX16(2),
.top = TRUE,
.angle = random() % 128 + (enemies[i].clock % 10 == 0 ? 128 : 256)
};
void updater(s16 j){
if(bullets[j].clock == 20){
bullets[j].speed = FIX16(1.75);
updateBulletVel(j);
} else if(bullets[j].clock == 40){
bullets[j].speed = FIX16(1.5);
updateBulletVel(j);
}
}
spawnBullet(spawner, updater);
}
// lasers
if(enemies[i].clock % 15 == 0){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x + FIX16(enemies[i].clock % 30 == 0 ? 32 : -32),
.y = enemies[i].pos.y,
.image = &hugeBullet,
.huge = TRUE,
.speed = FIX16(2),
.angle = 256
};
spawnBullet(spawner, EMPTY);
}
} else {
if(!enemies[i].bools[6]){
killBullets = TRUE;
enemies[i].bools[6] = TRUE;
enemies[i].clock = -60;
}
if(enemies[i].clock % 5 == 0){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.image = &bigBullet,
.big = TRUE,
.light = TRUE,
.speed = FIX16(2),
.top = TRUE,
.angle = random() % 128 + (enemies[i].clock % 10 == 0 ? 128 : 256)
};
spawner.fixes[0] = FIX16(GAME_H - 8);
void updater(s16 j){
if(bullets[j].pos.y >= bullets[j].fixes[0] && !bullets[j].bools[0]){
bullets[j].bools[0] = TRUE;
SPR_setAnim(bullets[j].image, 0);
bullets[j].angle = 768;
updateBulletVel(j);
}
}
spawnBullet(spawner, updater);
}
}
} else bossIntro(i);
}
void suicide(s16 i){
bossHealth = 0;
killBullets = TRUE;
}
spawnEnemy(spawner, updater, suicide);
}
static void waveBoss1(){
bossAnimateClock = 0;
struct enemySpawner spawner = {
.angle = 256,
.speed = FIX16(1),
.x = GAME_W / 2,
.y = -16,
.image = &cirno,
.offX = 24,
.offY = 28,
.boss = TRUE,
.health = 20
};
bossMax = spawner.health;
void updater(s16 i){
bossAnimate(i);
if(enemies[i].bools[0]){
bossHealth = enemies[i].health;
bossMove(i);
if(enemies[i].health > 60){
// homing
if(enemies[i].clock % 15 == 10){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.image = &bigBullet,
.big = TRUE,
.angle = 256,
.speed = FIX16(2),
.top = TRUE
};
spawner.vel = hone(enemies[i].pos, player.pos, spawner.speed, 32);
spawnBullet(spawner, EMPTY);
}
// puke
else if(enemies[i].clock % 15 == 0 || enemies[i].clock % 15 == 5){
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.image = &bigBullet,
.big = TRUE,
.angle = 64 + random() % 384,
.speed = FIX16(1.25),
.light = TRUE
};
spawnBullet(spawner, EMPTY);
}
} else if(enemies[i].health > 40){
if(!enemies[i].bools[3]){
enemies[i].bools[3] = TRUE;
struct bulletSpawner spawner = {
.x = enemies[i].pos.x,
.y = enemies[i].pos.y,
.image = &hugeBullet,
.huge = TRUE,
.angle = 768,
.speed = FIX16(2)
};
void updater(s16 j){
if(bullets[j].clock >= 20 && !bullets[j].bools[0]){
bullets[j].fixes[0] = bullets[j].pos.x;
bullets[j].fixes[1] = bullets[j].pos.y;
bullets[j].bools[0] = TRUE;
bullets[j].clock = -1;
bullets[j].angle = 0;
updateBulletVel(j);
} else if(bullets[j].bools[0]){
if(bullets[j].clock % 20 == 15){
bullets[j].angle += 64;
if(bullets[j].angle >= 1024){
bullets[j].angle -= 1024;
// bullets[j].pos.x = bullets[j].fixes[0];
// bullets[j].pos.y = bullets[j].fixes[1];
}
updateBulletVel(j);
}
if(bullets[j].clock % 20 == 0){
struct bulletSpawner spawner = {
.x = bullets[j].pos.x,
.y = bullets[j].pos.y,
.image = &bigBullet,
.big = TRUE,
// .angle = bullets[j].ints[2],
.angle = 0,
.light = bullets[j].clock % 40 == 0,
.top = TRUE,
.speed = FIX16(1.75)
};
for(u8 h = 0; h < 16; h++){
if(bullets[j].angle < 256){
if(spawner.angle >= 256 && spawner.angle < 512) spawnBullet(spawner, EMPTY);
} else if(bullets[j].angle < 512){
if(spawner.angle >= 512 && spawner.angle < 768) spawnBullet(spawner, EMPTY);
} else if(bullets[j].angle < 768){
if(spawner.angle >= 768) spawnBullet(spawner, EMPTY);
} else {
if(spawner.angle < 256) spawnBullet(spawner, EMPTY);
}
spawner.angle += 64;
}
bullets[j].ints[2] += 50;
if(bullets[j].ints[2] >= 1024) bullets[j].ints[2] -= 1024;
}
}
}
spawnBullet(spawner, updater);
}
} else if(enemies[i].health > 20){
if(enemies[i].clock % 3 == 0){
struct bulletSpawner spawner = {
.x = FIX16(random() % GAME_W),
.y = FIX16(32 + random() % 48),
.image = &bigBullet,
.big = TRUE,
.angle = 0,
.speed = FIX16(enemies[i].clock % 6 == 0 ? 2.5 : 3.5),
.light = enemies[i].clock % 6 == 0
};
for(u8 j = 0; j < 5; j++){
if(spawner.angle > 32 && spawner.angle < 480) spawnBullet(spawner, EMPTY);
spawner.angle += 205;
}
}
} else {
}
} else bossIntro(i);
}
void suicide(s16 i){
bossHealth = 0;
killBullets = TRUE;
}
spawnEnemy(spawner, updater, suicide);
}
// loop
s16 currentWave = 18;
void updateStage(){
if(enemyCount == 0){
switch(currentWave){
// sine from left
case 0:
waveSine(FALSE);
break;
// sine from right
case 1:
waveSine(TRUE);
break;
// big middle
case 2:
waveBig1();
break;
// sine from left, big right
case 3:
waveSine(FALSE);
waveBig2(FALSE);
break;
// sine from right, big left
case 4:
waveSine(TRUE);
waveBig2(TRUE);
break;
// big middle
case 5:
waveBig3();
break;
// swarm (8)
case 6:
waveSwarm(8);
break;
// big left and right
case 7:
waveBig4(TRUE, FALSE);
waveBig4(FALSE, FALSE);
break;
// swarm (2), big right
case 8:
waveSwarm(2);
waveBig4(TRUE, TRUE);
break;
// swarm (2), big left
case 9:
waveSwarm(2);
waveBig4(FALSE, TRUE);
break;
// midboss
case 10:
waveMidboss1();
break;
// big from left and right
case 11:
waveBig5(FALSE);
waveBig5(TRUE);
break;
// big from right and left
case 12:
waveBig6(TRUE);
waveBig6(FALSE);
break;
// big from left, small formation
case 13:
waveBig6(FALSE);
waveFormation(TRUE);
break;
// big from right, small formation
case 14:
waveBig6(TRUE);
waveFormation(FALSE);
break;
// big from left, small formation
case 15:
waveBig6(FALSE);
waveFormation(TRUE);
break;
// big from right, small formation
case 16:
waveBig6(TRUE);
waveFormation(FALSE);
break;
// midboss
case 17:
waveMidboss2();
break;
// midboss
case 18:
waveBoss1();
break;
}
currentWave++;
}
stageClock++;
if(stageClock >= CLOCK_LIMIT) stageClock -= CLOCK_LIMIT;
}
/*
sine from left
sine from right
big middle
sine from left, big right
sine from right, big left
big middle
swarm
big from left and right
swarm, big right
swarm, big left
midboss
big from left and right
big from right and left
big from left, small formation
big from right, small formation
big from left, small formation
big from right, small formation
midboss
final boss at 30 seconds left
*/