null check to squash bug. some gfx

This commit is contained in:
t. boddy 2026-02-15 15:57:58 -05:00
parent 19258268b0
commit a3f0474ec9
11 changed files with 60 additions and 42 deletions

BIN
res/alice.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
res/fairy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
res/fairy2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View file

@ -7,9 +7,13 @@ IMAGE sky "sky.png" NONE NONE
IMAGE fadeTop "fadetop.png" NONE NONE IMAGE fadeTop "fadetop.png" NONE NONE
IMAGE fadeBottom "fadebottom.png" NONE NONE IMAGE fadeBottom "fadebottom.png" NONE NONE
SPRITE sakuyaSprite "sakuya.png" 4 4 NONE 0 // SPRITE sakuyaSprite "sakuya.png" 4 4 NONE 0
SPRITE sakuyaSprite "sakuya2.png" 6 6 NONE 0
SPRITE bulletsSprite "bullets.png" 2 2 NONE 0 SPRITE bulletsSprite "bullets.png" 2 2 NONE 0
SPRITE pBulletSprite "pbullet.png" 4 4 NONE 0 SPRITE pBulletSprite "pbullet.png" 4 4 NONE 0
SPRITE butterflySprite "butterfly.png" 4 4 NONE 8 SPRITE butterflySprite "butterfly.png" 4 4 NONE 8
// SPRITE fairySprite "fairy.png" 4 4 NONE 8
SPRITE fairySprite "fairy2.png" 4 4 NONE 8
SPRITE aliceSprite "alice.png" 6 6 NONE 0

BIN
res/sakuya2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

1
runblastem.sh Executable file
View file

@ -0,0 +1 @@
./blastem/blastem out/rom.bin

View file

@ -59,7 +59,7 @@ static void doBulletRotation(u8 i){
void spawnBullet(struct bulletSpawner spawner, void(*updater)){ void spawnBullet(struct bulletSpawner spawner, void(*updater)){
// Don't spawn if offscreen // Don't spawn if offscreen
fix32 dx = getWrappedDelta(spawner.x, player.pos.x); fix32 dx = getWrappedDelta(spawner.x, player.pos.x);
bool offScreenX = (dx < FIX32(-256) || dx > FIX32(256)); bool offScreenX = (dx < -CULL_LIMIT || dx > CULL_LIMIT);
bool offScreenY = (spawner.y < FIX32(-16) || spawner.y > GAME_H_F + FIX32(16)); bool offScreenY = (spawner.y < FIX32(-16) || spawner.y > GAME_H_F + FIX32(16));
if(offScreenX || offScreenY) return; if(offScreenX || offScreenY) return;
@ -91,6 +91,11 @@ void spawnBullet(struct bulletSpawner spawner, void(*updater)){
-32, -32, -32, -32,
TILE_ATTR(gameOver ? PAL1 : PAL0, 0, 0, spawner.player && spawner.angle == 512 ? 1 : 0)); TILE_ATTR(gameOver ? PAL1 : PAL0, 0, 0, spawner.player && spawner.angle == 512 ? 1 : 0));
if(!bullets[i].image){
bullets[i].active = FALSE;
return;
}
if(spawner.anim) SPR_setAnim(bullets[i].image, spawner.anim); if(spawner.anim) SPR_setAnim(bullets[i].image, spawner.anim);
bullets[i].anim = spawner.anim; bullets[i].anim = spawner.anim;
bullets[i].frame = spawner.frame; bullets[i].frame = spawner.frame;
@ -100,20 +105,17 @@ void spawnBullet(struct bulletSpawner spawner, void(*updater)){
doBulletRotation(i); doBulletRotation(i);
} }
s32 bulletDist;
#define BULLET_CHECK FIX32(32) #define BULLET_CHECK FIX32(32)
s32 bulletDist;
static void collideWithEnemy(u8 i){ static void collideWithEnemy(u8 i){
for(s16 j = 0; j < ENEMY_COUNT; j++) { for(s16 j = 0; j < ENEMY_COUNT; j++) {
if(enemies[j].active){ if(enemies[j].active && enemies[j].onScreen && bullets[i].active){
fix32 deltaX = getWrappedDelta(bullets[i].pos.x, enemies[j].pos.x); fix32 deltaX = getWrappedDelta(bullets[i].pos.x, enemies[j].pos.x);
fix32 deltaY = bullets[i].pos.y - enemies[j].pos.y; fix32 deltaY = bullets[i].pos.y - enemies[j].pos.y;
if(deltaY >= -BULLET_CHECK && deltaY <= BULLET_CHECK && if(deltaY >= -BULLET_CHECK && deltaY <= BULLET_CHECK &&
deltaX >= -BULLET_CHECK && deltaX <= BULLET_CHECK){ deltaX >= -BULLET_CHECK && deltaX <= BULLET_CHECK){
bulletDist = getApproximatedDistance( bulletDist = getApproximatedDistance(fix32ToInt(deltaX), fix32ToInt(deltaY));
fix32ToInt(deltaX), if(bulletDist <= bullets[i].dist){
fix32ToInt(deltaY));
if(bulletDist <= bullets[i].dist){
killBullet(i); killBullet(i);
killEnemy(j); killEnemy(j);
} }
@ -123,18 +125,16 @@ static void collideWithEnemy(u8 i){
} }
static void collideWithPlayer(u8 i){ static void collideWithPlayer(u8 i){
if(!bullets[i].player && bullets[i].active){ fix32 deltaX = getWrappedDelta(bullets[i].pos.x, player.pos.x);
fix32 deltaX = getWrappedDelta(bullets[i].pos.x, player.pos.x); fix32 deltaY = bullets[i].pos.y - player.pos.y;
fix32 deltaY = bullets[i].pos.y - player.pos.y;
s32 dist = getApproximatedDistance( s32 dist = getApproximatedDistance(
fix32ToInt(deltaX), fix32ToInt(deltaX),
fix32ToInt(deltaY)); fix32ToInt(deltaY));
if(dist <= 4){ if(dist <= 4){
killBullet(i); killBullet(i);
// player.lives--; // player.lives--;
// if(player.lives <= 0) gameOver = TRUE; // if(player.lives <= 0) gameOver = TRUE;
}
} }
} }
@ -150,7 +150,7 @@ 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 < FIX32(-256) || dx > FIX32(256)); 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 offScreenY = (bullets[i].pos.y < FIX32(-16) || bullets[i].pos.y > GAME_H_F + FIX32(16));
@ -167,11 +167,14 @@ static void updateBullet(u8 i){
u8 off = bullets[i].player ? P_BULLET_OFF : BULLET_OFF; u8 off = bullets[i].player ? P_BULLET_OFF : BULLET_OFF;
SPR_setPosition(bullets[i].image, sx - off, sy - off); SPR_setPosition(bullets[i].image, sx - off, sy - off);
bullets[i].clock++; bullets[i].clock++;
bulletCount++;
} }
} }
void updateBullets(){ void updateBullets(){
bulletCount = 0;
for(s16 i = 0; i < BULLET_COUNT; i++) if(bullets[i].active) for(s16 i = 0; i < BULLET_COUNT; i++) if(bullets[i].active)
updateBullet(i); updateBullet(i);
intToStr(bulletCount, debugStr, 1);
} }

View file

@ -41,12 +41,12 @@ void spawnEnemy(u8 type, u8 zone){
enemies[i].pos.x = randX; enemies[i].pos.x = randX;
enemies[i].pos.y = randY; enemies[i].pos.y = randY;
enemies[i].off = 16; enemies[i].off = 16;
enemies[i].image = SPR_addSprite(&butterflySprite, enemies[i].image = SPR_addSprite(&fairySprite,
getScreenX(enemies[i].pos.x, player.camera) - enemies[i].off, fix32ToInt(enemies[i].pos.y) - enemies[i].off, TILE_ATTR(gameOver ? PAL1 : PAL0, 0, 0, 0)); getScreenX(enemies[i].pos.x, player.camera) - enemies[i].off, fix32ToInt(enemies[i].pos.y) - enemies[i].off, TILE_ATTR(gameOver ? PAL1 : PAL0, 0, 0, 0));
enemies[i].angle = random() % 2 < 1 ? 128 : 384; if(!enemies[i].image){
enemies[i].speed = FIX32(1); enemies[i].active = FALSE;
enemies[i].vel.x = fix32Mul(fix16ToFix32(cosFix16(enemies[i].angle)), enemies[i].speed); return;
enemies[i].vel.y = fix32Mul(fix16ToFix32(sinFix16(enemies[i].angle)), enemies[i].speed); }
for(u8 j = 0; j < PROP_COUNT; j++){ for(u8 j = 0; j < PROP_COUNT; j++){
enemies[i].ints[j] = 0; enemies[i].ints[j] = 0;
} }
@ -55,6 +55,8 @@ void spawnEnemy(u8 type, u8 zone){
loadEnemyOne(i); loadEnemyOne(i);
break; break;
} }
enemies[i].vel.x = fix32Mul(fix16ToFix32(cosFix16(enemies[i].angle)), enemies[i].speed);
enemies[i].vel.y = fix32Mul(fix16ToFix32(sinFix16(enemies[i].angle)), enemies[i].speed);
} }
@ -84,8 +86,8 @@ static void updateEnemy(u8 i){
s16 sx = getScreenX(enemies[i].pos.x, player.camera); s16 sx = getScreenX(enemies[i].pos.x, player.camera);
s16 sy = fix32ToInt(enemies[i].pos.y); s16 sy = fix32ToInt(enemies[i].pos.y);
fix32 dx = getWrappedDelta(enemies[i].pos.x, player.pos.x); fix32 dx = getWrappedDelta(enemies[i].pos.x, player.pos.x);
bool onScreen = (dx >= FIX32(-256) && dx <= FIX32(256)); enemies[i].onScreen = (dx >= -CULL_LIMIT && dx <= CULL_LIMIT);
SPR_setVisibility(enemies[i].image, onScreen ? VISIBLE : HIDDEN); SPR_setVisibility(enemies[i].image, enemies[i].onScreen ? VISIBLE : HIDDEN);
SPR_setPosition(enemies[i].image, sx - enemies[i].off, sy - enemies[i].off); SPR_setPosition(enemies[i].image, sx - enemies[i].off, sy - enemies[i].off);
enemies[i].clock++; enemies[i].clock++;
@ -97,5 +99,5 @@ void updateEnemies(){
enemyCount = 0; enemyCount = 0;
for(s16 i = 0; i < ENEMY_COUNT; i++) if(enemies[i].active) for(s16 i = 0; i < ENEMY_COUNT; i++) if(enemies[i].active)
updateEnemy(i); updateEnemy(i);
intToStr(enemyCount, debugStr, 1); // intToStr(enemyCount, debugStr, 1);
} }

View file

@ -1,5 +1,7 @@
void loadEnemyOne(u8 i){ void loadEnemyOne(u8 i){
enemies[i].ints[0] = random() % 60; enemies[i].ints[0] = random() % 60;
enemies[i].angle = ((random() % 4) * 256) + 128;
enemies[i].speed = FIX32(2);
} }
void updateEnemyOne(u8 i){ void updateEnemyOne(u8 i){
@ -7,15 +9,16 @@ void updateEnemyOne(u8 i){
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,
.anim = 6 + (random() % 3), // .anim = 6 + (random() % 3),
.anim = 6,
// .frame = 1, // .frame = 1,
.speed = FIX32(4), .speed = FIX32(2) + FIX16(random() % 4),
.angle = random() % 256, .angle = random() % 128,
}; };
if(random() % 2 < 1) spawner.anim += 3; // if(random() % 2 < 1) spawner.anim += 3;
for(u8 j = 0; j < 4; j++){ for(u8 j = 0; j < 8; j++){
spawnBullet(spawner, EMPTY); spawnBullet(spawner, EMPTY);
spawner.angle += 256; spawner.angle += 128;
} }
} }
} }

View file

@ -8,6 +8,8 @@ u32 clock;
#define SECTION_COUNT 4 #define SECTION_COUNT 4
#define GAME_WRAP (SECTION_SIZE * SECTION_COUNT) #define GAME_WRAP (SECTION_SIZE * SECTION_COUNT)
#define CULL_LIMIT FIX32(240)
u32 score; u32 score;
#define SCORE_LENGTH 8 #define SCORE_LENGTH 8
@ -17,7 +19,7 @@ char debugStr[8];
void EMPTY(s16 i){(void)i;} void EMPTY(s16 i){(void)i;}
bool gameOver; bool gameOver;
s16 enemyCount; s16 enemyCount, bulletCount;
// controls // controls
struct controls { struct controls {
@ -44,7 +46,7 @@ struct playerStruct {
Vect2D_f32 pos, vel; Vect2D_f32 pos, vel;
s16 shotAngle; s16 shotAngle;
u8 lives; u8 lives;
fix32 camera; fix32 camera, yCamera;
Sprite* image; Sprite* image;
}; };
struct playerStruct player; struct playerStruct player;
@ -71,10 +73,10 @@ struct bullet bullets[BULLET_COUNT];
// enemies // enemies
#define ENEMY_COUNT 24 #define ENEMY_COUNT 16
struct enemy { struct enemy {
bool active; bool active, onScreen;
u8 type; u8 type;
s16 angle, off; s16 angle, off;
u32 clock; u32 clock;

View file

@ -5,7 +5,7 @@
#define PLAYER_ACCEL PLAYER_SPEED >> 3 #define PLAYER_ACCEL PLAYER_SPEED >> 3
#define PLAYER_ACCEL_FOCUS PLAYER_SPEED_FOCUS >> 3 #define PLAYER_ACCEL_FOCUS PLAYER_SPEED_FOCUS >> 3
#define PLAYER_OFF 16 #define PLAYER_OFF 24
#define PLAYER_BOUND_Y FIX32(PLAYER_OFF) #define PLAYER_BOUND_Y FIX32(PLAYER_OFF)
#define PLAYER_BOUND_H FIX32(224 - PLAYER_OFF) #define PLAYER_BOUND_H FIX32(224 - PLAYER_OFF)
@ -84,6 +84,8 @@ static void boundsPlayer(){
player.camera += GAME_WRAP; player.camera += GAME_WRAP;
} }
player.yCamera = (fix32ToInt(player.pos.y) - FIX16(112)) >> 2;
} }
static void cameraPlayer(){ static void cameraPlayer(){
@ -120,6 +122,7 @@ void loadPlayer(){
fix32ToInt(player.pos.x) - PLAYER_OFF, fix32ToInt(player.pos.x) - PLAYER_OFF,
fix32ToInt(player.pos.y) - PLAYER_OFF, fix32ToInt(player.pos.y) - PLAYER_OFF,
TILE_ATTR(PAL0, 0, 0, 0)); TILE_ATTR(PAL0, 0, 0, 0));
player.yCamera = (fix32ToInt(player.pos.y) - FIX16(112)) >> 2;
} }
void updatePlayer(){ void updatePlayer(){
@ -134,5 +137,5 @@ void updatePlayer(){
SPR_setPosition(player.image, sx - PLAYER_OFF, sy - PLAYER_OFF); SPR_setPosition(player.image, sx - PLAYER_OFF, sy - PLAYER_OFF);
intToStr(fix32ToInt(player.pos.x), debugStr, 1); // intToStr(fix32ToInt(player.pos.x), debugStr, 1);
} }