diff --git a/src/display/camera.c b/src/display/camera.c index abccd9a..064dc07 100644 --- a/src/display/camera.c +++ b/src/display/camera.c @@ -63,6 +63,7 @@ void cameraPushMatrix(camera_t *camera) { ); break; + case CAMERA_PROJECTION_TYPE_PERSPECTIVE_FLIPPED: case CAMERA_PROJECTION_TYPE_PERSPECTIVE: const float_t aspect = ( (float_t)frameBufferGetWidth(FRAMEBUFFER_BOUND) / @@ -75,6 +76,12 @@ void cameraPushMatrix(camera_t *camera) { camera->farClip, projection ); + + if(camera->projType == CAMERA_PROJECTION_TYPE_PERSPECTIVE_FLIPPED) { + // Flip Y axis + projection[1][1] *= -1; + } + break; } switch(camera->viewType) { diff --git a/src/display/camera.h b/src/display/camera.h index 8fc7bce..08dde36 100644 --- a/src/display/camera.h +++ b/src/display/camera.h @@ -13,6 +13,7 @@ typedef enum { CAMERA_PROJECTION_TYPE_PERSPECTIVE, + CAMERA_PROJECTION_TYPE_PERSPECTIVE_FLIPPED, CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC } cameraprojectiontype_t; diff --git a/src/rpg/entity/entity.c b/src/rpg/entity/entity.c index ea0f152..87acd56 100644 --- a/src/rpg/entity/entity.c +++ b/src/rpg/entity/entity.c @@ -56,12 +56,21 @@ void entityUpdate(entity_t *entity) { worldChunkPosAdd(&entity->position[i], entity->velocity[i]); - if(entity->velocity[i] < 0) { - entity->velocity[i] += ENTITY_FRICTION; - if(entity->velocity[i] >= -ENTITY_MIN_VELOCITY) entity->velocity[i] = 0; - } else { - entity->velocity[i] -= ENTITY_FRICTION; - if(entity->velocity[i] <= ENTITY_MIN_VELOCITY) entity->velocity[i] = 0; + // Friction + worldsubtile_t v = entity->velocity[i]; + + if (v > 0) { + v -= ENTITY_FRICTION; + if (v < ENTITY_MIN_VELOCITY) v = 0; + } else if (v < 0) { + v += ENTITY_FRICTION; + if (v > -ENTITY_MIN_VELOCITY) v = 0; } + + if ((v > 0 && v < ENTITY_FRICTION) || (v < 0 && v > -ENTITY_FRICTION)) { + v = 0; + } + + entity->velocity[i] = v; } } \ No newline at end of file diff --git a/src/rpg/entity/player.c b/src/rpg/entity/player.c index 13dea19..bfd0a1f 100644 --- a/src/rpg/entity/player.c +++ b/src/rpg/entity/player.c @@ -18,49 +18,46 @@ void playerMovement(entity_t *entity) { assertNotNull(entity, "Entity pointer cannot be NULL"); // Get movement angle as 0-> normalized vector. - { - vec2 dir = { - inputAxis(INPUT_ACTION_LEFT, INPUT_ACTION_RIGHT), - inputAxis(INPUT_ACTION_DOWN, INPUT_ACTION_UP) - }; - if(dir[0] == 0 && dir[1] == 0) return; - glm_vec2_normalize(dir); - - entity->velocity[0] += (worldsubtile_t)(PLAYER_SPEED * dir[0]); - entity->velocity[1] += (worldsubtile_t)(PLAYER_SPEED * dir[1]); + vec2 dir = { + inputAxis(INPUT_ACTION_LEFT, INPUT_ACTION_RIGHT), + inputAxis(INPUT_ACTION_DOWN, INPUT_ACTION_UP) + }; + if(dir[0] == 0 && dir[1] == 0) return; + glm_vec2_normalize(dir); + + entity->velocity[0] += (worldsubtile_t)(PLAYER_SPEED * dir[0]); + entity->velocity[1] += (worldsubtile_t)(PLAYER_SPEED * dir[1]); + + // Update direction. + if(dir[0] > 0) { + if(entity->direction == DIRECTION_RIGHT) { + entity->direction = DIRECTION_RIGHT; + } else { + if(dir[1] < 0) { + entity->direction = DIRECTION_UP; + } else if(dir[1] > 0) { + entity->direction = DIRECTION_DOWN; + } else { + entity->direction = DIRECTION_RIGHT; + } + } + } else if(dir[0] < 0) { + if(entity->direction == DIRECTION_LEFT) { + entity->direction = DIRECTION_LEFT; + } else { + if(dir[1] < 0) { + entity->direction = DIRECTION_UP; + } else if(dir[1] > 0) { + entity->direction = DIRECTION_DOWN; + } else { + entity->direction = DIRECTION_LEFT; + } + } + } else if(dir[1] < 0) { + entity->direction = DIRECTION_UP; + } else if(dir[1] > 0) { + entity->direction = DIRECTION_DOWN; } - - - // // Update direction. - // if(dir[0] > 0) { - // if(entity->direction == DIRECTION_RIGHT) { - // entity->direction = DIRECTION_RIGHT; - // } else { - // if(dir[1] < 0) { - // entity->direction = DIRECTION_UP; - // } else if(dir[1] > 0) { - // entity->direction = DIRECTION_DOWN; - // } else { - // entity->direction = DIRECTION_RIGHT; - // } - // } - // } else if(dir[0] < 0) { - // if(entity->direction == DIRECTION_LEFT) { - // entity->direction = DIRECTION_LEFT; - // } else { - // if(dir[1] < 0) { - // entity->direction = DIRECTION_UP; - // } else if(dir[1] > 0) { - // entity->direction = DIRECTION_DOWN; - // } else { - // entity->direction = DIRECTION_LEFT; - // } - // } - // } else if(dir[1] < 0) { - // entity->direction = DIRECTION_UP; - // } else if(dir[1] > 0) { - // entity->direction = DIRECTION_DOWN; - // } } void playerInteraction(entity_t *entity) { diff --git a/src/rpg/entity/player.h b/src/rpg/entity/player.h index 41bd590..ff4dcf9 100644 --- a/src/rpg/entity/player.h +++ b/src/rpg/entity/player.h @@ -8,7 +8,7 @@ #pragma once #include "dusk.h" -#define PLAYER_SPEED 4 +#define PLAYER_SPEED 3 #define PLAYER_INTERACTION_RANGE 1.0f #define PLAYER_INTERACTION_SIZE 0.5f diff --git a/src/rpg/world/worldunit.c b/src/rpg/world/worldunit.c index 97ce1b7..d69e2e6 100644 --- a/src/rpg/world/worldunit.c +++ b/src/rpg/world/worldunit.c @@ -8,32 +8,33 @@ #include "worldunit.h" #include "assert/assert.h" -void worldChunkPosAdd( - worldchunkpos_t *pos, - const worldsubtile_t amt -) { - int8_t a = pos->subtile; // current signed subtile - int8_t b = amt; // signed delta - uint8_t unsignedAdded = (uint8_t)a + (uint8_t)b; // well-defined wrap add - int8_t r = (int8_t)unsignedAdded; // result in signed domain +void worldChunkPosAdd(worldchunkpos_t *pos, worldsubtile_t amt) { + assertNotNull(pos, "Position pointer cannot be NULL"); - pos->subtile = r; + /* + int32_t sum = (int32_t)pos->subtile + (int32_t)amt; + int32_t shifted = sum + 128; // may be negative or large + int32_t carry = div_floor(shifted, 256); // tiles to add (can be neg) + int32_t rem = mod_floor(shifted, 256); // 0..255 + int32_t new_sub = rem - 128; // back to [-128,127] - // Signed-overflow detection for a + b -> r: - // overflow if sign(a) == sign(b) and sign(r) != sign(a) - uint8_t ov = (uint8_t)((a ^ r) & (b ^ r)) >> 7; // 1 if overflow, else 0 - - // Direction of carry: +1 for b >= 0, -1 for b < 0 (computed branchlessly) - uint8_t neg = ((uint8_t)b) >> 7; // 0 if b>=0, 1 if b<0 - int8_t dir = (int8_t)(1 - (neg << 1)); // +1 or -1 - - // Apply tile adjustment (mod-256 via uint8_t arithmetic) - pos->tile = (uint8_t)(pos->tile + (uint8_t)(ov * (uint8_t)dir)); + pos->subtile = (int8_t)new_sub; + pos->tile = (uint8_t)((int32_t)pos->tile + carry); // wrap mod 256 + */ + + int32_t shiftedTotal = (int32_t)pos->subtile + (int32_t)amt + 128; + int32_t tileCarry = shiftedTotal >> 8; // divide by 256 + int32_t wrappedSubtile = shiftedTotal - (tileCarry << 8); + pos->subtile = (int8_t)(wrappedSubtile - 128); + pos->tile = (uint8_t)(pos->tile + (uint8_t)tileCarry); } -float_t worldChunkPosToF32( - const worldchunkpos_t pos, - const uint8_t tileSize -) { - return (float_t)(pos.tile * tileSize) + ((float_t)pos.subtile / 256.0f); + + +float_t worldChunkPosToF32(worldchunkpos_t pos, const uint8_t tileSize) { + const float scaleFactor = (float)tileSize * (1.0f / 256.0f); + return ( + (float)pos.tile * (float)tileSize + ((float)pos.subtile + 128.0f) * + scaleFactor + ); } \ No newline at end of file diff --git a/src/scene/scene/scenemap.c b/src/scene/scene/scenemap.c index fe9691d..9bd0436 100644 --- a/src/scene/scene/scenemap.c +++ b/src/scene/scene/scenemap.c @@ -12,11 +12,12 @@ #include "rpg/entity/entity.h" #include "display/screen.h" -#define TILE_WIDTH 1 +#define TILE_WIDTH 8 #define TILE_HEIGHT TILE_WIDTH errorret_t sceneMapInit(scenedata_t *data) { cameraInitPerspective(&data->sceneMap.camera); + data->sceneMap.camera.projType = CAMERA_PROJECTION_TYPE_PERSPECTIVE_FLIPPED; errorOk(); } @@ -25,7 +26,7 @@ void sceneMapUpdate(scenedata_t *data) { } void sceneMapRender(scenedata_t *data) { - const float_t camOffset = 12.0f; + const float_t camOffset = 32.0f; const float_t pixelPerfectOffset = tanf( data->sceneMap.camera.perspective.fov / 2.0f ) * ((float_t)SCREEN.height / 2.0f); @@ -56,6 +57,8 @@ void sceneMapRenderEntity(const entity_t *entity) { float_t x = worldChunkPosToF32(entity->position[0], TILE_WIDTH); float_t y = worldChunkPosToF32(entity->position[1], TILE_HEIGHT); + x -= TILE_WIDTH * 0.5f; + y -= TILE_HEIGHT * 0.5f; spriteBatchPush( NULL,