#include "enemytypes.h" #define ENEMY_MIN_DIST FIX32(64) static bool isValidEnemyPosition(fix32 x, fix32 y) { for(s16 j = 0; j < ENEMY_COUNT; j++) { if(enemies[j].active) { fix32 dx = getWrappedDelta(x, enemies[j].pos.x); fix32 dy = y - enemies[j].pos.y; // Check if within 64px in both X and Y if(dx >= -ENEMY_MIN_DIST && dx <= ENEMY_MIN_DIST && dy >= -ENEMY_MIN_DIST && dy <= ENEMY_MIN_DIST) { return FALSE; // Too close to existing enemy } } } return TRUE; // Position is valid } void spawnEnemy(u8 type, u8 zone){ // Find available slot, return if none s16 i = -1; for(s16 j = 0; j < ENEMY_COUNT; j++) if(!enemies[j].active) { i = j; break; } if(i == -1) return; enemies[i].active = TRUE; enemies[i].type = type; // Calculate zone bounds (each zone is 512px) fix32 zoneStart = FIX32(zone * 512); fix32 randX, randY; u16 attempts = 0; do { // Random X within zone: zoneStart + random(0-511) randX = zoneStart + FIX32(random() % 512); randY = FIX32(16 + (random() % 192)); attempts++; } while(!isValidEnemyPosition(randX, randY) && attempts < 100); enemies[i].pos.x = randX; enemies[i].pos.y = randY; enemies[i].off = 16; enemies[i].image = SPR_addSprite(&butterflySprite, 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; enemies[i].speed = FIX32(1); 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); for(u8 j = 0; j < PROP_COUNT; j++){ enemies[i].ints[j] = 0; } enemies[i].ints[0] = random() % 20; } static void boundsEnemy(u8 i){ if(enemies[i].pos.y >= GAME_H_F - FIX32(enemies[i].off) || enemies[i].pos.y <= FIX32(enemies[i].off)) enemies[i].vel.y *= -1; if(enemies[i].pos.x >= GAME_WRAP){ enemies[i].pos.x -= GAME_WRAP; } if(enemies[i].pos.x < 0){ enemies[i].pos.x += GAME_WRAP; } } static void updateEnemy(u8 i){ boundsEnemy(i); enemies[i].pos.x += enemies[i].vel.x; enemies[i].pos.y += enemies[i].vel.y; switch(enemies[i].type){ case 0: updateEnemyOne(i); break; } 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); bool onScreen = (dx >= FIX32(-256) && dx <= FIX32(256)); SPR_setVisibility(enemies[i].image, onScreen ? VISIBLE : HIDDEN); SPR_setPosition(enemies[i].image, sx - enemies[i].off, sy - enemies[i].off); enemies[i].clock++; if(enemies[i].clock >= CLOCK_LIMIT) enemies[i].clock = 0; enemyCount++; } void updateEnemies(){ enemyCount = 0; for(s16 i = 0; i < ENEMY_COUNT; i++) if(enemies[i].active) updateEnemy(i); intToStr(enemyCount, debugStr, 1); }