Merge remote-tracking branch 'origin/master'
commit
9a1e4bef96
|
@ -1,5 +1,10 @@
|
||||||
build
|
build
|
||||||
build_rel
|
build_rel
|
||||||
|
build_web
|
||||||
|
emsdk
|
||||||
|
deploy_web
|
||||||
|
run_web
|
||||||
|
butler
|
||||||
screenshots
|
screenshots
|
||||||
build.bat
|
build.bat
|
||||||
run.bat
|
run.bat
|
||||||
|
@ -12,7 +17,6 @@ GPATH
|
||||||
GRTAGS
|
GRTAGS
|
||||||
GTAGS
|
GTAGS
|
||||||
/run_release.bat
|
/run_release.bat
|
||||||
/package.bat
|
|
||||||
pkg
|
pkg
|
||||||
pkg.zip
|
pkg.zip
|
||||||
eco2d.zip
|
eco2d.zip
|
|
@ -8,11 +8,17 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/)
|
||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/)
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/)
|
||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR})
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR})
|
||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR})
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR})
|
||||||
|
SET(CMAKE_USE_RELATIVE_PATHS OFF)
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (EMSCRIPTEN)
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_GLFW=3 --profiling -s ASSERTIONS=1 -s WASM=1 -s INITIAL_MEMORY=268435456 -s FORCE_FILESYSTEM=1 --preload-file ${CMAKE_SOURCE_DIR}/art@art/ --shell-file ${CMAKE_SOURCE_DIR}/web/eco2d.html --post-js ${CMAKE_SOURCE_DIR}/web/eco2d-post.js")
|
||||||
|
set(CMAKE_EXECUTABLE_SUFFIX ".html")
|
||||||
|
endif ()
|
||||||
|
|
||||||
include_directories(code/common code/vendors code/vendors/flecs)
|
include_directories(code/common code/vendors code/vendors/flecs)
|
||||||
|
|
||||||
include(cmake/FindRaylib.cmake)
|
include(cmake/FindRaylib.cmake)
|
||||||
|
|
31
README.md
31
README.md
|
@ -1,11 +1,12 @@
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://github.com/zpl-c/zpl"><img src="https://user-images.githubusercontent.com/2182108/111983468-d5593e80-8b12-11eb-9c59-8c78ecc0504e.png" alt="eco2d" /></a>
|
<a href="https://zaklaus.itch.io/eco2d"><img src="https://user-images.githubusercontent.com/2182108/111983468-d5593e80-8b12-11eb-9c59-8c78ecc0504e.png" alt="eco2d" /></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://discord.gg/2fZVEym"><img src="https://img.shields.io/discord/354670964400848898?color=7289DA&style=for-the-badge" alt="discord" /></a>
|
<a href="https://discord.gg/2fZVEym"><img src="https://img.shields.io/discord/354670964400848898?color=7289DA&style=for-the-badge" alt="discord" /></a>
|
||||||
|
<a href="https://zaklaus.itch.io/eco2d"><img src="https://static.itch.io/images/badge-color.svg" alt="play" height="28px"/></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
@ -51,6 +52,30 @@ In the abstract sense, we call the Server the game master hosting all gameplay r
|
||||||
|
|
||||||
# Build the project
|
# Build the project
|
||||||
We use CMake to generate project files and manage builds.
|
We use CMake to generate project files and manage builds.
|
||||||
|
|
||||||
|
## Web
|
||||||
|
We have a set of scripts ready for web development, these steps will get you up and running with a web build:
|
||||||
|
```sh
|
||||||
|
# Setup emsdk locally and configure a web project
|
||||||
|
web/setup.sh
|
||||||
|
|
||||||
|
# Build the web project
|
||||||
|
web/build.sh
|
||||||
|
|
||||||
|
# Host the files on a web server (Python3)
|
||||||
|
web/host.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Desktop
|
||||||
|
### Pre-requisites
|
||||||
|
#### Linux
|
||||||
|
Follow [raylib-linux](https://github.com/raysan5/raylib/wiki/Working-on-GNU-Linux) guide to install dependencies on your system.
|
||||||
|
|
||||||
|
#### macOS
|
||||||
|
Follow [raylib-macos](https://github.com/raysan5/raylib/wiki/Working-on-macOS) guide to install dependencies on your system.
|
||||||
|
#### Windows
|
||||||
|
You need to have Visual Studio 2019+ installed on your system. Make sure to run the commands below in a VS Developer Command Prompt.
|
||||||
|
### Build
|
||||||
You can do the following on the command line to create and build this project:
|
You can do the following on the command line to create and build this project:
|
||||||
```sh
|
```sh
|
||||||
git clone https://github.com/zpl-c/eco2d.git
|
git clone https://github.com/zpl-c/eco2d.git
|
||||||
|
@ -61,10 +86,6 @@ cmake --build build
|
||||||
|
|
||||||
Run the following command to see all the options:
|
Run the following command to see all the options:
|
||||||
```sh
|
```sh
|
||||||
Windows:
|
|
||||||
build\Debug\eco2d.exe -?
|
|
||||||
|
|
||||||
Linux:
|
|
||||||
build\eco2d.exe -?
|
build\eco2d.exe -?
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ function(link_system_libs target_name)
|
||||||
target_link_libraries(${target_name} winmm)
|
target_link_libraries(${target_name} winmm)
|
||||||
elseif (APPLE)
|
elseif (APPLE)
|
||||||
target_link_libraries(${target_name} pthread m dl)
|
target_link_libraries(${target_name} pthread m dl)
|
||||||
|
elseif (EMSCRIPTEN)
|
||||||
|
target_link_libraries(${target_name} pthread m dl)
|
||||||
elseif (UNIX)
|
elseif (UNIX)
|
||||||
target_link_libraries(${target_name} pthread m dl atomic)
|
target_link_libraries(${target_name} pthread m dl atomic)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -43,5 +43,6 @@ add_executable(eco2d
|
||||||
target_compile_definitions(eco2d PRIVATE CLIENT)
|
target_compile_definitions(eco2d PRIVATE CLIENT)
|
||||||
include_directories(src ../modules ../../art/gen)
|
include_directories(src ../modules ../../art/gen)
|
||||||
target_link_libraries(eco2d raylib cwpack eco2d-modules flecs-bundle vendors-bundle)
|
target_link_libraries(eco2d raylib cwpack eco2d-modules flecs-bundle vendors-bundle)
|
||||||
|
target_compile_options(eco2d PRIVATE -Werror -Wall -Wextra -Wno-unused-function -Wno-unknown-pragmas -Wno-unused-variable -Wno-unused-parameter)
|
||||||
|
|
||||||
link_system_libs(eco2d)
|
link_system_libs(eco2d)
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
// can use it in other systems
|
// can use it in other systems
|
||||||
|
|
||||||
// NOTE(zaklaus): Register a block
|
// NOTE(zaklaus): Register a block
|
||||||
#include "blocks/blocks_list.c"
|
#include "world/blocks_list.c"
|
||||||
|
|
||||||
// NOTE(zaklaus): Register an item
|
// NOTE(zaklaus): Register an item
|
||||||
#include "items_list.c"
|
#include "items_list.c"
|
||||||
|
|
|
@ -23,6 +23,8 @@ typedef struct {
|
||||||
static int64_t assets_frame_counter = 1;
|
static int64_t assets_frame_counter = 1;
|
||||||
static double assets_frame_next_draw = 0.0;
|
static double assets_frame_next_draw = 0.0;
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
int32_t assets_setup(void) {
|
int32_t assets_setup(void) {
|
||||||
for (uint32_t i=0; i<ASSETS_COUNT; i++) {
|
for (uint32_t i=0; i<ASSETS_COUNT; i++) {
|
||||||
asset *b = &assets[i];
|
asset *b = &assets[i];
|
||||||
|
@ -43,13 +45,12 @@ int32_t assets_setup(void) {
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
assets_frame_next_draw = get_cached_time() + ASSET_FRAME_RENDER_MS;
|
||||||
assets_frame_next_draw = zpl_time_rel() + ASSET_FRAME_RENDER_MS;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t assets_frame(void) {
|
int32_t assets_frame(void) {
|
||||||
if (assets_frame_next_draw < zpl_time_rel()) {
|
if (assets_frame_next_draw < get_cached_time()) {
|
||||||
for (uint32_t i=0; i<ASSETS_COUNT; i++) {
|
for (uint32_t i=0; i<ASSETS_COUNT; i++) {
|
||||||
asset *b = &assets[i];
|
asset *b = &assets[i];
|
||||||
|
|
||||||
|
@ -63,7 +64,7 @@ int32_t assets_frame(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assets_frame_next_draw = zpl_time_rel() + ASSET_FRAME_RENDER_MS;
|
assets_frame_next_draw = get_cached_time() + ASSET_FRAME_RENDER_MS;
|
||||||
assets_frame_counter += ASSET_FRAME_SKIP;
|
assets_frame_counter += ASSET_FRAME_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ static asset assets[] = {
|
||||||
ASSET_TEX(ASSET_DEV),
|
ASSET_TEX(ASSET_DEV),
|
||||||
ASSET_TEX(ASSET_GROUND),
|
ASSET_TEX(ASSET_GROUND),
|
||||||
ASSET_TEX(ASSET_DIRT),
|
ASSET_TEX(ASSET_DIRT),
|
||||||
ASSET_ANI(ASSET_WATER),
|
ASSET_TEX(ASSET_WATER),
|
||||||
ASSET_TEX(ASSET_LAVA),
|
ASSET_TEX(ASSET_LAVA),
|
||||||
ASSET_TEX(ASSET_WALL),
|
ASSET_TEX(ASSET_WALL),
|
||||||
ASSET_TEX(ASSET_HILL),
|
ASSET_TEX(ASSET_HILL),
|
||||||
|
|
|
@ -116,7 +116,7 @@ void debug_replay_start(void) {
|
||||||
if (records) zpl_array_free(records);
|
if (records) zpl_array_free(records);
|
||||||
zpl_array_init_reserve(records, zpl_heap(), UINT16_MAX);
|
zpl_array_init_reserve(records, zpl_heap(), UINT16_MAX);
|
||||||
|
|
||||||
last_record_time = zpl_time_rel();
|
last_record_time = get_cached_time();
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(60);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ void debug_replay_run(void) {
|
||||||
if (mime) return;
|
if (mime) return;
|
||||||
is_playing = true;
|
is_playing = true;
|
||||||
record_pos = 0;
|
record_pos = 0;
|
||||||
playback_time = zpl_time_rel();
|
playback_time = get_cached_time();
|
||||||
zpl_array_init(temp_actors, zpl_heap());
|
zpl_array_init(temp_actors, zpl_heap());
|
||||||
|
|
||||||
plr = camera_get().ent_id;
|
plr = camera_get().ent_id;
|
||||||
|
@ -181,10 +181,10 @@ void ActSpawnBelt(void);
|
||||||
|
|
||||||
void debug_replay_update(void) {
|
void debug_replay_update(void) {
|
||||||
if (!is_playing) return;
|
if (!is_playing) return;
|
||||||
if (playback_time >= zpl_time_rel()) return;
|
if (playback_time >= get_cached_time()) return;
|
||||||
|
|
||||||
replay_record *r = &records[record_pos];
|
replay_record *r = &records[record_pos];
|
||||||
playback_time = zpl_time_rel() + r->delay;
|
playback_time = get_cached_time() + r->delay;
|
||||||
|
|
||||||
switch (r->kind) {
|
switch (r->kind) {
|
||||||
case RPKIND_KEY: {
|
case RPKIND_KEY: {
|
||||||
|
@ -249,7 +249,7 @@ void debug_replay_update(void) {
|
||||||
|
|
||||||
void debug_replay_record_keystate(pkt_send_keystate state) {
|
void debug_replay_record_keystate(pkt_send_keystate state) {
|
||||||
if (!is_recording) return;
|
if (!is_recording) return;
|
||||||
double record_time = zpl_time_rel();
|
double record_time = get_cached_time();
|
||||||
|
|
||||||
replay_record rec = {
|
replay_record rec = {
|
||||||
.kind = RPKIND_KEY,
|
.kind = RPKIND_KEY,
|
||||||
|
@ -258,13 +258,13 @@ void debug_replay_record_keystate(pkt_send_keystate state) {
|
||||||
};
|
};
|
||||||
|
|
||||||
zpl_array_append(records, rec);
|
zpl_array_append(records, rec);
|
||||||
last_record_time = zpl_time_rel();
|
last_record_time = get_cached_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
void debug_replay_special_action(replay_kind kind) {
|
void debug_replay_special_action(replay_kind kind) {
|
||||||
ZPL_ASSERT(kind != RPKIND_KEY);
|
ZPL_ASSERT(kind != RPKIND_KEY);
|
||||||
if (!is_recording || is_playing) return;
|
if (!is_recording || is_playing) return;
|
||||||
double record_time = zpl_time_rel();
|
double record_time = get_cached_time();
|
||||||
|
|
||||||
replay_record rec = {
|
replay_record rec = {
|
||||||
.kind = kind,
|
.kind = kind,
|
||||||
|
@ -272,5 +272,5 @@ void debug_replay_special_action(replay_kind kind) {
|
||||||
};
|
};
|
||||||
|
|
||||||
zpl_array_append(records, rec);
|
zpl_array_append(records, rec);
|
||||||
last_record_time = zpl_time_rel();
|
last_record_time = get_cached_time();
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ typedef struct {
|
||||||
#define DBG_FONT_SIZE 22
|
#define DBG_FONT_SIZE 22
|
||||||
#define DBG_FONT_SPACING DBG_FONT_SIZE * 1.2f
|
#define DBG_FONT_SPACING DBG_FONT_SIZE * 1.2f
|
||||||
#define DBG_START_XPOS 15
|
#define DBG_START_XPOS 15
|
||||||
#define DBG_START_YPOS 200
|
#define DBG_START_YPOS 30
|
||||||
#define DBG_LIST_XPOS_OFFSET 10
|
#define DBG_LIST_XPOS_OFFSET 10
|
||||||
#define DBG_SHADOW_OFFSET_XPOS 1
|
#define DBG_SHADOW_OFFSET_XPOS 1
|
||||||
#define DBG_SHADOW_OFFSET_YPOS 1
|
#define DBG_SHADOW_OFFSET_YPOS 1
|
||||||
|
@ -92,6 +92,7 @@ static debug_item items[] = {
|
||||||
.kind = DITEM_LIST,
|
.kind = DITEM_LIST,
|
||||||
.name = "general",
|
.name = "general",
|
||||||
.list = {
|
.list = {
|
||||||
|
.is_collapsed = true,
|
||||||
.items = (debug_item[]) {
|
.items = (debug_item[]) {
|
||||||
{ .kind = DITEM_TEXT, .name = "delta time", .proc = DrawDeltaTime },
|
{ .kind = DITEM_TEXT, .name = "delta time", .proc = DrawDeltaTime },
|
||||||
{ .kind = DITEM_TEXT, .name = "pos", .proc = DrawCameraPos },
|
{ .kind = DITEM_TEXT, .name = "pos", .proc = DrawCameraPos },
|
||||||
|
@ -104,6 +105,7 @@ static debug_item items[] = {
|
||||||
.kind = DITEM_LIST,
|
.kind = DITEM_LIST,
|
||||||
.name = "world simulation",
|
.name = "world simulation",
|
||||||
.list = {
|
.list = {
|
||||||
|
.is_collapsed = true,
|
||||||
.items = (debug_item[]) {
|
.items = (debug_item[]) {
|
||||||
{ .kind = DITEM_COND, .on_success = CondIsWorldRunning },
|
{ .kind = DITEM_COND, .on_success = CondIsWorldRunning },
|
||||||
{ .kind = DITEM_BUTTON, .name = "pause", .on_click = ActWorldToggleSim },
|
{ .kind = DITEM_BUTTON, .name = "pause", .on_click = ActWorldToggleSim },
|
||||||
|
@ -127,6 +129,7 @@ static debug_item items[] = {
|
||||||
.kind = DITEM_LIST,
|
.kind = DITEM_LIST,
|
||||||
.name = "debug actions",
|
.name = "debug actions",
|
||||||
.list = {
|
.list = {
|
||||||
|
.is_collapsed = true,
|
||||||
.items = (debug_item[]) {
|
.items = (debug_item[]) {
|
||||||
{ .kind = DITEM_BUTTON, .name = "spawn car", .on_click = ActSpawnCar },
|
{ .kind = DITEM_BUTTON, .name = "spawn car", .on_click = ActSpawnCar },
|
||||||
{ .kind = DITEM_BUTTON, .name = "place ice rink", .on_click = ActPlaceIceRink },
|
{ .kind = DITEM_BUTTON, .name = "place ice rink", .on_click = ActPlaceIceRink },
|
||||||
|
@ -157,6 +160,7 @@ static debug_item items[] = {
|
||||||
.kind = DITEM_LIST,
|
.kind = DITEM_LIST,
|
||||||
.name = "conn metrics",
|
.name = "conn metrics",
|
||||||
.list = {
|
.list = {
|
||||||
|
.is_collapsed = true,
|
||||||
.items = (debug_item[]) {
|
.items = (debug_item[]) {
|
||||||
{ .kind = DITEM_COND, .on_success = CondClientDisconnected },
|
{ .kind = DITEM_COND, .on_success = CondClientDisconnected },
|
||||||
{ .kind = DITEM_TEXT, .name = "status", .proc = DrawLiteral, .text = "disconnected" },
|
{ .kind = DITEM_TEXT, .name = "status", .proc = DrawLiteral, .text = "disconnected" },
|
||||||
|
@ -172,6 +176,7 @@ static debug_item items[] = {
|
||||||
},
|
},
|
||||||
.limit_to = L_MP,
|
.limit_to = L_MP,
|
||||||
},
|
},
|
||||||
|
#if !defined(PLATFORM_WEB)
|
||||||
{
|
{
|
||||||
.kind = DITEM_LIST,
|
.kind = DITEM_LIST,
|
||||||
.name = "replay system",
|
.name = "replay system",
|
||||||
|
@ -209,6 +214,7 @@ static debug_item items[] = {
|
||||||
},
|
},
|
||||||
.limit_to = L_SP,
|
.limit_to = L_SP,
|
||||||
},
|
},
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
.kind = DITEM_LIST,
|
.kind = DITEM_LIST,
|
||||||
.name = "profilers",
|
.name = "profilers",
|
||||||
|
@ -226,11 +232,13 @@ static debug_item items[] = {
|
||||||
.is_collapsed = 1
|
.is_collapsed = 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
#if !defined(PLATFORM_WEB)
|
||||||
{
|
{
|
||||||
.kind = DITEM_BUTTON,
|
.kind = DITEM_BUTTON,
|
||||||
.name = "exit game",
|
.name = "exit game",
|
||||||
.on_click = ActExitGame,
|
.on_click = ActExitGame,
|
||||||
},
|
},
|
||||||
|
#endif
|
||||||
{.kind = DITEM_END},
|
{.kind = DITEM_END},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ ActSpawnCar(void) {
|
||||||
Position const* origin = ecs_get(world_ecs(), plr, Position);
|
Position const* origin = ecs_get(world_ecs(), plr, Position);
|
||||||
Position * dest = ecs_get_mut(world_ecs(), e, Position);
|
Position * dest = ecs_get_mut(world_ecs(), e, Position);
|
||||||
*dest = *origin;
|
*dest = *origin;
|
||||||
|
entity_set_position(e, dest->x, dest->y);
|
||||||
|
|
||||||
debug_replay_special_action(RPKIND_SPAWN_CAR);
|
debug_replay_special_action(RPKIND_SPAWN_CAR);
|
||||||
}
|
}
|
||||||
|
@ -28,6 +29,7 @@ ActSpawnIcemaker(void) {
|
||||||
Position const* origin = ecs_get(world_ecs(), plr, Position);
|
Position const* origin = ecs_get(world_ecs(), plr, Position);
|
||||||
Position * dest = ecs_get_mut(world_ecs(), e, Position);
|
Position * dest = ecs_get_mut(world_ecs(), e, Position);
|
||||||
*dest = *origin;
|
*dest = *origin;
|
||||||
|
entity_set_position(e, dest->x, dest->y);
|
||||||
|
|
||||||
debug_replay_special_action(RPKIND_SPAWN_ICEMAKER_ITEM);
|
debug_replay_special_action(RPKIND_SPAWN_ICEMAKER_ITEM);
|
||||||
}
|
}
|
||||||
|
@ -40,6 +42,7 @@ ActSpawnChest(void) {
|
||||||
Position const* origin = ecs_get(world_ecs(), plr, Position);
|
Position const* origin = ecs_get(world_ecs(), plr, Position);
|
||||||
Position * dest = ecs_get_mut(world_ecs(), e, Position);
|
Position * dest = ecs_get_mut(world_ecs(), e, Position);
|
||||||
*dest = *origin;
|
*dest = *origin;
|
||||||
|
entity_set_position(e, dest->x, dest->y);
|
||||||
|
|
||||||
debug_replay_special_action(RPKIND_SPAWN_CHEST);
|
debug_replay_special_action(RPKIND_SPAWN_CHEST);
|
||||||
}
|
}
|
||||||
|
@ -52,6 +55,7 @@ ActSpawnBelt(void) {
|
||||||
Position const* origin = ecs_get(world_ecs(), plr, Position);
|
Position const* origin = ecs_get(world_ecs(), plr, Position);
|
||||||
Position * dest = ecs_get_mut(world_ecs(), e, Position);
|
Position * dest = ecs_get_mut(world_ecs(), e, Position);
|
||||||
*dest = *origin;
|
*dest = *origin;
|
||||||
|
entity_set_position(e, dest->x, dest->y);
|
||||||
|
|
||||||
debug_replay_special_action(RPKIND_SPAWN_BELT);
|
debug_replay_special_action(RPKIND_SPAWN_BELT);
|
||||||
}
|
}
|
||||||
|
@ -67,6 +71,8 @@ ActSpawnCirclingDriver(void) {
|
||||||
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
||||||
*veh_dest = *origin;
|
*veh_dest = *origin;
|
||||||
*dest = *origin;
|
*dest = *origin;
|
||||||
|
entity_set_position(ve, veh_dest->x, veh_dest->y);
|
||||||
|
entity_set_position(e, dest->x, dest->y);
|
||||||
|
|
||||||
Input *input = ecs_get_mut(world_ecs(), e, Input);
|
Input *input = ecs_get_mut(world_ecs(), e, Input);
|
||||||
zpl_zero_item(input);
|
zpl_zero_item(input);
|
||||||
|
|
|
@ -23,6 +23,7 @@ uint64_t entity_spawn(uint16_t class_id) {
|
||||||
#if 1
|
#if 1
|
||||||
pos->x=(float)(rand() % world_dim());
|
pos->x=(float)(rand() % world_dim());
|
||||||
pos->y=(float)(rand() % world_dim());
|
pos->y=(float)(rand() % world_dim());
|
||||||
|
entity_set_position(e, pos->x, pos->y);
|
||||||
#else
|
#else
|
||||||
pos->x=350.0f;
|
pos->x=350.0f;
|
||||||
pos->y=88.0f;
|
pos->y=88.0f;
|
||||||
|
@ -62,7 +63,7 @@ void entity_set_position(uint64_t ent_id, float x, float y) {
|
||||||
Position *p = ecs_get_mut(world_ecs(), ent_id, Position);
|
Position *p = ecs_get_mut(world_ecs(), ent_id, Position);
|
||||||
p->x = x;
|
p->x = x;
|
||||||
p->y = y;
|
p->y = y;
|
||||||
|
librg_entity_chunk_set(world_tracker(), ent_id, librg_chunk_from_realpos(world_tracker(), x, y, 0));
|
||||||
entity_wake(ent_id);
|
entity_wake(ent_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +79,7 @@ void entity_update_action_timers() {
|
||||||
static double last_update_time = 0.0f;
|
static double last_update_time = 0.0f;
|
||||||
if (!ecs_streaminfo) {
|
if (!ecs_streaminfo) {
|
||||||
ecs_streaminfo = ecs_query_new(world_ecs(), "components.StreamInfo");
|
ecs_streaminfo = ecs_query_new(world_ecs(), "components.StreamInfo");
|
||||||
last_update_time = zpl_time_rel();
|
last_update_time = get_cached_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
ecs_iter_t it = ecs_query_iter(world_ecs(), ecs_streaminfo);
|
ecs_iter_t it = ecs_query_iter(world_ecs(), ecs_streaminfo);
|
||||||
|
@ -86,18 +87,18 @@ void entity_update_action_timers() {
|
||||||
while (ecs_query_next(&it)) {
|
while (ecs_query_next(&it)) {
|
||||||
StreamInfo *si = ecs_field(&it, StreamInfo, 1);
|
StreamInfo *si = ecs_field(&it, StreamInfo, 1);
|
||||||
|
|
||||||
for (size_t i = 0; i < it.count; i++) {
|
for (int32_t i = 0; i < it.count; i++) {
|
||||||
if (si[i].last_update < zpl_time_rel()) {
|
if (si[i].last_update < get_cached_time()) {
|
||||||
si[i].last_update = zpl_time_rel() + si[i].tick_delay;
|
si[i].last_update = get_cached_time() + si[i].tick_delay;
|
||||||
si[i].tick_delay += (zpl_time_rel() - last_update_time) * 0.5f;
|
si[i].tick_delay += (get_cached_time() - last_update_time) * 0.5f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
last_update_time = zpl_time_rel();
|
last_update_time = get_cached_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool entity_can_stream(uint64_t ent_id) {
|
bool entity_can_stream(uint64_t ent_id) {
|
||||||
StreamInfo *si = ecs_get_mut(world_ecs(), ent_id, StreamInfo);
|
StreamInfo *si = ecs_get_mut(world_ecs(), ent_id, StreamInfo);
|
||||||
return (si->last_update < zpl_time_rel());
|
return (si->last_update < get_cached_time());
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,10 +50,10 @@ pkt_desc pkt_entity_view_desc[] = {
|
||||||
{ PKT_END },
|
{ PKT_END },
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t entity_view_pack_struct(void *data, size_t len, entity_view view) {
|
size_t entity_view_pack_struct(void *data, size_t len, entity_view *view) {
|
||||||
cw_pack_context pc = {0};
|
cw_pack_context pc = {0};
|
||||||
cw_pack_context_init(&pc, data, (unsigned long)len, 0);
|
cw_pack_context_init(&pc, data, (unsigned long)len, 0);
|
||||||
pkt_pack_struct(&pc, pkt_entity_view_desc, PKT_STRUCT_PTR(&view));
|
pkt_pack_struct(&pc, pkt_entity_view_desc, PKT_STRUCT_PTR(view));
|
||||||
return pc.current - pc.start;
|
return pc.current - pc.start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,7 @@ void entity_view_destroy(entity_view_tbl *map, uint64_t ent_id);
|
||||||
entity_view *entity_view_get(entity_view_tbl *map, uint64_t ent_id);
|
entity_view *entity_view_get(entity_view_tbl *map, uint64_t ent_id);
|
||||||
void entity_view_map(entity_view_tbl *map, void (*map_proc)(uint64_t key, entity_view *value));
|
void entity_view_map(entity_view_tbl *map, void (*map_proc)(uint64_t key, entity_view *value));
|
||||||
|
|
||||||
size_t entity_view_pack_struct(void *data, size_t len, entity_view view);
|
size_t entity_view_pack_struct(void *data, size_t len, entity_view *view);
|
||||||
entity_view entity_view_unpack_struct(void *data, size_t len);
|
entity_view entity_view_unpack_struct(void *data, size_t len);
|
||||||
|
|
||||||
void entity_view_mark_for_removal(entity_view_tbl *map, uint64_t ent_id);
|
void entity_view_mark_for_removal(entity_view_tbl *map, uint64_t ent_id);
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "profiler.h"
|
#include "profiler.h"
|
||||||
|
|
||||||
#include "flecs/flecs_os_api_stdcpp.h"
|
#include "flecs/flecs_os_api_stdcpp.h"
|
||||||
|
#include "flecs/flecs.h"
|
||||||
|
|
||||||
#include "modules/components.h"
|
#include "modules/components.h"
|
||||||
#include "modules/systems.h"
|
#include "modules/systems.h"
|
||||||
|
@ -72,7 +73,7 @@ void world_viewers_init(uint32_t num_viewers) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void world_viewers_destroy() {
|
void world_viewers_destroy() {
|
||||||
for (uint32_t i = 0; i < zpl_buffer_count(world_viewers); i++) {
|
for (zpl_isize i = 0; i < zpl_buffer_count(world_viewers); i++) {
|
||||||
world_view_destroy(&world_viewers[i]);
|
world_view_destroy(&world_viewers[i]);
|
||||||
}
|
}
|
||||||
zpl_buffer_free(world_viewers);
|
zpl_buffer_free(world_viewers);
|
||||||
|
@ -114,12 +115,14 @@ size_t game_world_view_count(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void flecs_dash_init() {
|
void flecs_dash_init() {
|
||||||
|
#if !defined(ZPL_SYSTEM_EMSCRIPTEN)
|
||||||
ecs_singleton_set(world_ecs(), EcsRest, {0});
|
ecs_singleton_set(world_ecs(), EcsRest, {0});
|
||||||
ECS_IMPORT(world_ecs(), FlecsMonitor);
|
ECS_IMPORT(world_ecs(), FlecsMonitor);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
float game_time() {
|
float game_time() {
|
||||||
return (float)zpl_time_rel();
|
return (float)get_cached_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_init(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled) {
|
void game_init(const char *ip, uint16_t port, game_kind play_mode, uint32_t num_viewers, int32_t seed, uint16_t chunk_size, uint16_t chunk_amount, int8_t is_dash_enabled) {
|
||||||
|
@ -229,15 +232,15 @@ void game_update() {
|
||||||
if (game_mode == GAMEKIND_HEADLESS) {
|
if (game_mode == GAMEKIND_HEADLESS) {
|
||||||
network_server_tick();
|
network_server_tick();
|
||||||
|
|
||||||
static uint64_t ms_report = 2500;
|
static float ms_report = 2.5f;
|
||||||
if (ms_report < zpl_time_rel_ms()) {
|
if (ms_report < get_cached_time()) {
|
||||||
ms_report = zpl_time_rel_ms() + 5000;
|
ms_report = get_cached_time() + 5.f;
|
||||||
zpl_printf("delta: %f ms.\n", (zpl_time_rel() - last_update)*1000.0f);
|
zpl_printf("delta: %f ms.\n", (get_cached_time() - last_update)*1000.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
last_update = zpl_time_rel();
|
last_update = get_cached_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_render() {
|
void game_render() {
|
||||||
|
|
|
@ -33,11 +33,11 @@ Texture2D GenColorEco(Color color) {
|
||||||
Texture2D texgen_build_anim(asset_id id, int64_t counter) {
|
Texture2D texgen_build_anim(asset_id id, int64_t counter) {
|
||||||
(void)counter;
|
(void)counter;
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case ASSET_WATER: {
|
// case ASSET_WATER: {
|
||||||
Image img = LoadImageEco("water");
|
// Image img = LoadImageEco("water");
|
||||||
ImageColorBrightness(&img, zpl_abs((counter % 64 - 32)*2));
|
// ImageColorBrightness(&img, zpl_abs((counter % 64 - 32)*2));
|
||||||
return Image2TexEco(img);
|
// return Image2TexEco(img);
|
||||||
}break;
|
// }break;
|
||||||
|
|
||||||
default: return GenColorEco(PINK); break;
|
default: return GenColorEco(PINK); break;
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,7 @@ Texture2D texgen_build_sprite(asset_id id) {
|
||||||
case ASSET_LAVA: return LoadTexEco("lava");
|
case ASSET_LAVA: return LoadTexEco("lava");
|
||||||
case ASSET_WOOD: return LoadTexEco("wood");
|
case ASSET_WOOD: return LoadTexEco("wood");
|
||||||
case ASSET_TREE: return LoadTexEco("tree");
|
case ASSET_TREE: return LoadTexEco("tree");
|
||||||
|
case ASSET_WATER: return LoadTexEco("water");
|
||||||
|
|
||||||
case ASSET_BELT:
|
case ASSET_BELT:
|
||||||
case ASSET_BELT_RIGHT: return LoadTexEco("belt_right");
|
case ASSET_BELT_RIGHT: return LoadTexEco("belt_right");
|
||||||
|
|
|
@ -45,7 +45,7 @@ void buildmode_draw(void) {
|
||||||
|
|
||||||
ItemDrop *item = &e->items[e->selected_item];
|
ItemDrop *item = &e->items[e->selected_item];
|
||||||
|
|
||||||
if (e->has_items && !e->inside_vehicle && item->quantity > 0 && !is_outside_range || build_is_deletion_mode) {
|
if (e->has_items && !e->inside_vehicle && item->quantity > 0 && (!is_outside_range || build_is_deletion_mode)) {
|
||||||
item_usage usage = 0;
|
item_usage usage = 0;
|
||||||
uint16_t item_id = 0;
|
uint16_t item_id = 0;
|
||||||
if (!build_is_deletion_mode){
|
if (!build_is_deletion_mode){
|
||||||
|
|
|
@ -86,12 +86,16 @@ void item_use(ecs_world_t *ecs, ItemDrop *it, Position p, uint64_t udata) {
|
||||||
|
|
||||||
ecs_entity_t e = entity_spawn_id(desc->place_item.id);
|
ecs_entity_t e = entity_spawn_id(desc->place_item.id);
|
||||||
ZPL_ASSERT(world_entity_valid(e));
|
ZPL_ASSERT(world_entity_valid(e));
|
||||||
Position *pos = ecs_get_mut(ecs, e, Position);
|
entity_set_position(e, p.x, p.y);
|
||||||
pos->x = p.x;
|
|
||||||
pos->y = p.y;
|
|
||||||
|
|
||||||
it->quantity--;
|
it->quantity--;
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
|
|
||||||
|
case UKIND_DELETE:
|
||||||
|
case UKIND_END_PLACE:
|
||||||
|
case UKIND_PROXY:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,11 @@
|
||||||
#include "modules/components.h"
|
#include "modules/components.h"
|
||||||
#include "modules/systems.h"
|
#include "modules/systems.h"
|
||||||
|
|
||||||
|
#if defined(PLATFORM_WEB)
|
||||||
|
#include <emscripten/emscripten.h>
|
||||||
|
void UpdateDrawFrame(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
#define DEFAULT_WORLD_SEED 302097
|
#define DEFAULT_WORLD_SEED 302097
|
||||||
#define DEFAULT_CHUNK_SIZE 16 /* amount of blocks within a chunk (single axis) */
|
#define DEFAULT_CHUNK_SIZE 16 /* amount of blocks within a chunk (single axis) */
|
||||||
#define DEFAULT_WORLD_SIZE 32 /* amount of chunks within a world (single axis) */
|
#define DEFAULT_WORLD_SIZE 32 /* amount of chunks within a world (single axis) */
|
||||||
|
@ -73,7 +78,9 @@ int main(int argc, char** argv) {
|
||||||
sighandler_register();
|
sighandler_register();
|
||||||
game_init(host, port, play_mode, num_viewers, seed, chunk_size, world_size, is_dash_enabled);
|
game_init(host, port, play_mode, num_viewers, seed, chunk_size, world_size, is_dash_enabled);
|
||||||
|
|
||||||
|
#if !defined(PLATFORM_WEB)
|
||||||
while (game_is_running()) {
|
while (game_is_running()) {
|
||||||
|
reset_cached_time();
|
||||||
profile (PROF_MAIN_LOOP) {
|
profile (PROF_MAIN_LOOP) {
|
||||||
game_input();
|
game_input();
|
||||||
game_update();
|
game_update();
|
||||||
|
@ -82,6 +89,9 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
profiler_collate();
|
profiler_collate();
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
emscripten_set_main_loop(UpdateDrawFrame, 0, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
game_shutdown();
|
game_shutdown();
|
||||||
sighandler_unregister();
|
sighandler_unregister();
|
||||||
|
@ -90,3 +100,25 @@ int main(int argc, char** argv) {
|
||||||
zpl_opts_free(&opts);
|
zpl_opts_free(&opts);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(PLATFORM_WEB)
|
||||||
|
void UpdateDrawFrame(void) {
|
||||||
|
reset_cached_time();
|
||||||
|
profile (PROF_MAIN_LOOP) {
|
||||||
|
game_input();
|
||||||
|
game_update();
|
||||||
|
game_render();
|
||||||
|
}
|
||||||
|
|
||||||
|
profiler_collate();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static float temp_time = 0.0f;
|
||||||
|
|
||||||
|
float get_cached_time(void) {
|
||||||
|
return temp_time;
|
||||||
|
}
|
||||||
|
void reset_cached_time(void) {
|
||||||
|
temp_time = zpl_time_rel();
|
||||||
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ network_client_fetch_stats(void) {
|
||||||
static float incoming_bandwidth = 0.0f;
|
static float incoming_bandwidth = 0.0f;
|
||||||
static float outgoing_bandwidth = 0.0f;
|
static float outgoing_bandwidth = 0.0f;
|
||||||
|
|
||||||
if (next_measure < zpl_time_rel()) {
|
if (next_measure < get_cached_time()) {
|
||||||
#define MAX_RATE_SAMPLES 8
|
#define MAX_RATE_SAMPLES 8
|
||||||
static uint64_t last_total_sent = 0;
|
static uint64_t last_total_sent = 0;
|
||||||
static uint64_t last_total_recv = 0;
|
static uint64_t last_total_recv = 0;
|
||||||
|
@ -145,7 +145,7 @@ network_client_fetch_stats(void) {
|
||||||
incoming_bandwidth = stats.incoming_bandwidth /= MAX_RATE_SAMPLES;
|
incoming_bandwidth = stats.incoming_bandwidth /= MAX_RATE_SAMPLES;
|
||||||
outgoing_bandwidth = stats.outgoing_bandwidth /= MAX_RATE_SAMPLES;
|
outgoing_bandwidth = stats.outgoing_bandwidth /= MAX_RATE_SAMPLES;
|
||||||
|
|
||||||
next_measure = zpl_time_rel() + 1.0;
|
next_measure = get_cached_time() + 1.0;
|
||||||
} else {
|
} else {
|
||||||
stats.incoming_bandwidth = incoming_bandwidth;
|
stats.incoming_bandwidth = incoming_bandwidth;
|
||||||
stats.outgoing_bandwidth = outgoing_bandwidth;
|
stats.outgoing_bandwidth = outgoing_bandwidth;
|
||||||
|
|
|
@ -105,6 +105,7 @@ int32_t pkt_unpack_struct(cw_unpack_context *uc, pkt_desc *desc, void *raw_blob,
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t pkt_pack_struct(cw_pack_context *pc, pkt_desc *desc, void *raw_blob, uint32_t blob_size) {
|
int32_t pkt_pack_struct(cw_pack_context *pc, pkt_desc *desc, void *raw_blob, uint32_t blob_size) {
|
||||||
|
(void)blob_size;
|
||||||
uint8_t *blob = (uint8_t*)raw_blob;
|
uint8_t *blob = (uint8_t*)raw_blob;
|
||||||
for (pkt_desc *field = desc; field->type != CWP_NOT_AN_ITEM; ++field) {
|
for (pkt_desc *field = desc; field->type != CWP_NOT_AN_ITEM; ++field) {
|
||||||
if (field->skip_count != 0) {
|
if (field->skip_count != 0) {
|
||||||
|
@ -158,6 +159,7 @@ int32_t pkt_pack_struct(cw_pack_context *pc, pkt_desc *desc, void *raw_blob, uin
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkt_dump_struct(pkt_desc *desc, void* raw_blob, uint32_t blob_size) {
|
void pkt_dump_struct(pkt_desc *desc, void* raw_blob, uint32_t blob_size) {
|
||||||
|
(void)blob_size;
|
||||||
uint8_t *blob = (uint8_t*)raw_blob;
|
uint8_t *blob = (uint8_t*)raw_blob;
|
||||||
zpl_printf("{\n");
|
zpl_printf("{\n");
|
||||||
for (pkt_desc *field = desc; field->type != CWP_NOT_AN_ITEM; ++field) {
|
for (pkt_desc *field = desc; field->type != CWP_NOT_AN_ITEM; ++field) {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "entity_view.h"
|
#include "entity_view.h"
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
#include "player.h"
|
#include "player.h"
|
||||||
|
#include "entity.h"
|
||||||
|
|
||||||
#include "modules/components.h"
|
#include "modules/components.h"
|
||||||
#include "modules/systems.h"
|
#include "modules/systems.h"
|
||||||
|
@ -30,9 +31,8 @@ int32_t pkt_00_init_handler(pkt_header *header) {
|
||||||
|
|
||||||
Position *pos = ecs_get_mut(world_ecs(), ent_id, Position);
|
Position *pos = ecs_get_mut(world_ecs(), ent_id, Position);
|
||||||
|
|
||||||
#if 0
|
#if 1
|
||||||
pos->x = world_dim()/2.0f + rand()%15*15.0f;
|
entity_set_position(ent_id, world_dim()/2.0f + rand()%15*15.0f, world_dim()/2.0f + rand()%15*15.0f);
|
||||||
pos->y = world_dim()/2.0f + rand()%15*15.0f;
|
|
||||||
#else
|
#else
|
||||||
pos->x = rand()%world_dim();
|
pos->x = rand()%world_dim();
|
||||||
pos->y = rand()%world_dim();
|
pos->y = rand()%world_dim();
|
||||||
|
|
|
@ -29,7 +29,7 @@ int32_t pkt_01_welcome_handler(pkt_header *header) {
|
||||||
|
|
||||||
world_view *view = game_world_view_get(header->view_id);
|
world_view *view = game_world_view_get(header->view_id);
|
||||||
|
|
||||||
zpl_printf("[INFO] initializing read-only world view id: %d...\n", header->view_id);
|
zpl_printf("[INFO] initializing read-only world view id: %d... (chunk_size: %d, world_size: %d)\n", header->view_id, table.chunk_size, table.world_size);
|
||||||
world_view_init(view, table.seed, table.ent_id, table.chunk_size, table.world_size);
|
world_view_init(view, table.seed, table.ent_id, table.chunk_size, table.world_size);
|
||||||
game_world_view_set_active(view);
|
game_world_view_set_active(view);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -20,6 +20,27 @@ size_t pkt_send_librg_update_encode(void *data, int32_t data_length, uint8_t lay
|
||||||
return pkt_pack_msg_size(&pc);
|
return pkt_pack_msg_size(&pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define NUM_SAMPLES 128
|
||||||
|
|
||||||
|
static float smooth_time(float time) {
|
||||||
|
static float time_samples[NUM_SAMPLES] = {};
|
||||||
|
static int32_t curr_index = 0;
|
||||||
|
|
||||||
|
time_samples[curr_index] = time;
|
||||||
|
if (++curr_index == NUM_SAMPLES)
|
||||||
|
curr_index = 0;
|
||||||
|
|
||||||
|
float average = 0;
|
||||||
|
for (int32_t i = NUM_SAMPLES; i--; )
|
||||||
|
average += time_samples[i];
|
||||||
|
average /= NUM_SAMPLES;
|
||||||
|
|
||||||
|
time = zpl_min(time, average * 2);
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef NUM_SAMPLES
|
||||||
|
|
||||||
int32_t pkt_send_librg_update_handler(pkt_header *header) {
|
int32_t pkt_send_librg_update_handler(pkt_header *header) {
|
||||||
cw_unpack_context uc = {0};
|
cw_unpack_context uc = {0};
|
||||||
pkt_unpack_msg(&uc, header, 2);
|
pkt_unpack_msg(&uc, header, 2);
|
||||||
|
@ -41,8 +62,8 @@ int32_t pkt_send_librg_update_handler(pkt_header *header) {
|
||||||
int32_t state = librg_world_read(view->tracker, header->view_id, uc.item.as.bin.start, uc.item.as.bin.length, NULL);
|
int32_t state = librg_world_read(view->tracker, header->view_id, uc.item.as.bin.start, uc.item.as.bin.length, NULL);
|
||||||
if (state < 0) zpl_printf("[ERROR] world read error: %d\n", state);
|
if (state < 0) zpl_printf("[ERROR] world read error: %d\n", state);
|
||||||
|
|
||||||
float now = (float)zpl_time_rel();
|
float now = (float)get_cached_time();
|
||||||
view->delta_time[layer_id] = now - view->last_update[layer_id];
|
view->delta_time[layer_id] = smooth_time(now - view->last_update[layer_id]);
|
||||||
view->last_update[layer_id] = now;
|
view->last_update[layer_id] = now;
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
|
|
|
@ -13,9 +13,20 @@
|
||||||
#include "debug_ui.h"
|
#include "debug_ui.h"
|
||||||
#include "utils/raylib_helpers.h"
|
#include "utils/raylib_helpers.h"
|
||||||
|
|
||||||
static uint16_t screenWidth = 1600;
|
#if defined(PLATFORM_WEB)
|
||||||
static uint16_t screenHeight = 900;
|
#include <emscripten.h>
|
||||||
static float target_zoom = 1.5f;
|
EM_JS(int, canvas_get_width, (), {
|
||||||
|
return canvas.width;
|
||||||
|
});
|
||||||
|
|
||||||
|
EM_JS(int, canvas_get_height, (), {
|
||||||
|
return canvas.height;
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static uint16_t screenWidth = 1024;
|
||||||
|
static uint16_t screenHeight = 768;
|
||||||
|
static float target_zoom = 0.6f;
|
||||||
static bool request_shutdown;
|
static bool request_shutdown;
|
||||||
|
|
||||||
#define GFX_KIND 2
|
#define GFX_KIND 2
|
||||||
|
@ -27,11 +38,19 @@ static bool request_shutdown;
|
||||||
|
|
||||||
void platform_init() {
|
void platform_init() {
|
||||||
SetTraceLogLevel(LOG_ERROR);
|
SetTraceLogLevel(LOG_ERROR);
|
||||||
|
|
||||||
|
#if defined(PLATFORM_WEB)
|
||||||
|
screenWidth = (uint16_t)canvas_get_width();
|
||||||
|
screenHeight = (uint16_t)canvas_get_height();
|
||||||
|
#endif
|
||||||
|
|
||||||
InitWindow(screenWidth, screenHeight, "eco2d");
|
InitWindow(screenWidth, screenHeight, "eco2d");
|
||||||
SetWindowState(/*FLAG_WINDOW_UNDECORATED|*/FLAG_WINDOW_MAXIMIZED|FLAG_WINDOW_RESIZABLE|FLAG_MSAA_4X_HINT);
|
SetWindowState(/*FLAG_WINDOW_UNDECORATED|*/FLAG_WINDOW_MAXIMIZED|FLAG_WINDOW_RESIZABLE|FLAG_MSAA_4X_HINT);
|
||||||
|
|
||||||
|
#if !defined(PLATFORM_WEB)
|
||||||
screenWidth = (uint16_t)GetScreenWidth();
|
screenWidth = (uint16_t)GetScreenWidth();
|
||||||
screenHeight = (uint16_t)GetScreenHeight();
|
screenHeight = (uint16_t)GetScreenHeight();
|
||||||
|
#endif
|
||||||
// ToggleFullscreen();
|
// ToggleFullscreen();
|
||||||
// SetTargetFPS(60.0);
|
// SetTargetFPS(60.0);
|
||||||
|
|
||||||
|
@ -119,7 +138,7 @@ void platform_input() {
|
||||||
float mouse_z = (GetMouseWheelMove()*0.5f);
|
float mouse_z = (GetMouseWheelMove()*0.5f);
|
||||||
|
|
||||||
if (mouse_z != 0.0f) {
|
if (mouse_z != 0.0f) {
|
||||||
target_zoom = zpl_clamp(target_zoom+mouse_z, 0.1f, 10.0f);
|
target_zoom = zpl_clamp(target_zoom+mouse_z, 0.1f, 11.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(zaklaus): keystate handling
|
// NOTE(zaklaus): keystate handling
|
||||||
|
@ -233,8 +252,18 @@ void draw_selected_item() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void platform_render() {
|
void platform_render() {
|
||||||
|
#if !defined(PLATFORM_WEB)
|
||||||
screenWidth = (uint16_t)GetScreenWidth();
|
screenWidth = (uint16_t)GetScreenWidth();
|
||||||
screenHeight = (uint16_t)GetScreenHeight();
|
screenHeight = (uint16_t)GetScreenHeight();
|
||||||
|
#else
|
||||||
|
uint16_t newScreenWidth = (uint16_t)canvas_get_width();
|
||||||
|
uint16_t newScreenHeight = (uint16_t)canvas_get_height();
|
||||||
|
if (newScreenWidth != screenWidth || newScreenHeight != screenHeight) {
|
||||||
|
screenWidth = newScreenWidth;
|
||||||
|
screenHeight = newScreenHeight;
|
||||||
|
SetWindowSize(screenWidth, screenHeight);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
profile(PROF_ENTITY_LERP) {
|
profile(PROF_ENTITY_LERP) {
|
||||||
game_world_view_active_entity_map(lerp_entity_positions);
|
game_world_view_active_entity_map(lerp_entity_positions);
|
||||||
|
|
|
@ -62,7 +62,7 @@ void predict_receive_update(entity_view *d, entity_view *data) {
|
||||||
data->tran_time = d->tran_time;
|
data->tran_time = d->tran_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ENTITY_DO_LERP_SP 0
|
#define ENTITY_DO_LERP_SP 1
|
||||||
|
|
||||||
void lerp_entity_positions(uint64_t key, entity_view *data) {
|
void lerp_entity_positions(uint64_t key, entity_view *data) {
|
||||||
(void)key;
|
(void)key;
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#define PROF_COLLATE_WINDOW 0.5
|
#define PROF_COLLATE_WINDOW 0.5
|
||||||
|
|
||||||
|
static float profiler_warmup = 3.0f;
|
||||||
|
|
||||||
// NOTE(zaklaus): KEEP ORDER IN SYNC WITH profiler_kind ENUM !!!
|
// NOTE(zaklaus): KEEP ORDER IN SYNC WITH profiler_kind ENUM !!!
|
||||||
static profiler profilers[] = {
|
static profiler profilers[] = {
|
||||||
{ .id = PROF_TOTAL_TIME, .name = "measured time" },
|
{ .id = PROF_TOTAL_TIME, .name = "measured time" },
|
||||||
|
@ -33,6 +35,13 @@ void profiler_stop(profiler_kind id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void profiler_collate() {
|
void profiler_collate() {
|
||||||
|
if (profiler_warmup > 0) {
|
||||||
|
profiler_warmup -= GetFrameTime();
|
||||||
|
for (uint32_t i = PROF_MAIN_LOOP; i < MAX_PROF; i += 1) {
|
||||||
|
profiler_reset(i);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
static double frame_counter = 0.0;
|
static double frame_counter = 0.0;
|
||||||
static uint64_t frames = 0;
|
static uint64_t frames = 0;
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
static Camera3D render_camera_3d;
|
static Camera3D render_camera_3d;
|
||||||
static float cam_zoom = 1.5f;
|
static float cam_zoom = 1.5f;
|
||||||
|
|
||||||
#define CAM_OVERLAY_ZOOM_LEVEL 0.80f
|
|
||||||
|
|
||||||
float zpl_lerp(float,float,float);
|
float zpl_lerp(float,float,float);
|
||||||
float zpl_to_degrees(float);
|
float zpl_to_degrees(float);
|
||||||
|
|
||||||
void DEBUG_draw_ground_3d(uint64_t key, entity_view * data) {
|
void DEBUG_draw_ground_3d(uint64_t key, entity_view * data) {
|
||||||
(void)key;
|
|
||||||
switch (data->kind) {
|
switch (data->kind) {
|
||||||
case EKIND_CHUNK: {
|
case EKIND_CHUNK: {
|
||||||
world_view *view = game_world_view_get_active();
|
world_view *view = game_world_view_get_active();
|
||||||
|
@ -145,7 +142,7 @@ void renderer_debug_draw_3d(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float renderer_zoom_get_3d(void) {
|
float renderer_zoom_get_3d(void) {
|
||||||
return 1.0f;
|
return cam_zoom;
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderer_draw_single_3d(float x, float y, asset_id id, Color color) {
|
void renderer_draw_single_3d(float x, float y, asset_id id, Color color) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
static Camera2D render_camera;
|
static Camera2D render_camera;
|
||||||
static float zoom_overlay_tran = 0.0f;
|
static float zoom_overlay_tran = 0.0f;
|
||||||
|
|
||||||
#define CAM_OVERLAY_ZOOM_LEVEL 0.80f
|
#define CAM_OVERLAY_ZOOM_LEVEL 0.15f
|
||||||
#define ALPHA(x) ColorAlpha(x, data->tran_time)
|
#define ALPHA(x) ColorAlpha(x, data->tran_time)
|
||||||
|
|
||||||
float zpl_lerp(float,float,float);
|
float zpl_lerp(float,float,float);
|
||||||
|
@ -23,13 +23,6 @@ void DEBUG_draw_ground(uint64_t key, entity_view * data) {
|
||||||
tex.texture.height *= (int32_t)scale;
|
tex.texture.height *= (int32_t)scale;
|
||||||
DrawTextureRec(tex.texture, (Rectangle){0, 0, size, -size}, (Vector2){x, y}, ColorAlpha(WHITE, data->tran_time));
|
DrawTextureRec(tex.texture, (Rectangle){0, 0, size, -size}, (Vector2){x, y}, ColorAlpha(WHITE, data->tran_time));
|
||||||
|
|
||||||
if (zoom_overlay_tran > 0.02f) {
|
|
||||||
DrawRectangleEco(x, y, size-offset, size-offset, ColorAlpha(ColorFromHSV((float)data->color, 0.13f, 0.89f), data->tran_time*zoom_overlay_tran*0.75f));
|
|
||||||
|
|
||||||
DrawTextEco(TextFormat("%d %d", (int)data->x, (int)data->y), x+15.0f, y+15.0f, 200 , ColorAlpha(BLACK, data->tran_time*zoom_overlay_tran), 0.0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t ty = 0; ty < view->chunk_size; ty++) {
|
for (size_t ty = 0; ty < view->chunk_size; ty++) {
|
||||||
for (size_t tx = 0; tx < view->chunk_size; tx++) {
|
for (size_t tx = 0; tx < view->chunk_size; tx++) {
|
||||||
block_id blk_id = data->outer_blocks[(ty*view->chunk_size)+tx];
|
block_id blk_id = data->outer_blocks[(ty*view->chunk_size)+tx];
|
||||||
|
@ -44,14 +37,32 @@ void DEBUG_draw_ground(uint64_t key, entity_view * data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DEBUG_draw_overlay(uint64_t key, entity_view * data) {
|
||||||
|
switch (data->kind) {
|
||||||
|
case EKIND_CHUNK: {
|
||||||
|
world_view *view = game_world_view_get_active();
|
||||||
|
float size = (float)(view->chunk_size * WORLD_BLOCK_SIZE);
|
||||||
|
float offset = 0.0;
|
||||||
|
|
||||||
|
float x = data->x * size + offset;
|
||||||
|
float y = data->y * size + offset;
|
||||||
|
|
||||||
|
DrawRectangleEco(x, y, size-offset, size-offset, ColorAlpha(ColorFromHSV((float)data->color, 0.13f, 0.89f), data->tran_time*zoom_overlay_tran*0.75f));
|
||||||
|
DrawTextEco(TextFormat("%d %d", (int)data->x, (int)data->y), x+15.0f, y+15.0f, 200 , ColorAlpha(BLACK, data->tran_time*zoom_overlay_tran), 0.0);
|
||||||
|
}break;
|
||||||
|
|
||||||
|
default:break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern bool inv_is_open;
|
extern bool inv_is_open;
|
||||||
|
|
||||||
void DEBUG_draw_entities(uint64_t key, entity_view * data) {
|
void DEBUG_draw_entities(uint64_t key, entity_view * data) {
|
||||||
uint16_t size = 16;
|
float size = 16.f;
|
||||||
uint16_t font_size = (uint16_t)lerp(4.0f, 32.0f, 0.5f/(float)render_camera.zoom);
|
float font_size = lerp(4.0f, 32.0f, 0.5f/(float)render_camera.zoom);
|
||||||
float font_spacing = 1.1f;
|
float font_spacing = 1.1f;
|
||||||
float title_bg_offset = 4;
|
float title_bg_offset = 4;
|
||||||
float fixed_title_offset = 8;
|
float fixed_title_offset = 8.f;
|
||||||
|
|
||||||
switch (data->kind) {
|
switch (data->kind) {
|
||||||
case EKIND_DEMO_NPC: {
|
case EKIND_DEMO_NPC: {
|
||||||
|
@ -64,10 +75,10 @@ void DEBUG_draw_entities(uint64_t key, entity_view * data) {
|
||||||
float y = data->y;
|
float y = data->y;
|
||||||
float health = (data->hp / data->max_hp);
|
float health = (data->hp / data->max_hp);
|
||||||
const char *title = TextFormat("Player %d", key);
|
const char *title = TextFormat("Player %d", key);
|
||||||
int title_w = MeasureTextEco(title, font_size, font_spacing);
|
float title_w = MeasureTextEco(title, font_size, font_spacing);
|
||||||
DrawRectangleEco(x-title_w/2-title_bg_offset/2, y-size-font_size-fixed_title_offset, title_w+title_bg_offset, font_size, ColorAlpha(BLACK, data->tran_time));
|
DrawRectangleEco(x-title_w/2.f-title_bg_offset/2.f, y-size-font_size-fixed_title_offset, title_w+title_bg_offset, font_size, ColorAlpha(BLACK, data->tran_time));
|
||||||
DrawRectangleEco(x-title_w/2-title_bg_offset/2, y-size-fixed_title_offset, title_w*health+title_bg_offset, font_size*0.2f, ColorAlpha(RED, data->tran_time));
|
DrawRectangleEco(x-title_w/2.f-title_bg_offset/2.f, y-size-fixed_title_offset, title_w*health+title_bg_offset, font_size*0.2f, ColorAlpha(RED, data->tran_time));
|
||||||
DrawTextEco(title, x-title_w/2, y-size-font_size-fixed_title_offset, font_size, ColorAlpha(RAYWHITE, data->tran_time), font_spacing);
|
DrawTextEco(title, x-title_w/2.f, y-size-font_size-fixed_title_offset, font_size, ColorAlpha(RAYWHITE, data->tran_time), font_spacing);
|
||||||
DrawCircleEco(x, y, size, ColorAlpha(YELLOW, data->tran_time));
|
DrawCircleEco(x, y, size, ColorAlpha(YELLOW, data->tran_time));
|
||||||
|
|
||||||
if (data->has_items && !data->inside_vehicle) {
|
if (data->has_items && !data->inside_vehicle) {
|
||||||
|
@ -79,7 +90,7 @@ void DEBUG_draw_entities(uint64_t key, entity_view * data) {
|
||||||
DrawTexturePro(GetSpriteTexture2D(assets_find(it_kind)), ASSET_SRC_RECT(), ((Rectangle){ix, iy, 32, 32}), (Vector2){0.5f,0.5f}, 0.0f, ALPHA(WHITE));
|
DrawTexturePro(GetSpriteTexture2D(assets_find(it_kind)), ASSET_SRC_RECT(), ((Rectangle){ix, iy, 32, 32}), (Vector2){0.5f,0.5f}, 0.0f, ALPHA(WHITE));
|
||||||
|
|
||||||
if (!inv_is_open)
|
if (!inv_is_open)
|
||||||
DrawTextEco(zpl_bprintf("%d", qty), ix+24, iy+24, 8, RAYWHITE, 0.0f);
|
DrawTextEco(zpl_bprintf("%d", qty), x+24, y+24, 8, RAYWHITE, 0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
@ -87,9 +98,9 @@ void DEBUG_draw_entities(uint64_t key, entity_view * data) {
|
||||||
float x = data->x;
|
float x = data->x;
|
||||||
float y = data->y;
|
float y = data->y;
|
||||||
const char *title = TextFormat("Bot %d", key);
|
const char *title = TextFormat("Bot %d", key);
|
||||||
int title_w = MeasureTextEco(title, font_size, font_spacing);
|
float title_w = MeasureTextEco(title, font_size, font_spacing);
|
||||||
DrawRectangleEco(x-title_w/2-title_bg_offset/2, y-size-font_size-fixed_title_offset, title_w+title_bg_offset, font_size, ColorAlpha(GRAY, data->tran_time));
|
DrawRectangleEco(x-title_w/2.f-title_bg_offset/2.f, y-size-font_size-fixed_title_offset, title_w+title_bg_offset, font_size, ColorAlpha(GRAY, data->tran_time));
|
||||||
DrawTextEco(title, x-title_w/2, y-size-font_size-fixed_title_offset, font_size, ColorAlpha(BLACK, data->tran_time), font_spacing);
|
DrawTextEco(title, x-title_w/2.f, y-size-font_size-fixed_title_offset, font_size, ColorAlpha(BLACK, data->tran_time), font_spacing);
|
||||||
DrawCircleEco(x, y, size, ColorAlpha(PURPLE, data->tran_time));
|
DrawCircleEco(x, y, size, ColorAlpha(PURPLE, data->tran_time));
|
||||||
}break;
|
}break;
|
||||||
case EKIND_ITEM: {
|
case EKIND_ITEM: {
|
||||||
|
@ -137,6 +148,10 @@ void renderer_draw_v0(void) {
|
||||||
game_world_view_active_entity_map(DEBUG_draw_ground);
|
game_world_view_active_entity_map(DEBUG_draw_ground);
|
||||||
game_world_view_active_entity_map(DEBUG_draw_entities_low);
|
game_world_view_active_entity_map(DEBUG_draw_entities_low);
|
||||||
game_world_view_active_entity_map(DEBUG_draw_entities);
|
game_world_view_active_entity_map(DEBUG_draw_entities);
|
||||||
|
|
||||||
|
if (zoom_overlay_tran > 0.02f) {
|
||||||
|
game_world_view_active_entity_map(DEBUG_draw_overlay);
|
||||||
|
}
|
||||||
EndMode2D();
|
EndMode2D();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ static BOOL WINAPI _sighandler_win32_control_handler(DWORD control_type)
|
||||||
#else //POSIX complaint
|
#else //POSIX complaint
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
static void _sighandler_posix_signal_handler(int sig) {
|
static void _sighandler_posix_signal_handler(int sig) {
|
||||||
|
(void)sig;
|
||||||
game_request_close();
|
game_request_close();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
#define ZPL_ENABLE_MATH
|
#define ZPL_ENABLE_MATH
|
||||||
#include "zpl.h"
|
#include "zpl.h"
|
||||||
|
|
||||||
|
float get_cached_time(void);
|
||||||
|
void reset_cached_time(void);
|
||||||
|
|
||||||
#define defer_var ZPL_CONCAT(_i_,__LINE__)
|
#define defer_var ZPL_CONCAT(_i_,__LINE__)
|
||||||
#define defer(s,e) for ( \
|
#define defer(s,e) for ( \
|
||||||
uint32_t defer_var = (s, 0); \
|
uint32_t defer_var = (s, 0); \
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "utils/options.h"
|
#include "utils/options.h"
|
||||||
|
|
||||||
void generate_minimap(int32_t seed, uint16_t block_size, uint16_t chunk_size, uint16_t world_size) {
|
void generate_minimap(int32_t seed, uint16_t block_size, uint16_t chunk_size, uint16_t world_size) {
|
||||||
|
(void)block_size;
|
||||||
world_init(seed, chunk_size, world_size);
|
world_init(seed, chunk_size, world_size);
|
||||||
|
|
||||||
block_id const *world;
|
block_id const *world;
|
||||||
|
|
|
@ -10,36 +10,36 @@
|
||||||
static inline float lerp(float a, float b, float t) { return a * (1.0f - t) + b * t; }
|
static inline float lerp(float a, float b, float t) { return a * (1.0f - t) + b * t; }
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void DrawTextEco(const char *text, float posX, float posY, int fontSize, Color color, float spacing) {
|
void DrawTextEco(const char *text, float posX, float posY, float fontSize, Color color, float spacing) {
|
||||||
#if 1
|
#if 1
|
||||||
// Check if default font has been loaded
|
// Check if default font has been loaded
|
||||||
if (GetFontDefault().texture.id != 0) {
|
if (GetFontDefault().texture.id != 0) {
|
||||||
Vector2 position = { (float)posX , (float)posY };
|
Vector2 position = { posX , posY };
|
||||||
|
|
||||||
float defaultFontSize = 10.0; // Default Font chars height in pixel
|
float defaultFontSize = 10.0; // Default Font chars height in pixel
|
||||||
float new_spacing = spacing == 0.0f ? (float)fontSize/defaultFontSize : spacing;
|
float new_spacing = spacing == 0.0f ? fontSize/defaultFontSize : spacing;
|
||||||
|
|
||||||
DrawTextEx(GetFontDefault(), text, position, (float)fontSize , (float)new_spacing , color);
|
DrawTextEx(GetFontDefault(), text, position, fontSize , new_spacing , color);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
int MeasureTextEco(const char *text, int fontSize, float spacing) {
|
float MeasureTextEco(const char *text, float fontSize, float spacing) {
|
||||||
#if 1
|
#if 1
|
||||||
Vector2 vec = { 0.0f, 0.0f };
|
Vector2 vec = { 0.0f, 0.0f };
|
||||||
|
|
||||||
// Check if default font has been loaded
|
// Check if default font has been loaded
|
||||||
if (GetFontDefault().texture.id != 0) {
|
if (GetFontDefault().texture.id != 0) {
|
||||||
float defaultFontSize = 10.0; // Default Font chars height in pixel
|
float defaultFontSize = 10.0; // Default Font chars height in pixel
|
||||||
float new_spacing = spacing == 0.0f ? (float)fontSize/defaultFontSize : spacing;
|
float new_spacing = spacing == 0.0f ? fontSize/defaultFontSize : spacing;
|
||||||
|
|
||||||
vec = MeasureTextEx(GetFontDefault(), text, (float)fontSize, (float)new_spacing);
|
vec = MeasureTextEx(GetFontDefault(), text, fontSize, (float)new_spacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (int)vec.x;
|
return vec.x;
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0.f;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,6 +157,12 @@ void EcoDrawCube(Vector3 position, float width, float height, float length, floa
|
||||||
// Draw codepoint at specified position in 3D space
|
// Draw codepoint at specified position in 3D space
|
||||||
void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontSize, bool backface, Color tint)
|
void DrawTextCodepoint3D(Font font, int codepoint, Vector3 position, float fontSize, bool backface, Color tint)
|
||||||
{
|
{
|
||||||
|
(void)font;
|
||||||
|
(void)codepoint;
|
||||||
|
(void)position;
|
||||||
|
(void)fontSize;
|
||||||
|
(void)backface;
|
||||||
|
(void)tint;
|
||||||
#if 0
|
#if 0
|
||||||
// Character index position in sprite font
|
// Character index position in sprite font
|
||||||
// NOTE: In case a codepoint is not available in the font, index returned points to '?'
|
// NOTE: In case a codepoint is not available in the font, index returned points to '?'
|
||||||
|
|
|
@ -6,6 +6,7 @@ typedef enum {
|
||||||
BLOCK_FLAG_COLLISION = (1 << 1),
|
BLOCK_FLAG_COLLISION = (1 << 1),
|
||||||
BLOCK_FLAG_HAZARD = (1 << 2),
|
BLOCK_FLAG_HAZARD = (1 << 2),
|
||||||
BLOCK_FLAG_ESSENTIAL = (1 << 3),
|
BLOCK_FLAG_ESSENTIAL = (1 << 3),
|
||||||
|
BLOCK_FLAG_DESTROY_ON_COLLISION = (1 << 4),
|
||||||
} block_flags;
|
} block_flags;
|
||||||
|
|
||||||
typedef uint16_t block_id;
|
typedef uint16_t block_id;
|
||||||
|
|
|
@ -16,7 +16,7 @@ static block blocks[] = {
|
||||||
BLOCK(ASSET_LAVA, BLOCK_FLAG_HAZARD, '!', .drag = 6.2f , .friction = 4.0f),
|
BLOCK(ASSET_LAVA, BLOCK_FLAG_HAZARD, '!', .drag = 6.2f , .friction = 4.0f),
|
||||||
BLOCK(ASSET_FENCE, BLOCK_FLAG_COLLISION, '#', .drag = 1.0f , .friction = 1.0f, .bounce = 1.0f),
|
BLOCK(ASSET_FENCE, BLOCK_FLAG_COLLISION, '#', .drag = 1.0f , .friction = 1.0f, .bounce = 1.0f),
|
||||||
BLOCK(ASSET_WOOD, BLOCK_FLAG_COLLISION, '#', .drag = 1.0f , .friction = 1.0f, .bounce = 0.0f),
|
BLOCK(ASSET_WOOD, BLOCK_FLAG_COLLISION, '#', .drag = 1.0f , .friction = 1.0f, .bounce = 0.0f),
|
||||||
BLOCK(ASSET_TREE, BLOCK_FLAG_COLLISION, '@', .drag = 1.0f , .friction = 1.0f, .bounce = 0.0f),
|
BLOCK(ASSET_TREE, BLOCK_FLAG_COLLISION|BLOCK_FLAG_DESTROY_ON_COLLISION, '@', .drag = 1.0f , .friction = 1.0f, .bounce = 0.0f),
|
||||||
|
|
||||||
BLOCK(ASSET_BELT_LEFT, 0, '@', .drag = 1.0f , .friction = 1.0f, .velx = -150.0f),
|
BLOCK(ASSET_BELT_LEFT, 0, '@', .drag = 1.0f , .friction = 1.0f, .velx = -150.0f),
|
||||||
BLOCK(ASSET_BELT_RIGHT, 0, '@', .drag = 1.0f , .friction = 1.0f, .velx = 150.0f),
|
BLOCK(ASSET_BELT_RIGHT, 0, '@', .drag = 1.0f , .friction = 1.0f, .velx = 150.0f),
|
||||||
|
|
|
@ -14,14 +14,16 @@
|
||||||
|
|
||||||
#include "packets/pkt_send_librg_update.h"
|
#include "packets/pkt_send_librg_update.h"
|
||||||
|
|
||||||
|
#define ECO2D_STREAM_ACTIONFILTER 1
|
||||||
|
|
||||||
ZPL_TABLE(static, world_snapshot, world_snapshot_, entity_view);
|
ZPL_TABLE(static, world_snapshot, world_snapshot_, entity_view);
|
||||||
|
|
||||||
static world_data world = {0};
|
static world_data world = {0};
|
||||||
static world_snapshot streamer_snapshot;
|
static world_snapshot streamer_snapshot;
|
||||||
|
|
||||||
entity_view world_build_entity_view(int64_t e) {
|
entity_view *world_build_entity_view(int64_t e) {
|
||||||
entity_view *cached_ev = world_snapshot_get(&streamer_snapshot, e);
|
entity_view *cached_ev = world_snapshot_get(&streamer_snapshot, e);
|
||||||
if (cached_ev) return *cached_ev;
|
if (cached_ev) return cached_ev;
|
||||||
|
|
||||||
entity_view view = {0};
|
entity_view view = {0};
|
||||||
|
|
||||||
|
@ -114,7 +116,7 @@ entity_view world_build_entity_view(int64_t e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
world_snapshot_set(&streamer_snapshot, e, view);
|
world_snapshot_set(&streamer_snapshot, e, view);
|
||||||
return view;
|
return world_snapshot_get(&streamer_snapshot, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tracker_write_create(librg_world *w, librg_event *e) {
|
int32_t tracker_write_create(librg_world *w, librg_event *e) {
|
||||||
|
@ -147,11 +149,11 @@ int32_t tracker_write_update(librg_world *w, librg_event *e) {
|
||||||
int64_t entity_id = librg_event_entity_get(w, e);
|
int64_t entity_id = librg_event_entity_get(w, e);
|
||||||
size_t actual_length = librg_event_size_get(w, e);
|
size_t actual_length = librg_event_size_get(w, e);
|
||||||
char *buffer = librg_event_buffer_get(w, e);
|
char *buffer = librg_event_buffer_get(w, e);
|
||||||
entity_view view = world_build_entity_view(entity_id);
|
entity_view *view = world_build_entity_view(entity_id);
|
||||||
|
|
||||||
// NOTE(zaklaus): exclude chunks from updates as they never move
|
// NOTE(zaklaus): exclude chunks from updates as they never move
|
||||||
{
|
{
|
||||||
if (view.kind == EKIND_CHUNK && !view.is_dirty) {
|
if (view->kind == EKIND_CHUNK && !view->is_dirty) {
|
||||||
return LIBRG_WRITE_REJECT;
|
return LIBRG_WRITE_REJECT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,7 +161,7 @@ int32_t tracker_write_update(librg_world *w, librg_event *e) {
|
||||||
// NOTE(zaklaus): action-based updates
|
// NOTE(zaklaus): action-based updates
|
||||||
#if ECO2D_STREAM_ACTIONFILTER
|
#if ECO2D_STREAM_ACTIONFILTER
|
||||||
{
|
{
|
||||||
if (view.kind != EKIND_CHUNK && !entity_can_stream(entity_id)) {
|
if (view->kind != EKIND_CHUNK && !entity_can_stream(entity_id)) {
|
||||||
return LIBRG_WRITE_REJECT;
|
return LIBRG_WRITE_REJECT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,7 +212,7 @@ void world_configure_tracker(void) {
|
||||||
ZPL_ASSERT_MSG(world.tracker, "[ERROR] An error occurred while trying to create a server world.");
|
ZPL_ASSERT_MSG(world.tracker, "[ERROR] An error occurred while trying to create a server world.");
|
||||||
|
|
||||||
/* config our world grid */
|
/* config our world grid */
|
||||||
librg_config_chunksize_set(world.tracker, WORLD_BLOCK_SIZE * world.chunk_size, WORLD_BLOCK_SIZE * world.chunk_size, 0);
|
librg_config_chunksize_set(world.tracker, WORLD_BLOCK_SIZE * world.chunk_size, WORLD_BLOCK_SIZE * world.chunk_size, 1);
|
||||||
librg_config_chunkamount_set(world.tracker, world.chunk_amount, world.chunk_amount, 0);
|
librg_config_chunkamount_set(world.tracker, world.chunk_amount, world.chunk_amount, 0);
|
||||||
librg_config_chunkoffset_set(world.tracker, LIBRG_OFFSET_BEG, LIBRG_OFFSET_BEG, LIBRG_OFFSET_BEG);
|
librg_config_chunkoffset_set(world.tracker, LIBRG_OFFSET_BEG, LIBRG_OFFSET_BEG, LIBRG_OFFSET_BEG);
|
||||||
|
|
||||||
|
@ -307,8 +309,8 @@ int32_t world_destroy(void) {
|
||||||
#define WORLD_LIBRG_BUFSIZ 2000000
|
#define WORLD_LIBRG_BUFSIZ 2000000
|
||||||
|
|
||||||
static void world_tracker_update(uint8_t ticker, float freq, uint8_t radius) {
|
static void world_tracker_update(uint8_t ticker, float freq, uint8_t radius) {
|
||||||
if (world.tracker_update[ticker] > (float)zpl_time_rel()) return;
|
if (world.tracker_update[ticker] > (float)(get_cached_time())) return;
|
||||||
world.tracker_update[ticker] = (float)zpl_time_rel() + freq;
|
world.tracker_update[ticker] = (float)(get_cached_time()) + freq;
|
||||||
|
|
||||||
profile(PROF_WORLD_WRITE) {
|
profile(PROF_WORLD_WRITE) {
|
||||||
ecs_iter_t it = ecs_query_iter(world_ecs(), world.ecs_update);
|
ecs_iter_t it = ecs_query_iter(world_ecs(), world.ecs_update);
|
||||||
|
@ -350,15 +352,17 @@ int32_t world_update() {
|
||||||
ecs_progress(world.ecs, 0.0f);
|
ecs_progress(world.ecs, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
float fast_ms = WORLD_TRACKER_UPDATE_FAST_MS;
|
float fast_ms = WORLD_TRACKER_UPDATE_MP_FAST_MS;
|
||||||
float normal_ms = WORLD_TRACKER_UPDATE_NORMAL_MS;
|
float normal_ms = WORLD_TRACKER_UPDATE_MP_NORMAL_MS;
|
||||||
float slow_ms = WORLD_TRACKER_UPDATE_SLOW_MS;
|
float slow_ms = WORLD_TRACKER_UPDATE_MP_SLOW_MS;
|
||||||
|
|
||||||
if (game_get_kind() != GAMEKIND_SINGLE) {
|
#if 1
|
||||||
fast_ms = WORLD_TRACKER_UPDATE_MP_FAST_MS;
|
if (game_get_kind() == GAMEKIND_SINGLE) {
|
||||||
normal_ms = WORLD_TRACKER_UPDATE_MP_NORMAL_MS;
|
fast_ms = WORLD_TRACKER_UPDATE_FAST_MS;
|
||||||
slow_ms = WORLD_TRACKER_UPDATE_MP_SLOW_MS;
|
normal_ms = WORLD_TRACKER_UPDATE_NORMAL_MS;
|
||||||
|
slow_ms = WORLD_TRACKER_UPDATE_SLOW_MS;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
world_tracker_update(0, fast_ms, 1);
|
world_tracker_update(0, fast_ms, 1);
|
||||||
world_tracker_update(1, normal_ms, 2);
|
world_tracker_update(1, normal_ms, 2);
|
||||||
|
@ -504,6 +508,7 @@ void world_chunk_destroy_block(float x, float y, bool drop_item) {
|
||||||
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
||||||
dest->x = x;
|
dest->x = x;
|
||||||
dest->y = y;
|
dest->y = y;
|
||||||
|
entity_set_position(e, dest->x, dest->y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "world/perlin.h"
|
#include "world/perlin.h"
|
||||||
|
|
||||||
#include "modules/components.h"
|
#include "modules/components.h"
|
||||||
|
#include "entity.h"
|
||||||
#include "vehicle.h"
|
#include "vehicle.h"
|
||||||
#include "items.h"
|
#include "items.h"
|
||||||
#include "world/blocks_info.h"
|
#include "world/blocks_info.h"
|
||||||
|
@ -133,6 +134,9 @@ static WORLD_BLOCK_OBSERVER(shaper_noise05b) {
|
||||||
return world_perlin_cond_offset(block_idx, 0.05, 32, 0) ? shaper(data, id, block_idx) : BLOCK_INVALID;
|
return world_perlin_cond_offset(block_idx, 0.05, 32, 0) ? shaper(data, id, block_idx) : BLOCK_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static WORLD_BLOCK_OBSERVER(shaper_noise01b) {
|
||||||
|
return world_perlin_cond_offset(block_idx, 0.01, 32, 0) ? shaper(data, id, block_idx) : BLOCK_INVALID;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
static WORLD_BLOCK_OBSERVER(shaper_noise80) {
|
static WORLD_BLOCK_OBSERVER(shaper_noise80) {
|
||||||
return rand()%10 < 8 ? shaper(id, block_idx) : BLOCK_INVALID;
|
return rand()%10 < 8 ? shaper(id, block_idx) : BLOCK_INVALID;
|
||||||
|
@ -177,7 +181,7 @@ int32_t worldgen_test(world_data *wld) {
|
||||||
// ground
|
// ground
|
||||||
world_fill_rect(world->data, grnd_id, 1, 1, world->dim-2, world->dim-2, NULL);
|
world_fill_rect(world->data, grnd_id, 1, 1, world->dim-2, world->dim-2, NULL);
|
||||||
world_fill_rect(world->data, dirt_id, 1, 1, world->dim-2, world->dim-2, shaper_noise05);
|
world_fill_rect(world->data, dirt_id, 1, 1, world->dim-2, world->dim-2, shaper_noise05);
|
||||||
world_fill_rect(world->outer_data, tree_id, 1, 1, world->dim-2, world->dim-2, shaper_noise05b);
|
world_fill_rect(world->outer_data, tree_id, 1, 1, world->dim-2, world->dim-2, shaper_noise01b);
|
||||||
|
|
||||||
// water
|
// water
|
||||||
#if 1
|
#if 1
|
||||||
|
@ -215,6 +219,7 @@ int32_t worldgen_test(world_data *wld) {
|
||||||
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
||||||
dest->x = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
dest->x = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
|
entity_set_position(e, dest->x, dest->y);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -226,6 +231,7 @@ int32_t worldgen_test(world_data *wld) {
|
||||||
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
||||||
dest->x = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
dest->x = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
|
entity_set_position(e, dest->x, dest->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<RAND_RANGE(328, 164); i++) {
|
for (int i=0; i<RAND_RANGE(328, 164); i++) {
|
||||||
|
@ -234,6 +240,7 @@ int32_t worldgen_test(world_data *wld) {
|
||||||
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
||||||
dest->x = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
dest->x = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
|
entity_set_position(e, dest->x, dest->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<RAND_RANGE(328, 164); i++) {
|
for (int i=0; i<RAND_RANGE(328, 164); i++) {
|
||||||
|
@ -242,6 +249,7 @@ int32_t worldgen_test(world_data *wld) {
|
||||||
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
||||||
dest->x = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
dest->x = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
|
entity_set_position(e, dest->x, dest->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<RAND_RANGE(128, 564); i++) {
|
for (int i=0; i<RAND_RANGE(128, 564); i++) {
|
||||||
|
@ -250,6 +258,7 @@ int32_t worldgen_test(world_data *wld) {
|
||||||
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
||||||
dest->x = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
dest->x = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
|
entity_set_position(e, dest->x, dest->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<RAND_RANGE(128, 964); i++) {
|
for (int i=0; i<RAND_RANGE(128, 964); i++) {
|
||||||
|
@ -258,6 +267,7 @@ int32_t worldgen_test(world_data *wld) {
|
||||||
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
Position *dest = ecs_get_mut(world_ecs(), e, Position);
|
||||||
dest->x = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
dest->x = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
dest->y = RAND_RANGEF(0, world->dim*WORLD_BLOCK_SIZE);
|
||||||
|
entity_set_position(e, dest->x, dest->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -26,7 +26,7 @@ int32_t tracker_read_update(librg_world *w, librg_event *e) {
|
||||||
entity_view *d = entity_view_get(&view->entities, entity_id);
|
entity_view *d = entity_view_get(&view->entities, entity_id);
|
||||||
#if 1
|
#if 1
|
||||||
if (d && d->layer_id < view->active_layer_id) {
|
if (d && d->layer_id < view->active_layer_id) {
|
||||||
if (zpl_time_rel_ms() - d->last_update > WORLD_TRACKER_UPDATE_NORMAL_MS) {
|
if ((get_cached_time()*1000.0f) - d->last_update > WORLD_TRACKER_UPDATE_NORMAL_MS) {
|
||||||
d->layer_id = zpl_min(WORLD_TRACKER_LAYERS-1, d->layer_id+1);
|
d->layer_id = zpl_min(WORLD_TRACKER_LAYERS-1, d->layer_id+1);
|
||||||
}
|
}
|
||||||
// NOTE(zaklaus): reject updates from slower layers
|
// NOTE(zaklaus): reject updates from slower layers
|
||||||
|
@ -34,7 +34,7 @@ int32_t tracker_read_update(librg_world *w, librg_event *e) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
data.last_update = zpl_time_rel_ms();
|
data.last_update = get_cached_time()*1000.0f;
|
||||||
data.layer_id = view->active_layer_id;
|
data.layer_id = view->active_layer_id;
|
||||||
predict_receive_update(d, &data);
|
predict_receive_update(d, &data);
|
||||||
entity_view_update_or_create(&view->entities, entity_id, data);
|
entity_view_update_or_create(&view->entities, entity_id, data);
|
||||||
|
@ -83,7 +83,7 @@ void world_view_init(world_view *view, uint32_t seed, uint64_t ent_id, uint16_t
|
||||||
|
|
||||||
librg_config_chunksize_set(view->tracker, WORLD_BLOCK_SIZE * chunk_size, WORLD_BLOCK_SIZE * chunk_size, 1);
|
librg_config_chunksize_set(view->tracker, WORLD_BLOCK_SIZE * chunk_size, WORLD_BLOCK_SIZE * chunk_size, 1);
|
||||||
librg_config_chunkamount_set(view->tracker, chunk_amount, chunk_amount, 1);
|
librg_config_chunkamount_set(view->tracker, chunk_amount, chunk_amount, 1);
|
||||||
librg_config_chunkoffset_set(view->tracker, LIBRG_OFFSET_BEG, LIBRG_OFFSET_BEG, 0);
|
librg_config_chunkoffset_set(view->tracker, LIBRG_OFFSET_BEG, LIBRG_OFFSET_BEG, LIBRG_OFFSET_BEG);
|
||||||
|
|
||||||
librg_event_set(view->tracker, LIBRG_READ_CREATE, tracker_read_create);
|
librg_event_set(view->tracker, LIBRG_READ_CREATE, tracker_read_create);
|
||||||
librg_event_set(view->tracker, LIBRG_READ_REMOVE, tracker_read_remove);
|
librg_event_set(view->tracker, LIBRG_READ_REMOVE, tracker_read_remove);
|
||||||
|
|
|
@ -27,37 +27,41 @@ void IntegratePositions(ecs_iter_t *it) {
|
||||||
Velocity *v = ecs_field(it, Velocity, 2);
|
Velocity *v = ecs_field(it, Velocity, 2);
|
||||||
|
|
||||||
for (int i = 0; i < it->count; i++) {
|
for (int i = 0; i < it->count; i++) {
|
||||||
// NOTE(zaklaus): world bounds
|
if (ecs_get(it->world, it->entities[i], IsInVehicle)) {
|
||||||
{
|
continue;
|
||||||
float w = (float)world_dim();
|
|
||||||
p[i].x = zpl_clamp(p[i].x, 0, w-1);
|
|
||||||
p[i].y = zpl_clamp(p[i].y, 0, w-1);
|
|
||||||
}
|
}
|
||||||
|
if (zpl_abs(v[i].x) >= 0.001f || zpl_abs(v[i].y) >= 0.001f) {
|
||||||
#if PHY_BLOCK_COLLISION==1
|
// NOTE(zaklaus): world bounds
|
||||||
// NOTE(zaklaus): X axis
|
{
|
||||||
{
|
float w = (float)world_dim();
|
||||||
world_block_lookup lookup = world_block_from_realpos(p[i].x+PHY_LOOKAHEAD(v[i].x), p[i].y);
|
p[i].x = zpl_clamp(p[i].x, 0, w-1);
|
||||||
uint32_t flags = blocks_get_flags(lookup.bid);
|
p[i].y = zpl_clamp(p[i].y, 0, w-1);
|
||||||
float bounce = blocks_get_bounce(lookup.bid);
|
|
||||||
if (flags & BLOCK_FLAG_COLLISION) {
|
|
||||||
v[i].x = physics_correction(lookup.ox, v[i].x, bounce);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE(zaklaus): Y axis
|
#if PHY_BLOCK_COLLISION==1
|
||||||
{
|
// NOTE(zaklaus): X axis
|
||||||
world_block_lookup lookup = world_block_from_realpos(p[i].x, p[i].y+PHY_LOOKAHEAD(v[i].y));
|
{
|
||||||
uint32_t flags = blocks_get_flags(lookup.bid);
|
world_block_lookup lookup = world_block_from_realpos(p[i].x+PHY_LOOKAHEAD(v[i].x), p[i].y);
|
||||||
float bounce = blocks_get_bounce(lookup.bid);
|
uint32_t flags = blocks_get_flags(lookup.bid);
|
||||||
if (flags & BLOCK_FLAG_COLLISION) {
|
float bounce = blocks_get_bounce(lookup.bid);
|
||||||
v[i].y = physics_correction(lookup.oy, v[i].y, bounce);
|
if (flags & BLOCK_FLAG_COLLISION) {
|
||||||
|
v[i].x = physics_correction(lookup.ox, v[i].x, bounce);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
p[i].x += v[i].x * safe_dt(it);
|
// NOTE(zaklaus): Y axis
|
||||||
p[i].y += v[i].y * safe_dt(it);
|
{
|
||||||
|
world_block_lookup lookup = world_block_from_realpos(p[i].x, p[i].y+PHY_LOOKAHEAD(v[i].y));
|
||||||
|
uint32_t flags = blocks_get_flags(lookup.bid);
|
||||||
|
float bounce = blocks_get_bounce(lookup.bid);
|
||||||
|
if (flags & BLOCK_FLAG_COLLISION) {
|
||||||
|
v[i].y = physics_correction(lookup.oy, v[i].y, bounce);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
entity_set_position(it->entities[i], p[i].x+v[i].x*safe_dt(it), p[i].y+v[i].y*safe_dt(it));
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
debug_v2 a = {p[i].x, p[i].y};
|
debug_v2 a = {p[i].x, p[i].y};
|
||||||
|
@ -68,20 +72,6 @@ void IntegratePositions(ecs_iter_t *it) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateTrackerPos(ecs_iter_t *it) {
|
|
||||||
Position *p = ecs_field(it, Position, 1);
|
|
||||||
|
|
||||||
for (int i = 0; i < it->count; i++){
|
|
||||||
librg_entity_chunk_set(world_tracker(), it->entities[i], librg_chunk_from_realpos(world_tracker(), p[i].x, p[i].y, 0));
|
|
||||||
|
|
||||||
{
|
|
||||||
debug_v2 a = {p[i].x-2.5f, p[i].y-2.5f};
|
|
||||||
debug_v2 b = {p[i].x+2.5f, p[i].y+2.5f};
|
|
||||||
debug_push_rect(a, b, 0x00FFFFFF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define HAZARD_BLOCK_TIME 1.0f
|
#define HAZARD_BLOCK_TIME 1.0f
|
||||||
#define HAZARD_BLOCK_DMG 5.0f
|
#define HAZARD_BLOCK_DMG 5.0f
|
||||||
|
|
||||||
|
@ -90,10 +80,10 @@ void HurtOnHazardBlock(ecs_iter_t *it) {
|
||||||
Health *h = ecs_field(it, Health, 2);
|
Health *h = ecs_field(it, Health, 2);
|
||||||
|
|
||||||
for (int i = 0; i < it->count; i++) {
|
for (int i = 0; i < it->count; i++) {
|
||||||
world_block_lookup l = world_block_from_realpos(p[i].x, p[i].y);
|
if (h->pain_time < 0.0f) {
|
||||||
if (blocks_get_flags(l.bid) & BLOCK_FLAG_HAZARD) {
|
h->pain_time = HAZARD_BLOCK_TIME;
|
||||||
if (h->pain_time < 0.0f) {
|
world_block_lookup l = world_block_from_realpos(p[i].x, p[i].y);
|
||||||
h->pain_time = HAZARD_BLOCK_TIME;
|
if (blocks_get_flags(l.bid) & BLOCK_FLAG_HAZARD) {
|
||||||
h->hp -= HAZARD_BLOCK_DMG;
|
h->hp -= HAZARD_BLOCK_DMG;
|
||||||
h->hp = zpl_max(0.0f, h->hp);
|
h->hp = zpl_max(0.0f, h->hp);
|
||||||
}
|
}
|
||||||
|
@ -141,6 +131,10 @@ void ApplyWorldDragOnVelocity(ecs_iter_t *it) {
|
||||||
Velocity *v = ecs_field(it, Velocity, 2);
|
Velocity *v = ecs_field(it, Velocity, 2);
|
||||||
|
|
||||||
for (int i = 0; i < it->count; i++) {
|
for (int i = 0; i < it->count; i++) {
|
||||||
|
if (zpl_abs(v[i].x) < 0.001f && zpl_abs(v[i].y) < 0.001f) continue;
|
||||||
|
if (ecs_get(it->world, it->entities[i], IsInVehicle)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
world_block_lookup lookup = world_block_from_realpos(p[i].x, p[i].y);
|
world_block_lookup lookup = world_block_from_realpos(p[i].x, p[i].y);
|
||||||
float drag = zpl_clamp(blocks_get_drag(lookup.bid), 0.0f, 1.0f);
|
float drag = zpl_clamp(blocks_get_drag(lookup.bid), 0.0f, 1.0f);
|
||||||
float friction = blocks_get_friction(lookup.bid);
|
float friction = blocks_get_friction(lookup.bid);
|
||||||
|
@ -225,8 +219,6 @@ void SystemsImport(ecs_world_t *ecs) {
|
||||||
|
|
||||||
ECS_SYSTEM(ecs, ResetActivators, EcsPostUpdate, components.Input);
|
ECS_SYSTEM(ecs, ResetActivators, EcsPostUpdate, components.Input);
|
||||||
|
|
||||||
ECS_SYSTEM(ecs, UpdateTrackerPos, EcsPostUpdate, components.Position, components.Velocity);
|
|
||||||
|
|
||||||
ECS_SYSTEM(ecs, ClearVehicle, EcsUnSet, components.Vehicle);
|
ECS_SYSTEM(ecs, ClearVehicle, EcsUnSet, components.Vehicle);
|
||||||
|
|
||||||
ECS_SYSTEM(ecs, DisableWorldEdit, EcsPostUpdate);
|
ECS_SYSTEM(ecs, DisableWorldEdit, EcsPostUpdate);
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#define ITEM_PICK_RADIUS 25.0f
|
#define ITEM_PICK_RADIUS 25.0f
|
||||||
#define ITEM_MERGER_RADIUS 75.0f
|
#define ITEM_MERGER_RADIUS 75.0f
|
||||||
#define ITEM_ATTRACT_RADIUS 75.0f
|
#define ITEM_ATTRACT_RADIUS 75.0f
|
||||||
#define ITEM_ATTRACT_FORCE 0.63f
|
#define ITEM_ATTRACT_FORCE 6.f
|
||||||
|
|
||||||
#define ITEM_CONTAINER_REACH_RADIUS 105.0f
|
#define ITEM_CONTAINER_REACH_RADIUS 105.0f
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ void PickItem(ecs_iter_t *it) {
|
||||||
|
|
||||||
for (int i = 0; i < it->count; i++) {
|
for (int i = 0; i < it->count; i++) {
|
||||||
if (inv[i].pickup_time > game_time()) continue;
|
if (inv[i].pickup_time > game_time()) continue;
|
||||||
|
inv[i].pickup_time = game_time() + 0.5f;
|
||||||
size_t ents_count;
|
size_t ents_count;
|
||||||
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 2);
|
int64_t *ents = world_chunk_query_entities(it->entities[i], &ents_count, 2);
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ void PickItem(ecs_iter_t *it) {
|
||||||
ItemDrop *drop = 0;
|
ItemDrop *drop = 0;
|
||||||
if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) {
|
if ((drop = ecs_get_mut_if(it->world, ents[j], ItemDrop))) {
|
||||||
Position *p2 = ecs_get_mut(it->world, ents[j], Position);
|
Position *p2 = ecs_get_mut(it->world, ents[j], Position);
|
||||||
|
Velocity *v2 = ecs_get_mut(it->world, ents[j], Velocity);
|
||||||
|
|
||||||
float dx = p2->x - p[i].x;
|
float dx = p2->x - p[i].x;
|
||||||
float dy = p2->y - p[i].y;
|
float dy = p2->y - p[i].y;
|
||||||
|
@ -43,9 +45,8 @@ void PickItem(ecs_iter_t *it) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (range <= ITEM_ATTRACT_RADIUS) {
|
} else if (range <= ITEM_ATTRACT_RADIUS) {
|
||||||
entity_set_position(ents[j],
|
v2->x = (p[i].x - p2->x) * ITEM_ATTRACT_FORCE;
|
||||||
zpl_lerp(p2->x, p[i].x, ITEM_ATTRACT_FORCE*it->delta_time),
|
v2->y = (p[i].y - p2->y) * ITEM_ATTRACT_FORCE;
|
||||||
zpl_lerp(p2->y, p[i].y, ITEM_ATTRACT_FORCE*it->delta_time));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,10 +143,17 @@ void VehicleHandling(ecs_iter_t *it) {
|
||||||
v[i].y += ((fr_y + bk_y) / 2.0f - p[i].y);
|
v[i].y += ((fr_y + bk_y) / 2.0f - p[i].y);
|
||||||
car->heading = zpl_arctan2(fr_y - bk_y, fr_x - bk_x);
|
car->heading = zpl_arctan2(fr_y - bk_y, fr_x - bk_x);
|
||||||
|
|
||||||
world_block_lookup lookahead = world_block_from_realpos(p[i].x+PHY_LOOKAHEAD(v[i].x), p[i].y+PHY_LOOKAHEAD(v[i].y));
|
float check_x = p[i].x+PHY_LOOKAHEAD(v[i].x);
|
||||||
|
float check_y = p[i].y+PHY_LOOKAHEAD(v[i].y);
|
||||||
|
world_block_lookup lookahead = world_block_from_realpos(check_x, check_y);
|
||||||
uint32_t flags = blocks_get_flags(lookahead.bid);
|
uint32_t flags = blocks_get_flags(lookahead.bid);
|
||||||
if (flags & BLOCK_FLAG_COLLISION) {
|
if (flags & BLOCK_FLAG_COLLISION) {
|
||||||
car->force = 0.0f;
|
if (flags & BLOCK_FLAG_DESTROY_ON_COLLISION) {
|
||||||
|
world_chunk_destroy_block(check_x, check_y, true);
|
||||||
|
car->force *= 0.8f;
|
||||||
|
} else {
|
||||||
|
car->force = 0.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < 4; j++) {
|
for (int j = 0; j < 4; j++) {
|
||||||
|
@ -155,11 +162,9 @@ void VehicleHandling(ecs_iter_t *it) {
|
||||||
|
|
||||||
// NOTE(zaklaus): Update passenger position
|
// NOTE(zaklaus): Update passenger position
|
||||||
{
|
{
|
||||||
Position *p2 = ecs_get_mut(it->world, pe, Position);
|
|
||||||
Velocity *v2 = ecs_get_mut(it->world, pe, Velocity);
|
Velocity *v2 = ecs_get_mut(it->world, pe, Velocity);
|
||||||
*p2 = p[i];
|
entity_set_position(pe, p[i].x, p[i].y);
|
||||||
*v2 = v[i];
|
*v2 = v[i];
|
||||||
entity_wake(pe);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,3 +7,4 @@ file(GLOB SRCS *.h
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(flecs-bundle STATIC ${SRCS})
|
add_library(flecs-bundle STATIC ${SRCS})
|
||||||
|
target_compile_options(flecs-bundle PRIVATE "-Wno-enum-constexpr-conversion")
|
||||||
|
|
|
@ -157,7 +157,7 @@
|
||||||
|
|
||||||
#define LIBRG_VERSION_MAJOR 7
|
#define LIBRG_VERSION_MAJOR 7
|
||||||
#define LIBRG_VERSION_MINOR 0
|
#define LIBRG_VERSION_MINOR 0
|
||||||
#define LIBRG_VERSION_PATCH 1
|
#define LIBRG_VERSION_PATCH 2
|
||||||
#define LIBRG_VERSION_PRE ""
|
#define LIBRG_VERSION_PRE ""
|
||||||
|
|
||||||
// file: librg_hedley.h
|
// file: librg_hedley.h
|
||||||
|
@ -21033,14 +21033,14 @@ int8_t librg_chunk_to_chunkpos(librg_world *world, librg_chunk id, int16_t *chun
|
||||||
return LIBRG_CHUNK_INVALID;
|
return LIBRG_CHUNK_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t z = (int16_t)(id / (wld->worldsize.x * wld->worldsize.y));
|
int64_t z = (int64_t)(id / (wld->worldsize.x * wld->worldsize.y));
|
||||||
int16_t r1 = (int16_t)(id % (wld->worldsize.x * wld->worldsize.y));
|
int64_t r1 = (int64_t)(id % (wld->worldsize.x * wld->worldsize.y));
|
||||||
int16_t y = r1 / wld->worldsize.x;
|
int64_t y = r1 / wld->worldsize.x;
|
||||||
int16_t x = r1 % wld->worldsize.x;
|
int64_t x = r1 % wld->worldsize.x;
|
||||||
|
|
||||||
if (chunk_x) *chunk_x = x - librg_util_chunkoffset_line(0, wld->chunkoffset.x, wld->worldsize.x);
|
if (chunk_x) *chunk_x = (int16_t)(x - librg_util_chunkoffset_line(0, wld->chunkoffset.x, wld->worldsize.x));
|
||||||
if (chunk_y) *chunk_y = y - librg_util_chunkoffset_line(0, wld->chunkoffset.y, wld->worldsize.y);
|
if (chunk_y) *chunk_y = (int16_t)(y - librg_util_chunkoffset_line(0, wld->chunkoffset.y, wld->worldsize.y));
|
||||||
if (chunk_z) *chunk_z = z - librg_util_chunkoffset_line(0, wld->chunkoffset.z, wld->worldsize.z);
|
if (chunk_z) *chunk_z = (int16_t)(z - librg_util_chunkoffset_line(0, wld->chunkoffset.z, wld->worldsize.z));
|
||||||
|
|
||||||
return LIBRG_OK;
|
return LIBRG_OK;
|
||||||
}
|
}
|
||||||
|
@ -21520,11 +21520,13 @@ int32_t librg_world_query(librg_world *world, int64_t owner_id, uint8_t chunk_ra
|
||||||
size_t buffer_limit = *entity_amount;
|
size_t buffer_limit = *entity_amount;
|
||||||
size_t total_count = zpl_array_count(wld->entity_map.entries);
|
size_t total_count = zpl_array_count(wld->entity_map.entries);
|
||||||
|
|
||||||
librg_table_i64 results = {0};
|
static librg_table_i64 results = {0};
|
||||||
librg_table_tbl dimensions = {0};
|
static librg_table_tbl dimensions = {0};
|
||||||
|
|
||||||
librg_table_i64_init(&results, wld->allocator);
|
if (!results.entries) {
|
||||||
librg_table_tbl_init(&dimensions, wld->allocator);
|
librg_table_i64_init(&results, wld->allocator);
|
||||||
|
librg_table_tbl_init(&dimensions, wld->allocator);
|
||||||
|
}
|
||||||
|
|
||||||
/* generate a map of visible chunks (only counting owned entities) */
|
/* generate a map of visible chunks (only counting owned entities) */
|
||||||
for (size_t i=0; i < total_count; ++i) {
|
for (size_t i=0; i < total_count; ++i) {
|
||||||
|
@ -21621,8 +21623,19 @@ int32_t librg_world_query(librg_world *world, int64_t owner_id, uint8_t chunk_ra
|
||||||
for (int i = 0; i < zpl_array_count(dimensions.entries); ++i)
|
for (int i = 0; i < zpl_array_count(dimensions.entries); ++i)
|
||||||
librg_table_i64_destroy(&dimensions.entries[i].value);
|
librg_table_i64_destroy(&dimensions.entries[i].value);
|
||||||
|
|
||||||
librg_table_tbl_destroy(&dimensions);
|
// NOTE(zaklaus): clear out our streaming snapshot
|
||||||
librg_table_i64_destroy(&results);
|
// TODO(zaklaus): move this to zpl
|
||||||
|
{
|
||||||
|
zpl_array_clear(results.hashes);
|
||||||
|
zpl_array_clear(results.entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(zaklaus): clear out our streaming snapshot
|
||||||
|
// TODO(zaklaus): move this to zpl
|
||||||
|
{
|
||||||
|
zpl_array_clear(dimensions.hashes);
|
||||||
|
zpl_array_clear(dimensions.entries);
|
||||||
|
}
|
||||||
|
|
||||||
*entity_amount = LIBRG_MIN(buffer_limit, count);
|
*entity_amount = LIBRG_MIN(buffer_limit, count);
|
||||||
return LIBRG_MAX(0, (int32_t)(count - buffer_limit));
|
return LIBRG_MAX(0, (int32_t)(count - buffer_limit));
|
||||||
|
@ -21983,4 +21996,3 @@ LIBRG_END_C_DECLS
|
||||||
#endif // LIBRG_IMPLEMENTATION
|
#endif // LIBRG_IMPLEMENTATION
|
||||||
|
|
||||||
#endif // LIBRG_H
|
#endif // LIBRG_H
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Symlink sources
|
||||||
|
if [ ! -d "build_web/map" ]; then
|
||||||
|
pushd build_web
|
||||||
|
mkdir -p "map/build_web"
|
||||||
|
ln -s "/workspaces/eco2d/code" "map/code"
|
||||||
|
ln -s "/workspaces/eco2d/build_web/_deps" "map/build_web/_deps"
|
||||||
|
popd
|
||||||
|
fi
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -xe
|
||||||
|
|
||||||
|
pushd build_web
|
||||||
|
if [ -f "index.html" ]; then
|
||||||
|
rm -rf index.html
|
||||||
|
fi
|
||||||
|
|
||||||
|
cmake --build . --parallel
|
||||||
|
if [ -f "eco2d.html" ]; then
|
||||||
|
mv eco2d.html index.html
|
||||||
|
fi
|
||||||
|
popd
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -xe
|
||||||
|
|
||||||
|
cmake --build build_web --target clean
|
|
@ -0,0 +1,39 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -xe
|
||||||
|
|
||||||
|
if [ ! -d "build_web" ]; then
|
||||||
|
echo "Build directory not found. Run setup_web.sh first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "butler" ]; then
|
||||||
|
mkdir butler
|
||||||
|
wget https://broth.itch.ovh/butler/linux-amd64/LATEST/archive/default -O butler.zip
|
||||||
|
mv butler.zip butler/
|
||||||
|
pushd butler/
|
||||||
|
unzip butler.zip
|
||||||
|
rm -rf butler.zip
|
||||||
|
chmod +x ./butler
|
||||||
|
./butler -V
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build the project
|
||||||
|
web/build.sh
|
||||||
|
|
||||||
|
# Package all assets
|
||||||
|
if [ ! -f "build_web/index.html" ]; then
|
||||||
|
echo "Build data not found. Compilation errors?"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p deploy_web
|
||||||
|
cp build_web/eco2d.* deploy_web/
|
||||||
|
cp build_web/index.html deploy_web/
|
||||||
|
|
||||||
|
# Deploy to itch.io
|
||||||
|
./butler/butler push deploy_web/ zaklaus/eco2d:html-latest
|
||||||
|
|
||||||
|
# Teardown
|
||||||
|
rm -rf deploy_web
|
|
@ -0,0 +1,2 @@
|
||||||
|
// Hack to enforce CLOCK_REALTIME, which is significantly faster for our purposes.
|
||||||
|
_emscripten_get_now = () => Date.now();
|
|
@ -0,0 +1,107 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en-us">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
|
||||||
|
<title>eco2d web game</title>
|
||||||
|
|
||||||
|
<meta name="title" content="eco2d web game">
|
||||||
|
<meta name="description" content="Small C99 2D game engine with a focus on prototyping">
|
||||||
|
<meta name="keywords" content="eco2d, html5, ecs, C, librg, chunks">
|
||||||
|
<meta name="viewport" content="width=device-width">
|
||||||
|
|
||||||
|
<!-- Open Graph metatags for sharing -->
|
||||||
|
<meta property="og:title" content="eco2d web game">
|
||||||
|
<meta property="og:image:type" content="image/png">
|
||||||
|
<meta property="og:image" content="https://avatars.githubusercontent.com/u/31039603?s=400&u=371f601b81fd4c6843f910b4565a54704caaa374&v=4">
|
||||||
|
<meta property="og:site_name" content="zpl.pw">
|
||||||
|
<meta property="og:url" content="https://github.com/zpl-c/eco2d">
|
||||||
|
<meta property="og:description" content="Small C99 2D game engine with a focus on prototyping">
|
||||||
|
|
||||||
|
<!-- Twitter metatags for sharing -->
|
||||||
|
<meta name="twitter:card" content="summary">
|
||||||
|
<meta name="twitter:site" content="@DMadarasz">
|
||||||
|
<meta name="twitter:title" content="eco2d web game">
|
||||||
|
<meta name="twitter:image" content="https://avatars.githubusercontent.com/u/31039603?s=400&u=371f601b81fd4c6843f910b4565a54704caaa374&v=4">
|
||||||
|
<meta name="twitter:url" content="https://github.com/zpl-c/eco2d">
|
||||||
|
<meta name="twitter:description" content="Small C99 2D game engine with a focus on prototyping">
|
||||||
|
|
||||||
|
<!-- Google tag (gtag.js) -->
|
||||||
|
<script async src="https://www.googletagmanager.com/gtag/js?id=G-R1QS3P3D1T"></script>
|
||||||
|
<script>
|
||||||
|
window.dataLayer = window.dataLayer || [];
|
||||||
|
function gtag(){dataLayer.push(arguments);}
|
||||||
|
gtag('js', new Date());
|
||||||
|
|
||||||
|
gtag('config', 'G-R1QS3P3D1T');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
html, body { margin: 0px; padding: 0px; background-color: black; width: 100%; height: 100%;}
|
||||||
|
canvas.emscripten {
|
||||||
|
border: 0px none; background-color: black;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script type='text/javascript' src="https://cdn.jsdelivr.net/gh/eligrey/FileSaver.js/dist/FileSaver.min.js"> </script>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
function saveFileFromMEMFSToDisk(memoryFSname, localFSname) // This can be called by C/C++ code
|
||||||
|
{
|
||||||
|
var isSafari = false; // Not supported, navigator.userAgent access is being restricted
|
||||||
|
//var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
||||||
|
var data = FS.readFile(memoryFSname);
|
||||||
|
var blob;
|
||||||
|
|
||||||
|
if (isSafari) blob = new Blob([data.buffer], { type: "application/octet-stream" });
|
||||||
|
else blob = new Blob([data.buffer], { type: "application/octet-binary" });
|
||||||
|
|
||||||
|
// NOTE: SaveAsDialog is a browser setting. For example, in Google Chrome,
|
||||||
|
// in Settings/Advanced/Downloads section you have a setting:
|
||||||
|
// 'Ask where to save each file before downloading' - which you can set true/false.
|
||||||
|
// If you enable this setting it would always ask you and bring the SaveAsDialog
|
||||||
|
saveAs(blob, localFSname);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas class=emscripten id=canvas oncontextmenu=event.preventDefault() tabindex=-1></canvas>
|
||||||
|
<script>
|
||||||
|
var Module = {
|
||||||
|
print: (function() {
|
||||||
|
return function(text) {
|
||||||
|
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
|
||||||
|
console.log(text);
|
||||||
|
};
|
||||||
|
})(),
|
||||||
|
printErr: (function() {
|
||||||
|
return function(text) {
|
||||||
|
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
|
||||||
|
console.error(text);
|
||||||
|
};
|
||||||
|
})(),
|
||||||
|
canvas: (function() {
|
||||||
|
var canvas = document.getElementById('canvas');
|
||||||
|
canvas.width = window.innerWidth;
|
||||||
|
canvas.height = window.innerHeight;
|
||||||
|
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
canvas.width = window.innerWidth;
|
||||||
|
canvas.height = window.innerHeight;
|
||||||
|
})
|
||||||
|
|
||||||
|
canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
|
||||||
|
|
||||||
|
return canvas;
|
||||||
|
})()
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
{{{ SCRIPT }}}
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -xe
|
||||||
|
|
||||||
|
python -m http.server --directory build_web --bind 127.0.0.1
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -xe
|
||||||
|
|
||||||
|
# Setup emsdk
|
||||||
|
if [ ! -d "emsdk" ]; then
|
||||||
|
wget https://github.com/emscripten-core/emsdk/archive/refs/heads/main.zip -O emscripten.zip
|
||||||
|
unzip emscripten.zip
|
||||||
|
mv emsdk-main emsdk
|
||||||
|
rm -rf emscripten.zip
|
||||||
|
fi
|
||||||
|
|
||||||
|
source ./emsdk/emsdk_env.sh
|
||||||
|
emsdk update
|
||||||
|
emsdk install latest
|
||||||
|
emsdk activate latest
|
||||||
|
source ./emsdk/emsdk_env.sh
|
||||||
|
|
||||||
|
# Setup web build
|
||||||
|
emcmake cmake -S . -B build_web -DCMAKE_BUILD_TYPE=Release -DPLATFORM=Web
|
|
@ -0,0 +1,18 @@
|
||||||
|
@echo off
|
||||||
|
|
||||||
|
cmake --build build_rel --parallel 32 --config Release
|
||||||
|
if not %ERRORLEVEL% == 0 exit /B 1
|
||||||
|
@rd /S /Q pkg
|
||||||
|
mkdir pkg
|
||||||
|
copy build_rel\eco2d.exe pkg
|
||||||
|
rem tools\upx -9 pkg\eco2d.exe
|
||||||
|
robocopy art pkg\art /E
|
||||||
|
@del pkg\art\*.ecotex
|
||||||
|
|
||||||
|
IF NOT "%1"=="SKIP_DEPLOY" (
|
||||||
|
pushd pkg
|
||||||
|
..\tools\7za.exe a -r ..\eco2d.zip *.*
|
||||||
|
popd
|
||||||
|
|
||||||
|
butler push eco2d.zip zaklaus/eco2d:win64-latest
|
||||||
|
)
|
Loading…
Reference in New Issue