diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/.gitignore | 2 | ||||
| -rwxr-xr-x | lib/build.sh | 29 | ||||
| -rw-r--r-- | lib/common.h | 1 | ||||
| -rw-r--r-- | lib/common.odin | 24 | ||||
| -rw-r--r-- | lib/components.odin | 18 | ||||
| -rw-r--r-- | lib/constants.h | 12 | ||||
| -rw-r--r-- | lib/log.c | 55 | ||||
| -rw-r--r-- | lib/log.h | 23 | ||||
| -rw-r--r-- | lib/log.odin | 116 | ||||
| -rw-r--r-- | lib/ols.json | 13 | ||||
| -rw-r--r-- | lib/physics.c | 146 | ||||
| -rw-r--r-- | lib/physics.h | 17 | ||||
| -rw-r--r-- | lib/player.c | 36 | ||||
| -rw-r--r-- | lib/player.h | 5 | ||||
| -rw-r--r-- | lib/simulation.odin | 261 | ||||
| -rw-r--r-- | lib/snapshot.c | 142 | ||||
| -rw-r--r-- | lib/snapshot.h | 43 | ||||
| -rw-r--r-- | lib/systems.odin | 44 | ||||
| -rw-r--r-- | lib/test.c | 24 | ||||
| -rw-r--r-- | lib/types.h | 21 | ||||
| -rw-r--r-- | lib/vec2.c | 68 |
21 files changed, 500 insertions, 600 deletions
diff --git a/lib/.gitignore b/lib/.gitignore index 567609b..ea1472e 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -1 +1 @@ -build/ +output/ diff --git a/lib/build.sh b/lib/build.sh index 3f8b5a6..1695dfe 100755 --- a/lib/build.sh +++ b/lib/build.sh @@ -5,11 +5,9 @@ fail() { exit 1 } -CC=cc -CFLAGS="-std=c99 -Wall -Wextra -Wpedantic -Og -g -D_POSIX_C_SOURCE=200809L" -LDFLAGS="-fPIC -lm" -SOURCES="test.c vec2.c snapshot.c log.c player.c physics.c" -output="build" +ODIN_FLAGS="-vet -warnings-as-errors -reloc-mode=pic" + +output="output" for arg ; do case "$arg" in @@ -19,6 +17,15 @@ for arg ; do --output=*) output="${arg#*=}" ;; + --release) + release=1 + ;; + --client) + ODIN_FLAGS="$ODIN_FLAGS -define:DJUP_CLIENT=true" + ;; + --server) + ODIN_FLAGS="$ODIN_FLAGS -define:DJUP_SERVER=true" + ;; *) echo "usage" ;; @@ -42,10 +49,20 @@ fi case "$runtime" in linux-x64) sofile="libdjup.so" + target="linux_amd64" ;; *) fail "Unsupported runtime $runtime" esac +if [ ! -z "$release" ]; then + optimize="-o=speed" +else + optimize="-o=none" +fi + echo Building for runtime "$runtime ..." -mkdir -p "$output/$runtime" && $CC $CFLAGS $SOURCES -shared $LDFLAGS -o "$output/$runtime/$sofile" && echo Done +echo ODIN_FLAGS=$ODIN_FLAGS +mkdir -p "$output/$runtime" && \ + odin build . -build-mode=shared -out="$output/$runtime/$sofile" $ODIN_FLAGS $optimize && \ + echo Done diff --git a/lib/common.h b/lib/common.h deleted file mode 100644 index d6d8816..0000000 --- a/lib/common.h +++ /dev/null @@ -1 +0,0 @@ -#define LENGTH(x) (sizeof(x) / sizeof(x[0])) diff --git a/lib/common.odin b/lib/common.odin new file mode 100644 index 0000000..3c6679f --- /dev/null +++ b/lib/common.odin @@ -0,0 +1,24 @@ +package djup + +import "core:math" + +vec2 :: [2]f32 + +vec2_dot :: proc(a, b: vec2) -> vec2 { + return vec2{a.x * b.x, a.y * b.y} +} + +vec2_length :: proc(v: vec2) -> f32 { + if v == (vec2{0, 0}) { + return 0 + } + return math.sqrt(math.pow(v.x, 2) + math.pow(v.y, 2)) +} + +vec2_normal :: proc(v: vec2) -> vec2 { + len := vec2_length(v) + if len == 0 { + return vec2{0, 0} + } + return v * (1 / len) +} diff --git a/lib/components.odin b/lib/components.odin new file mode 100644 index 0000000..56407a3 --- /dev/null +++ b/lib/components.odin @@ -0,0 +1,18 @@ +package djup + +Component :: enum i32 { + Exists, + Ball, + PlayerInput, +} + +Components :: bit_set[Component;i32] + +Ball :: struct { + position: vec2, + velocity: vec2, +} + +PlayerInput :: struct { + direction: vec2, +} diff --git a/lib/constants.h b/lib/constants.h deleted file mode 100644 index 817fa43..0000000 --- a/lib/constants.h +++ /dev/null @@ -1,12 +0,0 @@ -#define WORLD_MAX_PLAYERS 5 -#define WORLD_MAX_BULLETS 5000 - -#define PLAYER_ACCELERATION 150.0f -#define PLAYER_DRAG 2.0f - -enum { - INPUT_UP = 1 << 0, - INPUT_DOWN = 1 << 1, - INPUT_LEFT = 1 << 2, - INPUT_RIGHT = 1 << 3 -}; diff --git a/lib/log.c b/lib/log.c deleted file mode 100644 index c45f735..0000000 --- a/lib/log.c +++ /dev/null @@ -1,55 +0,0 @@ -#include <stdarg.h> -#include <stdlib.h> -#include <stdio.h> - -#include "log.h" - -/* Message buffer */ -#define MBUF_SIZE 512 - -static void (*log_output)(int level, const char *source, int line, const char *msg) = NULL; -static int min_level = LOGL_INFO; - -void -dp_log_set_output(void (*output)(int, const char *, int, const char *)) -{ - log_output = output; -} - -void -dp_log_set_level(int level) -{ - min_level = level; -} - -void -dp_log_write(int level, const char *source, int line, const char *fmt, ...) -{ - char mbuf[MBUF_SIZE]; - char *msg; - va_list va; - int len; - - if (level < min_level) - return; - if (!log_output) - return; - - msg = mbuf; - va_start(va, fmt); - len = vsnprintf(msg, MBUF_SIZE, fmt, va); - va_end(va); - - if (len >= MBUF_SIZE) - { - msg = (char *)malloc(len + 1); - va_start(va, fmt); - len = vsnprintf(msg, len + 1, fmt, va); - va_end(va); - } - - log_output(level, source, line, msg); - - if (msg != mbuf) - free(msg); -} diff --git a/lib/log.h b/lib/log.h deleted file mode 100644 index e1cdcb8..0000000 --- a/lib/log.h +++ /dev/null @@ -1,23 +0,0 @@ -#include <stdio.h> - -enum { LOGL_TRACE, LOGL_DEBUG, LOGL_INFO, LOGL_WARN, LOGL_ERROR, LOGL_FATAL }; - -/* - * log_info("Hello %s!", "World"); - * log_warn("warning"); - */ -#define log_trace(...) dp_log_write(LOGL_TRACE, __FILE__, __LINE__, __VA_ARGS__) -#define log_debug(...) dp_log_write(LOGL_DEBUG, __FILE__, __LINE__, __VA_ARGS__) -#define log_info(...) dp_log_write(LOGL_INFO, __FILE__, __LINE__, __VA_ARGS__) -#define log_warn(...) dp_log_write(LOGL_WARN, __FILE__, __LINE__, __VA_ARGS__) -#define log_error(...) dp_log_write(LOGL_ERROR, __FILE__, __LINE__, __VA_ARGS__) -#define log_fatal(...) dp_log_write(LOGL_FATAL, __FILE__, __LINE__, __VA_ARGS__) - -void dp_log_set_output(void (*)(int level, const char *source, int line, const char *msg)); - -/* - * Sets the minimum log level. Level is inclusive. - */ -void dp_log_set_level(int level); - -void dp_log_write(int level, const char *source, int line, const char *fmt, ...); diff --git a/lib/log.odin b/lib/log.odin new file mode 100644 index 0000000..eb80b5a --- /dev/null +++ b/lib/log.odin @@ -0,0 +1,116 @@ +package djup + +import "base:runtime" +import "core:c/libc" +import "core:fmt" +import "core:log" + +LogLevel :: enum i32 { + Debug = 0, + Info = 1, + Warning = 2, + Error = 3, + Fatal = 4, +} + +LogFunc :: #type proc "c" ( + level: LogLevel, + message: string, + source_procedure: string, + source_file: string, + source_line: i32, +) + +AssertFunc :: #type proc "c" ( + prefix, message: string, + source_procedure: string, + source_file: string, + source_line: i32, +) + +@(export = true) +sim_log_init :: proc "c" (ctx: ^SimulationContext, logf: LogFunc, assertf: AssertFunc) { + if ctx == nil { + return + } + + log_proc :: proc( + data: rawptr, + level: runtime.Logger_Level, + msg: string, + _: runtime.Logger_Options, + loc: runtime.Source_Code_Location, + ) { + f: LogFunc = cast(LogFunc)data + log_level: LogLevel + switch level { + case .Debug: + log_level = .Debug + case .Info: + log_level = .Info + case .Warning: + log_level = .Warning + case .Error: + log_level = .Error + case .Fatal: + log_level = .Fatal + } + f(log_level, msg, loc.procedure, loc.file_path, loc.line) + } + ctx.assert_func = assertf + + assert_proc :: proc(prefix, message: string, loc: runtime.Source_Code_Location) -> ! { + ctx := cast(^SimulationContext)context.user_ptr + if ctx.assert_func == nil { + fmt.eprintfln( + "assertion failure: %s (%s:%d): %s %s", + loc.procedure, + loc.file_path, + loc.line, + prefix, + message, + ) + libc.abort() + } + ctx.assert_func(prefix, message, loc.procedure, loc.file_path, loc.line) + fmt.println("AssertFunc returned") + libc.abort() + } + + if logf != nil { + ctx.ctx.logger = runtime.Logger { + procedure = log_proc, + data = cast(rawptr)logf, + } + } else { + context = ctx.ctx + ctx.ctx.logger = log.nil_logger() + } + + if assertf != nil { + ctx.ctx.assertion_failure_proc = assert_proc + } +} + +@(export = true) +sim_set_log_level :: proc "c" (ctx: ^SimulationContext, level: LogLevel) { + minimum_level: runtime.Logger_Level + switch level { + case .Debug: + minimum_level = .Debug + case .Info: + minimum_level = .Info + case .Warning: + minimum_level = .Warning + case .Error: + minimum_level = .Error + case .Fatal: + minimum_level = .Fatal + case: + context = ctx.ctx + log.errorf("Invalid minimum log level %d", level) + return + } + + ctx.ctx.logger.lowest_level = minimum_level +} diff --git a/lib/ols.json b/lib/ols.json new file mode 100644 index 0000000..89c69d7 --- /dev/null +++ b/lib/ols.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/ols.schema.json", + "profile": "default", + "profiles": [ + { + "name": "default", + "checker_path": [ "." ], + "defines": { + "ODIN_DEBUG": "true" + } + } + ] +} diff --git a/lib/physics.c b/lib/physics.c deleted file mode 100644 index 0039bd7..0000000 --- a/lib/physics.c +++ /dev/null @@ -1,146 +0,0 @@ -#include <assert.h> -#include <stdlib.h> -#include <string.h> - -#include "common.h" -#include "player.h" -#include "snapshot.h" -#include "types.h" - -#include "physics.h" - -struct context * -dp_physics_context_create(int32_t snapshots, int32_t players, int32_t balls) -{ - int32_t i, j; - struct context *ctx = NULL; - - if (!(ctx = malloc(sizeof(*ctx)))) - return NULL; - memset(ctx, 0, sizeof(*ctx)); - - ctx->snapshots_len = snapshots; - if (!(ctx->snapshots = malloc(sizeof(*ctx->snapshots) * snapshots))) - { - free(ctx); - return NULL; - } - memset(ctx->snapshots, 0, sizeof(*ctx->snapshots) * snapshots); - - for (i = 0; i < snapshots; i++) - { - if (dp_snapshot_init(&ctx->snapshots[i], players, balls) != 0) - { - for (j = 0; j < i; j++) - { - dp_snapshot_deinit(&ctx->snapshots[j]); - } - free(ctx); - } - } - - return ctx; -} - -void -dp_physics_context_free(struct context *ctx) -{ - int32_t i; - if (!ctx) - return; - if (ctx->snapshots) - { - for (i = 0; i < ctx->snapshots_len; i++) - { - dp_snapshot_deinit(&ctx->snapshots[i]); - } - free(ctx->snapshots); - } - free(ctx); -} - -struct snapshot * -dp_physics_context_get_snapshot(struct context *ctx) -{ - int32_t i; - struct snapshot *s; - - for (i = 0; i < ctx->snapshots_len; i++) - { - s = &ctx->snapshots[i]; - if (!s->active) - { - s->active = true; - return s; - } - } - return NULL; -} - -void -dp_physics_context_return_snapshot(struct context *ctx, struct snapshot *s) -{ - int32_t i; - - assert(s->active); - - for (i = 0; i < ctx->snapshots_len; i++) - { - if (s == &ctx->snapshots[i]) - { - s->active = false; - } - } - - assert(!s->active); -} - -static void -dp_physics_tick_player(const struct player *cur, double delta, struct player *next) -{ - vec2 acc; - - next->state = cur->state; - if (next->state == STATE_REMOVED) - next->state = STATE_INACTIVE; - if (next->state == STATE_INACTIVE) - return; - - acc = dp_player_calculate_acceleration(cur); - next->vel = dp_vec2_add(cur->vel, dp_vec2_mul(acc, delta)); - next->pos = dp_vec2_add(cur->pos, dp_vec2_mul(next->vel, delta)); -} - -static void -dp_physics_tick_ball(const struct ball *cur, double delta, struct ball *next) -{ - next->state = cur->state; - if (next->state == STATE_REMOVED) - next->state = STATE_INACTIVE; - if (next->state == STATE_INACTIVE) - return; - - next->pos = dp_vec2_add(cur->pos, dp_vec2_mul(cur->vel, delta)); -} - -int -dp_physics_tick(const struct snapshot *cur, double delta, struct snapshot *next) -{ - int32_t i; - - assert(cur->active); - assert(next->active); - - for (i = 0; i < cur->players_len; i++) - { - dp_physics_tick_player(&cur->players[i], delta, &next->players[i]); - } - - for (i = 0; i < cur->balls_len; i++) - { - dp_physics_tick_ball(&cur->balls[i], delta, &next->balls[i]); - } - - next->tick = cur->tick + 1; - return 0; -} diff --git a/lib/physics.h b/lib/physics.h deleted file mode 100644 index e1c53f3..0000000 --- a/lib/physics.h +++ /dev/null @@ -1,17 +0,0 @@ -#include "types.h" - -struct snapshot; - -/* A game world */ -struct context { - int32_t snapshots_len; - struct snapshot *snapshots; -}; - -struct context *dp_physics_context_create(int32_t snapshots, int32_t players, int32_t balls); -void dp_physics_context_free(struct context *); - -struct snapshot *dp_physics_context_get_snapshot(struct context *); -void dp_physics_context_return_snapshot(struct context *, struct snapshot *); - -int dp_physics_tick(const struct snapshot *current, double delta, struct snapshot *next); diff --git a/lib/player.c b/lib/player.c deleted file mode 100644 index 35c3b80..0000000 --- a/lib/player.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "snapshot.h" - -#include "player.h" - -vec2 -dp_player_calculate_acceleration(const struct player *p) -{ - vec2 acc, dec; - int x = 0, y = 0; - - if (p->input & INPUT_UP) - { - y -= 1; - } - if (p->input & INPUT_DOWN) - { - y += 1; - } - - if (p->input & INPUT_LEFT) - { - x -= 1; - } - if (p->input & INPUT_RIGHT) - { - x += 1; - } - - acc = dp_vec2_new((float)x, (float)y); - acc = dp_vec2_normal(acc); - acc = dp_vec2_mul(acc, PLAYER_ACCELERATION); - - dec = dp_vec2_mul(p->vel, -1.0f * PLAYER_DRAG); - - return dp_vec2_add(acc, dec); -} diff --git a/lib/player.h b/lib/player.h deleted file mode 100644 index 2f365bf..0000000 --- a/lib/player.h +++ /dev/null @@ -1,5 +0,0 @@ -#include "types.h" - -struct player; - -vec2 dp_player_calculate_acceleration(const struct player *); diff --git a/lib/simulation.odin b/lib/simulation.odin new file mode 100644 index 0000000..0ac8e89 --- /dev/null +++ b/lib/simulation.odin @@ -0,0 +1,261 @@ +package djup + +import "base:runtime" +import "core:log" + +#assert(#config(DJUP_CLIENT, false) || #config(DJUP_SERVER, false)) +#assert(!(#config(DJUP_CLIENT, false) && #config(DJUP_SERVER, false))) + +SimulationContext :: struct { + snapshots: []Snapshot, + ctx: runtime.Context, + assert_func: AssertFunc, +} + +Metadata :: Components + +entity_id :: distinct i32 + +Snapshot :: struct { + active: bool, + tick: u32, + metadata: []Metadata, + balls: []Ball, + player_inputs: []PlayerInput, + ctx: ^runtime.Context, +} + +@(export = true) +sim_create :: proc "c" (snapshots, entities: i32) -> ^SimulationContext { + if snapshots <= 0 || entities <= 0 { + return nil + } + + context = runtime.default_context() + context.logger = log.create_console_logger() + ctx := new(SimulationContext) + ctx.ctx = context + ctx.ctx.user_ptr = ctx + + snapshots, err := make([]Snapshot, snapshots) + if err != .None { + free(ctx) + return nil + } + ctx.snapshots = snapshots + + error := false + for &s in ctx.snapshots { + s.ctx = &ctx.ctx + if !snapshot_init(&s, entities) { + error = true + } + } + + if error { + for &s in ctx.snapshots { + snapshot_deinit(&s) + } + delete(ctx.snapshots) + free(ctx) + return nil + } + + log.destroy_console_logger(ctx.ctx.logger) + ctx.ctx.logger = log.nil_logger() + + return ctx +} + +@(export = true) +sim_free :: proc "c" (ctx: ^SimulationContext) { + if ctx == nil { + return + } + context = ctx.ctx + + for &s in ctx.snapshots { + snapshot_deinit(&s) + } + delete(ctx.snapshots) + free(ctx) +} + +snapshot_init :: proc(s: ^Snapshot, entities: i32) -> bool { + make_components :: proc($T: typeid, len: i32, error: ^bool) -> []T { + res, err := make([]T, len) + if err != .None { + log.errorf("Failed to allocate component array: %s", err) + error^ = true + return nil + } + return res + } + + error := false + components: Components = ~{} + for c in components { + switch c { + case .Exists: + s.metadata = make_components(Metadata, entities, &error) + case .Ball: + s.balls = make_components(Ball, entities, &error) + case .PlayerInput: + s.player_inputs = make_components(PlayerInput, entities, &error) + } + } + return !error +} + +snapshot_deinit :: proc(s: ^Snapshot) -> bool { + delete_components :: proc($T: typeid, slice: []T, error: ^bool) { + if slice == nil { + return + } + err := delete(slice) + if err != .None && error != nil { + log.errorf("Failed to delete component array: %s", err) + error^ = true + } + } + + error := false + components: Components = ~{} + for c in components { + switch c { + case .Exists: + delete_components(Metadata, s.metadata, &error) + case .Ball: + delete_components(Ball, s.balls, &error) + case .PlayerInput: + delete_components(PlayerInput, s.player_inputs, &error) + } + } + return !error +} + +@(export = true) +sim_get_snapshot :: proc "c" (ctx: ^SimulationContext) -> ^Snapshot { + if ctx == nil { + return nil + } + + for &s in ctx.snapshots { + if s.active { + continue + } + s.active = true + return &s + } + return nil +} + +@(export = true) +sim_return_snapshot :: proc "c" (ctx: ^SimulationContext, s: ^Snapshot) { + if ctx == nil || s == nil { + return + } + + s.active = false +} + +@(export = true) +snapshot_create_entity :: proc "c" (s: ^Snapshot) -> entity_id { + if s == nil { + return -1 + } + i := 0 + for i < len(s.metadata) { + if .Exists not_in s.metadata[i] { + s.metadata[i] = {.Exists} + return entity_id(i) + } + } + return -1 +} + +ComponentAddError :: enum u32 { + None, + InvalidArg, + InvalidId, + EntityNotFound, +} + +@(export = true) +snapshot_add_component :: proc "c" ( + s: ^Snapshot, + id: entity_id, + component: Component, + init: rawptr, +) -> ComponentAddError { + if s == nil { + return .InvalidArg + } + if (id < 0 && id >= entity_id(len(s.metadata))) { + return .InvalidId + } + + if .Exists not_in s.metadata[id] { + return .EntityNotFound + } + + add :: proc "contextless" (s: ^Snapshot, id: entity_id, c: Components, slice: []$T, init: ^T) { + s.metadata[id] += c + if init != nil { + slice[id] = init^ + } + } + + switch component { + case .Exists: + add(s, id, {.Exists}, s.metadata, nil) + case .Ball: + add(s, id, {.Ball}, s.balls, cast(^Ball)init) + case .PlayerInput: + add(s, id, {.PlayerInput}, s.player_inputs, cast(^PlayerInput)init) + } + return .None +} + +ComponentRemoveError :: enum u32 { + None, + InvalidArg, + InvalidId, + EntityNotFound, +} + +@(export = true) +snapshot_remove_components :: proc "c" ( + s: ^Snapshot, + id: entity_id, + components: Components, +) -> ComponentRemoveError { + if s == nil { + return .InvalidArg + } + if (id < 0 && id >= entity_id(len(s.metadata))) { + return .InvalidId + } + + if .Exists not_in s.metadata[id] { + return .EntityNotFound + } + + for c in components { + switch c { + case .Exists: + s.metadata[id] = {} + case .Ball: + s.balls[id] = Ball{} + case .PlayerInput: + s.player_inputs[id] = PlayerInput{} + } + } + + return .None +} + +@(export = true) +snapshot_reset_entity :: proc "c" (s: ^Snapshot, id: entity_id) -> ComponentRemoveError { + return snapshot_remove_components(s, id, ~{}) +} diff --git a/lib/snapshot.c b/lib/snapshot.c deleted file mode 100644 index d7dde50..0000000 --- a/lib/snapshot.c +++ /dev/null @@ -1,142 +0,0 @@ -#include <stdlib.h> -#include <string.h> - -#include "common.h" - -#include "snapshot.h" - -int -dp_snapshot_init(struct snapshot *s, int32_t players_len, int32_t balls_len) -{ - if (!s) - return -1; - - if (!(s->players = calloc(players_len, sizeof(*s->players)))) - return -1; - if (!(s->balls = calloc(balls_len, sizeof(*s->balls)))) - { - free(s->players); - return -1; - } - s->players_len = players_len; - s->balls_len = balls_len; - return 0; -} - -void -dp_snapshot_deinit(struct snapshot *s) -{ - if (!s) - return; - if (s->players) - { - free(s->players); - s->players = NULL; - } - if (s->balls) - { - free(s->balls); - s->balls = NULL; - } -} - -int -dp_snapshot_put_player(struct snapshot *s, int32_t id, const struct player *p) -{ - if (!s || !p) - return -1; - if (id >= s->players_len) - return -1; - - s->players[id] = *p; - s->players[id].state = STATE_ACTIVE; - return 0; -} - -struct player * -dp_snapshot_get_player(struct snapshot *s, int32_t id) -{ - struct player *p; - - if (!s) - return NULL; - if (id >= s->players_len) - return NULL; - - p = &s->players[id]; - if (p->state == STATE_INACTIVE) - return NULL; - return p; -} - -int -dp_snapshot_remove_player(struct snapshot *s, int32_t id) -{ - struct player *p; - - if (!s) - return -1; - if (id >= s->players_len) - return -1; - - p = dp_snapshot_get_player(s, id); - memset(p, 0, sizeof(*p)); - p->state = STATE_REMOVED; - return 0; -} - -int -dp_snapshot_set_player_input(struct snapshot *s, int32_t id, uint8_t input) -{ - struct player *p; - - if (!(p = dp_snapshot_get_player(s, id))) - return -1; - p->input = input; - return 0; -} - -int -dp_snapshot_put_ball(struct snapshot *s, int32_t id, const struct ball *b) -{ - if (!s || !b) - return -1; - if (id >= s->balls_len) - return -1; - - s->balls[id] = *b; - s->balls[id].state = STATE_ACTIVE; - return 0; -} - -struct ball * -dp_snapshot_get_ball(struct snapshot *s, int32_t id) -{ - struct ball *b; - - if (!s) - return NULL; - if (id >= s->balls_len) - return NULL; - - b = &s->balls[id]; - if (b->state == STATE_INACTIVE) - return NULL; - return b; -} - -int -dp_snapshot_remove_ball(struct snapshot *s, int32_t id) -{ - struct ball *b; - - if (!s) - return -1; - if (id >= s->balls_len) - return -1; - - b = dp_snapshot_get_ball(s, id); - memset(b, 0, sizeof(*b)); - b->state = STATE_REMOVED; - return 0; -} diff --git a/lib/snapshot.h b/lib/snapshot.h deleted file mode 100644 index 028eac2..0000000 --- a/lib/snapshot.h +++ /dev/null @@ -1,43 +0,0 @@ -#include "types.h" -#include "constants.h" - -enum { - STATE_INACTIVE = 0, - STATE_ACTIVE, - STATE_REMOVED, - STATE_DEAD -}; - -struct player { - uint8_t state; - uint8_t input; - vec2 pos; - vec2 vel; -}; - -struct ball { - uint8_t state; - vec2 pos; - vec2 vel; -}; - -struct snapshot { - char active; - uint32_t tick; - int32_t players_len; - struct player *players; - int32_t balls_len; - struct ball *balls; -}; - -int dp_snapshot_init(struct snapshot *, int32_t players_len, int32_t balls_len); -void dp_snapshot_deinit(struct snapshot *); - -int dp_snapshot_put_player(struct snapshot *, int32_t id, const struct player *); -struct player *dp_snapshot_get_player(struct snapshot *, int32_t id); -int dp_snapshot_remove_player(struct snapshot *, int32_t id); -int dp_snapshot_set_player_input(struct snapshot *, int32_t id, uint8_t input); - -int dp_snapshot_put_ball(struct snapshot *, int32_t id, const struct ball *); -struct ball *dp_snapshot_get_ball(struct snapshot *, int32_t id); -int dp_snapshot_remove_ball(struct snapshot *, int32_t id); diff --git a/lib/systems.odin b/lib/systems.odin new file mode 100644 index 0000000..288bd01 --- /dev/null +++ b/lib/systems.odin @@ -0,0 +1,44 @@ +package djup + +DELTA: f32 : 1.0 / 60.0 + +@(export = true) +sim_tick :: proc "c" (cur, next: ^Snapshot) { + if cur == nil || next == nil { + return + } + context = next.ctx^ + + next.tick = cur.tick + 1 + copy(next.metadata, cur.metadata) + + player_input_system(cur, next) + ball_movement_system(cur, next) +} + +player_input_system :: proc(cur, next: ^Snapshot) { + for &e, id in soa_zip(m = cur.metadata, input = cur.player_inputs, ball = cur.balls) { + if e.m < {.Exists, .PlayerInput, .Ball} { + continue + } + + PLAYER_ACCELERATION :: 1500 + PLAYER_DRAG :: 2 + + acc := + vec2_normal(e.input.direction) * PLAYER_ACCELERATION + e.ball.velocity * -PLAYER_DRAG + e.ball.velocity += acc * DELTA + next.player_inputs[id] = e.input + } +} + +ball_movement_system :: proc(cur, next: ^Snapshot) { + for &e, id in soa_zip(m = cur.metadata, ball = cur.balls) { + if e.m < {.Exists, .Ball} { + continue + } + + next.balls[id].position = e.ball.velocity * DELTA + next.balls[id].velocity = e.ball.velocity + } +} diff --git a/lib/test.c b/lib/test.c deleted file mode 100644 index 70b32fa..0000000 --- a/lib/test.c +++ /dev/null @@ -1,24 +0,0 @@ -#include <stdio.h> - -#include "types.h" - -void -dp_hello_world() -{ - printf("Hello World\n"); -} - -int -dp_get_num() -{ - return 1; -} - -vec2 -dp_get_vec2() -{ - vec2 vec; - vec.x = 1.0f; - vec.y = 2.5f; - return vec; -} diff --git a/lib/types.h b/lib/types.h deleted file mode 100644 index bf42576..0000000 --- a/lib/types.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _TYPES_H -#define _TYPES_H - -#include <stdbool.h> -#include <stddef.h> -#include <stdint.h> - -typedef struct { - float x; - float y; -} vec2; - -vec2 dp_vec2_new(float, float); -vec2 dp_vec2_add(vec2, vec2); -vec2 dp_vec2_sub(vec2, vec2); -vec2 dp_vec2_mul(vec2, float scalar); -vec2 dp_vec2_dot(vec2, vec2); -float dp_vec2_length(vec2); -vec2 dp_vec2_normal(vec2); - -#endif diff --git a/lib/vec2.c b/lib/vec2.c deleted file mode 100644 index 55f5078..0000000 --- a/lib/vec2.c +++ /dev/null @@ -1,68 +0,0 @@ -#include <assert.h> -#include <math.h> - -#include "types.h" - -vec2 -dp_vec2_new(float x, float y) -{ - vec2 new; - - assert(isfinite(x)); - assert(isfinite(y)); - - new.x = x; - new.y = y; - return new; -} - -vec2 -dp_vec2_add(vec2 a, vec2 b) -{ - vec2 new; - new.x = a.x + b.x; - new.y = a.y + b.y; - return new; -} - -vec2 -dp_vec2_sub(vec2 a, vec2 b) -{ - vec2 new; - new.x = a.x - b.x; - new.y = a.y - b.y; - return new; -} - -vec2 -dp_vec2_mul(vec2 vec, float scalar) -{ - vec2 new; - new.x = vec.x * scalar; - new.y = vec.y * scalar; - return new; -} - -vec2 -dp_vec2_dot(vec2 a, vec2 b) -{ - vec2 dot; - dot.x = a.x * b.x; - dot.y = a.y * b.y; - return dot; -} - -float -dp_vec2_length(vec2 v) -{ - return sqrtf(powf(v.x, 2.f) + powf(v.y, 2.f)); -} - -vec2 -dp_vec2_normal(vec2 v) -{ - float len = dp_vec2_length(v); - if (len == 0.0f) - return dp_vec2_new(0.0f, 0.0f); - return dp_vec2_mul(v, 1.0f / len); -} |
