// enemies // lifecycle void spawnEnemy(struct enemySpawner spawner, void(*updater), void(*suicide)){ s16 i = -1; for(s16 j = 0; j < ENEMY_COUNT; j++) if(!enemies[j].active && i == -1) i = j; if(i > -1){ enemies[i].active = TRUE; enemies[i].off.x = FIX16(spawner.offX); enemies[i].off.y = FIX16(spawner.offY); enemies[i].pos.x = FIX16(spawner.x); enemies[i].pos.y = FIX16(spawner.y); enemies[i].dist = intToFix32(spawner.offX - 2); enemies[i].speed = spawner.speed; enemies[i].angle = spawner.angle; enemies[i].boss = spawner.boss; enemies[i].shotClock = 0; enemies[i].dead = FALSE; enemies[i].health = spawner.health ? spawner.health : 1; if(spawner.vel.x && spawner.vel.y){ enemies[i].vel.x = spawner.vel.x; enemies[i].vel.y = spawner.vel.y; } else { enemies[i].vel.x = fix16Mul(cosFix16(spawner.angle), spawner.speed); enemies[i].vel.y = fix16Mul(sinFix16(spawner.angle), spawner.speed); } for(s16 j = 0; j < COUNT_INT; j++){ enemies[i].bools[j] = spawner.bools[j]; enemies[i].ints[j] = spawner.ints[j]; enemies[i].fixes[j] = spawner.fixes[j]; } enemies[i].updater = updater; enemies[i].suicide = suicide; enemies[i].clock = 0; enemies[i].seen = FALSE; enemies[i].image = SPR_addSprite(spawner.image, fix16ToInt(fix16Sub(enemies[i].pos.x, enemies[i].off.x)), fix16ToInt(fix16Sub(enemies[i].pos.y, enemies[i].off.y)), TILE_ATTR(PAL1, 0, 0, 0)); SPR_setAnim(enemies[i].image, spawner.anim ? spawner.anim : 0); SPR_setFrame(enemies[i].image, spawner.frame ? spawner.frame : 0); SPR_setDepth(enemies[i].image, 5); SPR_setVisibility(enemies[i].image, HIDDEN); } } void killEnemy(s16 i){ enemies[i].dead = TRUE; } // helpers void updateEnemyVel(s16 i){ enemies[i].vel.x = fix16Mul(cosFix16(enemies[i].angle), enemies[i].speed); enemies[i].vel.y = fix16Mul(sinFix16(enemies[i].angle), enemies[i].speed); } // loop static void updateEnemy(s16 i){ if(enemies[i].seen && (enemies[i].pos.x < fix16Sub(0, enemies[i].off.x) || enemies[i].pos.x > fix16Add(FIX16(GAME_W), enemies[i].off.x) || enemies[i].pos.y < fix16Sub(0, enemies[i].off.y) || enemies[i].pos.y > fix16Add(FIX16(GAME_H), enemies[i].off.y))){ killEnemy(i); enemies[i].suicide(i); } else { if(!enemies[i].seen && enemies[i].pos.x <= fix16Add(FIX16(GAME_W), enemies[i].off.x)){ enemies[i].seen = TRUE; SPR_setVisibility(enemies[i].image, VISIBLE); } enemies[i].pos.x = fix16Add(enemies[i].pos.x, enemies[i].vel.x); enemies[i].pos.y = fix16Add(enemies[i].pos.y, enemies[i].vel.y); if(enemies[i].seen){ enemies[i].updater(i); if(enemies[i].boss) bossHealth = enemies[i].health; // collideEnemy(i); enemies[i].clock++; if(enemies[i].clock >= CLOCK_LIMIT) enemies[i].clock -= CLOCK_LIMIT; SPR_setPosition(enemies[i].image, fix16ToInt(fix16Sub(enemies[i].pos.x, enemies[i].off.x)), fix16ToInt(fix16Sub(enemies[i].pos.y, enemies[i].off.y))); } } if(enemies[i].dead){ enemies[i].active = FALSE; SPR_releaseSprite(enemies[i].image); } } void updateEnemies(){ for(s16 i = 0; i < ENEMY_COUNT; i++) if(enemies[i].active) updateEnemy(i); }