/** * Copyright (c) 2024 Dominic Masters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #include "frame.h" #include "display/symbol.h" #include "rpg/world/map.h" #include "game.h" #include "ui/textbox.h" char_t FRAME_BUFFER[FRAME_HEIGHT * FRAME_WIDTH]; uint8_t FRAME_COLOR[FRAME_HEIGHT * FRAME_WIDTH]; void frameInit() { memset(FRAME_BUFFER, ' ', FRAME_HEIGHT * FRAME_WIDTH); frameUIReset(); } void frameUpdate() { map_t *map = GAME.currentMap; if(map == NULL) return; // Draw the map area. if(GAME.state == GAME_STATE_PAUSED) { framePausedDraw(); } else { frameMapDraw(); } } void framePausedDraw() { char_t *test = "Paused"; uint16_t x = (FRAME_WIDTH - strlen(test)) / 2; uint16_t y = (FRAME_HEIGHT - FRAME_BOTTOM_UI_HEIGHT) / 2; uint16_t j; for(uint16_t i = 0; i < strlen(test); i++) { j = (y * FRAME_WIDTH) + x + i; FRAME_BUFFER[j] = test[i]; FRAME_COLOR[j] = COLOR_WHITE; } } void frameUIReset() { memset( FRAME_BUFFER + (FRAME_HEIGHT - FRAME_BOTTOM_UI_HEIGHT) * FRAME_WIDTH, ' ', FRAME_WIDTH * FRAME_BOTTOM_UI_HEIGHT ); memset( FRAME_COLOR + (FRAME_HEIGHT - FRAME_BOTTOM_UI_HEIGHT) * FRAME_WIDTH, COLOR_WHITE, FRAME_WIDTH * FRAME_BOTTOM_UI_HEIGHT ); // Draw UI top and bottom borders for(uint16_t x = 0; x < FRAME_WIDTH; x++) { char_t c = x == 0 || x == FRAME_WIDTH-1 ? '+' : '-'; int32_t i = (FRAME_HEIGHT - 1) * FRAME_WIDTH + x; FRAME_BUFFER[i] = c; i = (FRAME_HEIGHT - FRAME_BOTTOM_UI_HEIGHT) * FRAME_WIDTH + x; FRAME_BUFFER[i] = c; } // Draw UI left and right borders for( uint16_t y = FRAME_HEIGHT - FRAME_BOTTOM_UI_HEIGHT + 1; y < FRAME_HEIGHT - 1; y++ ) { int32_t i = y * FRAME_WIDTH; FRAME_BUFFER[i] = '|'; i = y * FRAME_WIDTH + FRAME_WIDTH - 1; FRAME_BUFFER[i] = '|'; } } void frameMapDraw() { // Draw the map area. entity_t *ent; tile_t tile; uint32_t i; map_t *map = GAME.currentMap; if(map == NULL) return; // Try get player entity_t *player = mapEntityGetByType(map, ENTITY_TYPE_PLAYER); uint16_t cameraPositionX, cameraPositionY; if(player == NULL) { cameraPositionX = 0; cameraPositionY = 0; } else { cameraPositionX = player->x; cameraPositionY = player->y; } // If the size of the map's smaller than the frame, center it, otherwise use // the cameraPosition as the center point. int16_t offsetX = 0, offsetY = 0; if(map->width < FRAME_MAP_WIDTH) { offsetX = (FRAME_MAP_WIDTH - map->width) / 2; } else { // Clamp to map bounds if(cameraPositionX < FRAME_MAP_WIDTH / 2) { offsetX = 0; } else if(cameraPositionX >= map->width - (FRAME_MAP_WIDTH / 2)) { offsetX = -(map->width - FRAME_MAP_WIDTH); } else { offsetX = -(cameraPositionX - (FRAME_MAP_WIDTH / 2)); } } if(map->height < FRAME_MAP_HEIGHT) { offsetY = (FRAME_MAP_HEIGHT - map->height) / 2; } else { // Clamp to map bounds if(cameraPositionY < FRAME_MAP_HEIGHT / 2) { offsetY = 0; } else if(cameraPositionY >= map->height - (FRAME_MAP_HEIGHT / 2)) { offsetY = -(map->height - FRAME_MAP_HEIGHT); } else { offsetY = -(cameraPositionY - (FRAME_MAP_HEIGHT / 2)); } } // Draw the map i = 0; for(uint16_t y = 0; y < FRAME_MAP_HEIGHT; y++) { for(uint16_t x = 0; x < FRAME_MAP_WIDTH; x++) { if(x < offsetX || y < offsetY || x >= map->width + offsetX || y >= map->height + offsetY) { FRAME_COLOR[i] = COLOR_BLACK; FRAME_BUFFER[i++] = ' '; continue; } // Entity? ent = mapEntityGetByPosition(map, x - offsetX, y - offsetY); if(ent != NULL) { FRAME_COLOR[i] = symbolGetColorByEntity(ent); FRAME_BUFFER[i++] = symbolGetCharByEntity(ent); continue; } // Tile? tile = mapTileGetByPosition(map, x - offsetX, y - offsetY, 0); FRAME_COLOR[i] = symbolGetColorByTile(tile); FRAME_BUFFER[i++] = symbolGetCharByTile(tile); } } // Old code: // i = 0; // for(uint16_t y = 0; y < FRAME_HEIGHT - FRAME_BOTTOM_UI_HEIGHT; y++) { // for(uint16_t x = 0; x < FRAME_WIDTH; x++) { // if(x >= map->width || y >= map->height) { // FRAME_COLOR[i] = COLOR_BLACK; // FRAME_BUFFER[i++] = ' '; // continue; // } // // Entity? // ent = mapEntityGetByPosition(map, x, y); // if(ent != NULL) { // FRAME_COLOR[i] = symbolGetColorByEntity(ent); // FRAME_BUFFER[i++] = symbolGetCharByEntity(ent); // continue; // } // // Tile? // tile = mapTileGetByPosition(map, x, y, 0); // FRAME_COLOR[i] = symbolGetColorByTile(tile); // FRAME_BUFFER[i++] = symbolGetCharByTile(tile); // } // } }