explosion and more graphics

This commit is contained in:
t. boddy 2022-09-23 17:26:33 -04:00
parent 0750aef980
commit 600d04f3c9
14 changed files with 327 additions and 99 deletions

BIN
res/chrome/boss.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

BIN
res/enemies/cirno.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
res/explosions.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -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
SPRITE playerBullet "bullets/player.png" 4 3 FAST 5
// explosion
SPRITE explosion "explosions.png" 4 4 FAST 5

View File

@ -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;

View File

@ -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();
}

View File

@ -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;

29
src/explosions.h Normal file
View File

@ -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);
}

View File

@ -21,9 +21,11 @@
bool killBullets,
started;
s16 clock,
s16 clock, timeLeft,
bossHealth, bossMax;
char debugStr[8];
u32 score,
highScore;

View File

@ -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;
}

View File

@ -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){

View File

@ -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];
struct enemy enemies[ENEMY_COUNT];
// explosion
#define EXPLOSION_COUNT 16
struct explosion {
bool active;
s16 clock;
Sprite* image;
};
struct explosion explosions[EXPLOSION_COUNT];