From 0151304d0568a0027bc3e176904ad8eac16be52b Mon Sep 17 00:00:00 2001 From: Trevor Boddy Date: Tue, 17 Feb 2026 15:10:28 -0500 Subject: [PATCH] gfx, shit --- src/chrome.h | 58 +++++++++++++++++++++++++++++++++++++++++++++--- src/enemies.h | 22 ++++++++++++------ src/enemytypes.h | 6 ++--- src/global.h | 7 +++++- src/humans.h | 44 +++++++++++++++++++++++++++++++----- src/main.c | 25 ++++++++++++--------- src/player.h | 4 ++-- src/start.h | 7 ++++++ 8 files changed, 140 insertions(+), 33 deletions(-) diff --git a/src/chrome.h b/src/chrome.h index a82bc22..b3ec46c 100644 --- a/src/chrome.h +++ b/src/chrome.h @@ -95,7 +95,8 @@ static void updateMap(){ // compute new enemy positions for(s16 i = 0; i < ENEMY_COUNT; i++){ - if(!enemies[i].active || enemies[i].image == NULL){ + if(!enemies[i].active || enemies[i].image == NULL + || enemies[i].pos.y < FIX32(0) || enemies[i].pos.y > GAME_H_F){ mapNewCol[i] = -1; mapNewRow[i] = -1; continue; @@ -113,7 +114,7 @@ static void updateMap(){ // compute new human positions for(s16 i = 0; i < HUMAN_COUNT; i++){ - if(!humans[i].active || humans[i].image == NULL){ + if(!humans[i].active || humans[i].image == NULL || humans[i].state == HUMAN_COLLECTED){ mapNewHumanCol[i] = -1; mapNewHumanRow[i] = -1; continue; @@ -185,6 +186,7 @@ void loadChrome(){ } bool didGameOver; +u32 gameOverClock; static void doGameOver(){ didGameOver = TRUE; for(s16 i = 0; i < BULLET_COUNT; i++) if(bullets[i].active) SPR_setPalette(bullets[i].image, PAL1); @@ -203,9 +205,59 @@ static void doGameOver(){ VDP_drawText("PRESS ANY BUTTON", 12, 14); } +static void showPause(){ + for(s16 i = 0; i < BULLET_COUNT; i++) if(bullets[i].active) SPR_setPalette(bullets[i].image, PAL1); + for(s16 i = 0; i < ENEMY_COUNT; i++) if(enemies[i].active) SPR_setPalette(enemies[i].image, PAL1); + for(s16 i = 0; i < HUMAN_COUNT; i++) if(humans[i].active) SPR_setPalette(humans[i].image, PAL1); + SPR_setPalette(player.image, PAL1); + VDP_drawText("PAUSE", 17, 13); +} + +static void clearPause(){ + for(s16 i = 0; i < BULLET_COUNT; i++) if(bullets[i].active) SPR_setPalette(bullets[i].image, PAL0); + for(s16 i = 0; i < ENEMY_COUNT; i++) if(enemies[i].active) SPR_setPalette(enemies[i].image, PAL0); + for(s16 i = 0; i < HUMAN_COUNT; i++) if(humans[i].active) SPR_setPalette(humans[i].image, PAL0); + SPR_setPalette(player.image, PAL0); + VDP_clearText(17, 13, 5); +} + +u32 pauseClock; +static void updatePause(){ + if(gameOver) return; + if(ctrl.start){ + if(!isPausing){ + isPausing = TRUE; + if(!paused){ + pauseClock = 0; + paused = TRUE; + showPause(); + } else { + paused = FALSE; + clearPause(); + } + } + } else { + isPausing = FALSE; + } + if(paused){ + if(pauseClock % 60 < 30) + VDP_drawText("PAUSE", 17, 13); + else + VDP_clearText(17, 13, 5); + pauseClock++; + if(pauseClock >= 240) pauseClock = 0; + } +} + void updateChrome(){ + updatePause(); if(gameOver && !didGameOver) doGameOver(); - if(didGameOver) return; + if(didGameOver){ + gameOverClock++; + if((gameOverClock > 120 && (ctrl.a || ctrl.b || ctrl.c || ctrl.start)) || gameOverClock > 900) + SYS_hardReset(); + return; + } if(lastScore != score){ lastScore = score; drawScore(); diff --git a/src/enemies.h b/src/enemies.h index 1bc4039..1050fca 100644 --- a/src/enemies.h +++ b/src/enemies.h @@ -62,9 +62,16 @@ void spawnEnemy(u8 type, u8 zone){ static void boundsEnemy(u8 i){ if(enemies[i].ints[3] >= 0){ + s16 h = enemies[i].ints[3]; + // if the human was collected by player or gone, kill this enemy + if(!humans[h].active || humans[h].state == HUMAN_COLLECTED){ + enemies[i].ints[3] = -1; + humanBeingCarried = FALSE; + killEnemy(i); + return; + } // carrying: only check for reaching the top - if(enemies[i].pos.y <= FIX32(0)){ - s16 h = enemies[i].ints[3]; + else if(enemies[i].pos.y <= FIX32(0)){ if(humans[h].active) killHuman(h); enemies[i].ints[3] = -1; humanBeingCarried = FALSE; @@ -90,19 +97,20 @@ static void updateEnemy(u8 i){ enemies[i].pos.x += enemies[i].vel.x; enemies[i].pos.y += enemies[i].vel.y; + boundsEnemy(i); + if(!enemies[i].active) return; + + fix32 dx = getWrappedDelta(enemies[i].pos.x, player.pos.x); + enemies[i].onScreen = (dx >= -CULL_LIMIT && dx <= CULL_LIMIT); + switch(enemies[i].type){ case 0: updateEnemyOne(i); break; } - boundsEnemy(i); - if(!enemies[i].active) return; - s16 sx = getScreenX(enemies[i].pos.x, player.camera); s16 sy = fix32ToInt(enemies[i].pos.y); - fix32 dx = getWrappedDelta(enemies[i].pos.x, player.pos.x); - enemies[i].onScreen = (dx >= -CULL_LIMIT && dx <= CULL_LIMIT); SPR_setVisibility(enemies[i].image, enemies[i].onScreen ? VISIBLE : HIDDEN); SPR_setPosition(enemies[i].image, sx - enemies[i].off, sy - enemies[i].off); diff --git a/src/enemytypes.h b/src/enemytypes.h index 7d83041..f107ff3 100644 --- a/src/enemytypes.h +++ b/src/enemytypes.h @@ -70,13 +70,13 @@ void updateEnemyOne(u8 i){ } // normal shooting - if(enemies[i].clock % 60 == enemies[i].ints[0] && enemies[i].onScreen){ - enemies[i].clock % 120 == enemies[i].ints[0] ? sfxEnemyShotB() : sfxEnemyShotA(); + if(enemies[i].clock % 20 == enemies[i].ints[0] && enemies[i].onScreen){ + enemies[i].clock % 40 == enemies[i].ints[0] ? sfxEnemyShotB() : sfxEnemyShotA(); struct bulletSpawner spawner = { .x = enemies[i].pos.x, .y = enemies[i].pos.y, .anim = 3 + (random() % 3), - .speed = FIX32(2) + FIX16(random() % 4), + .speed = FIX32(4) + FIX32(random() % 4), .angle = random() % 128, }; switch(random() % 3){ diff --git a/src/global.h b/src/global.h index ba83d82..a323e45 100644 --- a/src/global.h +++ b/src/global.h @@ -23,7 +23,9 @@ u32 score; char debugStr[8]; void EMPTY(s16 i){(void)i;} +bool started; bool gameOver; +bool paused, isPausing; s16 enemyCount, bulletCount; // controls @@ -98,16 +100,19 @@ struct enemy enemies[ENEMY_COUNT]; #define HUMAN_WALKING 0 #define HUMAN_CARRIED 1 #define HUMAN_FALLING 2 +#define HUMAN_COLLECTED 3 struct human { bool active; u8 state; s16 carriedBy; + s16 trailIndex; Vect2D_f32 pos, vel; Sprite* image; }; struct human humans[HUMAN_COUNT]; bool humanBeingCarried; +s16 collectedCount; void killHuman(u8 i){ if(humans[i].state == HUMAN_CARRIED && humans[i].carriedBy >= 0){ @@ -152,7 +157,7 @@ void killEnemy(u8 i){ humans[h].state = HUMAN_FALLING; humans[h].carriedBy = -1; humans[h].vel.x = 0; - humans[h].vel.y = FIX32(2); + humans[h].vel.y = FIX32(3); } humanBeingCarried = FALSE; } diff --git a/src/humans.h b/src/humans.h index 633bb84..49db304 100644 --- a/src/humans.h +++ b/src/humans.h @@ -1,3 +1,5 @@ +#define HUMAN_OFF 16 + void spawnHuman(u8 zone){ s16 i = -1; @@ -16,8 +18,8 @@ void spawnHuman(u8 zone){ humans[i].vel.x = (random() % 2 == 0) ? speeds[random() % 3] : -speeds[random() % 3]; humans[i].vel.y = (random() % 2 == 0) ? FIX32(0.1) : FIX32(-0.1); - humans[i].image = SPR_addSprite(&humanSprite, - getScreenX(humans[i].pos.x, player.camera), fix32ToInt(humans[i].pos.y), + humans[i].image = SPR_addSprite(&koaSprite, + getScreenX(humans[i].pos.x, player.camera) - HUMAN_OFF, fix32ToInt(humans[i].pos.y) - HUMAN_OFF, TILE_ATTR(PAL0, 0, 0, 0)); if(!humans[i].image){ humans[i].active = FALSE; @@ -52,7 +54,7 @@ static void updateHuman(u8 i){ humans[i].state = HUMAN_FALLING; humans[i].carriedBy = -1; humans[i].vel.x = 0; - humans[i].vel.y = FIX32(2); + humans[i].vel.y = FIX32(3); humanBeingCarried = FALSE; } break; @@ -68,16 +70,46 @@ static void updateHuman(u8 i){ humans[i].vel.y = (random() % 2 == 0) ? FIX32(0.1) : FIX32(-0.1); } break; + + case HUMAN_COLLECTED: { + fix32 targetX, targetY; + if(humans[i].trailIndex == 0){ + targetX = player.pos.x; + targetY = player.pos.y + FIX32(24); + } else { + // find the human ahead in the chain + targetX = player.pos.x; + targetY = player.pos.y + FIX32(24); + for(s16 j = 0; j < HUMAN_COUNT; j++){ + if(humans[j].active && humans[j].state == HUMAN_COLLECTED + && humans[j].trailIndex == humans[i].trailIndex - 1){ + targetX = humans[j].pos.x; + targetY = humans[j].pos.y + FIX32(8); + break; + } + } + } + fix32 deltaX = getWrappedDelta(targetX, humans[i].pos.x); + humans[i].pos.x += deltaX >> 2; + humans[i].pos.y += (targetY - humans[i].pos.y) >> 2; + // X wrap + if(humans[i].pos.x >= GAME_WRAP) + humans[i].pos.x -= GAME_WRAP; + if(humans[i].pos.x < 0) + humans[i].pos.x += GAME_WRAP; + break; + } } // collect: check overlap with player (walking or falling only) fix32 dx = getWrappedDelta(humans[i].pos.x, player.pos.x); - if(humans[i].state != HUMAN_CARRIED){ + if(humans[i].state != HUMAN_CARRIED && humans[i].state != HUMAN_COLLECTED){ fix32 dy = humans[i].pos.y - player.pos.y; if(dx >= FIX32(-24) && dx <= FIX32(24) && dy >= FIX32(-24) && dy <= FIX32(24)){ score += (humans[i].state == HUMAN_FALLING) ? 2000 : 1000; sfxPickup(); - killHuman(i); + humans[i].state = HUMAN_COLLECTED; + humans[i].trailIndex = collectedCount++; return; } } @@ -86,7 +118,7 @@ static void updateHuman(u8 i){ s16 sy = fix32ToInt(humans[i].pos.y); bool visible = (dx >= -CULL_LIMIT && dx <= CULL_LIMIT); SPR_setVisibility(humans[i].image, visible ? VISIBLE : HIDDEN); - SPR_setPosition(humans[i].image, sx, sy); + SPR_setPosition(humans[i].image, sx - HUMAN_OFF, sy - HUMAN_OFF); } void updateHumans(){ diff --git a/src/main.c b/src/main.c index 896b72c..bfdbaa3 100644 --- a/src/main.c +++ b/src/main.c @@ -28,28 +28,31 @@ void loadGame(){ loadPlayer(); loadChrome(); loadStage(); + started = TRUE; } static void updateGame(){ updateChrome(); - updatePlayer(); updateSfx(); - if(clock % 2 == 0){ - updateEnemies(); - if(!gameOver && enemyCount == 0) gameOver = TRUE; - updateHumans(); - } else { - updateBackground(); - updateBullets(); + if(!paused){ + updatePlayer(); + if(clock % 2 == 0){ + updateEnemies(); + if(!gameOver && enemyCount == 0) gameOver = TRUE; + updateHumans(); + } else { + updateBackground(); + updateBullets(); + } } } int main(bool hardReset){ loadInternals(); - loadGame(); - // loadStart(); + loadStart(); while(1){ - updateGame(); + if(started) updateGame(); + else updateStart(); clock++; if(clock >= CLOCK_LIMIT) clock = 600; SPR_update(); diff --git a/src/player.h b/src/player.h index 607dff1..12b06f4 100644 --- a/src/player.h +++ b/src/player.h @@ -1,6 +1,6 @@ -#define PLAYER_SPEED FIX32(4) +#define PLAYER_SPEED FIX32(5) -#define PLAYER_SPEED_FOCUS FIX32(2.5) +#define PLAYER_SPEED_FOCUS FIX32(3) #define PLAYER_ACCEL PLAYER_SPEED >> 3 #define PLAYER_ACCEL_FOCUS PLAYER_SPEED_FOCUS >> 3 diff --git a/src/start.h b/src/start.h index 1842d2e..6ed936c 100644 --- a/src/start.h +++ b/src/start.h @@ -4,4 +4,11 @@ void loadStart(){ VDP_drawImageEx(BG_A, &logo, TILE_ATTR_FULL(PAL0, 0, 0, 0, START_I), 6, 10, FALSE, FALSE); VDP_drawText("press any button", 12, 16); VDP_drawText(" 2026 T.BODDY ", 12, 18); +} + +void updateStart(){ + if(ctrl.a || ctrl.b || ctrl.c || ctrl.start){ + VDP_clearTileMapRect(BG_A, 0, 0, 40, 28); + loadGame(); + } } \ No newline at end of file