146 lines
4.1 KiB
C
146 lines
4.1 KiB
C
/**
|
|
* Copyright (c) 2025 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "sceneoverworld.h"
|
|
#include "rpg/entity/entity.h"
|
|
#include "display/spritebatch.h"
|
|
#include "display/framebuffer.h"
|
|
#include "display/scene/scenemanager.h"
|
|
#include "display/mesh/quad.h"
|
|
#include "asset/assetmanager.h"
|
|
#include "assert/assert.h"
|
|
|
|
#include "display/tileset/tileset_entities.h"
|
|
|
|
sceneoverworld_t SCENE_OVERWORLD;
|
|
asset_t *testAsset;
|
|
ref_t testAssetRef;
|
|
|
|
errorret_t sceneOverworldInit(void) {
|
|
cameraInit(&SCENE_OVERWORLD.camera);
|
|
glm_vec3_copy((vec3){ 0.0f, 1.0f, 0.0f }, SCENE_OVERWORLD.camera.lookat.up);
|
|
SCENE_OVERWORLD.camera.perspective.fov = 45;
|
|
SCENE_OVERWORLD.camera.farClip = 10000.0f;
|
|
|
|
scene_t *scene = &SCENE_MANAGER_SCENES[SCENE_TYPE_OVERWORLD];
|
|
scene->flags |= SCENE_FLAG_ACTIVE | SCENE_FLAG_VISIBLE;
|
|
|
|
errorChain(assetManagerLoadAsset(
|
|
TILESET_ENTITIES.image, &testAsset, &testAssetRef
|
|
));
|
|
|
|
errorOk();
|
|
}
|
|
|
|
void sceneOverworldUpdate(void) {
|
|
if(RPG.map == NULL) return;
|
|
|
|
// Move camera to player.
|
|
const entity_t *start = &RPG.map->entities[0];
|
|
const entity_t *end = &RPG.map->entities[RPG.map->entityCount];
|
|
while(start < end) {
|
|
if(start->type == ENTITY_TYPE_PLAYER) {
|
|
SCENE_OVERWORLD.camera.lookat.target[0] = start->position[0];
|
|
SCENE_OVERWORLD.camera.lookat.target[1] = start->position[1];
|
|
break;
|
|
}
|
|
start++;
|
|
}
|
|
}
|
|
|
|
void sceneOverworldRender(void) {
|
|
const float_t camOffset = 12.0f;
|
|
const float_t fbWidth = frameBufferGetWidth(FRAMEBUFFER_BOUND);
|
|
const float_t fbHeight = frameBufferGetHeight(FRAMEBUFFER_BOUND);
|
|
const float_t aspect = fbWidth / fbHeight;
|
|
const float_t pixelPerfectOffset = tanf(
|
|
(glm_rad(180) - SCENE_OVERWORLD.camera.perspective.fov) / 2.0f
|
|
) * (fbHeight/ 2.0f);
|
|
|
|
// glm_vec3_copy((vec3){
|
|
// -100.0f, -100.0f, 0.0f
|
|
// }, SCENE_OVERWORLD.camera.lookat.target);
|
|
glm_vec3_copy((vec3){
|
|
SCENE_OVERWORLD.camera.lookat.target[0],
|
|
SCENE_OVERWORLD.camera.lookat.target[1] + camOffset,
|
|
SCENE_OVERWORLD.camera.lookat.target[2] + pixelPerfectOffset
|
|
}, SCENE_OVERWORLD.camera.lookat.position);
|
|
|
|
cameraPushMatrix(&SCENE_OVERWORLD.camera);
|
|
|
|
if(RPG.map != NULL) sceneOverworldRenderMap(RPG.map);
|
|
|
|
spriteBatchFlush();
|
|
cameraPopMatrix();
|
|
}
|
|
|
|
void sceneOverworldRenderMap(const map_t *map) {
|
|
assertNotNull(map, "Map pointer cannot be NULL");
|
|
|
|
// Draw base layer
|
|
sceneOverworldRenderMapLayer(map, &map->base);
|
|
|
|
// Draw entities
|
|
const entity_t *start = &map->entities[0];
|
|
const entity_t *end = &map->entities[map->entityCount];
|
|
while(start < end) {
|
|
// Render entity here.
|
|
sceneOverworldRenderEntity(start);
|
|
start++;
|
|
}
|
|
spriteBatchFlush();
|
|
|
|
// Draw overlay layer.
|
|
sceneOverworldRenderMapLayer(map, &map->overlay);
|
|
}
|
|
|
|
void sceneOverworldRenderEntity(const entity_t *entity) {
|
|
assertNotNull(entity, "Entity pointer cannot be NULL");
|
|
assertTrue(entity->type < ENTITY_TYPE_COUNT, "Invalid entity type");
|
|
assertTrue(entity->type != ENTITY_TYPE_NULL, "Cannot have NULL entity type");
|
|
|
|
vec4 uv;
|
|
tilesetPositionGetUV(&TILESET_ENTITIES, entity->direction, 0, uv);
|
|
|
|
// For now, just draw a placeholder quad.
|
|
spriteBatchPush(
|
|
&testAsset->paletteImage.texture,
|
|
entity->position[0], entity->position[1],
|
|
entity->position[0] + TILESET_ENTITIES.tileWidth,
|
|
entity->position[1] + TILESET_ENTITIES.tileHeight,
|
|
COLOR_WHITE,
|
|
uv[0], uv[1], uv[2], uv[3]
|
|
);
|
|
}
|
|
|
|
void sceneOverworldRenderMapLayer(const map_t *map, const maplayer_t *layer) {
|
|
assertNotNull(layer, "Map layer pointer cannot be NULL");
|
|
|
|
for(uint32_t y = 0; y < map->height; y++) {
|
|
for(uint32_t x = 0; x < map->width; x++) {
|
|
const tile_t *tile = &layer->tiles[y * map->width + x];
|
|
if(tile->id == 0) continue;
|
|
|
|
spriteBatchPush(
|
|
NULL,
|
|
x * TILESET_ENTITIES.tileWidth,
|
|
y * TILESET_ENTITIES.tileHeight,
|
|
(x + 1) * TILESET_ENTITIES.tileWidth,
|
|
(y + 1) * TILESET_ENTITIES.tileHeight,
|
|
COLOR_RED,
|
|
0, 0, 1, 1
|
|
);
|
|
}
|
|
}
|
|
|
|
spriteBatchFlush();
|
|
}
|
|
|
|
void sceneOverworldDispose(void) {
|
|
// Dispose of the overworld scene.
|
|
if(testAsset) assetUnlock(testAsset, testAssetRef);
|
|
} |