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)){
|
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;
|
s16 i = -1;
|
||||||
for(s16 j = 0; j < BULLET_COUNT; j++) if(!bullets[j].active && i == -1) i = j;
|
for(s16 j = 0; j < BULLET_COUNT; j++) if(!bullets[j].active) { i = j; break; }
|
||||||
if(i > -1){
|
if(i == -1) return;
|
||||||
bullets[i].active = TRUE;
|
|
||||||
bullets[i].pos.x = spawner.x;
|
bullets[i].active = TRUE;
|
||||||
bullets[i].pos.y = spawner.y;
|
bullets[i].pos.x = spawner.x;
|
||||||
bullets[i].angle = spawner.angle;
|
bullets[i].pos.y = spawner.y;
|
||||||
bullets[i].player = spawner.player;
|
bullets[i].angle = spawner.angle;
|
||||||
bullets[i].clock = 0;
|
bullets[i].player = spawner.player;
|
||||||
if(spawner.vel.x || spawner.vel.y){
|
bullets[i].clock = 0;
|
||||||
bullets[i].vel.x = spawner.vel.x;
|
if(spawner.vel.x || spawner.vel.y){
|
||||||
bullets[i].vel.y = spawner.vel.y;
|
bullets[i].vel.x = spawner.vel.x;
|
||||||
} else {
|
bullets[i].vel.y = spawner.vel.y;
|
||||||
bullets[i].vel.x = fix32Mul(fix16ToFix32(cosFix16(spawner.angle)), spawner.speed);
|
} else {
|
||||||
bullets[i].vel.y = fix32Mul(fix16ToFix32(sinFix16(spawner.angle)), spawner.speed);
|
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);
|
|
||||||
}
|
}
|
||||||
|
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;
|
s32 bulletDist;
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,53 @@
|
||||||
void spawnEnemy(u8 type){
|
#define ENEMY_MIN_DIST FIX32(64)
|
||||||
(void)type; // Unused parameter, kept for API compatibility
|
|
||||||
s16 i = -1;
|
static bool isValidEnemyPosition(fix32 x, fix32 y) {
|
||||||
for(s16 j = 0; j < ENEMY_COUNT; j++) if(!enemies[j].active && i == -1) i = j;
|
for(s16 j = 0; j < ENEMY_COUNT; j++) {
|
||||||
if(i > -1){
|
if(enemies[j].active) {
|
||||||
enemies[i].active = TRUE;
|
fix32 dx = getWrappedDelta(x, enemies[j].pos.x);
|
||||||
enemies[i].type = type;
|
fix32 dy = y - enemies[j].pos.y;
|
||||||
enemies[i].pos.x = FIX32(64);
|
// Check if within 64px in both X and Y
|
||||||
enemies[i].pos.y = FIX32(64);
|
if(dx >= -ENEMY_MIN_DIST && dx <= ENEMY_MIN_DIST &&
|
||||||
enemies[i].off = 16;
|
dy >= -ENEMY_MIN_DIST && dy <= ENEMY_MIN_DIST) {
|
||||||
enemies[i].image = SPR_addSprite(&butterflySprite,
|
return FALSE; // Too close to existing enemy
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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){
|
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);
|
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 = {
|
struct bulletSpawner spawner = {
|
||||||
.x = enemies[i].pos.x,
|
.x = enemies[i].pos.x,
|
||||||
.y = enemies[i].pos.y,
|
.y = enemies[i].pos.y,
|
||||||
.anim = 7,
|
.anim = 7,
|
||||||
// .frame = 1,
|
// .frame = 1,
|
||||||
.speed = FIX32(2),
|
.speed = FIX32(4),
|
||||||
.angle = random() % 128,
|
.angle = random() % 128,
|
||||||
};
|
};
|
||||||
for(u8 j = 0; j < 8; j++){
|
for(u8 j = 0; j < 8; j++){
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
u32 clock;
|
u32 clock;
|
||||||
#define CLOCK_LIMIT 32000
|
#define CLOCK_LIMIT 32000
|
||||||
|
#define PROP_COUNT 4
|
||||||
|
|
||||||
#define GAME_H_F FIX32(224)
|
#define GAME_H_F FIX32(224)
|
||||||
|
|
||||||
|
|
@ -70,7 +71,7 @@ struct bullet bullets[BULLET_COUNT];
|
||||||
|
|
||||||
|
|
||||||
// enemies
|
// enemies
|
||||||
#define ENEMY_COUNT 16
|
#define ENEMY_COUNT 24
|
||||||
|
|
||||||
struct enemy {
|
struct enemy {
|
||||||
bool active;
|
bool active;
|
||||||
|
|
@ -80,6 +81,7 @@ struct enemy {
|
||||||
fix32 speed;
|
fix32 speed;
|
||||||
Vect2D_f32 vel, pos;
|
Vect2D_f32 vel, pos;
|
||||||
Sprite* image;
|
Sprite* image;
|
||||||
|
s16 ints[PROP_COUNT];
|
||||||
};
|
};
|
||||||
struct enemy enemies[ENEMY_COUNT];
|
struct enemy enemies[ENEMY_COUNT];
|
||||||
|
|
||||||
|
|
|
||||||
10
src/main.c
10
src/main.c
|
|
@ -8,6 +8,7 @@
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "stage.h"
|
#include "stage.h"
|
||||||
#include "chrome.h"
|
#include "chrome.h"
|
||||||
|
#include "start.h"
|
||||||
|
|
||||||
static void loadInternals(){
|
static void loadInternals(){
|
||||||
JOY_init();
|
JOY_init();
|
||||||
|
|
@ -29,10 +30,13 @@ void loadGame(){
|
||||||
|
|
||||||
static void updateGame(){
|
static void updateGame(){
|
||||||
updateChrome();
|
updateChrome();
|
||||||
updateBackground();
|
|
||||||
updateEnemies();
|
|
||||||
updatePlayer();
|
updatePlayer();
|
||||||
updateBullets();
|
if(clock % 2 == 0){
|
||||||
|
updateEnemies();
|
||||||
|
} else {
|
||||||
|
updateBackground();
|
||||||
|
updateBullets();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(bool hardReset){
|
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 PLAYER_SPEED >> 3
|
||||||
#define PLAYER_ACCEL_FOCUS PLAYER_SPEED_FOCUS >> 3
|
#define PLAYER_ACCEL_FOCUS PLAYER_SPEED_FOCUS >> 3
|
||||||
|
|
@ -100,7 +100,7 @@ static void shootPlayer(){
|
||||||
.x = player.pos.x,
|
.x = player.pos.x,
|
||||||
.y = player.pos.y,
|
.y = player.pos.y,
|
||||||
.anim = 0,
|
.anim = 0,
|
||||||
.speed = FIX32(12),
|
.speed = FIX32(24),
|
||||||
.angle = player.shotAngle,
|
.angle = player.shotAngle,
|
||||||
.player = TRUE
|
.player = TRUE
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
void loadStage(){
|
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