/** * Copyright (c) 2025 Dominic Masters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #include "drawoverworld.h" #include "world/chunk.h" #include "world/overworld.h" #include "display/render.h" #include "assert/assert.h" Camera2D DRAW_OVERWORLD_CAMERA = { 0 }; void drawOverworldInit(void) { DRAW_OVERWORLD_CAMERA = (Camera2D){ .offset = { 0, 0 }, .target = { 0, 0 }, .rotation = 0.0f, .zoom = 1.0f }; } void drawOverworldDraw(void) { if(OVERWORLD_CAMERA_X < RENDER_WIDTH / 2) { DRAW_OVERWORLD_CAMERA.target.x = 0; } else { DRAW_OVERWORLD_CAMERA.target.x = OVERWORLD_CAMERA_X - (RENDER_WIDTH / 2); } if(OVERWORLD_CAMERA_Y < RENDER_HEIGHT / 2) { DRAW_OVERWORLD_CAMERA.target.y = 0; } else { DRAW_OVERWORLD_CAMERA.target.y = OVERWORLD_CAMERA_Y - (RENDER_HEIGHT / 2); } BeginMode2D(DRAW_OVERWORLD_CAMERA); // Bottom layer chunk_t *chunk = CHUNK_MAP.chunks; Color colors[] = { RED, GREEN, BLUE, YELLOW, PURPLE, ORANGE, PINK, BROWN, DARKGRAY, LIGHTGRAY, DARKBLUE, DARKGREEN, DARKPURPLE, DARKBROWN }; uint8_t colorCount = sizeof(colors) / sizeof(Color); BeginBlendMode(BLEND_ALPHA_PREMULTIPLY); do { // Base layer for(uint8_t i = 0; i < CHUNK_TILE_COUNT; i++) { tile_t tile = chunk->tilesBase[i]; if(tile == 0) continue; // Skip empty tiles uint32_t tilemapIndex = tile - 1; // Convert to zero-based index uint32_t x = (uint32_t)chunk->x * CHUNK_WIDTH * TILE_WIDTH + (i % CHUNK_WIDTH) * TILE_WIDTH; uint32_t y = (uint32_t)chunk->y * CHUNK_HEIGHT * TILE_HEIGHT + (i / CHUNK_WIDTH) * TILE_HEIGHT; uint32_t tilemapX = (tilemapIndex % (RENDER_TILEMAP_TEXTURE.width / TILE_WIDTH)) * TILE_WIDTH; uint32_t tilemapY = (tilemapIndex / (RENDER_TILEMAP_TEXTURE.width / TILE_WIDTH)) * TILE_HEIGHT; DrawTextureRec( RENDER_TILEMAP_TEXTURE, (Rectangle){ tilemapX, tilemapY, TILE_WIDTH, TILE_HEIGHT }, (Vector2){ x, y }, WHITE ); } // Base overlay layer for(uint8_t i = 0; i < CHUNK_TILE_COUNT; i++) { tile_t tile = chunk->tilesBaseOverlay[i]; if(tile == 0) continue; // Skip empty tiles uint32_t tilemapIndex = tile - 1; // Convert to zero-based index uint32_t x = (uint32_t)chunk->x * CHUNK_WIDTH * TILE_WIDTH + (i % CHUNK_WIDTH) * TILE_WIDTH; uint32_t y = (uint32_t)chunk->y * CHUNK_HEIGHT * TILE_HEIGHT + (i / CHUNK_WIDTH) * TILE_HEIGHT; uint32_t tilemapX = (tilemapIndex % (RENDER_TILEMAP_TEXTURE.width / TILE_WIDTH)) * TILE_WIDTH; uint32_t tilemapY = (tilemapIndex / (RENDER_TILEMAP_TEXTURE.width / TILE_WIDTH)) * TILE_HEIGHT; DrawTextureRec( RENDER_TILEMAP_TEXTURE, (Rectangle){ tilemapX, tilemapY, TILE_WIDTH, TILE_HEIGHT }, (Vector2){ x, y }, WHITE ); } chunk++; } while(chunk < CHUNK_MAP.chunks + CHUNK_MAP_COUNT); EndBlendMode(); // Entities entity_t *entity = ENTITIES; do { drawOverworldDrawEntity(entity++); } while(entity->type != ENTITY_TYPE_NULL); EndMode2D(); } void drawOverworldDrawEntity(const entity_t *entity) { assertNotNull(entity, "Entity pointer cannot be NULL"); uint32_t x = (uint32_t)floorf(entity->x); uint32_t y = (uint32_t)floorf(entity->y); uint32_t row = 0; uint32_t col = entity->dir; DrawTextureRec( RENDER_ENTITIES_TEXTURE, (Rectangle){ col * TILE_WIDTH, row * TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT }, (Vector2){ x, y }, WHITE ); // DrawRectangle( // x, // y, // TILE_WIDTH, // TILE_HEIGHT, // (entity->type == ENTITY_TYPE_PLAYER) ? BLUE : YELLOW // ); // switch(entity->dir) { // case ENTITY_DIR_NORTH: // DrawTriangle( // (Vector2){ x + TILE_WIDTH / 2, y }, // (Vector2){ x, y + TILE_HEIGHT }, // (Vector2){ x + TILE_WIDTH, y + TILE_HEIGHT }, // WHITE // ); // break; // case ENTITY_DIR_SOUTH: // DrawTriangle( // (Vector2){ x + TILE_WIDTH / 2, y + TILE_HEIGHT }, // (Vector2){ x + TILE_WIDTH, y }, // (Vector2){ x, y }, // WHITE // ); // break; // case ENTITY_DIR_WEST: // DrawTriangle( // (Vector2){ x, y + TILE_HEIGHT / 2 }, // (Vector2){ x + TILE_WIDTH, y + TILE_HEIGHT }, // (Vector2){ x + TILE_WIDTH, y }, // WHITE // ); // break; // case ENTITY_DIR_EAST: // DrawTriangle( // (Vector2){ x + TILE_WIDTH, y + TILE_HEIGHT / 2 }, // (Vector2){ x, y }, // (Vector2){ x, y + TILE_HEIGHT }, // WHITE // ); // break; // } }