diff --git a/res/chrome/boss.png b/res/chrome/boss.png new file mode 100644 index 0000000..c7b5e1e Binary files /dev/null and b/res/chrome/boss.png differ diff --git a/res/chrome/frame.png b/res/chrome/frame.png deleted file mode 100644 index 25fb574..0000000 Binary files a/res/chrome/frame.png and /dev/null differ diff --git a/res/enemies/cirno.png b/res/enemies/cirno.png new file mode 100644 index 0000000..e3751aa Binary files /dev/null and b/res/enemies/cirno.png differ diff --git a/res/explosions.png b/res/explosions.png new file mode 100644 index 0000000..d3f01a7 Binary files /dev/null and b/res/explosions.png differ diff --git a/res/font.png b/res/font.png index 198c082..c0e7aad 100644 Binary files a/res/font.png and b/res/font.png differ diff --git a/res/resources.res b/res/resources.res index 8e9a2c3..f46d91e 100644 --- a/res/resources.res +++ b/res/resources.res @@ -1,15 +1,22 @@ IMAGE font "font.png" BEST NONE + +// start + IMAGE startBg1 "start/bg1.png" FAST IMAGE startLogo1 "start/logo1.png" FAST -IMAGE frame "chrome/frame.png" FAST + +// chrome + +IMAGE bossBar "chrome/boss.png" FAST // background IMAGE bg1 "bg/1.png" FAST + // player and enemies SPRITE sunny "player/sunny.png" 6 5 FAST 10 @@ -19,9 +26,15 @@ SPRITE fairyRed "enemies/fairyred.png" 4 4 FAST 10 SPRITE fairyBlue "enemies/fairyblue.png" 4 4 FAST 10 SPRITE fairyYellow "enemies/fairyyellow.png" 4 4 FAST 10 SPRITE fairyGreen "enemies/fairygreen.png" 4 4 FAST 10 +SPRITE cirno "enemies/cirno.png" 6 7 FAST 0 SPRITE smallBullet "bullets/small.png" 1 1 FAST 5 SPRITE bigBullet "bullets/big.png" 2 2 FAST 5 SPRITE hugeBullet "bullets/huge.png" 4 4 FAST 5 -SPRITE playerBullet "bullets/player.png" 4 3 FAST 5 \ No newline at end of file +SPRITE playerBullet "bullets/player.png" 4 3 FAST 5 + + +// explosion + +SPRITE explosion "explosions.png" 4 4 FAST 5 \ No newline at end of file diff --git a/src/bullets.h b/src/bullets.h index 1b8ec9a..fa3565e 100644 --- a/src/bullets.h +++ b/src/bullets.h @@ -20,7 +20,7 @@ void spawnBullet(struct bulletSpawner spawner, void(*updater)){ bullets[i].active = TRUE; bullets[i].pos.x = spawner.x; bullets[i].pos.y = spawner.y; - bullets[i].dist = fix16ToFix32(spawner.huge ? BULLET_DIST_HUGE : (spawner.big ? BULLET_DIST_BIG : BULLET_DIST)); + bullets[i].dist = spawner.player ? BULLET_DIST_HUGE : (spawner.huge ? BULLET_DIST_HUGE : (spawner.big ? BULLET_DIST_BIG : BULLET_DIST)); bullets[i].speed = spawner.speed; bullets[i].angle = spawner.angle; bullets[i].player = spawner.player; @@ -28,6 +28,7 @@ void spawnBullet(struct bulletSpawner spawner, void(*updater)){ bullets[i].dead = FALSE; bullets[i].big = spawner.big; bullets[i].huge = spawner.huge; + bullets[i].light = spawner.light; for(u8 j = 0; j < COUNT_INT; j++){ bullets[i].bools[j] = spawner.bools[j]; bullets[i].ints[j] = spawner.ints[j]; @@ -55,7 +56,7 @@ static void killBullet(s16 i){ bullets[i].active = FALSE; SPR_releaseSprite(bullets[i].image); if(bullets[i].dead){ - // spawnExplosion(bullets[i].pos.x, bullets[i].pos.y, 0); + spawnExplosion(bullets[i].pos.x, bullets[i].pos.y, bullets[i].light ? 1 : 0); bullets[i].dead = FALSE; } } @@ -68,6 +69,20 @@ void updateBulletVel(s16 i){ // collision +fix32 bulletDist; +static void collideBulletWithEnemy(s16 i){ + for(s16 j = 0; j < ENEMY_COUNT; j++) if(enemies[j].active && enemies[j].pos.y >= FIX16(8)){ + bulletDist = getApproximatedDistance( + fix16ToFix32(fix16Sub(enemies[j].pos.x, bullets[i].pos.x)), + fix16ToFix32(fix16Sub(enemies[j].pos.y, bullets[i].pos.y))); + if(bulletDist <= fix32Add(enemies[j].dist, bullets[i].dist)){ + spawnExplosion(bullets[i].pos.x, fix16Add(enemies[j].pos.y, FIX16(8)), 2); + killBullet(i); + if(enemies[j].clock > 0) enemies[j].health--; + } + } +} + #define BULLET_LIMIT FIX16(0 - BULLET_OFF) #define BULLET_LIMIT_W FIX16(GAME_W + BULLET_OFF) #define BULLET_LIMIT_H FIX16(GAME_H + BULLET_OFF) @@ -86,7 +101,7 @@ static void collideBullet(s16 i){ bullets[i].pos.y < (bullets[i].huge ? BULLET_LIMIT_HUGE : (bullets[i].big ? BULLET_LIMIT_BIG : BULLET_LIMIT)) || bullets[i].pos.y > (bullets[i].huge ? BULLET_LIMIT_H_HUGE : (bullets[i].big ? BULLET_LIMIT_H_BIG : BULLET_LIMIT_H))){ killBullet(i); - } + } else if(bullets[i].player) collideBulletWithEnemy(i); } @@ -107,7 +122,7 @@ static void updateBullet(s16 i){ void updateBullets(){ if(killBullets){ for(s16 i = 0; i < BULLET_COUNT; i++) if(bullets[i].active){ - if(i % 4 == 0) bullets[i].dead = TRUE; + if(i % 3 == 0) bullets[i].dead = TRUE; killBullet(i); } killBullets = FALSE; diff --git a/src/chrome.h b/src/chrome.h index 94aab5d..856ad27 100644 --- a/src/chrome.h +++ b/src/chrome.h @@ -2,13 +2,6 @@ #define CHROME_I 64 -// frame - -static void loadFrame(){ - // VDP_loadTileSet(frame.tileset, CHROME_I, DMA); - // VDP_fillTileMapRect(BG_A, TILE_ATTR_FULL(PAL2, 1, 0, 0, CHROME_I), 0, 0, GAME_W_T, 4); -} - // score #define SCORE_X 1 @@ -19,7 +12,7 @@ u32 lastScore; char scoreStr[SCORE_LENGTH]; static void loadScore(){ - VDP_drawText("00000000", SCORE_X, SCORE_Y); + VDP_drawText("0000000000", SCORE_X, SCORE_Y); } // static void updateScore(){ @@ -42,27 +35,64 @@ static void loadTime(){ } -// heat +// boss -#define RANK_X 28 -#define RANK_Y 2 -#define RANK_LABEL_X 25 +#define BOSS_TILE_X 1 +#define BOSS_TILE_Y 2 +#define BOSS_TILE_COUNT 30 +#define BOSS_TILE_PX 30 * 8 -static void loadRank(){ - // VDP_drawText("RANK 1", RANK_LABEL_X, RANK_Y); - // VDP_drawText("100", RANK_X, HEAT_Y); +s16 lastBossHealth; +fix16 bossLimit; + +static void updateBoss(){ + if(lastBossHealth != bossHealth){ + bossLimit = fix16Div(fix16Mul(fix16Div(FIX16(bossHealth), FIX16(bossMax)), BOSS_TILE_PX), 8); + for(s16 x = 0; x < BOSS_TILE_COUNT; x++){ + if(bossHealth <= 0 || FIX16(x) >= bossLimit){ + VDP_clearText(x + BOSS_TILE_X, BOSS_TILE_Y, 1); + } + } + for(s16 x = 0; x < BOSS_TILE_COUNT; x++){ + if(bossHealth > 1 && FIX16(x) < bossLimit) VDP_setTileMapXY(BG_A, TILE_ATTR_FULL(PAL1, 1, 0, 0, CHROME_I), x + BOSS_TILE_X, BOSS_TILE_Y); + } + lastBossHealth = bossHealth; + } +} + + +// lives + +#define LIVES_X 1 +#define LIVES_Y 26 + +static void loadLives(){ + VDP_drawText("##", LIVES_X, LIVES_Y); +} + + +// bombs + +#define BOMBS_X 28 +#define BOMBS_Y 26 + +static void loadBombs(){ + VDP_drawText("***", BOMBS_X, BOMBS_Y); } // loop void loadChrome(){ - // loadFrame(); + VDP_loadTileSet(bossBar.tileset, CHROME_I, DMA); loadScore(); loadTime(); - // loadRank(); + loadLives(); + loadBombs(); } void updateChrome(){ + updateBoss(); + // VDP_drawText(debugStr, 0, 27); // updateScore(); } \ No newline at end of file diff --git a/src/enemies.h b/src/enemies.h index 5b4c008..9ec91a1 100644 --- a/src/enemies.h +++ b/src/enemies.h @@ -11,13 +11,15 @@ void spawnEnemy(struct enemySpawner spawner, void(*updater), void(*suicide)){ enemies[i].off.y = FIX16(spawner.offY); enemies[i].pos.x = FIX16(spawner.x); enemies[i].pos.y = FIX16(spawner.y); + enemies[i].last.x = FIX16(spawner.x); + enemies[i].last.y = FIX16(spawner.y); enemies[i].dist = intToFix32(spawner.offX - 2); enemies[i].speed = spawner.speed; enemies[i].angle = spawner.angle; enemies[i].boss = spawner.boss; - enemies[i].shotClock = 0; enemies[i].dead = FALSE; enemies[i].health = spawner.health ? spawner.health : 1; + enemies[i].flipClock = 0; if(spawner.vel.x && spawner.vel.y){ enemies[i].vel.x = spawner.vel.x; enemies[i].vel.y = spawner.vel.y; @@ -45,10 +47,6 @@ void spawnEnemy(struct enemySpawner spawner, void(*updater), void(*suicide)){ } } -void killEnemy(s16 i){ - enemies[i].dead = TRUE; -} - // helpers @@ -57,15 +55,38 @@ void updateEnemyVel(s16 i){ enemies[i].vel.y = fix16Mul(sinFix16(enemies[i].angle), enemies[i].speed); } +#define FLIP_MOD 15 +static void enemyAnimate(s16 i){ + if(enemies[i].flipClock == 0){ + if(enemies[i].last.x > enemies[i].pos.x){ + enemies[i].flipClock = FLIP_MOD; + SPR_setAnim(enemies[i].image, 1); + SPR_setHFlip(enemies[i].image, 0); + } else if(enemies[i].last.x < enemies[i].pos.x){ + enemies[i].flipClock = FLIP_MOD; + SPR_setAnim(enemies[i].image, 1); + SPR_setHFlip(enemies[i].image, 1); + } else { + enemies[i].flipClock = FLIP_MOD; + SPR_setAnim(enemies[i].image, 0); + SPR_setHFlip(enemies[i].image, 0); + } + } + if(enemies[i].flipClock > 0){ + enemies[i].flipClock--; + } +} // loop static void updateEnemy(s16 i){ + enemies[i].last.x = enemies[i].pos.x; + enemies[i].last.y = enemies[i].pos.y; if(enemies[i].seen && (enemies[i].pos.x < fix16Sub(0, enemies[i].off.x) || enemies[i].pos.x > fix16Add(FIX16(GAME_W), enemies[i].off.x) || enemies[i].pos.y < fix16Sub(0, enemies[i].off.y) || enemies[i].pos.y > fix16Add(FIX16(GAME_H), enemies[i].off.y))){ - killEnemy(i); + enemies[i].dead = TRUE; enemies[i].suicide(i); } else { if(!enemies[i].seen && enemies[i].pos.y >= fix16Sub(0, enemies[i].off.y)){ @@ -76,14 +97,18 @@ static void updateEnemy(s16 i){ enemies[i].pos.y = fix16Add(enemies[i].pos.y, enemies[i].vel.y); if(enemies[i].seen){ enemies[i].updater(i); - if(enemies[i].boss) bossHealth = enemies[i].health; - // collideEnemy(i); + if(!enemies[i].boss) enemyAnimate(i); enemies[i].clock++; if(enemies[i].clock >= CLOCK_LIMIT) enemies[i].clock -= CLOCK_LIMIT; SPR_setPosition(enemies[i].image, fix16ToInt(fix16Sub(enemies[i].pos.x, enemies[i].off.x)), fix16ToInt(fix16Sub(enemies[i].pos.y, enemies[i].off.y))); } + if(enemies[i].health <= 0){ + enemies[i].suicide(i); + enemies[i].dead = TRUE; + // SND_startPlayPCM_XGM(SFX_EXPLOSION_2, 15, SOUND_PCM_CH2); + } } if(enemies[i].dead){ enemies[i].active = FALSE; diff --git a/src/explosions.h b/src/explosions.h new file mode 100644 index 0000000..c0cf130 --- /dev/null +++ b/src/explosions.h @@ -0,0 +1,29 @@ +// explosions + +#define EXPLOSION_OFFSET FIX16(16) +#define EXPLOSION_TIME 20 + +void spawnExplosion(fix16 x, fix16 y, u8 type){ + s16 i = -1; + for(s16 j = 0; j < EXPLOSION_COUNT; j++) if(!explosions[j].active && i == -1) i = j; + explosions[i].active = TRUE; + explosions[i].clock = 0; + explosions[i].image = SPR_addSprite(&explosion, + fix16ToInt(fix16Sub(x, EXPLOSION_OFFSET)), + fix16ToInt(fix16Sub(y, EXPLOSION_OFFSET)), + TILE_ATTR(PAL1, 1, 0, 0)); + SPR_setAnim(explosions[i].image, type); + SPR_setDepth(explosions[i].image, 3); +} + +static void updateExplosion(s16 i){ + if(explosions[i].clock >= EXPLOSION_TIME){ + explosions[i].active = FALSE; + SPR_releaseSprite(explosions[i].image); + } + explosions[i].clock++; +} + +void updateExplosions(){ + for(s16 i = 0; i < EXPLOSION_COUNT; i++) if(explosions[i].active) updateExplosion(i); +} \ No newline at end of file diff --git a/src/global.h b/src/global.h index 9bd840f..ec4d617 100644 --- a/src/global.h +++ b/src/global.h @@ -21,9 +21,11 @@ bool killBullets, started; -s16 clock, +s16 clock, timeLeft, bossHealth, bossMax; +char debugStr[8]; + u32 score, highScore; diff --git a/src/main.c b/src/main.c index facc4f5..4b2b9c6 100644 --- a/src/main.c +++ b/src/main.c @@ -8,7 +8,7 @@ #include "controls.h" #include "start.h" #include "background.h" -// #include "foreground.h" +#include "explosions.h" #include "bullets.h" #include "player.h" #include "enemies.h" @@ -41,6 +41,7 @@ static void updateGame(){ updateBullets(); updateBg(); updateChrome(); + updateExplosions(); clock++; if(clock >= CLOCK_LIMIT) clock -= CLOCK_LIMIT; } diff --git a/src/stage.h b/src/stage.h index badc131..44b7eca 100644 --- a/src/stage.h +++ b/src/stage.h @@ -28,20 +28,19 @@ final boss at 30 seconds left */ -#define SPAWN_MID 128 - // groups static void waveSine(bool right){ struct enemySpawner spawner = { .angle = 256, - .speed = FIX16(0.8), + .speed = FIX16(1), .x = GAME_W / 5 * (right ? 3 : 2), .y = -16, .image = right ? &fairyRed : &fairyBlue, .offX = 16, - .offY = 16 + .offY = 16, + .health = 2 }; spawner.fixes[0] = FIX16(spawner.x); spawner.fixes[1] = FIX16(32); @@ -58,15 +57,16 @@ static void waveSine(bool right){ static void waveBig1(){ struct enemySpawner spawner = { .angle = 256, - .speed = FIX16(0.6), + .speed = FIX16(0.75), .x = GAME_W / 2, .y = -16, .image = &fairyGreen, .offX = 16, - .offY = 16 + .offY = 16, + .health = 8 }; void updater(s16 i){ - if(enemies[i].clock == 60){ + if(enemies[i].clock == 40){ struct bulletSpawner spawner = { .x = enemies[i].pos.x, .y = enemies[i].pos.y, @@ -80,6 +80,10 @@ static void waveBig1(){ spawner.angle += 64; } } + else if(enemies[i].clock == 120){ + enemies[i].speed = FIX16(0.5); + updateEnemyVel(i); + } } spawnEnemy(spawner, updater, EMPTY); } @@ -87,12 +91,13 @@ static void waveBig1(){ static void waveBig2(bool left){ struct enemySpawner spawner = { .angle = 256, - .speed = FIX16(0.6), + .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 + .offY = 16, + .health = 6 }; spawner.bools[0] = left; void updater(s16 i){ @@ -132,15 +137,16 @@ static void waveBig2(bool left){ static void waveBig3(){ struct enemySpawner spawner = { .angle = 256, - .speed = FIX16(0.6), + .speed = FIX16(0.75), .x = GAME_W / 2, .y = -16, .image = &fairyGreen, .offX = 16, - .offY = 16 + .offY = 16, + .health = 8 }; void updater(s16 i){ - if(enemies[i].clock >= 30 && enemies[i].clock <= 90 && enemies[i].clock % 30 == 0){ + 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, @@ -159,6 +165,10 @@ static void waveBig3(){ spawner.angle += 64; } } + else if(enemies[i].clock == 120){ + enemies[i].speed = FIX16(0.5); + updateEnemyVel(i); + } } spawnEnemy(spawner, updater, EMPTY); } @@ -171,7 +181,8 @@ static void waveSwarm(bool right, bool color){ .y = -16, .image = color ? &fairyRed : &fairyBlue, .offX = 16, - .offY = 16 + .offY = 16, + .health = 2 }; spawner.x += right ? (GAME_W / 2) : 64; spawnEnemy(spawner, EMPTY, EMPTY); @@ -185,7 +196,8 @@ static void waveBig4(bool right, bool second){ .y = -16, .image = right ? &fairyYellow : &fairyGreen, .offX = 16, - .offY = 16 + .offY = 16, + .health = 4 }; spawner.bools[0] = right; spawner.bools[1] = second; @@ -234,14 +246,16 @@ static void waveBig4(bool right, bool second){ fix16 bossLimitY, bossLimitH, bossLimitX, bossLimitW; static void bossIntro(s16 i){ - if(enemies[i].clock > 0 && enemies[i].clock % 30 == 0){ + enemies[i].last.x = enemies[i].pos.x; + enemies[i].clock = -1; + if(clock % 30 == 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.4); + // enemies[i].speed = FIX16(0.5); enemies[i].angle = 32; enemies[i].bools[0] = TRUE; enemies[i].clock = -1; @@ -250,6 +264,25 @@ static void bossIntro(s16 i){ } } +s16 bossAnimateClock; +static void bossAnimate(s16 i){ + + if(enemies[i].last.x > enemies[i].pos.x){ + 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){ + SPR_setAnim(enemies[i].image, 1); + SPR_setFrame(enemies[i].image, 0); + SPR_setHFlip(enemies[i].image, 1); + } else { + if(bossAnimateClock % 10 == 0) SPR_nextFrame(enemies[i].image); + SPR_setAnim(enemies[i].image, 0); + SPR_setHFlip(enemies[i].image, 0); + } + 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; @@ -261,64 +294,132 @@ static void bossMove(s16 i){ 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 = &fairyGreen, - .offX = 16, - .offY = 16 + .image = &cirno, + .offX = 24, + .offY = 28, + .boss = TRUE, + .health = 50 }; + bossMax = spawner.health; void updater(s16 i){ + bossAnimate(i); if(enemies[i].bools[0]){ - + bossHealth = enemies[i].health; + intToStr(bossHealth, debugStr, 2); bossMove(i); - - // 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.25), - .angle = 80 + random() % 32, - .light = TRUE - }; - for(u8 j = 3; j < 15; j++){ - if(j % 3 < 2) spawnBullet(spawner, EMPTY); - spawner.angle += 32; + if(enemies[i].health >= 25){ + // 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); + } } } - - // puke - else if(enemies[i].clock % 20 == 0){ - struct bulletSpawner spawner = { - .x = FIX16(enemies[i].clock % 180 < 90 ? 32 : GAME_W - 32), - .y = FIX16(40), - .image = &bigBullet, - .big = TRUE, - .speed = FIX16(1.75) - }; - velPos.x = spawner.x; - velPos.y = spawner.y; - spawner.vel = hone(velPos, player.pos, spawner.speed, 32); - spawnBullet(spawner, EMPTY); - } - } else bossIntro(i); } - spawnEnemy(spawner, updater, EMPTY); + void suicide(s16 i){ + bossHealth = 0; + killBullets = TRUE; + } + spawnEnemy(spawner, updater, suicide); } // loop -#define OBS_INTERVAL 15 - s16 stageClock, nextClock; @@ -332,13 +433,13 @@ static void updateWaves(){ // sine from left if(currentWave < 6){ waveSine(FALSE); - nextClock += currentWave == 5 ? 90 : 40; + nextClock += currentWave == 5 ? 60 : 30; } // sine from right else if(currentWave < 12){ waveSine(TRUE); - nextClock += currentWave == 11 ? 90 : 40; + nextClock += currentWave == 11 ? 60 : 30; } // big middle @@ -350,21 +451,21 @@ static void updateWaves(){ // sine from left, big right else if(currentWave < 18){ waveSine(FALSE); - if(currentWave == 14) waveBig2(FALSE); - nextClock += currentWave == 17 ? 90 : 40; + if(currentWave == 16) waveBig2(FALSE); + nextClock += currentWave == 17 ? 90 : 30; } // sine from right, big left else if(currentWave < 24){ waveSine(TRUE); - if(currentWave == 20) waveBig2(TRUE); - nextClock += currentWave == 23 ? 90 : 40; + if(currentWave == 22) waveBig2(TRUE); + nextClock += currentWave == 23 ? 120 : 30; } // big middle else if(currentWave == 24){ waveBig3(); - nextClock += 180; + nextClock += 210; } // swarm (8) @@ -390,7 +491,7 @@ static void updateWaves(){ else if(currentWave < 42){ waveSwarm(TRUE, currentWave % 2 < 1); if(currentWave == 39) waveBig4(FALSE, TRUE); - nextClock += currentWave == 41 ? 60 : 30; + nextClock += currentWave == 41 ? 210 : 30; } else if(currentWave == 42){ diff --git a/src/structs.h b/src/structs.h index d0f704e..6802ef8 100644 --- a/src/structs.h +++ b/src/structs.h @@ -15,7 +15,7 @@ struct bulletSpawner { fix16 fixes[COUNT_INT]; }; struct bullet { - bool active, player, dead, big, huge; + bool active, player, dead, big, huge, light; fix16 speed; fix32 dist; Vect2D_f16 pos, vel; @@ -59,8 +59,8 @@ struct enemy { bool active, boss, seen, seal, dead; fix16 speed; fix32 dist; - Vect2D_f16 pos, vel, off; - s16 angle, clock, health, shotClock; + Vect2D_f16 pos, vel, off, last; + s16 angle, clock, health, flipClock; Sprite* image; Sprite* sealImage; void (*updater)(s16); @@ -70,4 +70,16 @@ struct enemy { s16 ints[COUNT_INT]; fix16 fixes[COUNT_INT]; }; -struct enemy enemies[ENEMY_COUNT]; \ No newline at end of file +struct enemy enemies[ENEMY_COUNT]; + + +// explosion + +#define EXPLOSION_COUNT 16 + +struct explosion { + bool active; + s16 clock; + Sprite* image; +}; +struct explosion explosions[EXPLOSION_COUNT]; \ No newline at end of file