minimap etc
BIN
res/clouds.png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
res/ground.png
Normal file
|
After Width: | Height: | Size: 3 KiB |
BIN
res/mapenemy.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
res/mapframe.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
res/mapindicator.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
res/mapplayer.png
Normal file
|
After Width: | Height: | Size: 4 KiB |
|
|
@ -4,6 +4,9 @@ IMAGE shadow "shadow.png" NONE NONE
|
||||||
IMAGE logo "logo.png" NONE NONE
|
IMAGE logo "logo.png" NONE NONE
|
||||||
|
|
||||||
IMAGE sky "sky.png" NONE NONE
|
IMAGE sky "sky.png" NONE NONE
|
||||||
|
IMAGE ground "ground.png" NONE NONE
|
||||||
|
// IMAGE clouds "clouds.png" NONE NONE
|
||||||
|
|
||||||
IMAGE fadeTop "fadetop.png" NONE NONE
|
IMAGE fadeTop "fadetop.png" NONE NONE
|
||||||
IMAGE fadeBottom "fadebottom.png" NONE NONE
|
IMAGE fadeBottom "fadebottom.png" NONE NONE
|
||||||
|
|
||||||
|
|
@ -17,3 +20,7 @@ SPRITE butterflySprite "butterfly.png" 4 4 NONE 8
|
||||||
// SPRITE fairySprite "fairy.png" 4 4 NONE 8
|
// SPRITE fairySprite "fairy.png" 4 4 NONE 8
|
||||||
SPRITE fairySprite "fairy2.png" 4 4 NONE 8
|
SPRITE fairySprite "fairy2.png" 4 4 NONE 8
|
||||||
SPRITE aliceSprite "alice.png" 6 6 NONE 0
|
SPRITE aliceSprite "alice.png" 6 6 NONE 0
|
||||||
|
|
||||||
|
// IMAGE mapPlayer "mapplayer.png" NONE NONE
|
||||||
|
IMAGE mapIndicator "mapindicator.png" NONE NONE
|
||||||
|
// IMAGE mapFrame "mapframe.png" NONE NONE
|
||||||
BIN
res/sakuya2.png
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 2 KiB |
BIN
res/sky.png
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5 KiB |
|
|
@ -1,13 +1,14 @@
|
||||||
#define BG_I 8
|
#define BG_I 8
|
||||||
#define FADE_TOP_I BG_I + 64
|
// #define FADE_TOP_I BG_I + 64
|
||||||
#define FADE_BOTTOM_I FADE_TOP_I + 64
|
// #define FADE_BOTTOM_I FADE_TOP_I + 64
|
||||||
|
|
||||||
#define BG_OFF 112
|
#define BG_OFF 112
|
||||||
|
|
||||||
void loadBackground(){
|
void loadBackground(){
|
||||||
VDP_loadTileSet(sky.tileset, BG_I, DMA);
|
VDP_loadTileSet(sky.tileset, BG_I, DMA);
|
||||||
VDP_loadTileSet(fadeTop.tileset, FADE_TOP_I, DMA);
|
VDP_loadTileSet(ground.tileset, BG_I + 64, DMA);
|
||||||
VDP_loadTileSet(fadeBottom.tileset, FADE_BOTTOM_I, DMA);
|
// VDP_loadTileSet(fadeTop.tileset, FADE_TOP_I, DMA);
|
||||||
|
// VDP_loadTileSet(fadeBottom.tileset, FADE_BOTTOM_I, DMA);
|
||||||
for(u8 y = 0; y < 4; y++){
|
for(u8 y = 0; y < 4; y++){
|
||||||
for(u8 x = 0; x < 16; x++){
|
for(u8 x = 0; x < 16; x++){
|
||||||
VDP_fillTileMapRectInc(BG_B, TILE_ATTR_FULL(PAL1, 0, 0, 0, BG_I), x * 8, y * 8, 8, 8);
|
VDP_fillTileMapRectInc(BG_B, TILE_ATTR_FULL(PAL1, 0, 0, 0, BG_I), x * 8, y * 8, 8, 8);
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,14 @@ void spawnBullet(struct bulletSpawner spawner, void(*updater)){
|
||||||
// Find available slot, return if none
|
// 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 = j; break; }
|
for(s16 j = 0; j < BULLET_COUNT; j++) if(!bullets[j].active) { i = j; break; }
|
||||||
if(i == -1) return;
|
if(i == -1 && spawner.player){
|
||||||
|
|
||||||
|
for(s16 j = 0; j < BULLET_COUNT; j++) if(bullets[j].active && !bullets[j].player){
|
||||||
|
killBullet(j, FALSE);
|
||||||
|
i = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if(i == -1 && !spawner.player) return;
|
||||||
|
|
||||||
bullets[i].active = TRUE;
|
bullets[i].active = TRUE;
|
||||||
bullets[i].pos.x = spawner.x;
|
bullets[i].pos.x = spawner.x;
|
||||||
|
|
@ -154,7 +161,7 @@ static void updateBulletExplosion(u8 i){
|
||||||
s16 sx = getScreenX(bullets[i].pos.x, player.camera);
|
s16 sx = getScreenX(bullets[i].pos.x, player.camera);
|
||||||
s16 sy = fix32ToInt(bullets[i].pos.y);
|
s16 sy = fix32ToInt(bullets[i].pos.y);
|
||||||
u8 off = bullets[i].player ? P_BULLET_OFF : BULLET_OFF;
|
u8 off = bullets[i].player ? P_BULLET_OFF : BULLET_OFF;
|
||||||
SPR_setPosition(bullets[i].image, sx - off, sy);
|
SPR_setPosition(bullets[i].image, sx - off, sy - off);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void updateBullet(u8 i){
|
static void updateBullet(u8 i){
|
||||||
|
|
@ -176,7 +183,7 @@ static void updateBullet(u8 i){
|
||||||
bool offScreenX = (dx < -CULL_LIMIT || dx > CULL_LIMIT);
|
bool offScreenX = (dx < -CULL_LIMIT || dx > CULL_LIMIT);
|
||||||
|
|
||||||
bool offScreenTop = (bullets[i].pos.y < FIX32(-16));
|
bool offScreenTop = (bullets[i].pos.y < FIX32(-16));
|
||||||
bool offScreenBottom = (bullets[i].pos.y > GAME_H_F - FIX32(8));
|
bool offScreenBottom = (bullets[i].pos.y > GAME_H_F);
|
||||||
|
|
||||||
if(offScreenX || offScreenTop){
|
if(offScreenX || offScreenTop){
|
||||||
killBullet(i, FALSE);
|
killBullet(i, FALSE);
|
||||||
|
|
@ -204,5 +211,5 @@ void updateBullets(){
|
||||||
bulletCount = 0;
|
bulletCount = 0;
|
||||||
for(s16 i = 0; i < BULLET_COUNT; i++) if(bullets[i].active)
|
for(s16 i = 0; i < BULLET_COUNT; i++) if(bullets[i].active)
|
||||||
updateBullet(i);
|
updateBullet(i);
|
||||||
intToStr(bulletCount, debugStr, 1);
|
// intToStr(bulletCount, debugStr, 1);
|
||||||
}
|
}
|
||||||
96
src/chrome.h
|
|
@ -1,12 +1,101 @@
|
||||||
|
#define MAP_I 512
|
||||||
|
#define MAP_TILE TILE_ATTR_FULL(PAL1, 1, 0, 0, MAP_I)
|
||||||
|
#define MAP_PLAYER_TILE TILE_ATTR_FULL(PAL0, 1, 0, 0, MAP_I + 1)
|
||||||
|
#define MAP_ENEMY_TILE TILE_ATTR_FULL(PAL0, 1, 0, 0, MAP_I + 2)
|
||||||
|
#define MAP_BORDER_X_TILE TILE_ATTR_FULL(PAL0, 1, 0, 0, MAP_I + 3)
|
||||||
|
|
||||||
char scoreStr[SCORE_LENGTH];
|
char scoreStr[SCORE_LENGTH];
|
||||||
u32 lastScore;
|
u32 lastScore;
|
||||||
|
|
||||||
|
// previous map positions: -1 means not drawn
|
||||||
|
s16 mapEnemyCol[ENEMY_COUNT], mapEnemyRow[ENEMY_COUNT];
|
||||||
|
s16 mapPlayerRow;
|
||||||
|
|
||||||
static void drawScore(){
|
static void drawScore(){
|
||||||
uintToStr(score, scoreStr, 1);
|
uintToStr(score, scoreStr, 1);
|
||||||
VDP_drawText(scoreStr, 1, 1);
|
VDP_drawText(scoreStr, 1, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// load map when stage does so we have all enemies + player
|
||||||
|
void loadMap(){
|
||||||
|
VDP_fillTileMapRect(BG_A, MAP_TILE, MAP_X, MAP_Y, MAP_W, MAP_H);
|
||||||
|
|
||||||
|
// VDP_fillTileMapRect(BG_A, TILE_ATTR_FULL(PAL0, 1, 0, 0, MAP_I + 3), MAP_X, MAP_Y - 1, MAP_W, 1);
|
||||||
|
// VDP_fillTileMapRect(BG_A, TILE_ATTR_FULL(PAL0, 1, 1, 0, MAP_I + 3), MAP_X, MAP_Y + MAP_H, MAP_W, 1);
|
||||||
|
|
||||||
|
// VDP_fillTileMapRect(BG_A, TILE_ATTR_FULL(PAL0, 1, 0, 0, MAP_I + 4), MAP_X - 1, MAP_Y, 1, MAP_H);
|
||||||
|
|
||||||
|
for(s16 i = 0; i < ENEMY_COUNT; i++){
|
||||||
|
mapEnemyCol[i] = -1;
|
||||||
|
mapEnemyRow[i] = -1;
|
||||||
|
}
|
||||||
|
mapPlayerRow = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// temp arrays for new positions
|
||||||
|
s16 mapNewCol[ENEMY_COUNT], mapNewRow[ENEMY_COUNT];
|
||||||
|
|
||||||
|
static bool mapTileOccupied(s16 col, s16 row, s16 pRow){
|
||||||
|
// player always at center column
|
||||||
|
if(col == MAP_W / 2 && row == pRow) return TRUE;
|
||||||
|
for(s16 i = 0; i < ENEMY_COUNT; i++)
|
||||||
|
if(mapNewCol[i] == col && mapNewRow[i] == row) return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void updateMap(){
|
||||||
|
// compute new player row
|
||||||
|
s16 pRow = fix32ToInt(player.pos.y) / 75;
|
||||||
|
if(pRow < 0) pRow = 0;
|
||||||
|
if(pRow >= MAP_H) pRow = MAP_H - 1;
|
||||||
|
|
||||||
|
// compute new enemy positions
|
||||||
|
for(s16 i = 0; i < ENEMY_COUNT; i++){
|
||||||
|
if(!enemies[i].active || enemies[i].image == NULL){
|
||||||
|
mapNewCol[i] = -1;
|
||||||
|
mapNewRow[i] = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fix32 dx = getWrappedDelta(enemies[i].pos.x, player.pos.x);
|
||||||
|
s16 col = fix32ToInt(dx) / 54 + MAP_W / 2;
|
||||||
|
if(col < 0) col = 0;
|
||||||
|
if(col >= MAP_W) col = MAP_W - 1;
|
||||||
|
s16 row = fix32ToInt(enemies[i].pos.y) / 75;
|
||||||
|
if(row < 0) row = 0;
|
||||||
|
if(row >= MAP_H) row = MAP_H - 1;
|
||||||
|
mapNewCol[i] = col;
|
||||||
|
mapNewRow[i] = row;
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear old player tile if it moved and nothing new occupies it
|
||||||
|
if(mapPlayerRow >= 0 && mapPlayerRow != pRow)
|
||||||
|
if(!mapTileOccupied(MAP_W / 2, mapPlayerRow, pRow))
|
||||||
|
VDP_setTileMapXY(BG_A, MAP_TILE, MAP_X + MAP_W / 2, MAP_Y + mapPlayerRow);
|
||||||
|
|
||||||
|
// clear old enemy tiles that moved or disappeared
|
||||||
|
for(s16 i = 0; i < ENEMY_COUNT; i++){
|
||||||
|
if(mapEnemyCol[i] < 0) continue;
|
||||||
|
if(mapEnemyCol[i] == mapNewCol[i] && mapEnemyRow[i] == mapNewRow[i]) continue;
|
||||||
|
if(!mapTileOccupied(mapEnemyCol[i], mapEnemyRow[i], pRow))
|
||||||
|
VDP_setTileMapXY(BG_A, MAP_TILE, MAP_X + mapEnemyCol[i], MAP_Y + mapEnemyRow[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw enemy dots (skip if player occupies same tile)
|
||||||
|
for(s16 i = 0; i < ENEMY_COUNT; i++){
|
||||||
|
mapEnemyCol[i] = mapNewCol[i];
|
||||||
|
mapEnemyRow[i] = mapNewRow[i];
|
||||||
|
if(mapNewCol[i] < 0) continue;
|
||||||
|
if(mapNewCol[i] == MAP_W / 2 && mapNewRow[i] == pRow) continue;
|
||||||
|
VDP_setTileMapXY(BG_A, MAP_ENEMY_TILE, MAP_X + mapNewCol[i], MAP_Y + mapNewRow[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw player dot on top
|
||||||
|
mapPlayerRow = pRow;
|
||||||
|
VDP_setTileMapXY(BG_A, MAP_PLAYER_TILE, MAP_X + MAP_W / 2, MAP_Y + pRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadChrome(){
|
void loadChrome(){
|
||||||
|
VDP_loadTileSet(mapIndicator.tileset, MAP_I, DMA);
|
||||||
drawScore();
|
drawScore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -17,6 +106,7 @@ void updateChrome(){
|
||||||
lastScore = score;
|
lastScore = score;
|
||||||
drawScore();
|
drawScore();
|
||||||
}
|
}
|
||||||
VDP_clearText(1, 26, 4);
|
if(clock % 4 == 0) updateMap();
|
||||||
VDP_drawText(debugStr, 1, 26);
|
// VDP_clearText(1, 26, 4);
|
||||||
|
// VDP_drawText(debugStr, 1, 26);
|
||||||
}
|
}
|
||||||
|
|
@ -42,7 +42,7 @@ void spawnEnemy(u8 type, u8 zone){
|
||||||
enemies[i].pos.y = randY;
|
enemies[i].pos.y = randY;
|
||||||
enemies[i].off = 16;
|
enemies[i].off = 16;
|
||||||
enemies[i].image = SPR_addSprite(&fairySprite,
|
enemies[i].image = SPR_addSprite(&fairySprite,
|
||||||
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));
|
getScreenX(enemies[i].pos.x, player.camera) - enemies[i].off, fix32ToInt(enemies[i].pos.y) - enemies[i].off, TILE_ATTR(PAL0, 0, 0, 0));
|
||||||
if(!enemies[i].image){
|
if(!enemies[i].image){
|
||||||
enemies[i].active = FALSE;
|
enemies[i].active = FALSE;
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,25 @@
|
||||||
void loadEnemyOne(u8 i){
|
void loadEnemyOne(u8 i){
|
||||||
enemies[i].ints[0] = random() % 60;
|
enemies[i].ints[0] = random() % 40;
|
||||||
enemies[i].angle = ((random() % 4) * 256) + 128;
|
enemies[i].angle = ((random() % 4) * 256) + 128;
|
||||||
enemies[i].speed = FIX32(2);
|
enemies[i].speed = FIX32(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateEnemyOne(u8 i){
|
void updateEnemyOne(u8 i){
|
||||||
if(enemies[i].clock % 60 == enemies[i].ints[0] && enemies[i].onScreen){
|
if(enemies[i].clock % 40 == enemies[i].ints[0] && enemies[i].onScreen){
|
||||||
enemies[i].clock % 120 == enemies[i].ints[0] ? sfxEnemyShotB() : sfxEnemyShotA();
|
enemies[i].clock % 80 == enemies[i].ints[0] ? sfxEnemyShotB() : sfxEnemyShotA();
|
||||||
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 = 6 + (random() % 3),
|
.anim = 3 + (random() % 3),
|
||||||
.anim = 6,
|
// .anim = 6,
|
||||||
// .frame = 1,
|
// .frame = 1,
|
||||||
.speed = FIX32(2) + FIX16(random() % 4),
|
.speed = FIX32(2) + FIX16(random() % 4),
|
||||||
.angle = random() % 128,
|
.angle = random() % 128,
|
||||||
};
|
};
|
||||||
// if(random() % 2 < 1) spawner.anim += 3;
|
switch(random() % 3){
|
||||||
|
case 1: spawner.anim += 3; break;
|
||||||
|
case 2: spawner.anim += 6; break;
|
||||||
|
}
|
||||||
for(u8 j = 0; j < 8; j++){
|
for(u8 j = 0; j < 8; j++){
|
||||||
spawnBullet(spawner, EMPTY);
|
spawnBullet(spawner, EMPTY);
|
||||||
spawner.angle += 128;
|
spawner.angle += 128;
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,11 @@ u32 score;
|
||||||
|
|
||||||
#define FIRST_ROTATING_BULLET 3
|
#define FIRST_ROTATING_BULLET 3
|
||||||
|
|
||||||
|
#define MAP_X 1
|
||||||
|
#define MAP_Y 1
|
||||||
|
#define MAP_W 38
|
||||||
|
#define MAP_H 3
|
||||||
|
|
||||||
char debugStr[8];
|
char debugStr[8];
|
||||||
void EMPTY(s16 i){(void)i;}
|
void EMPTY(s16 i){(void)i;}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -138,5 +138,5 @@ void updatePlayer(){
|
||||||
|
|
||||||
SPR_setPosition(player.image, sx - PLAYER_OFF, sy - PLAYER_OFF);
|
SPR_setPosition(player.image, sx - PLAYER_OFF, sy - PLAYER_OFF);
|
||||||
|
|
||||||
// intToStr(fix32ToInt(player.pos.x), debugStr, 1);
|
intToStr(fix32ToInt(player.pos.x), debugStr, 1);
|
||||||
}
|
}
|
||||||
|
|
@ -5,4 +5,5 @@ void loadStage(){
|
||||||
spawnEnemy(0, zone);
|
spawnEnemy(0, zone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
loadMap();
|
||||||
}
|
}
|
||||||