2022-08-16 19:19:44 +00:00
|
|
|
// bullets
|
|
|
|
|
|
|
|
#define BULLET_OFF 4
|
|
|
|
#define BULLET_OFF_BIG 8
|
2022-09-23 14:21:36 +00:00
|
|
|
#define BULLET_OFF_HUGE 16
|
|
|
|
#define BULLET_OFF_P_X 16
|
|
|
|
#define BULLET_OFF_P_Y 12
|
2022-08-16 19:19:44 +00:00
|
|
|
|
|
|
|
#define BULLET_DIST FIX32(4)
|
|
|
|
#define BULLET_DIST_BIG FIX32(8)
|
2022-09-23 14:21:36 +00:00
|
|
|
#define BULLET_DIST_HUGE FIX32(16)
|
2022-08-16 19:19:44 +00:00
|
|
|
|
2022-08-17 03:13:05 +00:00
|
|
|
|
|
|
|
// lifecycle
|
|
|
|
|
2022-08-16 19:19:44 +00:00
|
|
|
void spawnBullet(struct bulletSpawner spawner, void(*updater)){
|
|
|
|
s16 i = -1;
|
|
|
|
for(s16 j = 0; j < BULLET_COUNT; j++) if(!bullets[j].active && i == -1) i = j;
|
|
|
|
if(i > -1 && (spawner.player || (player.invincibleClock < INVINCIBLE_LIMIT))){
|
|
|
|
bullets[i].active = TRUE;
|
|
|
|
bullets[i].pos.x = spawner.x;
|
|
|
|
bullets[i].pos.y = spawner.y;
|
2022-09-23 14:21:36 +00:00
|
|
|
bullets[i].dist = fix16ToFix32(spawner.huge ? BULLET_DIST_HUGE : (spawner.big ? BULLET_DIST_BIG : BULLET_DIST));
|
2022-08-16 19:19:44 +00:00
|
|
|
bullets[i].speed = spawner.speed;
|
|
|
|
bullets[i].angle = spawner.angle;
|
|
|
|
bullets[i].player = spawner.player;
|
|
|
|
bullets[i].clock = 0;
|
|
|
|
bullets[i].dead = FALSE;
|
|
|
|
bullets[i].big = spawner.big;
|
2022-09-23 14:21:36 +00:00
|
|
|
bullets[i].huge = spawner.huge;
|
2022-08-16 19:19:44 +00:00
|
|
|
for(u8 j = 0; j < COUNT_INT; j++){
|
|
|
|
bullets[i].bools[j] = spawner.bools[j];
|
|
|
|
bullets[i].ints[j] = spawner.ints[j];
|
|
|
|
bullets[i].fixes[j] = spawner.fixes[j];
|
|
|
|
}
|
|
|
|
if(spawner.vel.x && spawner.vel.y){
|
|
|
|
bullets[i].vel.x = spawner.vel.x;
|
|
|
|
bullets[i].vel.y = spawner.vel.y;
|
2022-09-23 14:21:36 +00:00
|
|
|
if(bullets[i].vel.y < 0 && !bullets[i].player && bullets[i].pos.y < player.pos.y) bullets[i].vel.y = -bullets[i].vel.y;
|
2022-08-16 19:19:44 +00:00
|
|
|
} else {
|
|
|
|
bullets[i].vel.x = fix16Mul(cosFix16(spawner.angle), spawner.speed);
|
|
|
|
bullets[i].vel.y = fix16Mul(sinFix16(spawner.angle), spawner.speed);
|
|
|
|
}
|
|
|
|
bullets[i].updater = updater;
|
|
|
|
bullets[i].image = SPR_addSprite(spawner.image,
|
2022-09-23 14:21:36 +00:00
|
|
|
fix16ToInt(fix16Sub(bullets[i].pos.x, FIX16(spawner.player ? BULLET_OFF_P_X : (spawner.huge ? BULLET_OFF_HUGE : (spawner.big ? BULLET_OFF_BIG : BULLET_OFF))))),
|
|
|
|
fix16ToInt(fix16Sub(bullets[i].pos.y, FIX16(spawner.player ? BULLET_OFF_P_Y : (spawner.huge ? BULLET_OFF_HUGE : (spawner.big ? BULLET_OFF_BIG : BULLET_OFF))))),
|
2022-08-16 19:19:44 +00:00
|
|
|
TILE_ATTR(PAL1, 0, 0, 0));
|
2022-09-23 14:21:36 +00:00
|
|
|
if(spawner.light) SPR_setAnim(bullets[i].image, 1);
|
|
|
|
SPR_setDepth(bullets[i].image, spawner.top ? 3 : 4);
|
2022-08-16 19:19:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
bullets[i].dead = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void updateBulletVel(s16 i){
|
|
|
|
bullets[i].vel.x = fix16Mul(cosFix16(bullets[i].angle), bullets[i].speed);
|
|
|
|
bullets[i].vel.y = fix16Mul(sinFix16(bullets[i].angle), bullets[i].speed);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// collision
|
|
|
|
|
2022-09-23 14:21:36 +00:00
|
|
|
#define BULLET_LIMIT FIX16(0 - BULLET_OFF)
|
2022-08-16 19:19:44 +00:00
|
|
|
#define BULLET_LIMIT_W FIX16(GAME_W + BULLET_OFF)
|
|
|
|
#define BULLET_LIMIT_H FIX16(GAME_H + BULLET_OFF)
|
|
|
|
|
2022-09-23 14:21:36 +00:00
|
|
|
#define BULLET_LIMIT_BIG FIX16(0 - BULLET_OFF_BIG)
|
2022-08-16 19:19:44 +00:00
|
|
|
#define BULLET_LIMIT_W_BIG FIX16(GAME_W + BULLET_OFF_BIG)
|
|
|
|
#define BULLET_LIMIT_H_BIG FIX16(GAME_H + BULLET_OFF_BIG)
|
|
|
|
|
2022-09-23 14:21:36 +00:00
|
|
|
#define BULLET_LIMIT_HUGE FIX16(0 - BULLET_OFF_HUGE)
|
|
|
|
#define BULLET_LIMIT_W_HUGE FIX16(GAME_W + BULLET_OFF_HUGE)
|
|
|
|
#define BULLET_LIMIT_H_HUGE FIX16(GAME_H + BULLET_OFF_HUGE)
|
|
|
|
|
2022-08-16 19:19:44 +00:00
|
|
|
static void collideBullet(s16 i){
|
2022-09-23 14:21:36 +00:00
|
|
|
if(bullets[i].pos.x < (bullets[i].huge ? BULLET_LIMIT_HUGE : (bullets[i].big ? BULLET_LIMIT_BIG : BULLET_LIMIT)) ||
|
|
|
|
bullets[i].pos.x > (bullets[i].huge ? BULLET_LIMIT_W_HUGE : (bullets[i].big ? BULLET_LIMIT_W_BIG : BULLET_LIMIT_W)) ||
|
|
|
|
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))){
|
2022-08-16 19:19:44 +00:00
|
|
|
killBullet(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// loop
|
|
|
|
|
|
|
|
static void updateBullet(s16 i){
|
|
|
|
bullets[i].pos.x = fix16Add(bullets[i].pos.x, bullets[i].vel.x);
|
|
|
|
bullets[i].pos.y = fix16Add(bullets[i].pos.y, bullets[i].vel.y);
|
|
|
|
bullets[i].updater(i);
|
|
|
|
collideBullet(i);
|
|
|
|
SPR_setPosition(
|
|
|
|
bullets[i].image,
|
2022-09-23 14:21:36 +00:00
|
|
|
fix16ToInt(fix16Sub(bullets[i].pos.x, FIX16(bullets[i].player ? BULLET_OFF_P_X : (bullets[i].huge ? BULLET_OFF_HUGE : (bullets[i].big ? BULLET_OFF_BIG : BULLET_OFF))))),
|
|
|
|
fix16ToInt(fix16Sub(bullets[i].pos.y, FIX16(bullets[i].player ? BULLET_OFF_P_Y : (bullets[i].huge ? BULLET_OFF_HUGE : (bullets[i].big ? BULLET_OFF_BIG : BULLET_OFF))))));
|
2022-08-16 19:19:44 +00:00
|
|
|
bullets[i].clock++;
|
|
|
|
}
|
|
|
|
|
|
|
|
void updateBullets(){
|
|
|
|
if(killBullets){
|
|
|
|
for(s16 i = 0; i < BULLET_COUNT; i++) if(bullets[i].active){
|
|
|
|
if(i % 4 == 0) bullets[i].dead = TRUE;
|
|
|
|
killBullet(i);
|
|
|
|
}
|
|
|
|
killBullets = FALSE;
|
|
|
|
} else {
|
|
|
|
for(s16 i = 0; i < BULLET_COUNT; i++) if(bullets[i].active) updateBullet(i);
|
|
|
|
}
|
|
|
|
}
|