This repository has been archived on 2022-09-26. You can view files and clone it, but cannot push or open issues or pull requests.
fd2/src/foreground.h
2022-08-20 21:32:36 -04:00

155 lines
3.5 KiB
C

// foreground
#define FG_I 576
#define FG_W 64
#define OBSTACLE_COUNT 24
#define FG_SPEED FIX16(1.75)
#define FG_SPEED_NORM FIX16(1.75 * 0.707)
struct obstacle {
bool active, top;
Vect2D_f16 pos, size;
s16 startX;
};
struct obstacle obstacles[OBSTACLE_COUNT];
s16 currentFg;
SpriteDefinition* currentTopImage;
SpriteDefinition* currentBottomImage;
// draw
#define CEIL_Y 3
#define FLOOR_Y 24
static void drawFg(){
switch(currentFg){
case 0:
currentTopImage = &rock1Top;
currentBottomImage = &rock1Bottom;
break;
case 1:
currentTopImage = &rock2Top;
currentBottomImage = &rock2Bottom;
break;
}
for(u16 x = 0; x < FG_W; x++){
if(x % 4 == 0){
VDP_drawImageEx(BG_B, currentTopImage, TILE_ATTR_FULL(PAL2, 1, 0, 0, FG_I), x, CEIL_Y, 0, DMA);
VDP_drawImageEx(BG_B, currentBottomImage, TILE_ATTR_FULL(PAL2, 1, 0, 0, FG_I + 16), x, FLOOR_Y, 0, DMA);
}
}
}
// obstacle
#define OBS_CEIL_Y 3
#define OBS_FLOOR_Y 20
#define OBS_X 32
#define OBS_TOP_Y FIX16(56)
#define OBS_BOTTOM_Y FIX16(160)
s16 fgPos, obsX;
#define OBS_I FG_I + 32
SpriteDefinition* obstacleImage;
s16 obstacleI;
static void spawnObstacle(bool top, s16 offset, u8 type){
s16 i = -1;
for(s16 j = 0; j < OBSTACLE_COUNT; j++) if(!obstacles[j].active && i == -1) i = j;
if(i > -1){
// obsX = OBS_X;
obsX = OBS_X + (fgPos != 0 ? (-fgPos / 8) : 0);
obstacles[i].active = TRUE;
obstacles[i].top = top;
obstacles[i].pos.x = FIX16(256);
obstacles[i].pos.y = top ? OBS_TOP_Y : OBS_BOTTOM_Y;
obstacles[i].size.x = FIX16(32);
obstacles[i].size.y = FIX16(32);
if(offset){
obstacles[i].pos.x = fix16Sub(obstacles[i].pos.x, FIX16(offset));
obsX -= offset / 8;
}
obstacles[i].startX = obsX;
switch(type){
case 0: obstacleImage = top ? &obstacle1LeftTop : &obstacle1LeftBottom; break;
case 1: obstacleImage = top ? &obstacle1MiddleTop : &obstacle1MiddleBottom; break;
case 2: obstacleImage = top ? &obstacle1RightTop : &obstacle1RightBottom; break;
}
obstacleI = type * 32;
if(top) obstacleI += 128;
VDP_drawImageEx(BG_B, obstacleImage,
TILE_ATTR_FULL(PAL2, 1, 0, 0, OBS_I + obstacleI),
obsX, top ? OBS_CEIL_Y : OBS_FLOOR_Y, 0, DMA);
}
}
#define OBSTACLE_MOD FIX16(8)
#define OBSTACLE_LIMIT_X FIX16(-64)
SpriteDefinition* obstacleImage;
static void killObstacle(s16 i){
obstacles[i].active = FALSE;
VDP_clearTileMapRect(BG_B, obstacles[i].startX, obstacles[i].top ? OBS_CEIL_Y + 4 : OBS_FLOOR_Y, 4, 4);
VDP_drawImageEx(BG_B,
obstacles[i].top ? currentTopImage : currentBottomImage,
TILE_ATTR_FULL(PAL2, 1, 0, 0, FG_I + (obstacles[i].top ? 0 : 16)),
obstacles[i].startX,
obstacles[i].top ? CEIL_Y : FLOOR_Y,
0, DMA_QUEUE);
}
static void collideObstacle(s16 i){
collideObstacleWithPlayer(i);
}
static void updateObstacle(s16 i){
obstacles[i].pos.x = fix16Sub(obstacles[i].pos.x, FG_SPEED);
obstacles[i].pos.x <= OBSTACLE_LIMIT_X ? killObstacle(i) : collideObstacle(i);
}
// update
#define FG_SIZE 32
#define FG_LIMIT FIX16(-512)
#define FG_SIZE_F 40
s16 fgPosX[GAME_H_T];
fix16 fgPosXF[GAME_H_T];
static void scrollFg(){
for(u8 y = 0; y < GAME_H_T; y++){
if(y > 2){
fgPosXF[y] = fix16Sub(fgPosXF[y], FG_SPEED);
if(fgPosXF[y] <= FG_LIMIT) fgPosXF[y] = 0;
fgPosX[y] = fix16ToInt(fgPosXF[y]);
}
}
fgPos = fgPosX[3];
}
void nextFg(){
VDP_clearTileMapRect(BG_B, 0, OBS_CEIL_Y + 4, FG_W, 17);
currentFg++;
drawFg();
}
// loop
void loadFg(){
drawFg();
}
void updateFg(){
VDP_setHorizontalScrollTile(BG_B, 0, fgPosX, GAME_H_T, DMA);
scrollFg();
for(s16 i = 0; i < OBSTACLE_COUNT; i++) if(obstacles[i].active) updateObstacle(i);
}