fp: Use meters for calculations

This commit is contained in:
doyle 2023-09-26 00:07:39 +10:00
parent dcf47a106a
commit 7a2bebf3c3
6 changed files with 75 additions and 44 deletions

View File

@ -131,6 +131,8 @@ void TELY_DLL_Init(void *user_data)
TELY_Assets *assets = &platform->assets; TELY_Assets *assets = &platform->assets;
FP_Game *game = Dqn_Arena_New(&platform->arena, FP_Game, Dqn_ZeroMem_Yes); FP_Game *game = Dqn_Arena_New(&platform->arena, FP_Game, Dqn_ZeroMem_Yes);
game->chunk_pool = &platform->chunk_pool; game->chunk_pool = &platform->chunk_pool;
game->meters_to_pixels = 65.416f;
platform->user_data = game; platform->user_data = game;
{ {
TELY_AssetSpriteSheet *sheet = &game->hero_sprite_sheet; TELY_AssetSpriteSheet *sheet = &game->hero_sprite_sheet;
@ -235,13 +237,11 @@ void TELY_DLL_Init(void *user_data)
// NOTE: Mob spawner =========================================================================== // NOTE: Mob spawner ===========================================================================
{ {
FP_GameEntityHandle mob_spawner = FP_Entity_CreateMobSpawner(game, Dqn_V2 mob_spawner_pos = FP_Game_MetersToPixelsNx2(game, 2.f, 5.f);
Dqn_V2_InitNx2(50.f, platform->core.window_size.y * .5f), FP_GameEntityHandle mob_spawner = FP_Entity_CreateMobSpawner(game, mob_spawner_pos, 16 /*spawn_cap*/, "Mob spawner");
16 /*spawn_cap*/,
"Mob spawner");
FP_Game_PushParentEntity(game, mob_spawner); FP_Game_PushParentEntity(game, mob_spawner);
FP_Entity_CreateWaypointF(game, Dqn_V2_InitNx2(800.f, -200.f), "Waypoint"); FP_Entity_CreateWaypointF(game, FP_Game_MetersToPixelsNx2(game, 2.f, 4.f), "Waypoint A");
FP_Entity_CreateWaypointF(game, Dqn_V2_InitNx2(932.f, 200.f), "Waypoint"); FP_Entity_CreateWaypointF(game, FP_Game_MetersToPixelsNx2(game, 14.f, 8.f), "Waypoint B");
FP_Game_PopParentEntity(game); FP_Game_PopParentEntity(game);
} }
@ -638,7 +638,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
entity->alive_time_s += PHYSICS_STEP; entity->alive_time_s += PHYSICS_STEP;
// NOTE: Move entity by keyboard and gamepad =============================================== // NOTE: Move entity by keyboard and gamepad ===============================================
Dqn_V2 acceleration = {}; Dqn_V2 acceleration_meters_per_s = {};
if (game->clicked_entity == entity->handle) { if (game->clicked_entity == entity->handle) {
if (entity->flags & (FP_GameEntityFlag_MoveByKeyboard | FP_GameEntityFlag_MoveByGamepad)) { if (entity->flags & (FP_GameEntityFlag_MoveByKeyboard | FP_GameEntityFlag_MoveByGamepad)) {
bool move_entity = false; bool move_entity = false;
@ -658,7 +658,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
} }
if (move_entity) { if (move_entity) {
acceleration = dir_vector * 10000000.f; acceleration_meters_per_s = dir_vector * 8;
if (dir_vector.x) if (dir_vector.x)
entity->direction = dir_vector.x > 0.f ? FP_GameDirection_Right : FP_GameDirection_Left; entity->direction = dir_vector.x > 0.f ? FP_GameDirection_Right : FP_GameDirection_Left;
else if (dir_vector.y) else if (dir_vector.y)
@ -668,7 +668,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
} }
// NOTE: Determine AI movement ============================================================= // NOTE: Determine AI movement =============================================================
if (acceleration.x == 0 && acceleration.y == 0) { if (acceleration_meters_per_s.x == 0 && acceleration_meters_per_s.y == 0) {
Dqn_V2 entity_pos = FP_Game_CalcEntityWorldPos(game, entity->handle); Dqn_V2 entity_pos = FP_Game_CalcEntityWorldPos(game, entity->handle);
if (entity->flags & FP_GameEntityFlag_AggrosWhenNearTerry) { if (entity->flags & FP_GameEntityFlag_AggrosWhenNearTerry) {
@ -689,7 +689,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
} }
} }
if (closest_terry_dist < DQN_SQUARED(200.f)) { if (closest_terry_dist < DQN_SQUARED(FP_Game_MetersToPixelsNx1(game, 5.f))) {
FP_SentinelListLink<FP_GameEntityHandle> *first_waypoint = FP_SentinelList_Front(&entity->waypoints); FP_SentinelListLink<FP_GameEntityHandle> *first_waypoint = FP_SentinelList_Front(&entity->waypoints);
if (first_waypoint->data != closest_terry->handle) { if (first_waypoint->data != closest_terry->handle) {
FP_SentinelListLink<FP_GameEntityHandle> *link = FP_SentinelList_MakeBefore(&entity->waypoints, first_waypoint, game->chunk_pool); FP_SentinelListLink<FP_GameEntityHandle> *link = FP_SentinelList_MakeBefore(&entity->waypoints, first_waypoint, game->chunk_pool);
@ -720,7 +720,7 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
// NOTE: We haven't arrived yet, calculate an acceleration vector to the waypoint // NOTE: We haven't arrived yet, calculate an acceleration vector to the waypoint
Dqn_V2 entity_to_waypoint_norm = Dqn_V2_Normalise(entity_to_waypoint); Dqn_V2 entity_to_waypoint_norm = Dqn_V2_Normalise(entity_to_waypoint);
acceleration = entity_to_waypoint_norm * 1'000'000.f; acceleration_meters_per_s = entity_to_waypoint_norm * 4.f;
break; break;
} }
} }
@ -734,12 +734,9 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
Dqn_f32 t = DQN_CAST(Dqn_f32)DQN_SQUARED(PHYSICS_STEP); Dqn_f32 t = DQN_CAST(Dqn_f32)DQN_SQUARED(PHYSICS_STEP);
Dqn_f32 t_squared = DQN_SQUARED(t); Dqn_f32 t_squared = DQN_SQUARED(t);
Dqn_f32 velocity_falloff_coefficient = 0.25f; Dqn_f32 velocity_falloff_coefficient = 0.82f;
if (entity->handle == game->clicked_entity) { Dqn_f32 acceleration_feel_good_factor = 15'000.f;
if (dir_vector.x || dir_vector.y) Dqn_V2 acceleration = FP_Game_MetersToPixelsV2(game, acceleration_meters_per_s) * acceleration_feel_good_factor;
velocity_falloff_coefficient = 0.82f;
}
entity->velocity = (acceleration * t) + entity->velocity * velocity_falloff_coefficient; entity->velocity = (acceleration * t) + entity->velocity * velocity_falloff_coefficient;
// NOTE: Zero out velocity with epsilon // NOTE: Zero out velocity with epsilon
@ -749,7 +746,6 @@ void FP_Update(TELY_Platform *platform, FP_Game *game, TELY_PlatformInput *input
entity->velocity.y = 0.f; entity->velocity.y = 0.f;
Dqn_V2 delta_pos = (acceleration * 0.5f * t_squared) + (entity->velocity * t); Dqn_V2 delta_pos = (acceleration * 0.5f * t_squared) + (entity->velocity * t);
Dqn_Rect entity_world_hit_box = FP_Game_CalcEntityWorldHitBox(game, entity->handle); Dqn_Rect entity_world_hit_box = FP_Game_CalcEntityWorldHitBox(game, entity->handle);
Dqn_V2 entity_pos = Dqn_Rect_Center(entity_world_hit_box); Dqn_V2 entity_pos = Dqn_Rect_Center(entity_world_hit_box);
Dqn_V2 entity_new_pos = entity_pos + delta_pos; Dqn_V2 entity_new_pos = entity_pos + delta_pos;
@ -1006,8 +1002,11 @@ void FP_Render(FP_Game *game, TELY_Platform *platform, TELY_Renderer *renderer)
} break; } break;
} }
Dqn_f32 sprite_in_meters = src_rect.size.y * FP_Game_PixelsToMeters(game);
Dqn_f32 size_scale = entity->sprite_height.meters / sprite_in_meters;
Dqn_Rect dest_rect = {}; Dqn_Rect dest_rect = {};
dest_rect.size = src_rect.size * entity->size_scale; dest_rect.size = src_rect.size * size_scale;
dest_rect.pos = world_pos - (dest_rect.size * .5f); dest_rect.pos = world_pos - (dest_rect.size * .5f);
if (sprite.flip & TELY_AssetFlip_X) if (sprite.flip & TELY_AssetFlip_X)

View File

@ -3,12 +3,6 @@
#include "feely_pona_unity.h" #include "feely_pona_unity.h"
#endif #endif
#define FP_SentinelDoublyLinkedList_Insert(list, item) \
item->next = list; \
item->prev = list->prev; \
item->next->prev = item; \
item->prev->next = item;
enum FP_ProfileZone enum FP_ProfileZone
{ {
FP_ProfileZone_FPUpdate = TELY_ProfileZone_Count, FP_ProfileZone_FPUpdate = TELY_ProfileZone_Count,
@ -22,3 +16,8 @@ enum FP_ProfileZone
FP_ProfileZone_FPRender, FP_ProfileZone_FPRender,
}; };
struct FP_Meters
{
Dqn_f32 meters;
};

View File

@ -45,8 +45,8 @@ static FP_GameEntityHandle FP_Entity_CreateSmoochie(FP_Game *game, Dqn_V2 pos, D
entity->type = FP_EntityType_Smoochie; entity->type = FP_EntityType_Smoochie;
entity->local_pos = pos; entity->local_pos = pos;
entity->size_scale = Dqn_V2_InitNx1(.25f); entity->sprite_height.meters = 1.6f;
entity->local_hit_box_size = Dqn_V2_InitNx2(428, 471) * entity->size_scale; entity->local_hit_box_size = Dqn_V2_InitNx2(0.4f, 1.6f) * FP_Game_MetersToPixels(game);
FP_Entity_AddDebugEditorFlags(game, entity->handle); FP_Entity_AddDebugEditorFlags(game, entity->handle);
entity->flags |= FP_GameEntityFlag_NonTraversable; entity->flags |= FP_GameEntityFlag_NonTraversable;
return result; return result;
@ -107,8 +107,8 @@ static FP_GameEntityHandle FP_Entity_CreateTerry(FP_Game *game, Dqn_V2 pos, DQN_
entity->type = FP_EntityType_Terry; entity->type = FP_EntityType_Terry;
entity->local_pos = pos; entity->local_pos = pos;
entity->size_scale = Dqn_V2_InitNx1(0.25f); entity->sprite_height.meters = 1.8f;
entity->local_hit_box_size = Dqn_V2_InitNx2(428, 471) * entity->size_scale; entity->local_hit_box_size = Dqn_V2_InitNx2(0.5f, entity->sprite_height.meters) * FP_Game_MetersToPixels(game);
FP_Entity_AddDebugEditorFlags(game, result); FP_Entity_AddDebugEditorFlags(game, result);
entity->flags |= FP_GameEntityFlag_NonTraversable; entity->flags |= FP_GameEntityFlag_NonTraversable;
return result; return result;
@ -125,7 +125,7 @@ static FP_GameEntityHandle FP_Entity_CreateMerchant(FP_Game *game, Dqn_V2 pos, D
entity->type = FP_EntityType_Merchant; entity->type = FP_EntityType_Merchant;
entity->local_pos = pos; entity->local_pos = pos;
entity->local_hit_box_size = Dqn_V2_InitNx2(50, 50); entity->local_hit_box_size = Dqn_V2_InitNx2(50, 50);
entity->size_scale = Dqn_V2_InitNx1(0.25f); entity->sprite_height.meters = 3.66f;
FP_Entity_AddDebugEditorFlags(game, result); FP_Entity_AddDebugEditorFlags(game, result);
entity->flags |= FP_GameEntityFlag_NonTraversable; entity->flags |= FP_GameEntityFlag_NonTraversable;

View File

@ -3,6 +3,36 @@
#include "feely_pona_unity.h" #include "feely_pona_unity.h"
#endif #endif
static Dqn_f32 FP_Game_PixelsToMeters(FP_Game const *game)
{
Dqn_f32 result = game ? (1.f / game->meters_to_pixels) : 10.f;
return result;
}
static Dqn_f32 FP_Game_MetersToPixels(FP_Game const *game)
{
Dqn_f32 result = game ? game->meters_to_pixels : 1 / 10.f;
return result;
}
static Dqn_V2 FP_Game_MetersToPixelsV2(FP_Game const *game, Dqn_V2 pos)
{
Dqn_V2 result = pos * FP_Game_MetersToPixels(game);
return result;
}
static Dqn_f32 FP_Game_MetersToPixelsNx1(FP_Game const *game, Dqn_f32 val)
{
Dqn_f32 result = val * FP_Game_MetersToPixels(game);
return result;
}
static Dqn_V2 FP_Game_MetersToPixelsNx2(FP_Game const *game, Dqn_f32 x, Dqn_f32 y)
{
Dqn_V2 result = Dqn_V2_InitNx2(x, y) * FP_Game_MetersToPixels(game);
return result;
}
static bool operator==(FP_GameEntityHandle const &lhs, FP_GameEntityHandle const &rhs) static bool operator==(FP_GameEntityHandle const &lhs, FP_GameEntityHandle const &rhs)
{ {
bool result = lhs.id == rhs.id; bool result = lhs.id == rhs.id;
@ -203,7 +233,7 @@ static FP_GameEntity *FP_Game_MakeEntityPointerFV(FP_Game *game, DQN_FMT_STRING_
result->handle.id = (game->entities.size - 1) & FP_GAME_ENTITY_HANDLE_INDEX_MASK; result->handle.id = (game->entities.size - 1) & FP_GAME_ENTITY_HANDLE_INDEX_MASK;
} }
result->size_scale = Dqn_V2_InitNx1(1); result->sprite_height.meters = 1;
result->parent = FP_Game_ActiveParentEntityPointer(game); result->parent = FP_Game_ActiveParentEntityPointer(game);
result->name = TELY_ChunkPool_AllocFmtFV(game->chunk_pool, fmt, args); result->name = TELY_ChunkPool_AllocFmtFV(game->chunk_pool, fmt, args);

View File

@ -97,7 +97,9 @@ struct FP_GameEntity
Dqn_String8 name; Dqn_String8 name;
FP_GameEntityHandle handle; FP_GameEntityHandle handle;
Dqn_V2 size_scale; // The target size to render the sprite in meters. The width of the sprite
// is scaled uniformly with respect to the height.
FP_Meters sprite_height;
FP_GameEntityAction action; FP_GameEntityAction action;
Dqn_V2 velocity; Dqn_V2 velocity;
@ -175,6 +177,7 @@ struct FP_Game
FP_GameCamera camera; FP_GameCamera camera;
TELY_RFui rfui; TELY_RFui rfui;
Dqn_f32 meters_to_pixels;
uint64_t clock_ms; uint64_t clock_ms;
}; };

View File

@ -61,10 +61,10 @@ DQN_MSVC_WARNING_DISABLE(4505) // warning C4505: unreferenced function with inte
#include "External/tely/tely_rfui.cpp" #include "External/tely/tely_rfui.cpp"
// NOTE: feely_pona ================================================================================ // NOTE: feely_pona ================================================================================
#include "feely_pona.h"
#include "feely_pona_stdlib.h" #include "feely_pona_stdlib.h"
#include "feely_pona_entity.h" #include "feely_pona_entity.h"
#include "feely_pona_game.h" #include "feely_pona_game.h"
#include "feely_pona.h"
#include "feely_pona_game.cpp" #include "feely_pona_game.cpp"
#include "feely_pona_entity.cpp" #include "feely_pona_entity.cpp"