start enemy work
This commit is contained in:
parent
78a032a6d9
commit
60aa78f3f1
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
|
@ -18,6 +18,8 @@ IMAGE rock1rt "fg/rock1rt.png" FAST
|
||||||
|
|
||||||
SPRITE nitori "player/nitori.png" 4 4 FAST
|
SPRITE nitori "player/nitori.png" 4 4 FAST
|
||||||
|
|
||||||
|
SPRITE fairy1 "enemies/fairy1.png" 6 4 FAST
|
||||||
|
|
||||||
SPRITE smallRedBullet "bullets/smallred.png" 1 1 FAST 5
|
SPRITE smallRedBullet "bullets/smallred.png" 1 1 FAST 5
|
||||||
SPRITE smallBlueBullet "bullets/smallblue.png" 1 1 FAST 5
|
SPRITE smallBlueBullet "bullets/smallblue.png" 1 1 FAST 5
|
||||||
SPRITE smallGreenBullet "bullets/smallgreen.png" 1 1 FAST 5
|
SPRITE smallGreenBullet "bullets/smallgreen.png" 1 1 FAST 5
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
// 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);
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
// foreground
|
// foreground
|
||||||
|
|
||||||
#define FG_I 576
|
#define FG_I 576
|
||||||
#define FG_W GAME_W_T + 30
|
#define FG_W 64
|
||||||
#define OBSTACLE_COUNT 8
|
#define OBSTACLE_COUNT 8
|
||||||
|
|
||||||
#define FG_SPEED FIX16(2)
|
#define FG_SPEED FIX16(2)
|
||||||
|
@ -38,33 +38,28 @@ static void drawFg(){
|
||||||
#define OBS_TOP_Y FIX16(56)
|
#define OBS_TOP_Y FIX16(56)
|
||||||
#define OBS_BOTTOM_Y FIX16(160)
|
#define OBS_BOTTOM_Y FIX16(160)
|
||||||
|
|
||||||
s16 fgPos;
|
s16 fgPos, obsX;
|
||||||
|
|
||||||
static void spawnObstacle(bool top){
|
static void spawnObstacle(bool top){
|
||||||
s16 i = -1;
|
s16 i = -1;
|
||||||
for(s16 j = 0; j < OBSTACLE_COUNT; j++) if(!obstacles[j].active && i == -1) i = j;
|
for(s16 j = 0; j < OBSTACLE_COUNT; j++) if(!obstacles[j].active && i == -1) i = j;
|
||||||
if(i > -1){
|
if(i > -1){
|
||||||
|
// obsX = OBS_X;
|
||||||
|
obsX = OBS_X + (fgPos != 0 ? (-fgPos / 8) : 0);
|
||||||
obstacles[i].active = TRUE;
|
obstacles[i].active = TRUE;
|
||||||
obstacles[i].top = top;
|
obstacles[i].top = top;
|
||||||
obstacles[i].pos.x = FIX16(256);
|
obstacles[i].pos.x = FIX16(256);
|
||||||
obstacles[i].pos.y = top ? OBS_TOP_Y : OBS_BOTTOM_Y;
|
obstacles[i].pos.y = top ? OBS_TOP_Y : OBS_BOTTOM_Y;
|
||||||
obstacles[i].size.x = FIX16(64);
|
obstacles[i].size.x = FIX16(64);
|
||||||
obstacles[i].size.y = FIX16(32);
|
obstacles[i].size.y = FIX16(32);
|
||||||
obstacles[i].startX = OBS_X;
|
obstacles[i].startX = obsX;
|
||||||
if(top){
|
for(u8 j = 0; j < 4; j++){
|
||||||
for(u8 j = 0; j < 4; j++){
|
VDP_drawImageEx(BG_B,
|
||||||
VDP_drawImageEx(BG_B,
|
top ? (j == 0 ? &rock1lt : (j == 1 ? &rock1t : (j == 2 ? &rock1rt : &rock1b))) : (j == 0 ? &rock1l : (j == 1 ? &rock1 : (j == 2 ? &rock1r : &rock1b))),
|
||||||
j == 0 ? &rock1lt : (j == 1 ? &rock1t : (j == 2 ? &rock1rt : &rock1b)),
|
TILE_ATTR_FULL(PAL2, 1, 0, 0, FG_I + (top ? (j == 0 ? 32 : (j == 1 ? 48 : (j == 2 ? 64 : 80))) : (j == 0 ? 112 : (j == 1 ? 128 : (j == 2 ? 144 : 80))))),
|
||||||
TILE_ATTR_FULL(PAL2, 1, 0, 0, FG_I + (j == 0 ? 32 : (j == 1 ? 48 : (j == 2 ? 64 : 80)))),
|
obsX + (top ? (j == 1 || j == 3 ? 2 : (j == 2 ? 6 : 0)) : ((j == 1 || j == 3 ? 2 : (j == 2 ? 6 : 0)))),
|
||||||
OBS_X + (j == 1 || j == 3 ? 2 : (j == 2 ? 6 : 0)),
|
top ? (OBS_CEIL_Y - (j == 0 || j == 2 ? 2 : (j == 3 ? 4 : 0))) : (OBS_FLOOR_Y + (j == 3 ? 4 : 0)),
|
||||||
OBS_CEIL_Y - (j == 0 || j == 2 ? 2 : (j == 3 ? 4 : 0)),
|
0, DMA_QUEUE);
|
||||||
0, DMA_QUEUE);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
VDP_drawImageEx(BG_B, &rock1l, TILE_ATTR_FULL(PAL2, 1, 0, 0, FG_I + 32 + 80), OBS_X, OBS_FLOOR_Y, 0, DMA_QUEUE);
|
|
||||||
VDP_drawImageEx(BG_B, &rock1, TILE_ATTR_FULL(PAL2, 1, 0, 0, FG_I + 48 + 80), OBS_X + 2, OBS_FLOOR_Y, 0, DMA_QUEUE);
|
|
||||||
VDP_drawImageEx(BG_B, &rock1r, TILE_ATTR_FULL(PAL2, 1, 0, 0, FG_I + 64 + 80), OBS_X + 2 + 4, OBS_FLOOR_Y, 0, DMA_QUEUE);
|
|
||||||
VDP_drawImageEx(BG_B, &rock1b, TILE_ATTR_FULL(PAL2, 1, 0, 0, FG_I + 80), OBS_X + 2, OBS_FLOOR_Y + 4, 0, DMA_QUEUE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +88,7 @@ static void updateObstacle(s16 i){
|
||||||
// update
|
// update
|
||||||
|
|
||||||
#define FG_SIZE 32
|
#define FG_SIZE 32
|
||||||
#define FG_LIMIT FIX16(-320)
|
#define FG_LIMIT FIX16(-512)
|
||||||
|
|
||||||
#define FG_SIZE_F 40
|
#define FG_SIZE_F 40
|
||||||
|
|
||||||
|
@ -117,12 +112,11 @@ static void scrollFg(){
|
||||||
|
|
||||||
void loadFg(){
|
void loadFg(){
|
||||||
drawFg();
|
drawFg();
|
||||||
spawnObstacle(FALSE);
|
|
||||||
spawnObstacle(TRUE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateFg(){
|
void updateFg(){
|
||||||
VDP_setHorizontalScrollTile(BG_B, 0, fgPosX, GAME_H_T, DMA);
|
VDP_setHorizontalScrollTile(BG_B, 0, fgPosX, GAME_H_T, DMA);
|
||||||
scrollFg();
|
scrollFg();
|
||||||
for(s16 i = 0; i < OBSTACLE_COUNT; i++) if(obstacles[i].active) updateObstacle(i);
|
for(s16 i = 0; i < OBSTACLE_COUNT; i++) if(obstacles[i].active) updateObstacle(i);
|
||||||
|
if(clock % 60 == 0) spawnObstacle(clock % 120 < 60);
|
||||||
}
|
}
|
20
src/global.h
20
src/global.h
|
@ -19,7 +19,8 @@
|
||||||
bool killBullets,
|
bool killBullets,
|
||||||
started;
|
started;
|
||||||
|
|
||||||
s16 clock;
|
s16 clock,
|
||||||
|
bossHealth, bossMax;
|
||||||
|
|
||||||
u32 score,
|
u32 score,
|
||||||
highScore;
|
highScore;
|
||||||
|
@ -30,3 +31,20 @@ void EMPTY(s16 i){emptyI = i;}
|
||||||
void loadGame();
|
void loadGame();
|
||||||
|
|
||||||
void collideObstacleWithPlayer(s16);
|
void collideObstacleWithPlayer(s16);
|
||||||
|
|
||||||
|
fix16 honeSpeed;
|
||||||
|
Vect2D_f16 hPos, velPos;
|
||||||
|
Vect2D_f16 hone(Vect2D_f16 pos, Vect2D_f16 target, fix16 speed, s16 lerp){
|
||||||
|
hPos.x = target.x;
|
||||||
|
hPos.y = target.y;
|
||||||
|
// if(lerp > 0){
|
||||||
|
// hPos.x = fix16Add(fix16Sub(hPos.x, FIX16(lerp)), FIX16(random() % (lerp * 2)));
|
||||||
|
// hPos.y = fix16Add(fix16Sub(hPos.y, FIX16(lerp)), FIX16(random() % (lerp * 2)));
|
||||||
|
// }
|
||||||
|
honeSpeed = fix32ToFix16(getApproximatedDistance(
|
||||||
|
fix32Sub(fix16ToFix32(pos.x), fix16ToFix32(hPos.x)),
|
||||||
|
fix32Sub(fix16ToFix32(pos.y), fix16ToFix32(hPos.y))));
|
||||||
|
hPos.x = fix16Mul(fix16Div(fix16Sub(hPos.x, pos.x), honeSpeed), speed);
|
||||||
|
hPos.y = fix16Mul(fix16Div(fix16Sub(hPos.y, pos.y), honeSpeed), speed);
|
||||||
|
return hPos;
|
||||||
|
}
|
|
@ -11,6 +11,8 @@
|
||||||
#include "foreground.h"
|
#include "foreground.h"
|
||||||
#include "bullets.h"
|
#include "bullets.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
#include "enemies.h"
|
||||||
|
#include "stage.h"
|
||||||
#include "chrome.h"
|
#include "chrome.h"
|
||||||
|
|
||||||
// game loop
|
// game loop
|
||||||
|
@ -36,6 +38,8 @@ void loadGame(){
|
||||||
|
|
||||||
static void updateGame(){
|
static void updateGame(){
|
||||||
updatePlayer();
|
updatePlayer();
|
||||||
|
updateEnemies();
|
||||||
|
updateStage();
|
||||||
updateBullets();
|
updateBullets();
|
||||||
updateBg();
|
updateBg();
|
||||||
updateFg();
|
updateFg();
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
// stage
|
||||||
|
|
||||||
|
#define SPAWN_MID 124
|
||||||
|
|
||||||
|
|
||||||
|
// waves
|
||||||
|
|
||||||
|
static void waveOne(){
|
||||||
|
|
||||||
|
struct enemySpawner spawner = {
|
||||||
|
.angle = 512,
|
||||||
|
.speed = FIX16(0.75),
|
||||||
|
.x = GAME_W + 24,
|
||||||
|
.y = SPAWN_MID,
|
||||||
|
.image = &fairy1,
|
||||||
|
.offX = 24,
|
||||||
|
.offY = 16
|
||||||
|
};
|
||||||
|
spawner.fixes[0] = FIX16(spawner.y);
|
||||||
|
spawner.fixes[1] = FIX16(8);
|
||||||
|
spawner.fixes[2] = FIX16(12);
|
||||||
|
spawner.fixes[3] = FIX16(0.1);
|
||||||
|
void updater(s16 i){
|
||||||
|
enemies[i].pos.y = fix16Sub(enemies[i].fixes[0], fix16Mul(sinFix16(enemies[i].fixes[1]), enemies[i].fixes[2]));
|
||||||
|
enemies[i].fixes[1] = fix16Add(enemies[i].fixes[1], enemies[i].fixes[3]);
|
||||||
|
if(enemies[i].clock == 30){
|
||||||
|
struct bulletSpawner spawner = {
|
||||||
|
.x = enemies[i].pos.x,
|
||||||
|
.y = enemies[i].pos.y,
|
||||||
|
.image = &smallRedBullet,
|
||||||
|
.angle = 512,
|
||||||
|
.speed = FIX16(1.5)
|
||||||
|
};
|
||||||
|
spawner.vel = hone(enemies[i].pos, player.pos, spawner.speed, 0);
|
||||||
|
spawnBullet(spawner, EMPTY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(u8 j = 0; j < 3; j++){
|
||||||
|
spawnEnemy(spawner, updater, EMPTY);
|
||||||
|
spawner.x += 50;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// loop
|
||||||
|
|
||||||
|
s16 stageClock;
|
||||||
|
|
||||||
|
static void updateWaves(){
|
||||||
|
switch(stageClock){
|
||||||
|
case 5: waveOne(); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateStage(){
|
||||||
|
updateWaves();
|
||||||
|
stageClock++;
|
||||||
|
if(stageClock >= CLOCK_LIMIT) stageClock -= CLOCK_LIMIT;
|
||||||
|
}
|
|
@ -1,5 +1,8 @@
|
||||||
// structs
|
// structs
|
||||||
|
|
||||||
|
|
||||||
|
// bullets
|
||||||
|
|
||||||
#define BULLET_COUNT 64
|
#define BULLET_COUNT 64
|
||||||
struct bulletSpawner {
|
struct bulletSpawner {
|
||||||
fix16 x, y, speed;
|
fix16 x, y, speed;
|
||||||
|
@ -26,9 +29,45 @@ struct bullet {
|
||||||
};
|
};
|
||||||
struct bullet bullets[BULLET_COUNT];
|
struct bullet bullets[BULLET_COUNT];
|
||||||
|
|
||||||
|
|
||||||
|
// player
|
||||||
|
|
||||||
struct playerStruct {
|
struct playerStruct {
|
||||||
Vect2D_f16 pos, vel;
|
Vect2D_f16 pos, vel;
|
||||||
Sprite* image;
|
Sprite* image;
|
||||||
s16 clock, invincibleClock, shotClock;
|
s16 clock, invincibleClock, shotClock;
|
||||||
};
|
};
|
||||||
struct playerStruct player;
|
struct playerStruct player;
|
||||||
|
|
||||||
|
|
||||||
|
// enemies
|
||||||
|
|
||||||
|
#define ENEMY_COUNT 32
|
||||||
|
|
||||||
|
struct enemySpawner {
|
||||||
|
fix16 speed;
|
||||||
|
s16 angle, offX, offY, x, y, anim, health, frame;
|
||||||
|
Vect2D_f16 vel;
|
||||||
|
Sprite* image;
|
||||||
|
bool boss, seal;
|
||||||
|
bool bools[COUNT_INT];
|
||||||
|
s16 ints[COUNT_INT];
|
||||||
|
fix16 fixes[COUNT_INT];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct enemy {
|
||||||
|
bool active, boss, seen, seal, dead;
|
||||||
|
fix16 speed;
|
||||||
|
fix32 dist;
|
||||||
|
Vect2D_f16 pos, vel, off;
|
||||||
|
s16 angle, clock, health, shotClock;
|
||||||
|
Sprite* image;
|
||||||
|
Sprite* sealImage;
|
||||||
|
void (*updater)(s16);
|
||||||
|
void (*bossUpdater)(s16);
|
||||||
|
void (*suicide)(s16);
|
||||||
|
bool bools[COUNT_INT];
|
||||||
|
s16 ints[COUNT_INT];
|
||||||
|
fix16 fixes[COUNT_INT];
|
||||||
|
};
|
||||||
|
struct enemy enemies[ENEMY_COUNT];
|
Reference in New Issue