sfx, explozion

This commit is contained in:
t. boddy 2026-02-16 09:24:19 -05:00
parent a3f0474ec9
commit 75f6c7d8dc
7 changed files with 146 additions and 12 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Before After
Before After

View file

@ -82,6 +82,7 @@ void spawnBullet(struct bulletSpawner spawner, void(*updater)){
bullets[i].vel.y = fix32Mul(fix16ToFix32(sinFix16(spawner.angle)), spawner.speed); bullets[i].vel.y = fix32Mul(fix16ToFix32(sinFix16(spawner.angle)), spawner.speed);
} }
bullets[i].updater = updater; bullets[i].updater = updater;
bullets[i].explosion = FALSE;
bullets[i].dist = bullets[i].player ? 16 : (spawner.anim == 0 ? 4 : 7); bullets[i].dist = bullets[i].player ? 16 : (spawner.anim == 0 ? 4 : 7);
u8 off = bullets[i].player ? P_BULLET_OFF : BULLET_OFF; u8 off = bullets[i].player ? P_BULLET_OFF : BULLET_OFF;
@ -116,8 +117,9 @@ static void collideWithEnemy(u8 i){
deltaX >= -BULLET_CHECK && deltaX <= BULLET_CHECK){ deltaX >= -BULLET_CHECK && deltaX <= BULLET_CHECK){
bulletDist = getApproximatedDistance(fix32ToInt(deltaX), fix32ToInt(deltaY)); bulletDist = getApproximatedDistance(fix32ToInt(deltaX), fix32ToInt(deltaY));
if(bulletDist <= bullets[i].dist){ if(bulletDist <= bullets[i].dist){
killBullet(i); killBullet(i, TRUE);
killEnemy(j); killEnemy(j);
sfxExplosion();
} }
} }
} }
@ -132,13 +134,34 @@ static void collideWithPlayer(u8 i){
fix32ToInt(deltaX), fix32ToInt(deltaX),
fix32ToInt(deltaY)); fix32ToInt(deltaY));
if(dist <= 4){ if(dist <= 4){
killBullet(i); killBullet(i, TRUE);
sfxExplosion();
// player.lives--; // player.lives--;
// if(player.lives <= 0) gameOver = TRUE; // if(player.lives <= 0) gameOver = TRUE;
} }
} }
static void updateBulletExplosion(u8 i){
bullets[i].clock++;
if(bullets[i].clock & 1){
bullets[i].frame++;
if(bullets[i].frame >= 5){
killBullet(i, FALSE);
return;
}
SPR_setFrame(bullets[i].image, bullets[i].frame);
}
s16 sx = getScreenX(bullets[i].pos.x, player.camera);
s16 sy = fix32ToInt(bullets[i].pos.y);
u8 off = bullets[i].player ? P_BULLET_OFF : BULLET_OFF;
SPR_setPosition(bullets[i].image, sx - off, sy);
}
static void updateBullet(u8 i){ static void updateBullet(u8 i){
if(bullets[i].explosion){
updateBulletExplosion(i);
return;
}
bullets[i].pos.x += bullets[i].vel.x; bullets[i].pos.x += bullets[i].vel.x;
bullets[i].pos.y += bullets[i].vel.y; bullets[i].pos.y += bullets[i].vel.y;
@ -152,10 +175,15 @@ static void updateBullet(u8 i){
fix32 dx = getWrappedDelta(bullets[i].pos.x, player.pos.x); fix32 dx = getWrappedDelta(bullets[i].pos.x, player.pos.x);
bool offScreenX = (dx < -CULL_LIMIT || dx > CULL_LIMIT); bool offScreenX = (dx < -CULL_LIMIT || dx > CULL_LIMIT);
bool offScreenY = (bullets[i].pos.y < FIX32(-16) || bullets[i].pos.y > GAME_H_F + FIX32(16)); bool offScreenTop = (bullets[i].pos.y < FIX32(-16));
bool offScreenBottom = (bullets[i].pos.y > GAME_H_F - FIX32(8));
if(offScreenX || offScreenY){ if(offScreenX || offScreenTop){
killBullet(i); killBullet(i, FALSE);
return;
}
if(offScreenBottom){
killBullet(i, TRUE);
return; return;
} }
if(bullets[i].clock > 0) bullets[i].updater(i); if(bullets[i].clock > 0) bullets[i].updater(i);

View file

@ -5,7 +5,8 @@ void loadEnemyOne(u8 i){
} }
void updateEnemyOne(u8 i){ void updateEnemyOne(u8 i){
if(enemies[i].clock % 60 == enemies[i].ints[0]){ if(enemies[i].clock % 60 == enemies[i].ints[0] && enemies[i].onScreen){
enemies[i].clock % 120 == enemies[i].ints[0] ? sfxEnemyShotB() : sfxEnemyShotA();
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,

View file

@ -62,7 +62,7 @@ struct bulletSpawner {
bool top, player; bool top, player;
}; };
struct bullet { struct bullet {
bool active, player, vFlip, hFlip; bool active, player, vFlip, hFlip, explosion;
Vect2D_f32 pos, vel; Vect2D_f32 pos, vel;
Sprite* image; Sprite* image;
s16 clock, angle, anim, frame; s16 clock, angle, anim, frame;
@ -87,9 +87,31 @@ struct enemy {
}; };
struct enemy enemies[ENEMY_COUNT]; struct enemy enemies[ENEMY_COUNT];
void killBullet(u8 i){ void killBullet(u8 i, bool explode){
bullets[i].active = FALSE; if(explode){
SPR_releaseSprite(bullets[i].image); if(bullets[i].player){
SPR_setAnim(bullets[i].image, 1);
} else {
s16 a = bullets[i].anim;
s16 explosionAnim;
if(a < FIRST_ROTATING_BULLET){
explosionAnim = 13 + bullets[i].frame;
} else {
s16 mod = a % 3;
explosionAnim = 13 + mod;
}
SPR_setAnim(bullets[i].image, explosionAnim);
}
bullets[i].clock = 0;
bullets[i].frame = 0;
bullets[i].explosion = TRUE;
SPR_setFrame(bullets[i].image, 0);
SPR_setHFlip(bullets[i].image, random() & 1);
// SPR_setVFlip(bullets[i].image, random() & 1);
} else {
bullets[i].active = FALSE;
SPR_releaseSprite(bullets[i].image);
}
} }
void killEnemy(u8 i){ void killEnemy(u8 i){

View file

@ -9,6 +9,7 @@
#include "stage.h" #include "stage.h"
#include "chrome.h" #include "chrome.h"
#include "start.h" #include "start.h"
#include "sfx.h"
static void loadInternals(){ static void loadInternals(){
JOY_init(); JOY_init();
@ -31,6 +32,7 @@ void loadGame(){
static void updateGame(){ static void updateGame(){
updateChrome(); updateChrome();
updatePlayer(); updatePlayer();
updateSfx();
if(clock % 2 == 0){ if(clock % 2 == 0){
updateEnemies(); updateEnemies();
} else { } else {

View file

@ -107,6 +107,7 @@ static void shootPlayer(){
.player = TRUE .player = TRUE
}; };
spawnBullet(spawner, EMPTY); spawnBullet(spawner, EMPTY);
sfxPlayerShot();
shotClock = SHOT_INTERVAL; shotClock = SHOT_INTERVAL;
} else if(shotClock > 0) shotClock--; } else if(shotClock > 0) shotClock--;
} }

80
src/sfx.h Normal file
View file

@ -0,0 +1,80 @@
static s16 sfxShotClock;
static u16 sfxShotFreq;
void sfxPlayerShot(){
sfxShotClock = 4;
sfxShotFreq = 150;
PSG_setEnvelope(2, 2);
PSG_setFrequency(2, sfxShotFreq);
}
static s16 sfxEnemyShotClock;
static u16 sfxEnemyShotFreq;
static u8 sfxEnemyShotType;
// high sharp zap - quick descending chirp
void sfxEnemyShotA(){
sfxEnemyShotClock = 3;
sfxEnemyShotFreq = 1200;
sfxEnemyShotType = 0;
PSG_setEnvelope(1, 3);
PSG_setFrequency(1, sfxEnemyShotFreq);
}
// mid buzzy pulse - sits in the midrange
void sfxEnemyShotB(){
sfxEnemyShotClock = 5;
sfxEnemyShotFreq = 400;
sfxEnemyShotType = 1;
PSG_setEnvelope(1, 3);
PSG_setFrequency(1, sfxEnemyShotFreq);
}
// quick rising ping - sweeps upward
void sfxEnemyShotC(){
sfxEnemyShotClock = 4;
sfxEnemyShotFreq = 300;
sfxEnemyShotType = 2;
PSG_setEnvelope(1, 3);
PSG_setFrequency(1, sfxEnemyShotFreq);
}
static s16 sfxExpClock;
void sfxExplosion(){
sfxExpClock = 18;
PSG_setNoise(PSG_NOISE_TYPE_WHITE, PSG_NOISE_FREQ_CLOCK2);
PSG_setEnvelope(3, 0);
}
void updateSfx(){
if(sfxExpClock > 0){
sfxExpClock--;
PSG_setEnvelope(3, (18 - sfxExpClock) * 15 / 18);
if(sfxExpClock == 0){
PSG_setEnvelope(3, 15);
}
}
if(sfxEnemyShotClock > 0){
sfxEnemyShotClock--;
if(sfxEnemyShotType == 0) sfxEnemyShotFreq -= 300;
else if(sfxEnemyShotType == 1) sfxEnemyShotFreq -= 50;
else sfxEnemyShotFreq += 150;
PSG_setFrequency(1, sfxEnemyShotFreq);
PSG_setEnvelope(1, 3 + (sfxEnemyShotType == 0 ? (3 - sfxEnemyShotClock) * 4 :
sfxEnemyShotType == 1 ? (5 - sfxEnemyShotClock) * 2 :
(4 - sfxEnemyShotClock) * 3));
if(sfxEnemyShotClock == 0){
PSG_setEnvelope(1, 15);
}
}
if(sfxShotClock > 0){
sfxShotClock--;
sfxShotFreq -= 30;
PSG_setFrequency(2, sfxShotFreq);
PSG_setEnvelope(2, 2 + (4 - sfxShotClock) * 3);
if(sfxShotClock == 0){
PSG_setEnvelope(2, 15);
}
}
}