rename 'game' -> 'sim'
This commit is contained in:
parent
b9ec028bfa
commit
4cbc6b6d59
10
src/app.c
10
src/app.c
@ -5,7 +5,7 @@
|
|||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
#include "work.h"
|
#include "work.h"
|
||||||
#include "user.h"
|
#include "user.h"
|
||||||
#include "game.h"
|
#include "sim.h"
|
||||||
#include "playback.h"
|
#include "playback.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
@ -139,8 +139,8 @@ void app_entry_point(void)
|
|||||||
{
|
{
|
||||||
/* FIXME: Switch this on to utilize all cores. Only decreasing worker count for testing purposes. */
|
/* FIXME: Switch this on to utilize all cores. Only decreasing worker count for testing purposes. */
|
||||||
#if !PROFILING && !RTC
|
#if !PROFILING && !RTC
|
||||||
/* 1. User thread, Input thread
|
/* 1. User thread
|
||||||
* 2. Game thread
|
* 2. Sim thread
|
||||||
* 3. Playback thread
|
* 3. Playback thread
|
||||||
*/
|
*/
|
||||||
u32 num_reserved_cores = 3;
|
u32 num_reserved_cores = 3;
|
||||||
@ -223,8 +223,8 @@ void app_entry_point(void)
|
|||||||
struct sound_startup_receipt sound_sr = sound_startup(&work_sr, &asset_cache_sr, &resource_sr);
|
struct sound_startup_receipt sound_sr = sound_startup(&work_sr, &asset_cache_sr, &resource_sr);
|
||||||
struct draw_startup_receipt draw_sr = draw_startup(&renderer_sr, &font_sr);
|
struct draw_startup_receipt draw_sr = draw_startup(&renderer_sr, &font_sr);
|
||||||
struct phys_startup_receipt phys_sr = phys_startup();
|
struct phys_startup_receipt phys_sr = phys_startup();
|
||||||
struct game_startup_receipt game_sr = game_startup(&mixer_sr, &sprite_sr, &sound_sr, &phys_sr, &host_sr);
|
struct sim_startup_receipt sim_sr = sim_startup(&mixer_sr, &sprite_sr, &sound_sr, &phys_sr, &host_sr);
|
||||||
struct user_startup_receipt user_sr = user_startup(&work_sr, &renderer_sr, &font_sr, &sprite_sr, &draw_sr, &game_sr, &asset_cache_sr, &mixer_sr, &host_sr, &window);
|
struct user_startup_receipt user_sr = user_startup(&work_sr, &renderer_sr, &font_sr, &sprite_sr, &draw_sr, &sim_sr, &asset_cache_sr, &mixer_sr, &host_sr, &window);
|
||||||
struct playback_startup_receipt playback_sr = playback_startup(&mixer_sr);
|
struct playback_startup_receipt playback_sr = playback_startup(&mixer_sr);
|
||||||
|
|
||||||
(UNUSED)user_sr;
|
(UNUSED)user_sr;
|
||||||
|
|||||||
30
src/config.h
30
src/config.h
@ -34,26 +34,26 @@
|
|||||||
#define SPACE_CELL_SIZE 1.0f
|
#define SPACE_CELL_SIZE 1.0f
|
||||||
|
|
||||||
|
|
||||||
#define GAME_FPS 50.0
|
#define SIM_FPS 50.0
|
||||||
#define GAME_TIMESCALE 1
|
#define SIM_TIMESCALE 1
|
||||||
|
|
||||||
#define GAME_PHYSICS_SUBSTEPS 4
|
#define SIM_PHYSICS_SUBSTEPS 4
|
||||||
#define GAME_PHYSICS_ENABLE_WARM_STARTING 1
|
#define SIM_PHYSICS_ENABLE_WARM_STARTING 1
|
||||||
#define GAME_PHYSICS_ENABLE_RELAXATION 1
|
#define SIM_PHYSICS_ENABLE_RELAXATION 1
|
||||||
#define GAME_PHYSICS_ENABLE_TOI 1
|
#define SIM_PHYSICS_ENABLE_TOI 1
|
||||||
|
|
||||||
#define GAME_PHYSICS_ENABLE_COLLISION 1
|
#define SIM_PHYSICS_ENABLE_COLLISION 1
|
||||||
#define GAME_SPAWN_TESTENT 0
|
#define SIM_SPAWN_TESTENT 0
|
||||||
#define GAME_PLAYER_AIM 1
|
#define SIM_PLAYER_AIM 1
|
||||||
|
|
||||||
//#define GAME_MAX_LINEAR_VELOCITY 500
|
//#define SIM_MAX_LINEAR_VELOCITY 500
|
||||||
//#define GAME_MAX_ANGULAR_VELOCITY (TAU * 20)
|
//#define SIM_MAX_ANGULAR_VELOCITY (TAU * 20)
|
||||||
#define GAME_MAX_LINEAR_VELOCITY F32_INFINITY
|
#define SIM_MAX_LINEAR_VELOCITY F32_INFINITY
|
||||||
#define GAME_MAX_ANGULAR_VELOCITY F32_INFINITY
|
#define SIM_MAX_ANGULAR_VELOCITY F32_INFINITY
|
||||||
|
|
||||||
/* How many ticks back in time should the user blend between?
|
/* How many ticks back in time should the user blend between?
|
||||||
* <Delay ms> = <USER_INTERP_OFFSET_TICK_RATIO> * <Game tick rate>
|
* <Delay ms> = <USER_INTERP_OFFSET_TICK_RATIO> * <Sim tick rate>
|
||||||
* E.g: At 1.5, the user thread will render 75ms back in time (if game thread runs at 50FPS)
|
* E.g: At 1.5, the user thread will render 75ms back in time (if sim thread runs at 50FPS)
|
||||||
*/
|
*/
|
||||||
#define USER_INTERP_OFFSET_TICK_RATIO 1.1
|
#define USER_INTERP_OFFSET_TICK_RATIO 1.1
|
||||||
#define USER_INTERP_ENABLED 1
|
#define USER_INTERP_ENABLED 1
|
||||||
|
|||||||
@ -391,8 +391,8 @@ void entity_set_xform(struct entity *ent, struct xform xf);
|
|||||||
void entity_set_local_xform(struct entity *ent, struct xform xf);
|
void entity_set_local_xform(struct entity *ent, struct xform xf);
|
||||||
|
|
||||||
/* Movement */
|
/* Movement */
|
||||||
INLINE void entity_set_linear_velocity(struct entity *ent, struct v2 velocity) { ent->linear_velocity = v2_clamp_len(velocity, GAME_MAX_LINEAR_VELOCITY); }
|
INLINE void entity_set_linear_velocity(struct entity *ent, struct v2 velocity) { ent->linear_velocity = v2_clamp_len(velocity, SIM_MAX_LINEAR_VELOCITY); }
|
||||||
INLINE void entity_set_angular_velocity(struct entity *ent, f32 velocity) { ent->angular_velocity = clamp_f32(velocity, -GAME_MAX_ANGULAR_VELOCITY, GAME_MAX_ANGULAR_VELOCITY); }
|
INLINE void entity_set_angular_velocity(struct entity *ent, f32 velocity) { ent->angular_velocity = clamp_f32(velocity, -SIM_MAX_ANGULAR_VELOCITY, SIM_MAX_ANGULAR_VELOCITY); }
|
||||||
void entity_apply_linear_impulse(struct entity *ent, struct v2 impulse, struct v2 world_point);
|
void entity_apply_linear_impulse(struct entity *ent, struct v2 impulse, struct v2 world_point);
|
||||||
void entity_apply_linear_impulse_to_center(struct entity *ent, struct v2 impulse);
|
void entity_apply_linear_impulse_to_center(struct entity *ent, struct v2 impulse);
|
||||||
void entity_apply_force_to_center(struct entity *ent, struct v2 force);
|
void entity_apply_force_to_center(struct entity *ent, struct v2 force);
|
||||||
|
|||||||
135
src/game.h
135
src/game.h
@ -1,135 +0,0 @@
|
|||||||
#ifndef GAME_H
|
|
||||||
#define GAME_H
|
|
||||||
|
|
||||||
#include "host.h"
|
|
||||||
|
|
||||||
struct world;
|
|
||||||
struct mixer_startup_receipt;
|
|
||||||
struct sprite_startup_receipt;
|
|
||||||
struct sound_startup_receipt;
|
|
||||||
struct phys_startup_receipt;
|
|
||||||
struct host_startup_receipt;
|
|
||||||
|
|
||||||
/* Absolute layers */
|
|
||||||
#define GAME_LAYER_FLOOR_DECALS -300
|
|
||||||
#define GAME_LAYER_BULLETS -200
|
|
||||||
#define GAME_LAYER_TRACERS -100
|
|
||||||
#define GAME_LAYER_SHOULDERS 0
|
|
||||||
|
|
||||||
/* Relative layers */
|
|
||||||
#define GAME_LAYER_RELATIVE_DEFAULT 0
|
|
||||||
#define GAME_LAYER_RELATIVE_WEAPON 1
|
|
||||||
|
|
||||||
struct game_startup_receipt { i32 _; };
|
|
||||||
struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
|
|
||||||
struct sprite_startup_receipt *sheet_sr,
|
|
||||||
struct sound_startup_receipt *sound_sr,
|
|
||||||
struct phys_startup_receipt *phys_sr,
|
|
||||||
struct host_startup_receipt *host_sr);
|
|
||||||
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Game cmd
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
enum game_cmd_state {
|
|
||||||
GAME_CMD_STATE_STOP = -1,
|
|
||||||
GAME_CMD_STATE_NO_CHANGE = 0,
|
|
||||||
GAME_CMD_STATE_START = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
enum game_cmd_kind {
|
|
||||||
GAME_CMD_KIND_NONE,
|
|
||||||
|
|
||||||
GAME_CMD_KIND_PLAYER_MOVE,
|
|
||||||
GAME_CMD_KIND_PLAYER_FIRE,
|
|
||||||
|
|
||||||
GAME_CMD_KIND_CLIENT_CONNECT,
|
|
||||||
GAME_CMD_KIND_CLIENT_DISCONNECT,
|
|
||||||
|
|
||||||
/* Testing */
|
|
||||||
GAME_CMD_KIND_CLEAR_ALL,
|
|
||||||
GAME_CMD_KIND_SPAWN_TEST,
|
|
||||||
GAME_CMD_KIND_PAUSE,
|
|
||||||
GAME_CMD_KIND_STEP,
|
|
||||||
GAME_CMD_KIND_DRAG_OBJECT,
|
|
||||||
GAME_CMD_KIND_CURSOR_MOVE,
|
|
||||||
|
|
||||||
GAME_CMD_KIND_COUNT
|
|
||||||
};
|
|
||||||
|
|
||||||
struct game_cmd {
|
|
||||||
enum game_cmd_kind kind;
|
|
||||||
enum game_cmd_state state;
|
|
||||||
struct host_channel_id channel_id;
|
|
||||||
|
|
||||||
/* GAME_CMD_KIND_PLAYER_MOVE */
|
|
||||||
struct v2 move_dir;
|
|
||||||
struct v2 aim_dir;
|
|
||||||
|
|
||||||
/* GAME_CMD_KIND_CURSOR_MOVE */
|
|
||||||
struct v2 cursor_pos;
|
|
||||||
|
|
||||||
/* GAME_CMD_KIND_PLAYER_DISCONNECT */
|
|
||||||
struct string disconnect_reason;
|
|
||||||
|
|
||||||
#if RTC
|
|
||||||
u32 collider_gjk_steps;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct game_cmd *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct game_cmd_list {
|
|
||||||
struct game_cmd *first;
|
|
||||||
struct game_cmd *last;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct string game_string_from_cmds(struct arena *arena, struct game_cmd_list cmds);
|
|
||||||
void game_cmds_from_host_events(struct arena *arena, struct host_event_array host_events, struct game_cmd_list *cmds_out);
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Game event
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
enum game_event_kind {
|
|
||||||
GAME_EVENT_KIND_NONE,
|
|
||||||
|
|
||||||
GAME_EVENT_KIND_CONNECT,
|
|
||||||
GAME_EVENT_KIND_DISCONNECT,
|
|
||||||
GAME_EVENT_KIND_SNAPSHOT_FULL,
|
|
||||||
|
|
||||||
//GAME_EVENT_KIND_ENTITY_UPDATE,
|
|
||||||
//GAME_EVENT_KIND_ENTITY_CREATE,
|
|
||||||
//GAME_EVENT_KIND_ENTITY_DESTROY
|
|
||||||
};
|
|
||||||
|
|
||||||
struct game_event {
|
|
||||||
enum game_event_kind kind;
|
|
||||||
struct host_channel_id channel_id;
|
|
||||||
|
|
||||||
struct string snapshot_data;
|
|
||||||
struct string disconnect_reason;
|
|
||||||
|
|
||||||
//struct entity_handle entity;
|
|
||||||
//struct string update_data;
|
|
||||||
|
|
||||||
struct game_event *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct game_event_list {
|
|
||||||
struct game_event *first;
|
|
||||||
struct game_event *last;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct string game_string_from_events(struct arena *arena, struct game_event_list events);
|
|
||||||
void game_events_from_host_events(struct arena *arena, struct host_event_array host_events, struct game_event_list *events_out);
|
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Snapshot
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
struct string game_string_from_tick(struct arena *arena, struct world *tick);
|
|
||||||
void game_tick_from_string(struct string str, struct world *tick_out);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
20
src/phys.c
20
src/phys.c
@ -19,7 +19,7 @@ GLOBAL struct {
|
|||||||
struct phys_startup_receipt phys_startup(void)
|
struct phys_startup_receipt phys_startup(void)
|
||||||
{
|
{
|
||||||
/* Initialize constants */
|
/* Initialize constants */
|
||||||
const f32 substep_dt = (1.f / ((f32)GAME_FPS * (f32)GAME_PHYSICS_SUBSTEPS));
|
const f32 substep_dt = (1.f / ((f32)SIM_FPS * (f32)SIM_PHYSICS_SUBSTEPS));
|
||||||
|
|
||||||
const f32 contact_frequency = (1.f / substep_dt) / 8.f;
|
const f32 contact_frequency = (1.f / substep_dt) / 8.f;
|
||||||
const f32 contact_damping_ratio = 10;
|
const f32 contact_damping_ratio = 10;
|
||||||
@ -354,7 +354,7 @@ void phys_prepare_contacts(struct phys_ctx *ctx, u64 phys_iteration)
|
|||||||
contact->inv_tangent_mass = k > 0.0f ? 1.0f / k : 0.0f;
|
contact->inv_tangent_mass = k > 0.0f ? 1.0f / k : 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !GAME_PHYSICS_ENABLE_WARM_STARTING
|
#if !SIM_PHYSICS_ENABLE_WARM_STARTING
|
||||||
contact->normal_impulse = 0;
|
contact->normal_impulse = 0;
|
||||||
contact->tangent_impulse = 0;
|
contact->tangent_impulse = 0;
|
||||||
#endif
|
#endif
|
||||||
@ -646,7 +646,7 @@ void phys_prepare_motor_joints(struct phys_ctx *ctx)
|
|||||||
|
|
||||||
joint->angular_mass = 1.f / (inv_i0 + inv_i1);
|
joint->angular_mass = 1.f / (inv_i0 + inv_i1);
|
||||||
|
|
||||||
#if !GAME_PHYSICS_ENABLE_WARM_STARTING
|
#if !SIM_PHYSICS_ENABLE_WARM_STARTING
|
||||||
joint->linear_impulse = V2(0, 0);
|
joint->linear_impulse = V2(0, 0);
|
||||||
joint->angular_impulse = 0;
|
joint->angular_impulse = 0;
|
||||||
#endif
|
#endif
|
||||||
@ -874,7 +874,7 @@ void phys_prepare_mouse_joints(struct phys_ctx *ctx)
|
|||||||
linear_mass_xf.by.y = inv_m + inv_i * vcp.x * vcp.x;
|
linear_mass_xf.by.y = inv_m + inv_i * vcp.x * vcp.x;
|
||||||
joint->linear_mass_xf = xform_invert(linear_mass_xf);
|
joint->linear_mass_xf = xform_invert(linear_mass_xf);
|
||||||
|
|
||||||
#if !GAME_PHYSICS_ENABLE_WARM_STARTING
|
#if !SIM_PHYSICS_ENABLE_WARM_STARTING
|
||||||
joint->linear_impulse = V2(0, 0);
|
joint->linear_impulse = V2(0, 0);
|
||||||
joint->angular_impulse = 0;
|
joint->angular_impulse = 0;
|
||||||
#endif
|
#endif
|
||||||
@ -1150,7 +1150,7 @@ u64 phys_step(struct phys_ctx *ctx, f32 timestep, u64 last_phys_iteration)
|
|||||||
/* TOI */
|
/* TOI */
|
||||||
f32 step_dt = remaining_dt;
|
f32 step_dt = remaining_dt;
|
||||||
{
|
{
|
||||||
#if GAME_PHYSICS_ENABLE_TOI
|
#if SIM_PHYSICS_ENABLE_TOI
|
||||||
const f32 min_toi = 0.000001f;
|
const f32 min_toi = 0.000001f;
|
||||||
const f32 tolerance = 0.0001f;
|
const f32 tolerance = 0.0001f;
|
||||||
const u32 max_iterations = 16;
|
const u32 max_iterations = 16;
|
||||||
@ -1175,19 +1175,19 @@ u64 phys_step(struct phys_ctx *ctx, f32 timestep, u64 last_phys_iteration)
|
|||||||
ctx->pre_solve_callback(collision_data);
|
ctx->pre_solve_callback(collision_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
f32 substep_dt = step_dt / GAME_PHYSICS_SUBSTEPS;
|
f32 substep_dt = step_dt / SIM_PHYSICS_SUBSTEPS;
|
||||||
for (u32 i = 0; i < GAME_PHYSICS_SUBSTEPS; ++i) {
|
for (u32 i = 0; i < SIM_PHYSICS_SUBSTEPS; ++i) {
|
||||||
__profscope(substep);
|
__profscope(substep);
|
||||||
|
|
||||||
/* Warm start */
|
/* Warm start */
|
||||||
#if GAME_PHYSICS_ENABLE_WARM_STARTING
|
#if SIM_PHYSICS_ENABLE_WARM_STARTING
|
||||||
phys_warm_start_contacts(ctx);
|
phys_warm_start_contacts(ctx);
|
||||||
phys_warm_start_motor_joints(ctx);
|
phys_warm_start_motor_joints(ctx);
|
||||||
phys_warm_start_mouse_joints(ctx);
|
phys_warm_start_mouse_joints(ctx);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Solve */
|
/* Solve */
|
||||||
#if GAME_PHYSICS_ENABLE_COLLISION
|
#if SIM_PHYSICS_ENABLE_COLLISION
|
||||||
phys_solve_contacts(ctx, substep_dt, true);
|
phys_solve_contacts(ctx, substep_dt, true);
|
||||||
#endif
|
#endif
|
||||||
phys_solve_motor_joints(ctx, substep_dt);
|
phys_solve_motor_joints(ctx, substep_dt);
|
||||||
@ -1197,7 +1197,7 @@ u64 phys_step(struct phys_ctx *ctx, f32 timestep, u64 last_phys_iteration)
|
|||||||
phys_integrate_velocities(ctx, substep_dt);
|
phys_integrate_velocities(ctx, substep_dt);
|
||||||
|
|
||||||
/* Relaxation solve */
|
/* Relaxation solve */
|
||||||
#if GAME_PHYSICS_ENABLE_COLLISION && GAME_PHYSICS_ENABLE_RELAXATION
|
#if SIM_PHYSICS_ENABLE_COLLISION && SIM_PHYSICS_ENABLE_RELAXATION
|
||||||
phys_solve_contacts(ctx, substep_dt, false);
|
phys_solve_contacts(ctx, substep_dt, false);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#include "game.h"
|
#include "sim.h"
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
@ -19,8 +19,8 @@
|
|||||||
#include "host.h"
|
#include "host.h"
|
||||||
|
|
||||||
GLOBAL struct {
|
GLOBAL struct {
|
||||||
struct atomic_i32 game_thread_shutdown;
|
struct atomic_i32 sim_thread_shutdown;
|
||||||
struct sys_thread game_thread;
|
struct sys_thread sim_thread;
|
||||||
|
|
||||||
u64 last_phys_iteration;
|
u64 last_phys_iteration;
|
||||||
|
|
||||||
@ -47,17 +47,17 @@ GLOBAL struct {
|
|||||||
|
|
||||||
/* Tick */
|
/* Tick */
|
||||||
struct world tick;
|
struct world tick;
|
||||||
} G = ZI, DEBUG_ALIAS(G, G_game);
|
} G = ZI, DEBUG_ALIAS(G, G_sim);
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Startup
|
* Startup
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(game_shutdown);
|
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(sim_shutdown);
|
||||||
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(game_thread_entry_point, arg);
|
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sim_thread_entry_point, arg);
|
||||||
INTERNAL void reset_world(void);
|
INTERNAL void reset_world(void);
|
||||||
|
|
||||||
struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
|
struct sim_startup_receipt sim_startup(struct mixer_startup_receipt *mixer_sr,
|
||||||
struct sprite_startup_receipt *sheet_sr,
|
struct sprite_startup_receipt *sheet_sr,
|
||||||
struct sound_startup_receipt *sound_sr,
|
struct sound_startup_receipt *sound_sr,
|
||||||
struct phys_startup_receipt *phys_sr,
|
struct phys_startup_receipt *phys_sr,
|
||||||
@ -77,17 +77,17 @@ struct game_startup_receipt game_startup(struct mixer_startup_receipt *mixer_sr,
|
|||||||
/* Initialize empty world */
|
/* Initialize empty world */
|
||||||
reset_world();
|
reset_world();
|
||||||
|
|
||||||
G.game_thread = sys_thread_alloc(&game_thread_entry_point, NULL, LIT("[P2] Game thread"));
|
G.sim_thread = sys_thread_alloc(&sim_thread_entry_point, NULL, LIT("[P2] Sim thread"));
|
||||||
app_register_exit_callback(&game_shutdown);
|
app_register_exit_callback(&sim_shutdown);
|
||||||
|
|
||||||
return (struct game_startup_receipt) { 0 };
|
return (struct sim_startup_receipt) { 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(game_shutdown)
|
INTERNAL APP_EXIT_CALLBACK_FUNC_DEF(sim_shutdown)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
atomic_i32_eval_exchange(&G.game_thread_shutdown, true);
|
atomic_i32_eval_exchange(&G.sim_thread_shutdown, true);
|
||||||
sys_thread_wait_release(&G.game_thread);
|
sys_thread_wait_release(&G.sim_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -116,7 +116,7 @@ INTERNAL void reset_world(void)
|
|||||||
|
|
||||||
/* Re-create world */
|
/* Re-create world */
|
||||||
world_alloc(&G.tick);
|
world_alloc(&G.tick);
|
||||||
G.tick.timescale = GAME_TIMESCALE;
|
G.tick.timescale = SIM_TIMESCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -174,7 +174,7 @@ INTERNAL void spawn_test_entities(void)
|
|||||||
//e->sprite_span_name = LIT("idle.unarmed");
|
//e->sprite_span_name = LIT("idle.unarmed");
|
||||||
//e->sprite_span_name = LIT("idle.one_handed");
|
//e->sprite_span_name = LIT("idle.one_handed");
|
||||||
e->sprite_span_name = LIT("idle.two_handed");
|
e->sprite_span_name = LIT("idle.two_handed");
|
||||||
e->layer = GAME_LAYER_SHOULDERS;
|
e->layer = SIM_LAYER_SHOULDERS;
|
||||||
|
|
||||||
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
||||||
//xf.bx.y = -1.f;
|
//xf.bx.y = -1.f;
|
||||||
@ -207,7 +207,7 @@ INTERNAL void spawn_test_entities(void)
|
|||||||
|
|
||||||
e->sprite = sprite_tag_from_path(LIT("res/graphics/tim.ase"));
|
e->sprite = sprite_tag_from_path(LIT("res/graphics/tim.ase"));
|
||||||
e->sprite_collider_slice = LIT("shape");
|
e->sprite_collider_slice = LIT("shape");
|
||||||
e->layer = GAME_LAYER_SHOULDERS;
|
e->layer = SIM_LAYER_SHOULDERS;
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_PHYSICAL_DYNAMIC);
|
entity_enable_prop(e, ENTITY_PROP_PHYSICAL_DYNAMIC);
|
||||||
e->mass_unscaled = 10;
|
e->mass_unscaled = 10;
|
||||||
@ -230,7 +230,7 @@ INTERNAL void spawn_test_entities(void)
|
|||||||
|
|
||||||
e->sprite = sprite_tag_from_path(LIT("res/graphics/box.ase"));
|
e->sprite = sprite_tag_from_path(LIT("res/graphics/box.ase"));
|
||||||
e->sprite_collider_slice = LIT("shape");
|
e->sprite_collider_slice = LIT("shape");
|
||||||
e->layer = GAME_LAYER_SHOULDERS;
|
e->layer = SIM_LAYER_SHOULDERS;
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_PHYSICAL_DYNAMIC);
|
entity_enable_prop(e, ENTITY_PROP_PHYSICAL_DYNAMIC);
|
||||||
e->mass_unscaled = 100;
|
e->mass_unscaled = 100;
|
||||||
@ -253,7 +253,7 @@ INTERNAL void spawn_test_entities(void)
|
|||||||
|
|
||||||
e->sprite = sprite_tag_from_path(LIT("res/graphics/bullet.ase"));
|
e->sprite = sprite_tag_from_path(LIT("res/graphics/bullet.ase"));
|
||||||
e->sprite_collider_slice = LIT("shape");
|
e->sprite_collider_slice = LIT("shape");
|
||||||
e->layer = GAME_LAYER_SHOULDERS;
|
e->layer = SIM_LAYER_SHOULDERS;
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_PHYSICAL_DYNAMIC);
|
entity_enable_prop(e, ENTITY_PROP_PHYSICAL_DYNAMIC);
|
||||||
e->mass_unscaled = 0.5;
|
e->mass_unscaled = 0.5;
|
||||||
@ -269,7 +269,7 @@ INTERNAL void spawn_test_entities(void)
|
|||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_ATTACHED);
|
entity_enable_prop(e, ENTITY_PROP_ATTACHED);
|
||||||
e->attach_slice = LIT("attach.wep");
|
e->attach_slice = LIT("attach.wep");
|
||||||
e->layer = GAME_LAYER_RELATIVE_WEAPON;
|
e->layer = SIM_LAYER_RELATIVE_WEAPON;
|
||||||
|
|
||||||
entity_enable_prop(e, ENTITY_PROP_WEAPON);
|
entity_enable_prop(e, ENTITY_PROP_WEAPON);
|
||||||
//e->trigger_delay = 1.0f / 10.0f;
|
//e->trigger_delay = 1.0f / 10.0f;
|
||||||
@ -406,7 +406,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, array)
|
|||||||
struct entity *decal = entity_alloc(root);
|
struct entity *decal = entity_alloc(root);
|
||||||
decal->sprite = sprite_tag_from_path(LIT("res/graphics/blood.ase"));
|
decal->sprite = sprite_tag_from_path(LIT("res/graphics/blood.ase"));
|
||||||
decal->sprite_tint = RGBA_32_F(1, 1, 1, 0.25f);
|
decal->sprite_tint = RGBA_32_F(1, 1, 1, 0.25f);
|
||||||
decal->layer = GAME_LAYER_FLOOR_DECALS;
|
decal->layer = SIM_LAYER_FLOOR_DECALS;
|
||||||
entity_set_xform(decal, xf);
|
entity_set_xform(decal, xf);
|
||||||
|
|
||||||
f32 perp_range = 0.5;
|
f32 perp_range = 0.5;
|
||||||
@ -433,7 +433,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, array)
|
|||||||
* Update
|
* Update
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
INTERNAL void game_update(void)
|
INTERNAL void sim_update(void)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
|
|
||||||
@ -456,7 +456,7 @@ INTERNAL void game_update(void)
|
|||||||
|
|
||||||
++G.tick.tick_id;
|
++G.tick.tick_id;
|
||||||
|
|
||||||
G.tick.dt_ns = NS_FROM_SECONDS(max_f64(0.0, (1.0 / GAME_FPS) * G.tick.timescale));
|
G.tick.dt_ns = NS_FROM_SECONDS(max_f64(0.0, (1.0 / SIM_FPS) * G.tick.timescale));
|
||||||
G.tick.time_ns += G.tick.dt_ns;
|
G.tick.time_ns += G.tick.dt_ns;
|
||||||
|
|
||||||
f64 dt = SECONDS_FROM_NS(G.tick.dt_ns);
|
f64 dt = SECONDS_FROM_NS(G.tick.dt_ns);
|
||||||
@ -525,48 +525,48 @@ INTERNAL void game_update(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Process host events into game cmds
|
* Process host events into sim cmds
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
|
|
||||||
struct game_cmd_list game_cmds = ZI;
|
struct sim_cmd_list sim_cmds = ZI;
|
||||||
{
|
{
|
||||||
struct host_event_array host_events = host_pop_events(scratch.arena, G.host);
|
struct host_event_array host_events = host_pop_events(scratch.arena, G.host);
|
||||||
game_cmds_from_host_events(scratch.arena, host_events, &game_cmds);
|
sim_cmds_from_host_events(scratch.arena, host_events, &sim_cmds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Process game cmds
|
* Process sim cmds
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
for (struct game_cmd *cmd = game_cmds.first; cmd; cmd = cmd->next) {
|
for (struct sim_cmd *cmd = sim_cmds.first; cmd; cmd = cmd->next) {
|
||||||
enum game_cmd_kind kind = cmd->kind;
|
enum sim_cmd_kind kind = cmd->kind;
|
||||||
struct host_channel_id channel_id = cmd->channel_id;
|
struct host_channel_id channel_id = cmd->channel_id;
|
||||||
|
|
||||||
struct client *client = client_from_channel_id(G.client_store, channel_id);
|
struct client *client = client_from_channel_id(G.client_store, channel_id);
|
||||||
if (client->valid || host_channel_id_is_nil(channel_id)) {
|
if (client->valid || host_channel_id_is_nil(channel_id)) {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
/* Cursor */
|
/* Cursor */
|
||||||
case GAME_CMD_KIND_CURSOR_MOVE:
|
case SIM_CMD_KIND_CURSOR_MOVE:
|
||||||
{
|
{
|
||||||
G.user_cursor = cmd->cursor_pos;
|
G.user_cursor = cmd->cursor_pos;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
/* Clear level */
|
/* Clear level */
|
||||||
case GAME_CMD_KIND_CLEAR_ALL:
|
case SIM_CMD_KIND_CLEAR_ALL:
|
||||||
{
|
{
|
||||||
G.should_reset_level = true;
|
G.should_reset_level = true;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
/* Spawn test */
|
/* Spawn test */
|
||||||
case GAME_CMD_KIND_SPAWN_TEST:
|
case SIM_CMD_KIND_SPAWN_TEST:
|
||||||
{
|
{
|
||||||
logf_info("Spawning (test)");
|
logf_info("Spawning (test)");
|
||||||
spawn_test_entities();
|
spawn_test_entities();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
/* Disconnect client */
|
/* Disconnect client */
|
||||||
case GAME_CMD_KIND_CLIENT_DISCONNECT:
|
case SIM_CMD_KIND_CLIENT_DISCONNECT:
|
||||||
{
|
{
|
||||||
if (client->valid) {
|
if (client->valid) {
|
||||||
struct entity *client_ent = entity_from_handle(entity_store, client->ent);
|
struct entity *client_ent = entity_from_handle(entity_store, client->ent);
|
||||||
@ -581,7 +581,7 @@ INTERNAL void game_update(void)
|
|||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
};
|
};
|
||||||
} else if (kind == GAME_CMD_KIND_CLIENT_CONNECT && !host_channel_id_is_nil(channel_id) && !client->valid) {
|
} else if (kind == SIM_CMD_KIND_CLIENT_CONNECT && !host_channel_id_is_nil(channel_id) && !client->valid) {
|
||||||
/* Connect client */
|
/* Connect client */
|
||||||
client = client_alloc(G.client_store, channel_id);
|
client = client_alloc(G.client_store, channel_id);
|
||||||
struct entity *client_ent = entity_alloc(root);
|
struct entity *client_ent = entity_alloc(root);
|
||||||
@ -724,21 +724,21 @@ INTERNAL void game_update(void)
|
|||||||
struct v2 focus = ent->control.focus;
|
struct v2 focus = ent->control.focus;
|
||||||
b32 firing = entity_has_prop(ent, ENTITY_PROP_TRIGGERING_EQUIPPED);
|
b32 firing = entity_has_prop(ent, ENTITY_PROP_TRIGGERING_EQUIPPED);
|
||||||
|
|
||||||
for (struct game_cmd *cmd = game_cmds.first; cmd; cmd = cmd->next) {
|
for (struct sim_cmd *cmd = sim_cmds.first; cmd; cmd = cmd->next) {
|
||||||
b32 start = cmd->state == GAME_CMD_STATE_START;
|
b32 start = cmd->state == SIM_CMD_STATE_START;
|
||||||
b32 stop = cmd->state == GAME_CMD_STATE_STOP;
|
b32 stop = cmd->state == SIM_CMD_STATE_STOP;
|
||||||
|
|
||||||
/* TODO: Combine movement from multiple inputs? E.G. a sudden
|
/* TODO: Combine movement from multiple inputs? E.G. a sudden
|
||||||
* start and immediate stop cmd should still move the player a
|
* start and immediate stop cmd should still move the player a
|
||||||
* tad. */
|
* tad. */
|
||||||
switch (cmd->kind) {
|
switch (cmd->kind) {
|
||||||
case GAME_CMD_KIND_PLAYER_MOVE:
|
case SIM_CMD_KIND_PLAYER_MOVE:
|
||||||
{
|
{
|
||||||
move = cmd->move_dir;
|
move = cmd->move_dir;
|
||||||
focus = cmd->aim_dir;
|
focus = cmd->aim_dir;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case GAME_CMD_KIND_PLAYER_FIRE:
|
case SIM_CMD_KIND_PLAYER_FIRE:
|
||||||
{
|
{
|
||||||
if (start) {
|
if (start) {
|
||||||
firing = true;
|
firing = true;
|
||||||
@ -871,7 +871,7 @@ INTERNAL void game_update(void)
|
|||||||
bullet->bullet_knockback = 10;
|
bullet->bullet_knockback = 10;
|
||||||
bullet->mass_unscaled = 0.04f;
|
bullet->mass_unscaled = 0.04f;
|
||||||
bullet->inertia_unscaled = 0.00001f;
|
bullet->inertia_unscaled = 0.00001f;
|
||||||
bullet->layer = GAME_LAYER_BULLETS;
|
bullet->layer = SIM_LAYER_BULLETS;
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
/* Point collider */
|
/* Point collider */
|
||||||
@ -890,7 +890,7 @@ INTERNAL void game_update(void)
|
|||||||
{
|
{
|
||||||
struct entity *tracer = entity_alloc(root);
|
struct entity *tracer = entity_alloc(root);
|
||||||
tracer->tracer_fade_duration = 0.025f;
|
tracer->tracer_fade_duration = 0.025f;
|
||||||
tracer->layer = GAME_LAYER_TRACERS;
|
tracer->layer = SIM_LAYER_TRACERS;
|
||||||
entity_enable_prop(tracer, ENTITY_PROP_TRACER);
|
entity_enable_prop(tracer, ENTITY_PROP_TRACER);
|
||||||
|
|
||||||
bullet->bullet_tracer = tracer->handle;
|
bullet->bullet_tracer = tracer->handle;
|
||||||
@ -947,7 +947,7 @@ INTERNAL void game_update(void)
|
|||||||
* Create forces from control focus (aim)
|
* Create forces from control focus (aim)
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
#if GAME_PLAYER_AIM
|
#if SIM_PLAYER_AIM
|
||||||
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
|
for (u64 entity_index = 0; entity_index < entity_store->num_reserved; ++entity_index) {
|
||||||
struct entity *ent = &entity_store->entities[entity_index];
|
struct entity *ent = &entity_store->entities[entity_index];
|
||||||
if (!entity_is_valid_and_active(ent)) continue;
|
if (!entity_is_valid_and_active(ent)) continue;
|
||||||
@ -1082,11 +1082,11 @@ INTERNAL void game_update(void)
|
|||||||
|
|
||||||
/* Mouse drag */
|
/* Mouse drag */
|
||||||
ctx.dbg_cursor_pos = G.user_cursor;
|
ctx.dbg_cursor_pos = G.user_cursor;
|
||||||
for (struct game_cmd *cmd = game_cmds.first; cmd; cmd = cmd->next) {
|
for (struct sim_cmd *cmd = sim_cmds.first; cmd; cmd = cmd->next) {
|
||||||
if (cmd->kind == GAME_CMD_KIND_DRAG_OBJECT) {
|
if (cmd->kind == SIM_CMD_KIND_DRAG_OBJECT) {
|
||||||
if (cmd->state == GAME_CMD_STATE_START) {
|
if (cmd->state == SIM_CMD_STATE_START) {
|
||||||
ctx.dbg_start_dragging = true;
|
ctx.dbg_start_dragging = true;
|
||||||
} else if (cmd->state == GAME_CMD_STATE_STOP) {
|
} else if (cmd->state == SIM_CMD_STATE_STOP) {
|
||||||
ctx.dbg_stop_dragging = true;
|
ctx.dbg_stop_dragging = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1279,7 +1279,7 @@ INTERNAL void game_update(void)
|
|||||||
* Update sound emitters
|
* Update sound emitters
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* TODO: Sound entities should be created by game thread, but played by the
|
/* TODO: Sound entities should be created by sim thread, but played by the
|
||||||
* user thread. This is so sounds play at the correct time on the user
|
* user thread. This is so sounds play at the correct time on the user
|
||||||
* thread regardless of interp delay. */
|
* thread regardless of interp delay. */
|
||||||
|
|
||||||
@ -1318,14 +1318,14 @@ INTERNAL void game_update(void)
|
|||||||
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
||||||
|
|
||||||
/* TODO: Not like this */
|
/* TODO: Not like this */
|
||||||
struct game_event snapshot_event = ZI;
|
struct sim_event snapshot_event = ZI;
|
||||||
snapshot_event.kind = GAME_EVENT_KIND_SNAPSHOT_FULL;
|
snapshot_event.kind = SIM_EVENT_KIND_SNAPSHOT_FULL;
|
||||||
snapshot_event.snapshot_data = game_string_from_tick(temp.arena, &G.tick);
|
snapshot_event.snapshot_data = sim_string_from_tick(temp.arena, &G.tick);
|
||||||
|
|
||||||
struct game_event_list l = ZI;
|
struct sim_event_list l = ZI;
|
||||||
l.first = &snapshot_event;
|
l.first = &snapshot_event;
|
||||||
l.last = &snapshot_event;
|
l.last = &snapshot_event;
|
||||||
struct string msg = game_string_from_events(temp.arena, l);
|
struct string msg = sim_string_from_events(temp.arena, l);
|
||||||
|
|
||||||
host_queue_write(G.host, HOST_CHANNEL_ID_ALL, msg, 0);
|
host_queue_write(G.host, HOST_CHANNEL_ID_ALL, msg, 0);
|
||||||
|
|
||||||
@ -1333,7 +1333,7 @@ INTERNAL void game_update(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
host_update(G.host);
|
host_update(G.host);
|
||||||
__profframe("Game");
|
__profframe("Sim");
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* End frame cache scopes
|
* End frame cache scopes
|
||||||
@ -1345,15 +1345,15 @@ INTERNAL void game_update(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Game cmd
|
* Sim cmd
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct string game_string_from_cmds(struct arena *arena, struct game_cmd_list cmds)
|
struct string sim_string_from_cmds(struct arena *arena, struct sim_cmd_list cmds)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct byte_writer bw = bw_from_arena(arena);
|
struct byte_writer bw = bw_from_arena(arena);
|
||||||
|
|
||||||
for (struct game_cmd *cmd = cmds.first; cmd; cmd = cmd->next) {
|
for (struct sim_cmd *cmd = cmds.first; cmd; cmd = cmd->next) {
|
||||||
struct byte_writer bw_size = bw_branch(&bw, sizeof(u64));
|
struct byte_writer bw_size = bw_branch(&bw, sizeof(u64));
|
||||||
u64 start = bw_pos(&bw);
|
u64 start = bw_pos(&bw);
|
||||||
|
|
||||||
@ -1365,13 +1365,13 @@ struct string game_string_from_cmds(struct arena *arena, struct game_cmd_list cm
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch (cmd->kind) {
|
switch (cmd->kind) {
|
||||||
case GAME_CMD_KIND_PLAYER_MOVE:
|
case SIM_CMD_KIND_PLAYER_MOVE:
|
||||||
{
|
{
|
||||||
bw_write_v2(&bw, cmd->move_dir);
|
bw_write_v2(&bw, cmd->move_dir);
|
||||||
bw_write_v2(&bw, cmd->aim_dir);
|
bw_write_v2(&bw, cmd->aim_dir);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case GAME_CMD_KIND_CURSOR_MOVE:
|
case SIM_CMD_KIND_CURSOR_MOVE:
|
||||||
{
|
{
|
||||||
bw_write_v2(&bw, cmd->cursor_pos);
|
bw_write_v2(&bw, cmd->cursor_pos);
|
||||||
} break;
|
} break;
|
||||||
@ -1386,7 +1386,7 @@ struct string game_string_from_cmds(struct arena *arena, struct game_cmd_list cm
|
|||||||
return bw_get_written(&bw);
|
return bw_get_written(&bw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_cmds_from_host_events(struct arena *arena, struct host_event_array host_events, struct game_cmd_list *cmds_out)
|
void sim_cmds_from_host_events(struct arena *arena, struct host_event_array host_events, struct sim_cmd_list *cmds_out)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
for (u64 i = 0; i < host_events.count; ++i) {
|
for (u64 i = 0; i < host_events.count; ++i) {
|
||||||
@ -1395,8 +1395,8 @@ void game_cmds_from_host_events(struct arena *arena, struct host_event_array hos
|
|||||||
switch (host_event_kind) {
|
switch (host_event_kind) {
|
||||||
case HOST_EVENT_KIND_CHANNEL_OPENED:
|
case HOST_EVENT_KIND_CHANNEL_OPENED:
|
||||||
{
|
{
|
||||||
struct game_cmd *cmd = arena_push_zero(arena, struct game_cmd);
|
struct sim_cmd *cmd = arena_push_zero(arena, struct sim_cmd);
|
||||||
cmd->kind = GAME_CMD_KIND_CLIENT_CONNECT;
|
cmd->kind = SIM_CMD_KIND_CLIENT_CONNECT;
|
||||||
cmd->channel_id = host_event.channel_id;
|
cmd->channel_id = host_event.channel_id;
|
||||||
if (cmds_out->last) {
|
if (cmds_out->last) {
|
||||||
cmds_out->last->next = cmd;
|
cmds_out->last->next = cmd;
|
||||||
@ -1408,8 +1408,8 @@ void game_cmds_from_host_events(struct arena *arena, struct host_event_array hos
|
|||||||
|
|
||||||
case HOST_EVENT_KIND_CHANNEL_CLOSED:
|
case HOST_EVENT_KIND_CHANNEL_CLOSED:
|
||||||
{
|
{
|
||||||
struct game_cmd *cmd = arena_push_zero(arena, struct game_cmd);
|
struct sim_cmd *cmd = arena_push_zero(arena, struct sim_cmd);
|
||||||
cmd->kind = GAME_CMD_KIND_CLIENT_DISCONNECT;
|
cmd->kind = SIM_CMD_KIND_CLIENT_DISCONNECT;
|
||||||
cmd->disconnect_reason = LIT("Connection lost");
|
cmd->disconnect_reason = LIT("Connection lost");
|
||||||
if (cmds_out->last) {
|
if (cmds_out->last) {
|
||||||
cmds_out->last->next = cmd;
|
cmds_out->last->next = cmd;
|
||||||
@ -1423,7 +1423,7 @@ void game_cmds_from_host_events(struct arena *arena, struct host_event_array hos
|
|||||||
{
|
{
|
||||||
struct byte_reader br = br_from_buffer(host_event.msg);
|
struct byte_reader br = br_from_buffer(host_event.msg);
|
||||||
while (br_bytes_left(&br) > 0) {
|
while (br_bytes_left(&br) > 0) {
|
||||||
struct game_cmd *cmd = arena_push_zero(arena, struct game_cmd);
|
struct sim_cmd *cmd = arena_push_zero(arena, struct sim_cmd);
|
||||||
u64 cmd_size = br_read_u64(&br);
|
u64 cmd_size = br_read_u64(&br);
|
||||||
u64 cmd_pos_end = br_pos(&br) + cmd_size;
|
u64 cmd_pos_end = br_pos(&br) + cmd_size;
|
||||||
cmd->kind = br_read_i8(&br);
|
cmd->kind = br_read_i8(&br);
|
||||||
@ -1433,13 +1433,13 @@ void game_cmds_from_host_events(struct arena *arena, struct host_event_array hos
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch (cmd->kind) {
|
switch (cmd->kind) {
|
||||||
case GAME_CMD_KIND_PLAYER_MOVE:
|
case SIM_CMD_KIND_PLAYER_MOVE:
|
||||||
{
|
{
|
||||||
cmd->move_dir = br_read_v2(&br);
|
cmd->move_dir = br_read_v2(&br);
|
||||||
cmd->aim_dir = br_read_v2(&br);
|
cmd->aim_dir = br_read_v2(&br);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case GAME_CMD_KIND_CURSOR_MOVE:
|
case SIM_CMD_KIND_CURSOR_MOVE:
|
||||||
{
|
{
|
||||||
cmd->cursor_pos = br_read_v2(&br);
|
cmd->cursor_pos = br_read_v2(&br);
|
||||||
} break;
|
} break;
|
||||||
@ -1465,20 +1465,20 @@ void game_cmds_from_host_events(struct arena *arena, struct host_event_array hos
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Game event
|
* Sim event
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct string game_string_from_events(struct arena *arena, struct game_event_list events)
|
struct string sim_string_from_events(struct arena *arena, struct sim_event_list events)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct byte_writer bw = bw_from_arena(arena);
|
struct byte_writer bw = bw_from_arena(arena);
|
||||||
for (struct game_event *event = events.first; event; event = event->next) {
|
for (struct sim_event *event = events.first; event; event = event->next) {
|
||||||
struct byte_writer bw_size = bw_branch(&bw, sizeof(u64));
|
struct byte_writer bw_size = bw_branch(&bw, sizeof(u64));
|
||||||
u64 start = bw_pos(&bw);
|
u64 start = bw_pos(&bw);
|
||||||
bw_write_i8(&bw, event->kind);
|
bw_write_i8(&bw, event->kind);
|
||||||
|
|
||||||
switch (event->kind) {
|
switch (event->kind) {
|
||||||
case GAME_EVENT_KIND_SNAPSHOT_FULL:
|
case SIM_EVENT_KIND_SNAPSHOT_FULL:
|
||||||
{
|
{
|
||||||
bw_write_string(&bw, event->snapshot_data);
|
bw_write_string(&bw, event->snapshot_data);
|
||||||
} break;
|
} break;
|
||||||
@ -1492,24 +1492,24 @@ struct string game_string_from_events(struct arena *arena, struct game_event_lis
|
|||||||
return bw_get_written(&bw);
|
return bw_get_written(&bw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_events_from_host_events(struct arena *arena, struct host_event_array host_events, struct game_event_list *events_out)
|
void sim_events_from_host_events(struct arena *arena, struct host_event_array host_events, struct sim_event_list *events_out)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
for (u64 i = 0; i < host_events.count; ++i) {
|
for (u64 i = 0; i < host_events.count; ++i) {
|
||||||
struct game_event *game_event = arena_push_zero(arena, struct game_event);
|
struct sim_event *sim_event = arena_push_zero(arena, struct sim_event);
|
||||||
struct host_event host_event = host_events.events[i];
|
struct host_event host_event = host_events.events[i];
|
||||||
enum host_event_kind host_event_kind = host_event.kind;
|
enum host_event_kind host_event_kind = host_event.kind;
|
||||||
game_event->channel_id = host_event.channel_id;
|
sim_event->channel_id = host_event.channel_id;
|
||||||
switch (host_event_kind) {
|
switch (host_event_kind) {
|
||||||
case HOST_EVENT_KIND_CHANNEL_OPENED:
|
case HOST_EVENT_KIND_CHANNEL_OPENED:
|
||||||
{
|
{
|
||||||
game_event->kind = GAME_EVENT_KIND_CONNECT;
|
sim_event->kind = SIM_EVENT_KIND_CONNECT;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case HOST_EVENT_KIND_CHANNEL_CLOSED:
|
case HOST_EVENT_KIND_CHANNEL_CLOSED:
|
||||||
{
|
{
|
||||||
game_event->kind = GAME_EVENT_KIND_DISCONNECT;
|
sim_event->kind = SIM_EVENT_KIND_DISCONNECT;
|
||||||
game_event->disconnect_reason = LIT("Connection lost");
|
sim_event->disconnect_reason = LIT("Connection lost");
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case HOST_EVENT_KIND_MSG:
|
case HOST_EVENT_KIND_MSG:
|
||||||
@ -1519,11 +1519,11 @@ void game_events_from_host_events(struct arena *arena, struct host_event_array h
|
|||||||
u64 event_size = br_read_u64(&br);
|
u64 event_size = br_read_u64(&br);
|
||||||
u64 event_pos_end = br_pos(&br) + event_size;
|
u64 event_pos_end = br_pos(&br) + event_size;
|
||||||
|
|
||||||
game_event->kind = br_read_i8(&br);
|
sim_event->kind = br_read_i8(&br);
|
||||||
switch (game_event->kind) {
|
switch (sim_event->kind) {
|
||||||
case GAME_EVENT_KIND_SNAPSHOT_FULL:
|
case SIM_EVENT_KIND_SNAPSHOT_FULL:
|
||||||
{
|
{
|
||||||
game_event->snapshot_data = br_read_string(arena, &br);
|
sim_event->snapshot_data = br_read_string(arena, &br);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
@ -1538,11 +1538,11 @@ void game_events_from_host_events(struct arena *arena, struct host_event_array h
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (events_out->last) {
|
if (events_out->last) {
|
||||||
events_out->last->next = game_event;
|
events_out->last->next = sim_event;
|
||||||
} else {
|
} else {
|
||||||
events_out->first = game_event;
|
events_out->first = sim_event;
|
||||||
}
|
}
|
||||||
events_out->last = game_event;
|
events_out->last = sim_event;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1550,7 +1550,7 @@ void game_events_from_host_events(struct arena *arena, struct host_event_array h
|
|||||||
* Snapshot
|
* Snapshot
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct string game_string_from_tick(struct arena *arena, struct world *tick)
|
struct string sim_string_from_tick(struct arena *arena, struct world *tick)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct byte_writer bw = bw_from_arena(arena);
|
struct byte_writer bw = bw_from_arena(arena);
|
||||||
@ -1574,7 +1574,7 @@ struct string game_string_from_tick(struct arena *arena, struct world *tick)
|
|||||||
return bw_get_written(&bw);
|
return bw_get_written(&bw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_tick_from_string(struct string str, struct world *tick_out)
|
void sim_tick_from_string(struct string str, struct world *tick_out)
|
||||||
{
|
{
|
||||||
__prof;
|
__prof;
|
||||||
struct byte_reader br = br_from_buffer(str);
|
struct byte_reader br = br_from_buffer(str);
|
||||||
@ -1606,19 +1606,19 @@ void game_tick_from_string(struct string str, struct world *tick_out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Game thread
|
* Sim thread
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
|
|
||||||
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(game_thread_entry_point, arg)
|
INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sim_thread_entry_point, arg)
|
||||||
{
|
{
|
||||||
(UNUSED)arg;
|
(UNUSED)arg;
|
||||||
i64 last_frame_ns = 0;
|
i64 last_frame_ns = 0;
|
||||||
i64 target_dt_ns = NS_FROM_SECONDS(GAME_FPS > (0) ? (1.0 / GAME_FPS) : 0);
|
i64 target_dt_ns = NS_FROM_SECONDS(SIM_FPS > (0) ? (1.0 / SIM_FPS) : 0);
|
||||||
while (!atomic_i32_eval(&G.game_thread_shutdown)) {
|
while (!atomic_i32_eval(&G.sim_thread_shutdown)) {
|
||||||
__profscope(game_update_w_sleep);
|
__profscope(sim_update_w_sleep);
|
||||||
sleep_frame(last_frame_ns, target_dt_ns);
|
sleep_frame(last_frame_ns, target_dt_ns);
|
||||||
last_frame_ns = sys_time_ns();
|
last_frame_ns = sys_time_ns();
|
||||||
game_update();
|
sim_update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
135
src/sim.h
Normal file
135
src/sim.h
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#ifndef SIM_H
|
||||||
|
#define SIM_H
|
||||||
|
|
||||||
|
#include "host.h"
|
||||||
|
|
||||||
|
struct world;
|
||||||
|
struct mixer_startup_receipt;
|
||||||
|
struct sprite_startup_receipt;
|
||||||
|
struct sound_startup_receipt;
|
||||||
|
struct phys_startup_receipt;
|
||||||
|
struct host_startup_receipt;
|
||||||
|
|
||||||
|
/* Absolute layers */
|
||||||
|
#define SIM_LAYER_FLOOR_DECALS -300
|
||||||
|
#define SIM_LAYER_BULLETS -200
|
||||||
|
#define SIM_LAYER_TRACERS -100
|
||||||
|
#define SIM_LAYER_SHOULDERS 0
|
||||||
|
|
||||||
|
/* Relative layers */
|
||||||
|
#define SIM_LAYER_RELATIVE_DEFAULT 0
|
||||||
|
#define SIM_LAYER_RELATIVE_WEAPON 1
|
||||||
|
|
||||||
|
struct sim_startup_receipt { i32 _; };
|
||||||
|
struct sim_startup_receipt sim_startup(struct mixer_startup_receipt *mixer_sr,
|
||||||
|
struct sprite_startup_receipt *sheet_sr,
|
||||||
|
struct sound_startup_receipt *sound_sr,
|
||||||
|
struct phys_startup_receipt *phys_sr,
|
||||||
|
struct host_startup_receipt *host_sr);
|
||||||
|
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Sim cmd
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
enum sim_cmd_state {
|
||||||
|
SIM_CMD_STATE_STOP = -1,
|
||||||
|
SIM_CMD_STATE_NO_CHANGE = 0,
|
||||||
|
SIM_CMD_STATE_START = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum sim_cmd_kind {
|
||||||
|
SIM_CMD_KIND_NONE,
|
||||||
|
|
||||||
|
SIM_CMD_KIND_PLAYER_MOVE,
|
||||||
|
SIM_CMD_KIND_PLAYER_FIRE,
|
||||||
|
|
||||||
|
SIM_CMD_KIND_CLIENT_CONNECT,
|
||||||
|
SIM_CMD_KIND_CLIENT_DISCONNECT,
|
||||||
|
|
||||||
|
/* Testing */
|
||||||
|
SIM_CMD_KIND_CLEAR_ALL,
|
||||||
|
SIM_CMD_KIND_SPAWN_TEST,
|
||||||
|
SIM_CMD_KIND_PAUSE,
|
||||||
|
SIM_CMD_KIND_STEP,
|
||||||
|
SIM_CMD_KIND_DRAG_OBJECT,
|
||||||
|
SIM_CMD_KIND_CURSOR_MOVE,
|
||||||
|
|
||||||
|
SIM_CMD_KIND_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sim_cmd {
|
||||||
|
enum sim_cmd_kind kind;
|
||||||
|
enum sim_cmd_state state;
|
||||||
|
struct host_channel_id channel_id;
|
||||||
|
|
||||||
|
/* SIM_CMD_KIND_PLAYER_MOVE */
|
||||||
|
struct v2 move_dir;
|
||||||
|
struct v2 aim_dir;
|
||||||
|
|
||||||
|
/* SIM_CMD_KIND_CURSOR_MOVE */
|
||||||
|
struct v2 cursor_pos;
|
||||||
|
|
||||||
|
/* SIM_CMD_KIND_PLAYER_DISCONNECT */
|
||||||
|
struct string disconnect_reason;
|
||||||
|
|
||||||
|
#if RTC
|
||||||
|
u32 collider_gjk_steps;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct sim_cmd *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sim_cmd_list {
|
||||||
|
struct sim_cmd *first;
|
||||||
|
struct sim_cmd *last;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct string sim_string_from_cmds(struct arena *arena, struct sim_cmd_list cmds);
|
||||||
|
void sim_cmds_from_host_events(struct arena *arena, struct host_event_array host_events, struct sim_cmd_list *cmds_out);
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Sim event
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
enum sim_event_kind {
|
||||||
|
SIM_EVENT_KIND_NONE,
|
||||||
|
|
||||||
|
SIM_EVENT_KIND_CONNECT,
|
||||||
|
SIM_EVENT_KIND_DISCONNECT,
|
||||||
|
SIM_EVENT_KIND_SNAPSHOT_FULL,
|
||||||
|
|
||||||
|
//SIM_EVENT_KIND_ENTITY_UPDATE,
|
||||||
|
//SIM_EVENT_KIND_ENTITY_CREATE,
|
||||||
|
//SIM_EVENT_KIND_ENTITY_DESTROY
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sim_event {
|
||||||
|
enum sim_event_kind kind;
|
||||||
|
struct host_channel_id channel_id;
|
||||||
|
|
||||||
|
struct string snapshot_data;
|
||||||
|
struct string disconnect_reason;
|
||||||
|
|
||||||
|
//struct entity_handle entity;
|
||||||
|
//struct string update_data;
|
||||||
|
|
||||||
|
struct sim_event *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sim_event_list {
|
||||||
|
struct sim_event *first;
|
||||||
|
struct sim_event *last;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct string sim_string_from_events(struct arena *arena, struct sim_event_list events);
|
||||||
|
void sim_events_from_host_events(struct arena *arena, struct host_event_array host_events, struct sim_event_list *events_out);
|
||||||
|
|
||||||
|
/* ========================== *
|
||||||
|
* Snapshot
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
|
struct string sim_string_from_tick(struct arena *arena, struct world *tick);
|
||||||
|
void sim_tick_from_string(struct string str, struct world *tick_out);
|
||||||
|
|
||||||
|
#endif
|
||||||
92
src/user.c
92
src/user.c
@ -6,7 +6,7 @@
|
|||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "intrinsics.h"
|
#include "intrinsics.h"
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "game.h"
|
#include "sim.h"
|
||||||
#include "asset_cache.h"
|
#include "asset_cache.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "scratch.h"
|
#include "scratch.h"
|
||||||
@ -148,7 +148,7 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
|
|||||||
struct font_startup_receipt *font_sr,
|
struct font_startup_receipt *font_sr,
|
||||||
struct sprite_startup_receipt *sprite_sr,
|
struct sprite_startup_receipt *sprite_sr,
|
||||||
struct draw_startup_receipt *draw_sr,
|
struct draw_startup_receipt *draw_sr,
|
||||||
struct game_startup_receipt *game_sr,
|
struct sim_startup_receipt *sim_sr,
|
||||||
struct asset_cache_startup_receipt *asset_cache_sr,
|
struct asset_cache_startup_receipt *asset_cache_sr,
|
||||||
struct mixer_startup_receipt *mixer_sr,
|
struct mixer_startup_receipt *mixer_sr,
|
||||||
struct host_startup_receipt *host_sr,
|
struct host_startup_receipt *host_sr,
|
||||||
@ -159,7 +159,7 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
|
|||||||
(UNUSED)font_sr;
|
(UNUSED)font_sr;
|
||||||
(UNUSED)sprite_sr;
|
(UNUSED)sprite_sr;
|
||||||
(UNUSED)draw_sr;
|
(UNUSED)draw_sr;
|
||||||
(UNUSED)game_sr;
|
(UNUSED)sim_sr;
|
||||||
(UNUSED)asset_cache_sr;
|
(UNUSED)asset_cache_sr;
|
||||||
(UNUSED)mixer_sr;
|
(UNUSED)mixer_sr;
|
||||||
(UNUSED)host_sr;
|
(UNUSED)host_sr;
|
||||||
@ -227,7 +227,7 @@ INTERNAL SYS_WINDOW_EVENT_CALLBACK_FUNC_DEF(window_event_callback, event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Game -> user communication
|
* Sim -> user communication
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -293,12 +293,12 @@ INTERNAL struct interp_ticks pull_ticks(i64 blend_time_ns)
|
|||||||
|
|
||||||
struct world *from_tick;
|
struct world *from_tick;
|
||||||
struct world *to_tick;
|
struct world *to_tick;
|
||||||
if (newest_tick && game_get_latest_tick_continuity_gen() == newest_tick->continuity_gen) {
|
if (newest_tick && sim_get_latest_tick_continuity_gen() == newest_tick->continuity_gen) {
|
||||||
/* Pull new tick from game thread if necessary */
|
/* Pull new tick from sim thread if necessary */
|
||||||
if (!newest_tick || game_get_latest_tick_id() > newest_tick->tick_id) {
|
if (!newest_tick || sim_get_latest_tick_id() > newest_tick->tick_id) {
|
||||||
struct blend_tick *latest_bt = blend_tick_alloc();
|
struct blend_tick *latest_bt = blend_tick_alloc();
|
||||||
newest_tick = &latest_bt->world;
|
newest_tick = &latest_bt->world;
|
||||||
game_get_latest_tick(newest_tick);
|
sim_get_latest_tick(newest_tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find oldest tick */
|
/* Find oldest tick */
|
||||||
@ -365,7 +365,7 @@ INTERNAL struct interp_ticks pull_ticks(i64 blend_time_ns)
|
|||||||
/* Allocate new blend tick */
|
/* Allocate new blend tick */
|
||||||
struct blend_tick *bt = blend_tick_alloc();
|
struct blend_tick *bt = blend_tick_alloc();
|
||||||
struct world *tick = &bt->world;
|
struct world *tick = &bt->world;
|
||||||
game_get_latest_tick(tick);
|
sim_get_latest_tick(tick);
|
||||||
|
|
||||||
from_tick = tick;
|
from_tick = tick;
|
||||||
to_tick = tick;
|
to_tick = tick;
|
||||||
@ -472,9 +472,9 @@ INTERNAL SORT_COMPARE_FUNC_DEF(entity_draw_order_cmp, arg_a, arg_b, udata)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
INTERNAL void queue_game_cmd(struct arena *arena, struct game_cmd_list *list, struct game_cmd src)
|
INTERNAL void queue_sim_cmd(struct arena *arena, struct sim_cmd_list *list, struct sim_cmd src)
|
||||||
{
|
{
|
||||||
struct game_cmd *cmd = arena_push(arena, struct game_cmd);
|
struct sim_cmd *cmd = arena_push(arena, struct sim_cmd);
|
||||||
*cmd = src;
|
*cmd = src;
|
||||||
if (list->last) {
|
if (list->last) {
|
||||||
list->last->next = cmd;
|
list->last->next = cmd;
|
||||||
@ -519,19 +519,19 @@ INTERNAL void user_update(void)
|
|||||||
|
|
||||||
struct entity_store *store = G.world.entity_store;
|
struct entity_store *store = G.world.entity_store;
|
||||||
struct sprite_scope *sprite_frame_scope = sprite_scope_begin();
|
struct sprite_scope *sprite_frame_scope = sprite_scope_begin();
|
||||||
struct game_cmd_list cmd_list = ZI;
|
struct sim_cmd_list cmd_list = ZI;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Interpolate between game ticks
|
* Interpolate between sim ticks
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
{
|
{
|
||||||
__profscope(interpolate_ticks);
|
__profscope(interpolate_ticks);
|
||||||
|
|
||||||
#if USER_INTERP_ENABLED
|
#if USER_INTERP_ENABLED
|
||||||
/* TODO: Use actual fps of game thread (will differ from GAME_FPS if game thread is lagging) to hide lag with slow-motion? */
|
/* TODO: Use actual fps of sim thread (will differ from SIM_FPS if sim thread is lagging) to hide lag with slow-motion? */
|
||||||
i64 blend_time_offset_ns = NS_FROM_SECONDS((1.0 / GAME_FPS) * USER_INTERP_OFFSET_TICK_RATIO);
|
i64 blend_time_offset_ns = NS_FROM_SECONDS((1.0 / SIM_FPS) * USER_INTERP_OFFSET_TICK_RATIO);
|
||||||
i64 blend_time_ns = G.time_ns > blend_time_offset_ns ? G.time_ns - blend_time_offset_ns : 0;
|
i64 blend_time_ns = G.time_ns > blend_time_offset_ns ? G.time_ns - blend_time_offset_ns : 0;
|
||||||
|
|
||||||
/* Pull ticks */
|
/* Pull ticks */
|
||||||
@ -573,7 +573,7 @@ INTERNAL void user_update(void)
|
|||||||
e->local_xform = xform_lerp(e0->local_xform, e1->local_xform, tick_blend);
|
e->local_xform = xform_lerp(e0->local_xform, e1->local_xform, tick_blend);
|
||||||
|
|
||||||
if (e->is_top) {
|
if (e->is_top) {
|
||||||
/* TODO: Cache parent & child xforms in game thread */
|
/* TODO: Cache parent & child xforms in sim thread */
|
||||||
struct xform e0_xf = entity_get_xform(e0);
|
struct xform e0_xf = entity_get_xform(e0);
|
||||||
struct xform e1_xf = entity_get_xform(e1);
|
struct xform e1_xf = entity_get_xform(e1);
|
||||||
entity_set_xform(e, xform_lerp(e0_xf, e1_xf, tick_blend));
|
entity_set_xform(e, xform_lerp(e0_xf, e1_xf, tick_blend));
|
||||||
@ -610,17 +610,17 @@ INTERNAL void user_update(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Process host events into game events
|
* Process host events into sim events
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
struct game_event_list game_events = ZI;
|
struct sim_event_list sim_events = ZI;
|
||||||
{
|
{
|
||||||
struct host_event_array host_events = host_pop_events(scratch.arena, G.host);
|
struct host_event_array host_events = host_pop_events(scratch.arena, G.host);
|
||||||
game_events_from_host_events(scratch.arena, host_events, &game_events);
|
sim_events_from_host_events(scratch.arena, host_events, &sim_events);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Process game events
|
* Process sim events
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -632,24 +632,24 @@ INTERNAL void user_update(void)
|
|||||||
last_try_connect = now;
|
last_try_connect = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (struct game_event *event = game_events.first; event; event = event->next) {
|
for (struct sim_event *event = sim_events.first; event; event = event->next) {
|
||||||
enum game_event_kind kind = event->kind;
|
enum sim_event_kind kind = event->kind;
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case GAME_EVENT_KIND_CONNECT:
|
case SIM_EVENT_KIND_CONNECT:
|
||||||
{
|
{
|
||||||
last_try_connect = F64_INFINITY;
|
last_try_connect = F64_INFINITY;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case GAME_EVENT_KIND_DISCONNECT:
|
case SIM_EVENT_KIND_DISCONNECT:
|
||||||
{
|
{
|
||||||
last_try_connect = 0;
|
last_try_connect = 0;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case GAME_EVENT_KIND_SNAPSHOT_FULL:
|
case SIM_EVENT_KIND_SNAPSHOT_FULL:
|
||||||
{
|
{
|
||||||
struct string snapshot_data = event->snapshot_data;
|
struct string snapshot_data = event->snapshot_data;
|
||||||
game_tick_from_string(snapshot_data, &G.world);
|
sim_tick_from_string(snapshot_data, &G.world);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
@ -759,8 +759,8 @@ INTERNAL void user_update(void)
|
|||||||
{
|
{
|
||||||
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_CLEAR];
|
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_CLEAR];
|
||||||
if (state.num_presses) {
|
if (state.num_presses) {
|
||||||
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) {
|
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
|
||||||
.kind = GAME_CMD_KIND_CLEAR_ALL
|
.kind = SIM_CMD_KIND_CLEAR_ALL
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -769,8 +769,8 @@ INTERNAL void user_update(void)
|
|||||||
{
|
{
|
||||||
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_PAUSE];
|
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_PAUSE];
|
||||||
if (state.num_presses) {
|
if (state.num_presses) {
|
||||||
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) {
|
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
|
||||||
.kind = GAME_CMD_KIND_PAUSE
|
.kind = SIM_CMD_KIND_PAUSE
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -779,8 +779,8 @@ INTERNAL void user_update(void)
|
|||||||
{
|
{
|
||||||
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_STEP];
|
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_STEP];
|
||||||
for (u32 i = 0; i < state.num_presses_and_repeats; ++i) {
|
for (u32 i = 0; i < state.num_presses_and_repeats; ++i) {
|
||||||
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) {
|
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
|
||||||
.kind = GAME_CMD_KIND_STEP
|
.kind = SIM_CMD_KIND_STEP
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -789,8 +789,8 @@ INTERNAL void user_update(void)
|
|||||||
{
|
{
|
||||||
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN];
|
struct bind_state state = G.bind_states[USER_BIND_KIND_DEBUG_SPAWN];
|
||||||
if (state.num_presses) {
|
if (state.num_presses) {
|
||||||
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) {
|
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
|
||||||
.kind = GAME_CMD_KIND_SPAWN_TEST
|
.kind = SIM_CMD_KIND_SPAWN_TEST
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1554,15 +1554,15 @@ INTERNAL void user_update(void)
|
|||||||
struct v2 input_aim_dir = v2_sub(G.world_cursor, entity_get_xform(active_player).og);
|
struct v2 input_aim_dir = v2_sub(G.world_cursor, entity_get_xform(active_player).og);
|
||||||
|
|
||||||
/* Queue cursor move cmd */
|
/* Queue cursor move cmd */
|
||||||
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) {
|
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
|
||||||
.kind = GAME_CMD_KIND_CURSOR_MOVE,
|
.kind = SIM_CMD_KIND_CURSOR_MOVE,
|
||||||
.cursor_pos = G.world_cursor
|
.cursor_pos = G.world_cursor
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Queue player input cmd */
|
/* Queue player input cmd */
|
||||||
if (!G.debug_camera) {
|
if (!G.debug_camera) {
|
||||||
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) {
|
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
|
||||||
.kind = GAME_CMD_KIND_PLAYER_MOVE,
|
.kind = SIM_CMD_KIND_PLAYER_MOVE,
|
||||||
.move_dir = input_move_dir,
|
.move_dir = input_move_dir,
|
||||||
.aim_dir = input_aim_dir
|
.aim_dir = input_aim_dir
|
||||||
});
|
});
|
||||||
@ -1571,18 +1571,18 @@ INTERNAL void user_update(void)
|
|||||||
/* Queue player fire cmd */
|
/* Queue player fire cmd */
|
||||||
i32 fire_presses = G.bind_states[USER_BIND_KIND_FIRE].num_presses - G.bind_states[USER_BIND_KIND_FIRE].num_releases;
|
i32 fire_presses = G.bind_states[USER_BIND_KIND_FIRE].num_presses - G.bind_states[USER_BIND_KIND_FIRE].num_releases;
|
||||||
if (!G.debug_camera && fire_presses) {
|
if (!G.debug_camera && fire_presses) {
|
||||||
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) {
|
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
|
||||||
.kind = GAME_CMD_KIND_PLAYER_FIRE,
|
.kind = SIM_CMD_KIND_PLAYER_FIRE,
|
||||||
.state = fire_presses > 0 ? GAME_CMD_STATE_START : GAME_CMD_STATE_STOP
|
.state = fire_presses > 0 ? SIM_CMD_STATE_START : SIM_CMD_STATE_STOP
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Queue physics drag cmd */
|
/* Queue physics drag cmd */
|
||||||
i32 drag_presses = G.bind_states[USER_BIND_KIND_DEBUG_DRAG].num_presses - G.bind_states[USER_BIND_KIND_DEBUG_DRAG].num_releases;
|
i32 drag_presses = G.bind_states[USER_BIND_KIND_DEBUG_DRAG].num_presses - G.bind_states[USER_BIND_KIND_DEBUG_DRAG].num_releases;
|
||||||
if (drag_presses) {
|
if (drag_presses) {
|
||||||
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) {
|
queue_sim_cmd(scratch.arena, &cmd_list, (struct sim_cmd) {
|
||||||
.kind = GAME_CMD_KIND_DRAG_OBJECT,
|
.kind = SIM_CMD_KIND_DRAG_OBJECT,
|
||||||
.state = drag_presses > 0 ? GAME_CMD_STATE_START : GAME_CMD_STATE_STOP
|
.state = drag_presses > 0 ? SIM_CMD_STATE_START : SIM_CMD_STATE_STOP
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1689,11 +1689,11 @@ INTERNAL void user_update(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Publish game cmds */
|
/* Publish sim cmds */
|
||||||
{
|
{
|
||||||
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
struct temp_arena temp = arena_temp_begin(scratch.arena);
|
||||||
|
|
||||||
struct string cmds_str = game_string_from_cmds(temp.arena, cmd_list);
|
struct string cmds_str = sim_string_from_cmds(temp.arena, cmd_list);
|
||||||
host_queue_write(G.host, HOST_CHANNEL_ID_ALL, cmds_str, 0);
|
host_queue_write(G.host, HOST_CHANNEL_ID_ALL, cmds_str, 0);
|
||||||
|
|
||||||
arena_temp_end(temp);
|
arena_temp_end(temp);
|
||||||
|
|||||||
@ -7,7 +7,7 @@ struct renderer_startup_receipt;
|
|||||||
struct font_startup_receipt;
|
struct font_startup_receipt;
|
||||||
struct sprite_startup_receipt;
|
struct sprite_startup_receipt;
|
||||||
struct draw_startup_receipt;
|
struct draw_startup_receipt;
|
||||||
struct game_startup_receipt;
|
struct sim_startup_receipt;
|
||||||
struct asset_cache_startup_receipt;
|
struct asset_cache_startup_receipt;
|
||||||
struct mixer_startup_receipt;
|
struct mixer_startup_receipt;
|
||||||
struct host_startup_receipt;
|
struct host_startup_receipt;
|
||||||
@ -54,7 +54,7 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
|
|||||||
struct font_startup_receipt *font_sr,
|
struct font_startup_receipt *font_sr,
|
||||||
struct sprite_startup_receipt *sprite_sr,
|
struct sprite_startup_receipt *sprite_sr,
|
||||||
struct draw_startup_receipt *draw_sr,
|
struct draw_startup_receipt *draw_sr,
|
||||||
struct game_startup_receipt *game_sr,
|
struct sim_startup_receipt *sim_sr,
|
||||||
struct asset_cache_startup_receipt *asset_cache_sr,
|
struct asset_cache_startup_receipt *asset_cache_sr,
|
||||||
struct mixer_startup_receipt *mixer_sr,
|
struct mixer_startup_receipt *mixer_sr,
|
||||||
struct host_startup_receipt *host_sr,
|
struct host_startup_receipt *host_sr,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user