From 600d04f3c96431a06acccfa4ae6cab5af46cc4eb Mon Sep 17 00:00:00 2001 From: Trevor Boddy Date: Fri, 23 Sep 2022 17:26:33 -0400 Subject: [PATCH] explosion and more graphics --- res/chrome/boss.png | Bin 0 -> 1882 bytes res/chrome/frame.png | Bin 4139 -> 0 bytes res/enemies/cirno.png | Bin 0 -> 6604 bytes res/explosions.png | Bin 0 -> 3676 bytes res/font.png | Bin 3460 -> 3467 bytes res/resources.res | 17 +++- src/bullets.h | 23 ++++- src/chrome.h | 64 ++++++++---- src/enemies.h | 41 ++++++-- src/explosions.h | 29 ++++++ src/global.h | 4 +- src/main.c | 3 +- src/stage.h | 225 ++++++++++++++++++++++++++++++------------ src/structs.h | 20 +++- 14 files changed, 327 insertions(+), 99 deletions(-) create mode 100644 res/chrome/boss.png delete mode 100644 res/chrome/frame.png create mode 100644 res/enemies/cirno.png create mode 100644 res/explosions.png create mode 100644 src/explosions.h diff --git a/res/chrome/boss.png b/res/chrome/boss.png new file mode 100644 index 0000000000000000000000000000000000000000..c7b5e1eba99cf467765828a8e156667c58085a2d GIT binary patch literal 1882 zcmbVN%WvF795z%!A+#qRst^d{9w-uH&-k_Wv`a{KH_b}%vPu_`NIftfk9V!CJ+AF! zH<3UHi9-)aoPh%p2X1gfLY3eT=!p}TUbu1r35i=JX7=HRD2<}7)}HaqH{b8|&CI=i z@79&oS63B9xzgQg?}&CqJ}Z~R`=8%>Ka1wg{`R0F+CTsJ`;)t$H_(mOUwh-;#@fGY z+mG(Q^~IO^`rd=R?|;1U)5qTl(DV7$Ua2TAyeOY%l&`+IswmI>k_>jM-C!G2p6Vpx zA=9U6F3^f{b8VUvy3Z;#WWywDYJc7TRa29wseR}KFvweMlx!Ur?DlbQK#%vSA8Bjv zsyC-t5TvXk>NFi^C7w3587~%nIc#X^3{vekwRLGw-3|I`ix*67=m<~Pl1bjTrJcnR)+QBe zYO-zsiN8585k?5xE`Sb(a1ITG6e3cQ8f*gS1JfEH8{0mB_G2WElKAL+TtsoqicvTnPn2`BX=iLmQ6yoS@DfW@8(Y$s+QY=jPQ5%eO5g&uLq za($cA16e(}ey-$*Q^8T^42O^~#2PNJk&S@s*bWHY*aXx<#EW7RH6nA#_I{Cw%|ym0 zS*2HzU?gVTfL`bU%O@eQtuO=xQb&B6R_uswOk7QUY`4Y7ya;$Cvwd>B+iLX-9w%cl zQSRK@P`jO$i+tAwrjDfKXVSx4Nh#`kwAe(q+1*8NoTxLkVM67GXlhg{fkoP4I5{Js z7ju11I~g%SdX7Hku#(5sgcNLjD3X5x1sYFsza)p}J0DuEZ+o!^98VUJu@HE!YXaYe zLd14xLuxI9Kht>|TWBfnr*nRhS~?=xkclJK(4Ib=i;4SGEzaD27mLNx;s1|<`La{7 z81h`5i_AE!zuDZ0Ggwq|HY5&q*{!b>@ljt&EE8!e#Fg{)2Uj16>+0ohdwsC-JB>bl kc2j?Nx%cq$E7vb6tKTY{@4a;Aj=a#ionHHgjgLP24@(tDtN;K2 literal 0 HcmV?d00001 diff --git a/res/chrome/frame.png b/res/chrome/frame.png deleted file mode 100644 index 25fb5740c3b8612fc58f87ac79df343386b7657a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4139 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 literal 0 HcmV?d00001 diff --git a/res/explosions.png b/res/explosions.png new file mode 100644 index 0000000000000000000000000000000000000000..d3f01a7d892b6772bcf5a3c975b96a7c691fb650 GIT binary patch literal 3676 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 e+?D@YOBQ|5i+WzeeOxE$O1u 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