#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]; u32 lastScore; // previous map positions: -1 means not drawn s16 mapEnemyCol[ENEMY_COUNT], mapEnemyRow[ENEMY_COUNT]; s16 mapPlayerRow; static void drawScore(){ uintToStr(score, scoreStr, 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(){ VDP_loadTileSet(mapIndicator.tileset, MAP_I, DMA); drawScore(); } void updateChrome(){ score++; if(score > 99999999) score = 0; if(lastScore != score){ lastScore = score; drawScore(); } if(clock % 4 == 0) updateMap(); // VDP_clearText(1, 26, 4); // VDP_drawText(debugStr, 1, 26); }