enemy spawning etc
This commit is contained in:
parent
b2c0eaf30b
commit
11547e9d13
6 changed files with 109 additions and 54 deletions
|
|
@ -57,36 +57,47 @@ static void doBulletRotation(u8 i){
|
|||
}
|
||||
|
||||
void spawnBullet(struct bulletSpawner spawner, void(*updater)){
|
||||
// Don't spawn if offscreen
|
||||
fix32 dx = getWrappedDelta(spawner.x, player.pos.x);
|
||||
bool offScreenX = (dx < FIX32(-256) || dx > FIX32(256));
|
||||
bool offScreenY = (spawner.y < FIX32(-16) || spawner.y > GAME_H_F + FIX32(16));
|
||||
if(offScreenX || offScreenY) return;
|
||||
|
||||
// Find available slot, return if none
|
||||
s16 i = -1;
|
||||
for(s16 j = 0; j < BULLET_COUNT; j++) if(!bullets[j].active && i == -1) i = j;
|
||||
if(i > -1){
|
||||
bullets[i].active = TRUE;
|
||||
bullets[i].pos.x = spawner.x;
|
||||
bullets[i].pos.y = spawner.y;
|
||||
bullets[i].angle = spawner.angle;
|
||||
bullets[i].player = spawner.player;
|
||||
bullets[i].clock = 0;
|
||||
if(spawner.vel.x || spawner.vel.y){
|
||||
bullets[i].vel.x = spawner.vel.x;
|
||||
bullets[i].vel.y = spawner.vel.y;
|
||||
} else {
|
||||
bullets[i].vel.x = fix32Mul(fix16ToFix32(cosFix16(spawner.angle)), spawner.speed);
|
||||
bullets[i].vel.y = fix32Mul(fix16ToFix32(sinFix16(spawner.angle)), spawner.speed);
|
||||
}
|
||||
bullets[i].updater = updater;
|
||||
bullets[i].dist = bullets[i].player ? 16 : (spawner.anim == 0 ? 4 : 7);
|
||||
bullets[i].image = SPR_addSprite(spawner.player ? &pBulletSprite : &bulletsSprite,
|
||||
getScreenX(bullets[i].pos.x, player.camera) - (spawner.player ? P_BULLET_OFF : BULLET_OFF),
|
||||
fix32ToInt(bullets[i].pos.y) - (spawner.player ? P_BULLET_OFF : BULLET_OFF),
|
||||
TILE_ATTR(gameOver ? PAL1 : PAL0, 0, 0, spawner.player && spawner.angle == 512 ? 1 : 0));
|
||||
if(spawner.anim) SPR_setAnim(bullets[i].image, spawner.anim);
|
||||
bullets[i].anim = spawner.anim;
|
||||
bullets[i].frame = spawner.frame;
|
||||
SPR_setFrame(bullets[i].image, spawner.frame);
|
||||
SPR_setAnim(bullets[i].image, spawner.anim);
|
||||
SPR_setDepth(bullets[i].image, spawner.player ? 7 : (spawner.top ? 3 : 4));
|
||||
doBulletRotation(i);
|
||||
for(s16 j = 0; j < BULLET_COUNT; j++) if(!bullets[j].active) { i = j; break; }
|
||||
if(i == -1) return;
|
||||
|
||||
bullets[i].active = TRUE;
|
||||
bullets[i].pos.x = spawner.x;
|
||||
bullets[i].pos.y = spawner.y;
|
||||
bullets[i].angle = spawner.angle;
|
||||
bullets[i].player = spawner.player;
|
||||
bullets[i].clock = 0;
|
||||
if(spawner.vel.x || spawner.vel.y){
|
||||
bullets[i].vel.x = spawner.vel.x;
|
||||
bullets[i].vel.y = spawner.vel.y;
|
||||
} else {
|
||||
bullets[i].vel.x = fix32Mul(fix16ToFix32(cosFix16(spawner.angle)), spawner.speed);
|
||||
bullets[i].vel.y = fix32Mul(fix16ToFix32(sinFix16(spawner.angle)), spawner.speed);
|
||||
}
|
||||
bullets[i].updater = updater;
|
||||
bullets[i].dist = bullets[i].player ? 16 : (spawner.anim == 0 ? 4 : 7);
|
||||
|
||||
u8 off = bullets[i].player ? P_BULLET_OFF : BULLET_OFF;
|
||||
s16 sx = getScreenX(bullets[i].pos.x, player.camera);
|
||||
s16 sy = fix32ToInt(bullets[i].pos.y);
|
||||
bullets[i].image = SPR_addSprite(spawner.player ? &pBulletSprite : &bulletsSprite,
|
||||
-32, -32,
|
||||
TILE_ATTR(gameOver ? PAL1 : PAL0, 0, 0, spawner.player && spawner.angle == 512 ? 1 : 0));
|
||||
|
||||
if(spawner.anim) SPR_setAnim(bullets[i].image, spawner.anim);
|
||||
bullets[i].anim = spawner.anim;
|
||||
bullets[i].frame = spawner.frame;
|
||||
SPR_setFrame(bullets[i].image, spawner.frame);
|
||||
SPR_setAnim(bullets[i].image, spawner.anim);
|
||||
SPR_setDepth(bullets[i].image, spawner.player ? 7 : (spawner.top ? 3 : 4));
|
||||
doBulletRotation(i);
|
||||
}
|
||||
|
||||
s32 bulletDist;
|
||||
|
|
|
|||
|
|
@ -1,20 +1,53 @@
|
|||
void spawnEnemy(u8 type){
|
||||
(void)type; // Unused parameter, kept for API compatibility
|
||||
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].type = type;
|
||||
enemies[i].pos.x = FIX32(64);
|
||||
enemies[i].pos.y = FIX32(64);
|
||||
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 = 128;
|
||||
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);
|
||||
#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() % 45;
|
||||
}
|
||||
|
||||
static void boundsEnemy(u8 i){
|
||||
|
|
@ -43,13 +76,13 @@ static void updateEnemy(u8 i){
|
|||
|
||||
SPR_setPosition(enemies[i].image, sx - enemies[i].off, sy - enemies[i].off);
|
||||
|
||||
if(enemies[i].clock % 45 == 0){
|
||||
if(enemies[i].clock % 45 == enemies[i].ints[0]){
|
||||
struct bulletSpawner spawner = {
|
||||
.x = enemies[i].pos.x,
|
||||
.y = enemies[i].pos.y,
|
||||
.anim = 7,
|
||||
// .frame = 1,
|
||||
.speed = FIX32(2),
|
||||
.speed = FIX32(4),
|
||||
.angle = random() % 128,
|
||||
};
|
||||
for(u8 j = 0; j < 8; j++){
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
u32 clock;
|
||||
#define CLOCK_LIMIT 32000
|
||||
#define PROP_COUNT 4
|
||||
|
||||
#define GAME_H_F FIX32(224)
|
||||
|
||||
|
|
@ -70,7 +71,7 @@ struct bullet bullets[BULLET_COUNT];
|
|||
|
||||
|
||||
// enemies
|
||||
#define ENEMY_COUNT 16
|
||||
#define ENEMY_COUNT 24
|
||||
|
||||
struct enemy {
|
||||
bool active;
|
||||
|
|
@ -80,6 +81,7 @@ struct enemy {
|
|||
fix32 speed;
|
||||
Vect2D_f32 vel, pos;
|
||||
Sprite* image;
|
||||
s16 ints[PROP_COUNT];
|
||||
};
|
||||
struct enemy enemies[ENEMY_COUNT];
|
||||
|
||||
|
|
|
|||
10
src/main.c
10
src/main.c
|
|
@ -8,6 +8,7 @@
|
|||
#include "player.h"
|
||||
#include "stage.h"
|
||||
#include "chrome.h"
|
||||
#include "start.h"
|
||||
|
||||
static void loadInternals(){
|
||||
JOY_init();
|
||||
|
|
@ -29,10 +30,13 @@ void loadGame(){
|
|||
|
||||
static void updateGame(){
|
||||
updateChrome();
|
||||
updateBackground();
|
||||
updateEnemies();
|
||||
updatePlayer();
|
||||
updateBullets();
|
||||
if(clock % 2 == 0){
|
||||
updateEnemies();
|
||||
} else {
|
||||
updateBackground();
|
||||
updateBullets();
|
||||
}
|
||||
}
|
||||
|
||||
int main(bool hardReset){
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#define PLAYER_SPEED FIX32(5)
|
||||
#define PLAYER_SPEED FIX32(4)
|
||||
|
||||
#define PLAYER_SPEED_FOCUS FIX32(3)
|
||||
#define PLAYER_SPEED_FOCUS FIX32(2.5)
|
||||
|
||||
#define PLAYER_ACCEL PLAYER_SPEED >> 3
|
||||
#define PLAYER_ACCEL_FOCUS PLAYER_SPEED_FOCUS >> 3
|
||||
|
|
@ -100,7 +100,7 @@ static void shootPlayer(){
|
|||
.x = player.pos.x,
|
||||
.y = player.pos.y,
|
||||
.anim = 0,
|
||||
.speed = FIX32(12),
|
||||
.speed = FIX32(24),
|
||||
.angle = player.shotAngle,
|
||||
.player = TRUE
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
void loadStage(){
|
||||
spawnEnemy(0);
|
||||
// Spawn 2 enemies per zone (4 zones = 8 total)
|
||||
for(u8 zone = 0; zone < 4; zone++){
|
||||
for(u8 i = 0; i < 2; i++){
|
||||
spawnEnemy(0, zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue