explosion and more graphics
This commit is contained in:
parent
0750aef980
commit
600d04f3c9
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.6 KiB |
BIN
res/font.png
BIN
res/font.png
Binary file not shown.
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
@ -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
|
|
@ -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;
|
||||
|
|
64
src/chrome.h
64
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();
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -21,9 +21,11 @@
|
|||
bool killBullets,
|
||||
started;
|
||||
|
||||
s16 clock,
|
||||
s16 clock, timeLeft,
|
||||
bossHealth, bossMax;
|
||||
|
||||
char debugStr[8];
|
||||
|
||||
u32 score,
|
||||
highScore;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
225
src/stage.h
225
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){
|
||||
|
|
|
@ -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];
|
Reference in New Issue