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
|
IMAGE font "font.png" BEST NONE
|
||||||
|
|
||||||
|
|
||||||
|
// start
|
||||||
|
|
||||||
IMAGE startBg1 "start/bg1.png" FAST
|
IMAGE startBg1 "start/bg1.png" FAST
|
||||||
IMAGE startLogo1 "start/logo1.png" FAST
|
IMAGE startLogo1 "start/logo1.png" FAST
|
||||||
|
|
||||||
IMAGE frame "chrome/frame.png" FAST
|
|
||||||
|
// chrome
|
||||||
|
|
||||||
|
IMAGE bossBar "chrome/boss.png" FAST
|
||||||
|
|
||||||
|
|
||||||
// background
|
// background
|
||||||
|
|
||||||
IMAGE bg1 "bg/1.png" FAST
|
IMAGE bg1 "bg/1.png" FAST
|
||||||
|
|
||||||
|
|
||||||
// player and enemies
|
// player and enemies
|
||||||
|
|
||||||
SPRITE sunny "player/sunny.png" 6 5 FAST 10
|
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 fairyBlue "enemies/fairyblue.png" 4 4 FAST 10
|
||||||
SPRITE fairyYellow "enemies/fairyyellow.png" 4 4 FAST 10
|
SPRITE fairyYellow "enemies/fairyyellow.png" 4 4 FAST 10
|
||||||
SPRITE fairyGreen "enemies/fairygreen.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 smallBullet "bullets/small.png" 1 1 FAST 5
|
||||||
SPRITE bigBullet "bullets/big.png" 2 2 FAST 5
|
SPRITE bigBullet "bullets/big.png" 2 2 FAST 5
|
||||||
SPRITE hugeBullet "bullets/huge.png" 4 4 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].active = TRUE;
|
||||||
bullets[i].pos.x = spawner.x;
|
bullets[i].pos.x = spawner.x;
|
||||||
bullets[i].pos.y = spawner.y;
|
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].speed = spawner.speed;
|
||||||
bullets[i].angle = spawner.angle;
|
bullets[i].angle = spawner.angle;
|
||||||
bullets[i].player = spawner.player;
|
bullets[i].player = spawner.player;
|
||||||
|
@ -28,6 +28,7 @@ void spawnBullet(struct bulletSpawner spawner, void(*updater)){
|
||||||
bullets[i].dead = FALSE;
|
bullets[i].dead = FALSE;
|
||||||
bullets[i].big = spawner.big;
|
bullets[i].big = spawner.big;
|
||||||
bullets[i].huge = spawner.huge;
|
bullets[i].huge = spawner.huge;
|
||||||
|
bullets[i].light = spawner.light;
|
||||||
for(u8 j = 0; j < COUNT_INT; j++){
|
for(u8 j = 0; j < COUNT_INT; j++){
|
||||||
bullets[i].bools[j] = spawner.bools[j];
|
bullets[i].bools[j] = spawner.bools[j];
|
||||||
bullets[i].ints[j] = spawner.ints[j];
|
bullets[i].ints[j] = spawner.ints[j];
|
||||||
|
@ -55,7 +56,7 @@ static void killBullet(s16 i){
|
||||||
bullets[i].active = FALSE;
|
bullets[i].active = FALSE;
|
||||||
SPR_releaseSprite(bullets[i].image);
|
SPR_releaseSprite(bullets[i].image);
|
||||||
if(bullets[i].dead){
|
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;
|
bullets[i].dead = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,6 +69,20 @@ void updateBulletVel(s16 i){
|
||||||
|
|
||||||
// collision
|
// 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 FIX16(0 - BULLET_OFF)
|
||||||
#define BULLET_LIMIT_W FIX16(GAME_W + BULLET_OFF)
|
#define BULLET_LIMIT_W FIX16(GAME_W + BULLET_OFF)
|
||||||
#define BULLET_LIMIT_H FIX16(GAME_H + 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_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))){
|
bullets[i].pos.y > (bullets[i].huge ? BULLET_LIMIT_H_HUGE : (bullets[i].big ? BULLET_LIMIT_H_BIG : BULLET_LIMIT_H))){
|
||||||
killBullet(i);
|
killBullet(i);
|
||||||
}
|
} else if(bullets[i].player) collideBulletWithEnemy(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,7 +122,7 @@ static void updateBullet(s16 i){
|
||||||
void updateBullets(){
|
void updateBullets(){
|
||||||
if(killBullets){
|
if(killBullets){
|
||||||
for(s16 i = 0; i < BULLET_COUNT; i++) if(bullets[i].active){
|
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);
|
killBullet(i);
|
||||||
}
|
}
|
||||||
killBullets = FALSE;
|
killBullets = FALSE;
|
||||||
|
|
64
src/chrome.h
64
src/chrome.h
|
@ -2,13 +2,6 @@
|
||||||
|
|
||||||
#define CHROME_I 64
|
#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
|
// score
|
||||||
|
|
||||||
#define SCORE_X 1
|
#define SCORE_X 1
|
||||||
|
@ -19,7 +12,7 @@ u32 lastScore;
|
||||||
char scoreStr[SCORE_LENGTH];
|
char scoreStr[SCORE_LENGTH];
|
||||||
|
|
||||||
static void loadScore(){
|
static void loadScore(){
|
||||||
VDP_drawText("00000000", SCORE_X, SCORE_Y);
|
VDP_drawText("0000000000", SCORE_X, SCORE_Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static void updateScore(){
|
// static void updateScore(){
|
||||||
|
@ -42,27 +35,64 @@ static void loadTime(){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// heat
|
// boss
|
||||||
|
|
||||||
#define RANK_X 28
|
#define BOSS_TILE_X 1
|
||||||
#define RANK_Y 2
|
#define BOSS_TILE_Y 2
|
||||||
#define RANK_LABEL_X 25
|
#define BOSS_TILE_COUNT 30
|
||||||
|
#define BOSS_TILE_PX 30 * 8
|
||||||
|
|
||||||
static void loadRank(){
|
s16 lastBossHealth;
|
||||||
// VDP_drawText("RANK 1", RANK_LABEL_X, RANK_Y);
|
fix16 bossLimit;
|
||||||
// VDP_drawText("100", RANK_X, HEAT_Y);
|
|
||||||
|
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
|
// loop
|
||||||
|
|
||||||
void loadChrome(){
|
void loadChrome(){
|
||||||
// loadFrame();
|
VDP_loadTileSet(bossBar.tileset, CHROME_I, DMA);
|
||||||
loadScore();
|
loadScore();
|
||||||
loadTime();
|
loadTime();
|
||||||
// loadRank();
|
loadLives();
|
||||||
|
loadBombs();
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateChrome(){
|
void updateChrome(){
|
||||||
|
updateBoss();
|
||||||
|
// VDP_drawText(debugStr, 0, 27);
|
||||||
// updateScore();
|
// updateScore();
|
||||||
}
|
}
|
|
@ -11,13 +11,15 @@ void spawnEnemy(struct enemySpawner spawner, void(*updater), void(*suicide)){
|
||||||
enemies[i].off.y = FIX16(spawner.offY);
|
enemies[i].off.y = FIX16(spawner.offY);
|
||||||
enemies[i].pos.x = FIX16(spawner.x);
|
enemies[i].pos.x = FIX16(spawner.x);
|
||||||
enemies[i].pos.y = FIX16(spawner.y);
|
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].dist = intToFix32(spawner.offX - 2);
|
||||||
enemies[i].speed = spawner.speed;
|
enemies[i].speed = spawner.speed;
|
||||||
enemies[i].angle = spawner.angle;
|
enemies[i].angle = spawner.angle;
|
||||||
enemies[i].boss = spawner.boss;
|
enemies[i].boss = spawner.boss;
|
||||||
enemies[i].shotClock = 0;
|
|
||||||
enemies[i].dead = FALSE;
|
enemies[i].dead = FALSE;
|
||||||
enemies[i].health = spawner.health ? spawner.health : 1;
|
enemies[i].health = spawner.health ? spawner.health : 1;
|
||||||
|
enemies[i].flipClock = 0;
|
||||||
if(spawner.vel.x && spawner.vel.y){
|
if(spawner.vel.x && spawner.vel.y){
|
||||||
enemies[i].vel.x = spawner.vel.x;
|
enemies[i].vel.x = spawner.vel.x;
|
||||||
enemies[i].vel.y = spawner.vel.y;
|
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
|
// helpers
|
||||||
|
|
||||||
|
@ -57,15 +55,38 @@ void updateEnemyVel(s16 i){
|
||||||
enemies[i].vel.y = fix16Mul(sinFix16(enemies[i].angle), enemies[i].speed);
|
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
|
// loop
|
||||||
|
|
||||||
static void updateEnemy(s16 i){
|
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) ||
|
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.x > fix16Add(FIX16(GAME_W), enemies[i].off.x) ||
|
||||||
enemies[i].pos.y < fix16Sub(0, enemies[i].off.y) ||
|
enemies[i].pos.y < fix16Sub(0, enemies[i].off.y) ||
|
||||||
enemies[i].pos.y > fix16Add(FIX16(GAME_H), 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);
|
enemies[i].suicide(i);
|
||||||
} else {
|
} else {
|
||||||
if(!enemies[i].seen && enemies[i].pos.y >= fix16Sub(0, enemies[i].off.y)){
|
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);
|
enemies[i].pos.y = fix16Add(enemies[i].pos.y, enemies[i].vel.y);
|
||||||
if(enemies[i].seen){
|
if(enemies[i].seen){
|
||||||
enemies[i].updater(i);
|
enemies[i].updater(i);
|
||||||
if(enemies[i].boss) bossHealth = enemies[i].health;
|
if(!enemies[i].boss) enemyAnimate(i);
|
||||||
// collideEnemy(i);
|
|
||||||
enemies[i].clock++;
|
enemies[i].clock++;
|
||||||
if(enemies[i].clock >= CLOCK_LIMIT) enemies[i].clock -= CLOCK_LIMIT;
|
if(enemies[i].clock >= CLOCK_LIMIT) enemies[i].clock -= CLOCK_LIMIT;
|
||||||
SPR_setPosition(enemies[i].image,
|
SPR_setPosition(enemies[i].image,
|
||||||
fix16ToInt(fix16Sub(enemies[i].pos.x, enemies[i].off.x)),
|
fix16ToInt(fix16Sub(enemies[i].pos.x, enemies[i].off.x)),
|
||||||
fix16ToInt(fix16Sub(enemies[i].pos.y, enemies[i].off.y)));
|
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){
|
if(enemies[i].dead){
|
||||||
enemies[i].active = FALSE;
|
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,
|
bool killBullets,
|
||||||
started;
|
started;
|
||||||
|
|
||||||
s16 clock,
|
s16 clock, timeLeft,
|
||||||
bossHealth, bossMax;
|
bossHealth, bossMax;
|
||||||
|
|
||||||
|
char debugStr[8];
|
||||||
|
|
||||||
u32 score,
|
u32 score,
|
||||||
highScore;
|
highScore;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include "controls.h"
|
#include "controls.h"
|
||||||
#include "start.h"
|
#include "start.h"
|
||||||
#include "background.h"
|
#include "background.h"
|
||||||
// #include "foreground.h"
|
#include "explosions.h"
|
||||||
#include "bullets.h"
|
#include "bullets.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "enemies.h"
|
#include "enemies.h"
|
||||||
|
@ -41,6 +41,7 @@ static void updateGame(){
|
||||||
updateBullets();
|
updateBullets();
|
||||||
updateBg();
|
updateBg();
|
||||||
updateChrome();
|
updateChrome();
|
||||||
|
updateExplosions();
|
||||||
clock++;
|
clock++;
|
||||||
if(clock >= CLOCK_LIMIT) clock -= CLOCK_LIMIT;
|
if(clock >= CLOCK_LIMIT) clock -= CLOCK_LIMIT;
|
||||||
}
|
}
|
||||||
|
|
175
src/stage.h
175
src/stage.h
|
@ -28,20 +28,19 @@ final boss at 30 seconds left
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define SPAWN_MID 128
|
|
||||||
|
|
||||||
|
|
||||||
// groups
|
// groups
|
||||||
|
|
||||||
static void waveSine(bool right){
|
static void waveSine(bool right){
|
||||||
struct enemySpawner spawner = {
|
struct enemySpawner spawner = {
|
||||||
.angle = 256,
|
.angle = 256,
|
||||||
.speed = FIX16(0.8),
|
.speed = FIX16(1),
|
||||||
.x = GAME_W / 5 * (right ? 3 : 2),
|
.x = GAME_W / 5 * (right ? 3 : 2),
|
||||||
.y = -16,
|
.y = -16,
|
||||||
.image = right ? &fairyRed : &fairyBlue,
|
.image = right ? &fairyRed : &fairyBlue,
|
||||||
.offX = 16,
|
.offX = 16,
|
||||||
.offY = 16
|
.offY = 16,
|
||||||
|
.health = 2
|
||||||
};
|
};
|
||||||
spawner.fixes[0] = FIX16(spawner.x);
|
spawner.fixes[0] = FIX16(spawner.x);
|
||||||
spawner.fixes[1] = FIX16(32);
|
spawner.fixes[1] = FIX16(32);
|
||||||
|
@ -58,15 +57,16 @@ static void waveSine(bool right){
|
||||||
static void waveBig1(){
|
static void waveBig1(){
|
||||||
struct enemySpawner spawner = {
|
struct enemySpawner spawner = {
|
||||||
.angle = 256,
|
.angle = 256,
|
||||||
.speed = FIX16(0.6),
|
.speed = FIX16(0.75),
|
||||||
.x = GAME_W / 2,
|
.x = GAME_W / 2,
|
||||||
.y = -16,
|
.y = -16,
|
||||||
.image = &fairyGreen,
|
.image = &fairyGreen,
|
||||||
.offX = 16,
|
.offX = 16,
|
||||||
.offY = 16
|
.offY = 16,
|
||||||
|
.health = 8
|
||||||
};
|
};
|
||||||
void updater(s16 i){
|
void updater(s16 i){
|
||||||
if(enemies[i].clock == 60){
|
if(enemies[i].clock == 40){
|
||||||
struct bulletSpawner spawner = {
|
struct bulletSpawner spawner = {
|
||||||
.x = enemies[i].pos.x,
|
.x = enemies[i].pos.x,
|
||||||
.y = enemies[i].pos.y,
|
.y = enemies[i].pos.y,
|
||||||
|
@ -80,6 +80,10 @@ static void waveBig1(){
|
||||||
spawner.angle += 64;
|
spawner.angle += 64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(enemies[i].clock == 120){
|
||||||
|
enemies[i].speed = FIX16(0.5);
|
||||||
|
updateEnemyVel(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
spawnEnemy(spawner, updater, EMPTY);
|
spawnEnemy(spawner, updater, EMPTY);
|
||||||
}
|
}
|
||||||
|
@ -87,12 +91,13 @@ static void waveBig1(){
|
||||||
static void waveBig2(bool left){
|
static void waveBig2(bool left){
|
||||||
struct enemySpawner spawner = {
|
struct enemySpawner spawner = {
|
||||||
.angle = 256,
|
.angle = 256,
|
||||||
.speed = FIX16(0.6),
|
.speed = FIX16(0.5),
|
||||||
.x = left ? GAME_W / 5 - 16 : GAME_W / 5 * 4 + 16,
|
.x = left ? GAME_W / 5 - 16 : GAME_W / 5 * 4 + 16,
|
||||||
.y = -16,
|
.y = -16,
|
||||||
.image = left ? &fairyGreen : &fairyYellow,
|
.image = left ? &fairyGreen : &fairyYellow,
|
||||||
.offX = 16,
|
.offX = 16,
|
||||||
.offY = 16
|
.offY = 16,
|
||||||
|
.health = 6
|
||||||
};
|
};
|
||||||
spawner.bools[0] = left;
|
spawner.bools[0] = left;
|
||||||
void updater(s16 i){
|
void updater(s16 i){
|
||||||
|
@ -132,15 +137,16 @@ static void waveBig2(bool left){
|
||||||
static void waveBig3(){
|
static void waveBig3(){
|
||||||
struct enemySpawner spawner = {
|
struct enemySpawner spawner = {
|
||||||
.angle = 256,
|
.angle = 256,
|
||||||
.speed = FIX16(0.6),
|
.speed = FIX16(0.75),
|
||||||
.x = GAME_W / 2,
|
.x = GAME_W / 2,
|
||||||
.y = -16,
|
.y = -16,
|
||||||
.image = &fairyGreen,
|
.image = &fairyGreen,
|
||||||
.offX = 16,
|
.offX = 16,
|
||||||
.offY = 16
|
.offY = 16,
|
||||||
|
.health = 8
|
||||||
};
|
};
|
||||||
void updater(s16 i){
|
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 = {
|
struct bulletSpawner spawner = {
|
||||||
.x = enemies[i].pos.x,
|
.x = enemies[i].pos.x,
|
||||||
.y = enemies[i].pos.y,
|
.y = enemies[i].pos.y,
|
||||||
|
@ -159,6 +165,10 @@ static void waveBig3(){
|
||||||
spawner.angle += 64;
|
spawner.angle += 64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(enemies[i].clock == 120){
|
||||||
|
enemies[i].speed = FIX16(0.5);
|
||||||
|
updateEnemyVel(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
spawnEnemy(spawner, updater, EMPTY);
|
spawnEnemy(spawner, updater, EMPTY);
|
||||||
}
|
}
|
||||||
|
@ -171,7 +181,8 @@ static void waveSwarm(bool right, bool color){
|
||||||
.y = -16,
|
.y = -16,
|
||||||
.image = color ? &fairyRed : &fairyBlue,
|
.image = color ? &fairyRed : &fairyBlue,
|
||||||
.offX = 16,
|
.offX = 16,
|
||||||
.offY = 16
|
.offY = 16,
|
||||||
|
.health = 2
|
||||||
};
|
};
|
||||||
spawner.x += right ? (GAME_W / 2) : 64;
|
spawner.x += right ? (GAME_W / 2) : 64;
|
||||||
spawnEnemy(spawner, EMPTY, EMPTY);
|
spawnEnemy(spawner, EMPTY, EMPTY);
|
||||||
|
@ -185,7 +196,8 @@ static void waveBig4(bool right, bool second){
|
||||||
.y = -16,
|
.y = -16,
|
||||||
.image = right ? &fairyYellow : &fairyGreen,
|
.image = right ? &fairyYellow : &fairyGreen,
|
||||||
.offX = 16,
|
.offX = 16,
|
||||||
.offY = 16
|
.offY = 16,
|
||||||
|
.health = 4
|
||||||
};
|
};
|
||||||
spawner.bools[0] = right;
|
spawner.bools[0] = right;
|
||||||
spawner.bools[1] = second;
|
spawner.bools[1] = second;
|
||||||
|
@ -234,14 +246,16 @@ static void waveBig4(bool right, bool second){
|
||||||
fix16 bossLimitY, bossLimitH, bossLimitX, bossLimitW;
|
fix16 bossLimitY, bossLimitH, bossLimitX, bossLimitW;
|
||||||
|
|
||||||
static void bossIntro(s16 i){
|
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));
|
enemies[i].speed = fix16Sub(enemies[i].speed, FIX16(0.25));
|
||||||
if(enemies[i].speed <= 0){
|
if(enemies[i].speed <= 0){
|
||||||
bossLimitY = fix16Sub(enemies[i].pos.y, BOSS_MOD_Y);
|
bossLimitY = fix16Sub(enemies[i].pos.y, BOSS_MOD_Y);
|
||||||
bossLimitH = fix16Add(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);
|
bossLimitX = fix16Sub(enemies[i].pos.x, BOSS_MOD_X);
|
||||||
bossLimitW = fix16Add(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].angle = 32;
|
||||||
enemies[i].bools[0] = TRUE;
|
enemies[i].bools[0] = TRUE;
|
||||||
enemies[i].clock = -1;
|
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){
|
static void bossMove(s16 i){
|
||||||
if(enemies[i].pos.x > bossLimitW || enemies[i].pos.x < bossLimitX){
|
if(enemies[i].pos.x > bossLimitW || enemies[i].pos.x < bossLimitX){
|
||||||
enemies[i].pos.x = enemies[i].pos.x > bossLimitW ? bossLimitW : bossLimitX;
|
enemies[i].pos.x = enemies[i].pos.x > bossLimitW ? bossLimitW : bossLimitX;
|
||||||
|
@ -261,23 +294,34 @@ static void bossMove(s16 i){
|
||||||
enemies[i].angle = 1024 - enemies[i].angle;
|
enemies[i].angle = 1024 - enemies[i].angle;
|
||||||
updateEnemyVel(i);
|
updateEnemyVel(i);
|
||||||
}
|
}
|
||||||
|
if(enemies[i].clock % 120 == 119){
|
||||||
|
enemies[i].speed = enemies[i].speed == 0 ? FIX16(0.5) : 0;
|
||||||
|
updateEnemyVel(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void waveMidboss1(){
|
static void waveMidboss1(){
|
||||||
|
bossAnimateClock = 0;
|
||||||
struct enemySpawner spawner = {
|
struct enemySpawner spawner = {
|
||||||
.angle = 256,
|
.angle = 256,
|
||||||
.speed = FIX16(1),
|
.speed = FIX16(1),
|
||||||
.x = GAME_W / 2,
|
.x = GAME_W / 2,
|
||||||
.y = -16,
|
.y = -16,
|
||||||
.image = &fairyGreen,
|
.image = &cirno,
|
||||||
.offX = 16,
|
.offX = 24,
|
||||||
.offY = 16
|
.offY = 28,
|
||||||
|
.boss = TRUE,
|
||||||
|
.health = 50
|
||||||
};
|
};
|
||||||
|
bossMax = spawner.health;
|
||||||
void updater(s16 i){
|
void updater(s16 i){
|
||||||
|
bossAnimate(i);
|
||||||
if(enemies[i].bools[0]){
|
if(enemies[i].bools[0]){
|
||||||
|
bossHealth = enemies[i].health;
|
||||||
|
intToStr(bossHealth, debugStr, 2);
|
||||||
bossMove(i);
|
bossMove(i);
|
||||||
|
if(enemies[i].health >= 25){
|
||||||
// ring
|
// ring
|
||||||
if(enemies[i].clock % 90 == 0){
|
if(enemies[i].clock % 90 == 0){
|
||||||
struct bulletSpawner spawner = {
|
struct bulletSpawner spawner = {
|
||||||
|
@ -285,7 +329,7 @@ static void waveMidboss1(){
|
||||||
.y = enemies[i].pos.y,
|
.y = enemies[i].pos.y,
|
||||||
.image = &bigBullet,
|
.image = &bigBullet,
|
||||||
.big = TRUE,
|
.big = TRUE,
|
||||||
.speed = FIX16(1.25),
|
.speed = FIX16(1.5),
|
||||||
.angle = 80 + random() % 32,
|
.angle = 80 + random() % 32,
|
||||||
.light = TRUE
|
.light = TRUE
|
||||||
};
|
};
|
||||||
|
@ -294,31 +338,88 @@ static void waveMidboss1(){
|
||||||
spawner.angle += 32;
|
spawner.angle += 32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// puke
|
// puke
|
||||||
else if(enemies[i].clock % 20 == 0){
|
else if(enemies[i].clock % 20 == 0){
|
||||||
struct bulletSpawner spawner = {
|
struct bulletSpawner spawner = {
|
||||||
.x = FIX16(enemies[i].clock % 180 < 90 ? 32 : GAME_W - 32),
|
.x = FIX16(enemies[i].clock % 180 < 90 ? 32 : GAME_W - 32),
|
||||||
.y = FIX16(40),
|
.y = FIX16(48),
|
||||||
.image = &bigBullet,
|
.image = &bigBullet,
|
||||||
.big = TRUE,
|
.big = TRUE,
|
||||||
.speed = FIX16(1.75)
|
.top = TRUE,
|
||||||
|
.speed = FIX16(2)
|
||||||
};
|
};
|
||||||
velPos.x = spawner.x;
|
velPos.x = spawner.x;
|
||||||
velPos.y = spawner.y;
|
velPos.y = spawner.y;
|
||||||
spawner.vel = hone(velPos, player.pos, spawner.speed, 32);
|
spawner.vel = hone(velPos, player.pos, spawner.speed, 32);
|
||||||
spawnBullet(spawner, EMPTY);
|
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);
|
} else bossIntro(i);
|
||||||
}
|
}
|
||||||
spawnEnemy(spawner, updater, EMPTY);
|
void suicide(s16 i){
|
||||||
|
bossHealth = 0;
|
||||||
|
killBullets = TRUE;
|
||||||
|
}
|
||||||
|
spawnEnemy(spawner, updater, suicide);
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop
|
// loop
|
||||||
|
|
||||||
#define OBS_INTERVAL 15
|
|
||||||
|
|
||||||
s16 stageClock,
|
s16 stageClock,
|
||||||
nextClock;
|
nextClock;
|
||||||
|
|
||||||
|
@ -332,13 +433,13 @@ static void updateWaves(){
|
||||||
// sine from left
|
// sine from left
|
||||||
if(currentWave < 6){
|
if(currentWave < 6){
|
||||||
waveSine(FALSE);
|
waveSine(FALSE);
|
||||||
nextClock += currentWave == 5 ? 90 : 40;
|
nextClock += currentWave == 5 ? 60 : 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sine from right
|
// sine from right
|
||||||
else if(currentWave < 12){
|
else if(currentWave < 12){
|
||||||
waveSine(TRUE);
|
waveSine(TRUE);
|
||||||
nextClock += currentWave == 11 ? 90 : 40;
|
nextClock += currentWave == 11 ? 60 : 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
// big middle
|
// big middle
|
||||||
|
@ -350,21 +451,21 @@ static void updateWaves(){
|
||||||
// sine from left, big right
|
// sine from left, big right
|
||||||
else if(currentWave < 18){
|
else if(currentWave < 18){
|
||||||
waveSine(FALSE);
|
waveSine(FALSE);
|
||||||
if(currentWave == 14) waveBig2(FALSE);
|
if(currentWave == 16) waveBig2(FALSE);
|
||||||
nextClock += currentWave == 17 ? 90 : 40;
|
nextClock += currentWave == 17 ? 90 : 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sine from right, big left
|
// sine from right, big left
|
||||||
else if(currentWave < 24){
|
else if(currentWave < 24){
|
||||||
waveSine(TRUE);
|
waveSine(TRUE);
|
||||||
if(currentWave == 20) waveBig2(TRUE);
|
if(currentWave == 22) waveBig2(TRUE);
|
||||||
nextClock += currentWave == 23 ? 90 : 40;
|
nextClock += currentWave == 23 ? 120 : 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
// big middle
|
// big middle
|
||||||
else if(currentWave == 24){
|
else if(currentWave == 24){
|
||||||
waveBig3();
|
waveBig3();
|
||||||
nextClock += 180;
|
nextClock += 210;
|
||||||
}
|
}
|
||||||
|
|
||||||
// swarm (8)
|
// swarm (8)
|
||||||
|
@ -390,7 +491,7 @@ static void updateWaves(){
|
||||||
else if(currentWave < 42){
|
else if(currentWave < 42){
|
||||||
waveSwarm(TRUE, currentWave % 2 < 1);
|
waveSwarm(TRUE, currentWave % 2 < 1);
|
||||||
if(currentWave == 39) waveBig4(FALSE, TRUE);
|
if(currentWave == 39) waveBig4(FALSE, TRUE);
|
||||||
nextClock += currentWave == 41 ? 60 : 30;
|
nextClock += currentWave == 41 ? 210 : 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(currentWave == 42){
|
else if(currentWave == 42){
|
||||||
|
|
|
@ -15,7 +15,7 @@ struct bulletSpawner {
|
||||||
fix16 fixes[COUNT_INT];
|
fix16 fixes[COUNT_INT];
|
||||||
};
|
};
|
||||||
struct bullet {
|
struct bullet {
|
||||||
bool active, player, dead, big, huge;
|
bool active, player, dead, big, huge, light;
|
||||||
fix16 speed;
|
fix16 speed;
|
||||||
fix32 dist;
|
fix32 dist;
|
||||||
Vect2D_f16 pos, vel;
|
Vect2D_f16 pos, vel;
|
||||||
|
@ -59,8 +59,8 @@ struct enemy {
|
||||||
bool active, boss, seen, seal, dead;
|
bool active, boss, seen, seal, dead;
|
||||||
fix16 speed;
|
fix16 speed;
|
||||||
fix32 dist;
|
fix32 dist;
|
||||||
Vect2D_f16 pos, vel, off;
|
Vect2D_f16 pos, vel, off, last;
|
||||||
s16 angle, clock, health, shotClock;
|
s16 angle, clock, health, flipClock;
|
||||||
Sprite* image;
|
Sprite* image;
|
||||||
Sprite* sealImage;
|
Sprite* sealImage;
|
||||||
void (*updater)(s16);
|
void (*updater)(s16);
|
||||||
|
@ -71,3 +71,15 @@ struct enemy {
|
||||||
fix16 fixes[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