fpona: Add tile coordinates
This commit is contained in:
parent
5d84b91118
commit
bc047675d8
2
External/tely
vendored
2
External/tely
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 9b91e7e1b9bb3a6eb103aeb5de457c4a56fee331
|
Subproject commit 1b331f9ab37baa31b345d5be8d71a8c4c7946f87
|
157
feely_pona.cpp
157
feely_pona.cpp
@ -192,6 +192,21 @@ void TELY_DLL_Init(void *user_data)
|
|||||||
enemy->flags |= TELY_EntityFlag_MoveByMouse;
|
enemy->flags |= TELY_EntityFlag_MoveByMouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: Wall
|
||||||
|
{
|
||||||
|
TELY_GameEntity *entity = TELY_Game_MakeEntityPointerF(game, "V. Wall");
|
||||||
|
entity->local_pos = Dqn_V2_InitNx2(100.f, 300.f);
|
||||||
|
entity->local_hit_box_size = Dqn_V2_InitNx2(100.f, 300.f);
|
||||||
|
entity->flags |= TELY_EntityFlag_Clickable;
|
||||||
|
entity->flags |= TELY_EntityFlag_MoveByKeyboard;
|
||||||
|
entity->flags |= TELY_EntityFlag_MoveByMouse;
|
||||||
|
|
||||||
|
TELY_GameShape *wall = Dqn_FArray_Make(&entity->shapes, Dqn_ZeroMem_Yes);
|
||||||
|
wall->type = TELY_GameShapeType_Rect;
|
||||||
|
wall->p2 = entity->local_hit_box_size;
|
||||||
|
wall->colour = TELY_COLOUR_GREEN_DARK_KHAKI_V4;
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t font_size = 18;
|
uint16_t font_size = 18;
|
||||||
game->camera.scale = Dqn_V2_InitNx1(1);
|
game->camera.scale = Dqn_V2_InitNx1(1);
|
||||||
pona->inter_regular_font = platform->func_load_font(assets, DQN_STRING8("Inter (Regular)"), DQN_STRING8("Data/Inter-Regular.otf"), font_size);
|
pona->inter_regular_font = platform->func_load_font(assets, DQN_STRING8("Inter (Regular)"), DQN_STRING8("Data/Inter-Regular.otf"), font_size);
|
||||||
@ -214,12 +229,38 @@ void TELY_Game_EntityChangeState(TELY_GameEntity *entity, TELY_GameEntityState s
|
|||||||
{
|
{
|
||||||
if (entity->state == state)
|
if (entity->state == state)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
entity->state = state;
|
entity->state = state;
|
||||||
entity->anim.frame = 0;
|
entity->anim.frame = 0;
|
||||||
entity->anim.ticks = 0;
|
entity->anim.ticks = 0;
|
||||||
|
|
||||||
|
// decouple the state from the animation, e.g. the wall doesn't have an animation
|
||||||
|
uint16_t desired_sprite_anim_index = 0;
|
||||||
|
switch (state) {
|
||||||
|
case TELY_GameEntityState_Nil: {
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case TELY_GameEntityState_Idle: {
|
||||||
|
desired_sprite_anim_index = TELY_Asset_GetSpriteAnim(entity->sprite_anims, DQN_STRING8("Idle"));
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case TELY_GameEntityState_Attack: {
|
||||||
|
desired_sprite_anim_index = TELY_Asset_GetSpriteAnim(entity->sprite_anims, DQN_STRING8("Attack A"));
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case TELY_GameEntityState_Run: {
|
||||||
|
desired_sprite_anim_index = TELY_Asset_GetSpriteAnim(entity->sprite_anims, DQN_STRING8("Running"));
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FP_GameUpdate(TELY_Game *game, TELY_Renderer *renderer, TELY_PlatformInput *input)
|
if (entity->sprite_sheet && entity->sprite_anims.size) {
|
||||||
|
TELY_AssetSpriteAnimation const *sprite_anim = entity->sprite_anims.data + entity->anim.index;
|
||||||
|
entity->anim.index = desired_sprite_anim_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dqn_f32 const FP_TILE_SIZE = 37.f;
|
||||||
|
void FP_GameUpdate(TELY_Platform *platform, TELY_Game *game, TELY_Renderer *renderer, TELY_PlatformInput *input)
|
||||||
{
|
{
|
||||||
if (TELY_Platform_InputKeyIsReleased(input->mouse_left))
|
if (TELY_Platform_InputKeyIsReleased(input->mouse_left))
|
||||||
game->clicked_entity = game->prev_active_entity;
|
game->clicked_entity = game->prev_active_entity;
|
||||||
@ -252,6 +293,12 @@ void FP_GameUpdate(TELY_Game *game, TELY_Renderer *renderer, TELY_PlatformInput
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TELY_Platform_InputScanCodeIsPressed(input, TELY_PlatformInputScanCode_F1)) {
|
||||||
|
// NOTE: Do A* algorithm
|
||||||
|
Dqn_V2 world_pos = TELY_Game_CalcEntityWorldPos(game, player->handle);
|
||||||
|
Dqn_V2I player_tile = platform->core.window_size / FP_TILE_SIZE;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
game->camera.world_pos += dir_vector * 5.f;
|
game->camera.world_pos += dir_vector * 5.f;
|
||||||
}
|
}
|
||||||
@ -278,7 +325,24 @@ void FP_GameUpdate(TELY_Game *game, TELY_Renderer *renderer, TELY_PlatformInput
|
|||||||
Dqn_f32 t = DQN_CAST(Dqn_f32)DQN_SQUARED(input->delta_s);
|
Dqn_f32 t = DQN_CAST(Dqn_f32)DQN_SQUARED(input->delta_s);
|
||||||
Dqn_f32 t_squared = DQN_SQUARED(t);
|
Dqn_f32 t_squared = DQN_SQUARED(t);
|
||||||
entity->velocity = (acceleration * t) + entity->velocity * 0.82f;
|
entity->velocity = (acceleration * t) + entity->velocity * 0.82f;
|
||||||
entity->local_pos += (acceleration * 0.5f * t_squared) + (entity->velocity * t);
|
|
||||||
|
Dqn_V2 delta_p = (acceleration * 0.5f * t_squared) + (entity->velocity * t);
|
||||||
|
entity->local_pos += delta_p;
|
||||||
|
|
||||||
|
Dqn_Rect world_hit_box = TELY_Game_CalcEntityWorldHitBox(game, entity->handle);
|
||||||
|
Dqn_Rect new_world_hit_box = world_hit_box;
|
||||||
|
new_world_hit_box.pos += delta_p;
|
||||||
|
|
||||||
|
for (TELY_GameEntityIterator collider_it = {}; TELY_Game_DFSPostOrderWalkEntityTree(game, &collider_it, game->root_entity); ) {
|
||||||
|
TELY_GameEntity *collider = collider_it.entity;
|
||||||
|
if (collider->handle == entity->handle)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// TODO(doyle): Minkowski sweep?
|
||||||
|
Dqn_Rect collider_world_hit_box = TELY_Game_CalcEntityWorldHitBox(game, collider->handle);
|
||||||
|
if (Dqn_Rect_Intersects(new_world_hit_box, collider_world_hit_box)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Move entity by mouse ==============================================================
|
// NOTE: Move entity by mouse ==============================================================
|
||||||
@ -309,51 +373,36 @@ void FP_GameUpdate(TELY_Game *game, TELY_Renderer *renderer, TELY_PlatformInput
|
|||||||
entity->local_hit_box_size = padded_bbox.size;
|
entity->local_hit_box_size = padded_bbox.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Handle animation state ============================================================
|
// NOTE: Tick entity action ================================================================
|
||||||
uint16_t desired_anim_index = 0;
|
|
||||||
switch (entity->state) {
|
|
||||||
case TELY_GameEntityState_Idle: {
|
|
||||||
desired_anim_index = TELY_Asset_GetSpriteAnim(entity->sprite_anims, DQN_STRING8("Idle"));
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case TELY_GameEntityState_Attack: {
|
|
||||||
desired_anim_index = TELY_Asset_GetSpriteAnim(entity->sprite_anims, DQN_STRING8("Attack A"));
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case TELY_GameEntityState_Run: {
|
|
||||||
desired_anim_index = TELY_Asset_GetSpriteAnim(entity->sprite_anims, DQN_STRING8("Run"));
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
|
bool action_is_done = false;
|
||||||
TELY_AssetSpriteAnimation const *sprite_anim = entity->sprite_anims.data + entity->anim.index;
|
TELY_AssetSpriteAnimation const *sprite_anim = entity->sprite_anims.data + entity->anim.index;
|
||||||
if (desired_anim_index == entity->anim.index) { // NOTE: Current anim matches, check if its finished
|
if (sprite_anim) {
|
||||||
if (entity->anim.frame >= sprite_anim->count) { // NOTE: Animation is finished
|
if (entity->anim.frame >= sprite_anim->count) { // NOTE: Animation is finished
|
||||||
entity->anim.frame = 0;
|
entity->anim.frame = 0;
|
||||||
entity->anim.ticks = 0;
|
entity->anim.ticks = 0;
|
||||||
switch (entity->state) {
|
action_is_done = true;
|
||||||
case TELY_GameEntityState_Idle: {
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case TELY_GameEntityState_Attack: {
|
|
||||||
entity->state = TELY_GameEntityState_Idle;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case TELY_GameEntityState_Run: {
|
|
||||||
if (dir_vector.x == 0 && dir_vector.y == 0) {
|
|
||||||
entity->state = TELY_GameEntityState_Idle;
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (entity->anim.ticks++ > 4 /*ticks_per_anim_frame*/) {
|
if (entity->anim.ticks++ > 4 /*ticks_per_anim_frame*/) {
|
||||||
entity->anim.frame++;
|
entity->anim.frame++;
|
||||||
entity->anim.ticks = 0;
|
entity->anim.ticks = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
// NOTE: Current animation does not match the desired animation, change anim
|
|
||||||
entity->anim.index = desired_anim_index;
|
if (action_is_done) {
|
||||||
|
switch (entity->state) {
|
||||||
|
case TELY_GameEntityState_Nil: break;
|
||||||
|
case TELY_GameEntityState_Idle: break;
|
||||||
|
case TELY_GameEntityState_Attack: {
|
||||||
|
TELY_Game_EntityChangeState(entity, TELY_GameEntityState_Idle);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case TELY_GameEntityState_Run: {
|
||||||
|
if (dir_vector.x == 0 && dir_vector.y == 0)
|
||||||
|
TELY_Game_EntityChangeState(entity, TELY_GameEntityState_Idle);
|
||||||
|
} break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,13 +428,10 @@ void FP_GameUpdate(TELY_Game *game, TELY_Renderer *renderer, TELY_PlatformInput
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Resolve collision ====================================================================
|
// NOTE: Do attacks ============================================================================
|
||||||
for (TELY_GameEntityIterator attacker_it = {}; TELY_Game_DFSPostOrderWalkEntityTree(game, &attacker_it, game->root_entity); ) {
|
for (TELY_GameEntityIterator attacker_it = {}; TELY_Game_DFSPostOrderWalkEntityTree(game, &attacker_it, game->root_entity); ) {
|
||||||
TELY_GameEntity *attacker = attacker_it.entity;
|
TELY_GameEntity *attacker = attacker_it.entity;
|
||||||
|
|
||||||
// NOTE: Resolve box collision
|
|
||||||
Dqn_Rect attacker_hit_box = TELY_Game_CalcEntityWorldHitBox(game, attacker->handle);
|
|
||||||
|
|
||||||
// NOTE: Resolve attack boxes
|
// NOTE: Resolve attack boxes
|
||||||
if (Dqn_V2_Area(attacker->attack_box_size)) {
|
if (Dqn_V2_Area(attacker->attack_box_size)) {
|
||||||
Dqn_Rect attacker_box = TELY_Game_CalcEntityAttackWorldHitBox(game, attacker->handle);
|
Dqn_Rect attacker_box = TELY_Game_CalcEntityAttackWorldHitBox(game, attacker->handle);
|
||||||
@ -426,6 +472,23 @@ void FP_GameRender(TELY_Game *game, TELY_Platform *platform, TELY_Renderer *rend
|
|||||||
Dqn_M2x3 model_view = TELY_Game_CameraModelViewM2x3(game->camera, platform);
|
Dqn_M2x3 model_view = TELY_Game_CameraModelViewM2x3(game->camera, platform);
|
||||||
Dqn_V2 world_mouse_p = Dqn_M2x3_MulV2(model_view, input->mouse_p);
|
Dqn_V2 world_mouse_p = Dqn_M2x3_MulV2(model_view, input->mouse_p);
|
||||||
|
|
||||||
|
// NOTE: Draw tiles ============================================================================
|
||||||
|
Dqn_usize tile_count_x = DQN_CAST(Dqn_usize)(platform->core.window_size.w / FP_TILE_SIZE);
|
||||||
|
Dqn_usize tile_count_y = DQN_CAST(Dqn_usize)(platform->core.window_size.h / FP_TILE_SIZE);
|
||||||
|
|
||||||
|
for (Dqn_usize x = 0; x < tile_count_x; x++) {
|
||||||
|
Dqn_V2 start = Dqn_V2_InitNx2((x + 1) * FP_TILE_SIZE, 0);
|
||||||
|
Dqn_V2 end = Dqn_V2_InitNx2(start.x, platform->core.window_size.h);
|
||||||
|
TELY_Render_LineColourV4(renderer, start, end, TELY_Colour_V4Alpha(TELY_COLOUR_WHITE_V4, .25f), 1.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Dqn_usize y = 0; y < tile_count_y; y++) {
|
||||||
|
Dqn_V2 start = Dqn_V2_InitNx2(0, (y + 1) * FP_TILE_SIZE);
|
||||||
|
Dqn_V2 end = Dqn_V2_InitNx2(platform->core.window_size.w, start.y);
|
||||||
|
TELY_Render_LineColourV4(renderer, start, end, TELY_Colour_V4Alpha(TELY_COLOUR_WHITE_V4, .25f), 1.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Draw entities =========================================================================
|
||||||
for (TELY_GameEntityIterator it = {}; TELY_Game_DFSPostOrderWalkEntityTree(game, &it, game->root_entity); ) {
|
for (TELY_GameEntityIterator it = {}; TELY_Game_DFSPostOrderWalkEntityTree(game, &it, game->root_entity); ) {
|
||||||
TELY_GameEntity *entity = it.entity;
|
TELY_GameEntity *entity = it.entity;
|
||||||
entity->alive_time_s += input->delta_s;
|
entity->alive_time_s += input->delta_s;
|
||||||
@ -498,14 +561,20 @@ void FP_GameRender(TELY_Game *game, TELY_Platform *platform, TELY_Renderer *rend
|
|||||||
Dqn_V4 hot_colour = game->hot_entity == entity->handle ? TELY_COLOUR_RED_TOMATO_V4 : TELY_Colour_V4Alpha(TELY_COLOUR_YELLOW_SANDY_V4, .5f);
|
Dqn_V4 hot_colour = game->hot_entity == entity->handle ? TELY_COLOUR_RED_TOMATO_V4 : TELY_Colour_V4Alpha(TELY_COLOUR_YELLOW_SANDY_V4, .5f);
|
||||||
TELY_Render_RectColourV4(renderer, world_hit_box, TELY_RenderShapeMode_Line, hot_colour);
|
TELY_Render_RectColourV4(renderer, world_hit_box, TELY_RenderShapeMode_Line, hot_colour);
|
||||||
|
|
||||||
if (game->hot_entity == entity->handle && (entity->name.size)) {
|
}
|
||||||
|
|
||||||
|
if (game->clicked_entity == entity->handle || game->hot_entity == entity->handle) {
|
||||||
|
if (entity->name.size) {
|
||||||
|
Dqn_V2I player_tile = Dqn_V2I_InitNx2(world_pos.x / FP_TILE_SIZE, world_pos.y / FP_TILE_SIZE);
|
||||||
Dqn_V2 entity_world_pos = TELY_Game_CalcEntityWorldPos(game, entity->handle);
|
Dqn_V2 entity_world_pos = TELY_Game_CalcEntityWorldPos(game, entity->handle);
|
||||||
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr);
|
Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr);
|
||||||
Dqn_String8 label = Dqn_String8_InitF(scratch.allocator,
|
Dqn_String8 label = Dqn_String8_InitF(scratch.allocator,
|
||||||
"%.*s (%.1f, %.1f)",
|
"%.*s (%.1f, %.1f) (%I32d, %I32d)",
|
||||||
DQN_STRING_FMT(entity->name),
|
DQN_STRING_FMT(entity->name),
|
||||||
entity_world_pos.x,
|
entity_world_pos.x,
|
||||||
entity_world_pos.y);
|
entity_world_pos.y,
|
||||||
|
player_tile.x,
|
||||||
|
player_tile.y);
|
||||||
TELY_Render_Text(renderer, world_mouse_p, Dqn_V2_InitNx2(0.f, 1), label);
|
TELY_Render_Text(renderer, world_mouse_p, Dqn_V2_InitNx2(0.f, 1), label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -606,7 +675,7 @@ void TELY_DLL_FrameUpdate(void *user_data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FP_GameUpdate(game, renderer, input);
|
FP_GameUpdate(platform, game, renderer, input);
|
||||||
FP_GameRender(game, platform, renderer);
|
FP_GameRender(game, platform, renderer);
|
||||||
TELY_Audio_MixPlaybackSamples(audio, assets);
|
TELY_Audio_MixPlaybackSamples(audio, assets);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user