Fix loop to be more accuratly timed, and added custom ruby libs inclusion setup
This commit is contained in:
+3
-1
@@ -3,4 +3,6 @@
|
|||||||
build/*
|
build/*
|
||||||
bin/*
|
bin/*
|
||||||
|
|
||||||
.clangd
|
.clangd
|
||||||
|
|
||||||
|
include/binding/ruby_compiled.h
|
||||||
@@ -14,6 +14,7 @@ CXX := $(CCACHE) clang++
|
|||||||
CC := $(CCACHE) clang
|
CC := $(CCACHE) clang
|
||||||
|
|
||||||
# ---------------- SDL3 ----------------
|
# ---------------- SDL3 ----------------
|
||||||
|
|
||||||
SDL_CFLAGS := $(shell pkg-config --cflags sdl3 sdl3-ttf sdl3-image)
|
SDL_CFLAGS := $(shell pkg-config --cflags sdl3 sdl3-ttf sdl3-image)
|
||||||
SDL_LIBS_DEBUG := $(shell pkg-config --libs sdl3 sdl3-ttf sdl3-image)
|
SDL_LIBS_DEBUG := $(shell pkg-config --libs sdl3 sdl3-ttf sdl3-image)
|
||||||
SDL_LIBS_RELEASE := $(shell pkg-config --libs sdl3 sdl3-ttf sdl3-image)
|
SDL_LIBS_RELEASE := $(shell pkg-config --libs sdl3 sdl3-ttf sdl3-image)
|
||||||
@@ -42,9 +43,11 @@ PCH_CFLAGS_RELEASE := $(CFLAGS_RELEASE) -x c++-header
|
|||||||
|
|
||||||
LIBS := ./libs/mruby/build/host/lib/libmruby.a
|
LIBS := ./libs/mruby/build/host/lib/libmruby.a
|
||||||
|
|
||||||
|
MGEM_DIR := ./libs/l_mgems
|
||||||
|
|
||||||
# ---------------- SOURCES ----------------
|
# ---------------- SOURCES ----------------
|
||||||
|
|
||||||
SRC := $(wildcard $(SRC_DIR)/*.cc) $(wildcard $(SRC_DIR)/**/*.cc)
|
SRC := $(shell find $(SRC_DIR) -name "*.cc")
|
||||||
|
|
||||||
OBJ_DEBUG := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/debug/%.o,$(SRC))
|
OBJ_DEBUG := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/debug/%.o,$(SRC))
|
||||||
OBJ_RELEASE := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/release/%.o,$(SRC))
|
OBJ_RELEASE := $(patsubst $(SRC_DIR)/%.cc,$(OBJ_DIR)/release/%.o,$(SRC))
|
||||||
@@ -54,13 +57,13 @@ DEP_RELEASE := $(OBJ_RELEASE:.o=.d)
|
|||||||
|
|
||||||
# ---------------- TARGETS ----------------
|
# ---------------- TARGETS ----------------
|
||||||
|
|
||||||
.PHONY: all debug release clean setup
|
.PHONY: all debug release clean setup mgems
|
||||||
|
|
||||||
all: debug
|
all: debug
|
||||||
|
|
||||||
debug: $(TARGET_DEBUG)
|
debug: mgems $(TARGET_DEBUG)
|
||||||
|
|
||||||
release: $(TARGET_RELEASE)
|
release: mgems $(TARGET_RELEASE)
|
||||||
|
|
||||||
# ---------------- CLANGD ----------------
|
# ---------------- CLANGD ----------------
|
||||||
|
|
||||||
@@ -68,6 +71,11 @@ setup: setup.rb
|
|||||||
@echo "Setting up clangd configuration..."
|
@echo "Setting up clangd configuration..."
|
||||||
ruby setup.rb
|
ruby setup.rb
|
||||||
|
|
||||||
|
# ---------------- MRB_MGEMS ----------------
|
||||||
|
|
||||||
|
mgems:
|
||||||
|
$(MGEM_DIR)/compile.sh
|
||||||
|
|
||||||
# ---------------- PCH ----------------
|
# ---------------- PCH ----------------
|
||||||
|
|
||||||
$(PCH_DEBUG): $(INCLUDE_DIR)/pch.h
|
$(PCH_DEBUG): $(INCLUDE_DIR)/pch.h
|
||||||
|
|||||||
+13
-9
@@ -54,8 +54,7 @@ struct EImage : Element {
|
|||||||
Animation &animation = *animation_pool[animation_id];
|
Animation &animation = *animation_pool[animation_id];
|
||||||
if (animation.frames.empty())
|
if (animation.frames.empty())
|
||||||
return;
|
return;
|
||||||
|
int frame_index = (int)((abs_time * animation.frame_rate) / 1e9) % animation.frames.size();
|
||||||
int frame_index = (int)((abs_time * animation.frame_rate) / 1000) % animation.frames.size();
|
|
||||||
window.draw(animation.frames[frame_index], position, z, rotation, scale, alpha);
|
window.draw(animation.frames[frame_index], position, z, rotation, scale, alpha);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -166,10 +165,10 @@ struct Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void update_scene(uint64_t delta_time) {
|
void update_scene(uint64_t delta_time) {
|
||||||
if (!mrb_nil_p(update.proc)) {
|
if (mrb_nil_p(update.proc))
|
||||||
mrb_value dt_val = mrb_int_value(Ruby::mrb, delta_time);
|
return;
|
||||||
update.call(1, &dt_val);
|
mrb_value dt_val = mrb_float_value(Ruby::mrb, delta_time / 1e9);
|
||||||
}
|
update.call(1, &dt_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void click(Vec2<float> position) {
|
void click(Vec2<float> position) {
|
||||||
@@ -234,7 +233,7 @@ struct App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
const uint64_t target_ms = 1000 / 60;
|
const uint64_t TARGET_NS = 1e9 / 60;
|
||||||
|
|
||||||
uint64_t time_a = window.get_time();
|
uint64_t time_a = window.get_time();
|
||||||
uint64_t time_b = window.get_time();
|
uint64_t time_b = window.get_time();
|
||||||
@@ -242,8 +241,13 @@ struct App {
|
|||||||
while (running) {
|
while (running) {
|
||||||
time_a = window.get_time();
|
time_a = window.get_time();
|
||||||
uint64_t frame_time = time_a - time_b;
|
uint64_t frame_time = time_a - time_b;
|
||||||
if (frame_time <= target_ms)
|
|
||||||
usleep((target_ms - frame_time) * 1000);
|
if (frame_time <= TARGET_NS) {
|
||||||
|
struct timespec req;
|
||||||
|
req.tv_sec = 0;
|
||||||
|
req.tv_nsec = TARGET_NS - frame_time;
|
||||||
|
nanosleep(&req, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
time_b = window.get_time();
|
time_b = window.get_time();
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include "binding/ruby_compiled.h"
|
||||||
|
|
||||||
#define DEF_SYM(name) inline mrb_sym sym_##name = mrb_intern_cstr(Ruby::mrb, #name);
|
#define DEF_SYM(name) inline mrb_sym sym_##name = mrb_intern_cstr(Ruby::mrb, #name);
|
||||||
#define SYM(name) mrb_symbol_value(sym_##name)
|
#define SYM(name) mrb_symbol_value(sym_##name)
|
||||||
|
|
||||||
@@ -83,7 +85,15 @@ struct Block {
|
|||||||
};
|
};
|
||||||
|
|
||||||
inline void run_string(const char *code, size_t length) {
|
inline void run_string(const char *code, size_t length) {
|
||||||
|
int ai = mrb_gc_arena_save(mrb);
|
||||||
mrb_load_nstring(mrb, code, length);
|
mrb_load_nstring(mrb, code, length);
|
||||||
|
mrb_gc_arena_restore(mrb, ai);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void load_mgems() {
|
||||||
|
int ai = mrb_gc_arena_save(mrb);
|
||||||
|
mrb_load_irep(mrb, mgems);
|
||||||
|
mrb_gc_arena_restore(mrb, ai);
|
||||||
}
|
}
|
||||||
}; // namespace Ruby
|
}; // namespace Ruby
|
||||||
|
|
||||||
|
|||||||
@@ -341,8 +341,8 @@ public:
|
|||||||
|
|
||||||
// Time
|
// Time
|
||||||
|
|
||||||
uint64_t get_time(); // returns the time in milliseconds since the window was created
|
uint64_t get_time(); // returns the time in nanoseconds since the window was created
|
||||||
uint64_t delta_time(); // returns the time in milliseconds since the last render call
|
uint64_t delta_time(); // returns the time in nanoseconds since the last render call
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// internal data and functions
|
// internal data and functions
|
||||||
|
|||||||
Executable
+40
@@ -0,0 +1,40 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
OUTPUT_TMP=$(mktemp)
|
||||||
|
OUTPUT="$SCRIPT_DIR/../../include/binding/ruby_compiled.h"
|
||||||
|
|
||||||
|
if test "$1" = "clean"; then
|
||||||
|
rm -f "$OUTPUT"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
trap 'rm -f "$OUTPUT_TMP"' EXIT
|
||||||
|
|
||||||
|
mapfile -t FILES < <(find "$SCRIPT_DIR" -name "*.rb" | sort)
|
||||||
|
|
||||||
|
LATEST_FILE_TIME=$(for file in "${FILES[@]}"; do
|
||||||
|
echo $(stat -c "%Y" "$file")
|
||||||
|
done | sort -n | tail -1)
|
||||||
|
|
||||||
|
OUTPUT_TIME=$(stat -c "%Y" "$OUTPUT" 2>/dev/null || echo 0)
|
||||||
|
|
||||||
|
if test "$OUTPUT_TIME" -ge "$LATEST_FILE_TIME"; then
|
||||||
|
echo "mgems is up to date."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$SCRIPT_DIR/../mruby/bin/mrbc" -o "$OUTPUT_TMP" "${FILES[@]}"
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "#ifndef MGEMS_H"
|
||||||
|
echo "#define MGEMS_H"
|
||||||
|
xxd -i -n mgems $OUTPUT_TMP \
|
||||||
|
| sed -e 's/^unsigned char /constexpr unsigned char /' \
|
||||||
|
-e 's/^unsigned int /constexpr unsigned int /'
|
||||||
|
echo "#endif"
|
||||||
|
} > "$OUTPUT"
|
||||||
|
|
||||||
|
echo "Compiled mgems!"
|
||||||
+1010
File diff suppressed because it is too large
Load Diff
+20
-9
@@ -22,6 +22,7 @@ rect.on_click do
|
|||||||
rect.color = rect.color == 0xFF0000 ?
|
rect.color = rect.color == 0xFF0000 ?
|
||||||
0x00FF00 :
|
0x00FF00 :
|
||||||
0xFF0000
|
0xFF0000
|
||||||
|
main_scene << text unless main_scene.elements.include?(text)
|
||||||
text.params[:name] = text.params[:name] == "Me" ?
|
text.params[:name] = text.params[:name] == "Me" ?
|
||||||
"You" :
|
"You" :
|
||||||
"Me"
|
"Me"
|
||||||
@@ -30,35 +31,45 @@ end
|
|||||||
|
|
||||||
App.map_key :mouse_left, :press
|
App.map_key :mouse_left, :press
|
||||||
|
|
||||||
|
start = Time.now
|
||||||
|
c_ = 0.0
|
||||||
|
c_c = 0
|
||||||
|
|
||||||
main_scene.on_update do |delta_time|
|
main_scene.on_update do |delta_time|
|
||||||
# puts "Delta time: #{delta_time}ms"
|
c_ += delta_time
|
||||||
|
c_c += 1
|
||||||
|
|
||||||
|
# puts "Delta time: #{delta_time}s"
|
||||||
# commented out to avoid spamming the console, but you can uncomment to see the delta time being printed every frame
|
# commented out to avoid spamming the console, but you can uncomment to see the delta time being printed every frame
|
||||||
# runs at 60fps, so you should see around 16-17ms being printed
|
# runs at 60fps, so you should see around 16-17ms being printed
|
||||||
|
|
||||||
el = main_scene.elements_at(App.mouse_position)
|
el = main_scene.elements_at(App.mouse_position)
|
||||||
|
|
||||||
puts App.text_input if App.text_input != ""
|
pp App.text_input if App.text_input != ""
|
||||||
|
|
||||||
next unless App.pressed?(:press)
|
next unless App.pressed?(:press)
|
||||||
|
|
||||||
puts "#{App.pressed?(:press)}, #{App.down?(:press)}, #{App.released?(:press)}"
|
pp "#{App.pressed?(:press)}, #{App.down?(:press)}, #{App.released?(:press)}"
|
||||||
|
|
||||||
for elem in el
|
for elem in el
|
||||||
if elem == image_element
|
if elem == image_element
|
||||||
puts "Down over image element"
|
pp "Down over image element"
|
||||||
elsif elem == rect
|
elsif elem == rect
|
||||||
puts "Down over rect element"
|
pp "Down over rect element"
|
||||||
elsif elem == text
|
elsif elem == text
|
||||||
puts "Down over text element"
|
pp "Down over text element"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
main_scene << text
|
main_scene << text
|
||||||
main_scene << rect
|
main_scene << rect
|
||||||
main_scene << image_element
|
main_scene << image_element
|
||||||
|
|
||||||
# main_scene.delete(text) # Uncomment to test element deletion
|
main_scene.delete(text)
|
||||||
|
|
||||||
App.start main_scene
|
App.start main_scene
|
||||||
|
|
||||||
|
p "Average delta time: #{c_ / c_c}s"
|
||||||
|
p "Time since start (real): #{Time.now - start}s"
|
||||||
|
p "Time since start (from dt): #{c_}s"
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "binding/definitions.h"
|
#include "binding/definitions.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
Ruby::load_mgems();
|
||||||
definitions::setup();
|
definitions::setup();
|
||||||
|
|
||||||
char *startup_script = nullptr;
|
char *startup_script = nullptr;
|
||||||
|
|||||||
@@ -451,14 +451,17 @@ const char *Window::paste() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Window::get_time() {
|
uint64_t Window::get_time() {
|
||||||
return SDL_GetTicks();
|
return SDL_GetTicksNS();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Window::delta_time() {
|
uint64_t Window::delta_time() {
|
||||||
static uint64_t last_time = 0;
|
static uint64_t last_time = 0;
|
||||||
uint64_t current_time = SDL_GetTicks();
|
static bool first_call = 1;
|
||||||
|
uint64_t current_time = SDL_GetTicksNS();
|
||||||
uint64_t delta = current_time - last_time;
|
uint64_t delta = current_time - last_time;
|
||||||
last_time = current_time;
|
last_time = current_time;
|
||||||
|
if (first_call)
|
||||||
|
return (first_call = 0);
|
||||||
return delta;
|
return delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -234,6 +234,7 @@ Other features that a game engine should have/has (need to go in depth)
|
|||||||
- audio playing
|
- audio playing
|
||||||
- network interface, with a lib to work with rack backends (and generic socket api)
|
- network interface, with a lib to work with rack backends (and generic socket api)
|
||||||
- persistence store
|
- persistence store
|
||||||
|
- rng helpers
|
||||||
|
|
||||||
## Embedded scripting language choice.
|
## Embedded scripting language choice.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user