while (true) {
await anim_frame();
- WASM_EXPORTS.new_frame_callback();
+ WASM_EXPORTS.loop();
}
}
i32map_put(^map, id, sprite);
}
-atlas_lookup :: proc (use atlas: ^Atlas, id: i32) -> AtlasSprite {
+atlas_lookup :: proc (use atlas: ^Atlas, id: i32, offset := 0) -> AtlasSprite {
sprite := i32map_get(^map, id, AtlasSprite.{});
+
+ if offset != 0 {
+ sprite.x += ~~offset * sprite.w;
+
+ while sprite.x >= ~~texture.width {
+ sprite.y += sprite.h;
+ sprite.x -= ~~texture.width;
+ }
+ }
+
sprite.x /= ~~texture.width;
sprite.y /= ~~texture.width;
sprite.w /= ~~texture.width;
--- /dev/null
+package gfx
+
+use package core
+use package globals
+use package vecmath
+use package main { RenderContext, draw_textured_rect }
+
+#private_file
+font_chars :: "0123456789!\"#$% ABCDEFGHIJKLMNOPQRSTUVWXYZ'()*+,abcdefghijklmnopqrstuvwxyz,-./\\,^:;<=>?[]~|_";
+
+#private_file
+char_to_tex_offset :: proc (ch: u8) -> u32 {
+ loc := 0;
+ for c: font_chars {
+ if c == ch do break;
+ loc += 1;
+ }
+ return loc;
+}
+
+draw_text :: proc (renderer: ^RenderContext, s: string, pos: V2f, scale := 1.0f) {
+ x := pos.x;
+ y := pos.y;
+
+ font_size := scale * 16.0f;
+
+ for ch: s {
+ char_sprite := atlas_lookup(^atlas, 2, char_to_tex_offset(ch));
+ draw_textured_rect(renderer, x, y, font_size, font_size, char_sprite.x, char_sprite.y, char_sprite.w, char_sprite.h);
+
+ x += font_size * 0.85f;
+ }
+}
\ No newline at end of file
}
case MouseDown {
- mouse.dx += (ev.mouse.pos_x - half_window_width) - mouse.x;
- mouse.dy += (ev.mouse.pos_y - half_window_height) - mouse.y;
- mouse.x = ev.mouse.pos_x - half_window_width;
- mouse.y = ev.mouse.pos_y - half_window_height;
+ mouse.dx += ev.mouse.pos_x - mouse.x;
+ mouse.dy += ev.mouse.pos_y - mouse.y;
+ mouse.x = ev.mouse.pos_x;
+ mouse.y = ev.mouse.pos_y;
mouse.buttons_just_down[cast(u32) ev.mouse.button] = !mouse.buttons_down[cast(u32) ev.mouse.button];
mouse.buttons_down[cast(u32) ev.mouse.button] = true;
}
case MouseUp {
- mouse.dx += (ev.mouse.pos_x - half_window_width) - mouse.x;
- mouse.dy += (ev.mouse.pos_y - half_window_height) - mouse.y;
- mouse.x = ev.mouse.pos_x - half_window_width;
- mouse.y = ev.mouse.pos_y - half_window_height;
+ mouse.dx += ev.mouse.pos_x - mouse.x;
+ mouse.dy += ev.mouse.pos_y - mouse.y;
+ mouse.x = ev.mouse.pos_x;
+ mouse.y = ev.mouse.pos_y;
mouse.buttons_down[cast(u32) ev.mouse.button] = false;
mouse.buttons_just_down[cast(u32) ev.mouse.button] = false;
}
case MouseMove {
- mouse.dx += (ev.mouse.pos_x - half_window_width) - mouse.x;
- mouse.dy += (ev.mouse.pos_y - half_window_height) - mouse.y;
- mouse.x = ev.mouse.pos_x - half_window_width;
- mouse.y = ev.mouse.pos_y - half_window_height;
+ mouse.dx += ev.mouse.pos_x - mouse.x;
+ mouse.dy += ev.mouse.pos_y - mouse.y;
+ mouse.x = ev.mouse.pos_x;
+ mouse.y = ev.mouse.pos_y;
}
case MouseWheel {
#include_file "gfx/quad_renderer"
#include_file "gfx/texture"
#include_file "gfx/atlas"
+#include_file "gfx/font"
#include_file "events"
#include_file "input"
#include_file "font"
}
render_context_ui :: proc (use rc: ^RenderContext) {
- quad_renderer_update_world(quad_renderer, 1.0f, 1.0f, 0.0f, 0.0f);
+ quad_renderer_update_world(quad_renderer, 1.0f, 1.0f, ~~-half_window_width, ~~-half_window_height);
quad_rebuffer_data(quad_renderer);
quad_renderer_draw(quad_renderer, curr_quad_idx);
quad_scratch_buffer : [512 * 1024] u8;
simulating := true;
-update :: proc () {
+update :: proc (dt: f32) {
input.preupdate(^input_state);
defer input.postupdate(^input_state);
poll_events();
if input.key_just_down(^input_state, Key.Space) do simulating = !simulating;
- if input.key_down(^input_state, Key.ArrowUp) do renderer.trans_y += 15.0f / renderer.scale;
- if input.key_down(^input_state, Key.ArrowDown) do renderer.trans_y -= 15.0f / renderer.scale;
- if input.key_down(^input_state, Key.ArrowLeft) do renderer.trans_x += 15.0f / renderer.scale;
- if input.key_down(^input_state, Key.ArrowRight) do renderer.trans_x -= 15.0f / renderer.scale;
+ if input.key_down(^input_state, Key.ArrowUp) do renderer.trans_y += (500.0f / renderer.scale) * dt;
+ if input.key_down(^input_state, Key.ArrowDown) do renderer.trans_y -= (500.0f / renderer.scale) * dt;
+ if input.key_down(^input_state, Key.ArrowLeft) do renderer.trans_x += (500.0f / renderer.scale) * dt;
+ if input.key_down(^input_state, Key.ArrowRight) do renderer.trans_x -= (500.0f / renderer.scale) * dt;
if input_state.mouse.wheel_ups > ~~0 do renderer.scale *= 1.125f;
if input_state.mouse.wheel_downs > ~~0 do renderer.scale /= 1.125f;
quadtree_init(^dude_tree, AABB.{ ~~-half_window_width, ~~-half_window_height, ~~window_width, ~~window_height });
for ^d: dudes do quadtree_insert(^dude_tree, d, quad_alloc);
- for ^d: dudes do dude_update(d, ^dude_tree);
+ for ^d: dudes do dude_update(d, dt, ^dude_tree);
for ^d: dudes {
- if d.can_move_x do d.pos.x += d.vel.x;
- if d.can_move_y do d.pos.y += d.vel.y;
+ if d.can_move_x do d.pos.x += d.vel.x * dt;
+ if d.can_move_y do d.pos.y += d.vel.y * dt;
if !d.can_move_x && !d.can_move_y do d.couldnt_move_count += ~~1;
}
// UI Rendering
renderer.color = Color4f32.{ 0.0f, 0.0f, 0.0f, 1.0f };
draw_rect(^renderer, ~~input_state.mouse.x, ~~input_state.mouse.y, 10f, 10f);
+
+ renderer.color = Color4f32.{ 1.0f, 1.0f, 1.0f, 1.0f };
+ draw_rect(^renderer, 10.0f, 10.0f, 500.0f, 50.0f);
+
+ renderer.color = Color4f32.{ 0.0f, 0.0f, 0.0f, 1.0f };
+ draw_text(^renderer, "Hello. Test(12486),$! 0AaQq:", V2f.{ 10.0f, 10.0f }, 1.0f);
render_context_ui(^renderer);
}
debugger :: proc () #foreign "dummy" "breakable" ---
// This procedure is called asynchronously from JS every frame.
-new_frame_callback :: proc () #export {
- update();
+
+// @CLEANUP: Add local persistant variables so this can go in the loop() body.
+last_time := 0;
+
+loop :: proc () #export {
+ time_now :: proc () -> u32 #foreign "time" "now" ---;
+
+ curr_time := time_now();
+ if last_time == 0 do last_time = curr_time;
+ delta := curr_time - last_time;
+ last_time = curr_time;
+
+ update(~~delta / 1000.0f);
draw();
}
atlas_map(^atlas, 0, AtlasSprite.{ x = 16.0f, y = 0.0f, w = 16.0f, h = 16.0f });
atlas_map(^atlas, 1, AtlasSprite.{ x = 32.0f, y = 0.0f, w = 16.0f, h = 16.0f });
+ atlas_map(^atlas, 2, AtlasSprite.{ x = 0.0f, y = 160.0f, w = 16.0f, h = 16.0f });
+
event.init();
input.init(^input_state);
Dude_Color_Table[2] = Color4f32.{ 0.2f, 0.2f, 1.0f, 1.0f };
array_init(^dudes);
- for i: 0 .. 500 {
+ for i: 0 .. 1000 {
array_push(^dudes, dude_create_random());
}
};
}
-dude_update :: proc (use dude: ^Dude, other_dudes: ^QuadTree(Dude)) {
+dude_update :: proc (use dude: ^Dude, dt: f32, other_dudes: ^QuadTree(Dude)) {
if random_between(0, 100) < 1 || couldnt_move_count >= ~~2 {
- vel.x = random_float(-3.0f, 3.0f);
- vel.y = random_float(-3.0f, 3.0f);
+ vel.x = random_float(-300.0f, 300.0f);
+ vel.y = random_float(-300.0f, 300.0f);
couldnt_move_count = ~~0;
}
+ dude_try_move(dude, dt, other_dudes);
+
if tile := tilemap_screen_coord_to_tile(^tilemap, pos); tile != null {
target_r := cast(u8) cast(u32) (color.r * 255.0f);
target_g := cast(u8) cast(u32) (color.g * 255.0f);
target_b := cast(u8) cast(u32) (color.b * 255.0f);
- diff_r := cast(i32) (target_r - tile.r) >>> 2;
- diff_g := cast(i32) (target_g - tile.g) >>> 2;
- diff_b := cast(i32) (target_b - tile.b) >>> 2;
+ diff_r := (cast(i32) target_r - cast(i32) tile.r) >>> 2;
+ diff_g := (cast(i32) target_g - cast(i32) tile.g) >>> 2;
+ diff_b := (cast(i32) target_b - cast(i32) tile.b) >>> 2;
tile.r += ~~diff_r;
tile.g += ~~diff_g;
tile.b += ~~diff_b;
}
-
-
- dude_try_move(dude, other_dudes);
}
-dude_try_move :: proc (use dude: ^Dude, other_dudes: ^QuadTree(Dude)) {
+dude_try_move :: proc (use dude: ^Dude, dt: f32, other_dudes: ^QuadTree(Dude)) {
old_pos := pos;
potential_dudes : [..] ^Dude;
collided := false;
- pos.x += vel.x;
+ pos.x += vel.x * dt;
if pos.x - size < ~~-half_window_width || pos.x + size >= ~~half_window_width do collided = true;
dude_aabb := dude_get_aabb(dude);
}
can_move_x = !collided;
- pos.x -= vel.x;
+ pos.x -= vel.x * dt;
collided = false;
- pos.y += vel.y;
+ pos.y += vel.y * dt;
if pos.y - size < ~~-half_window_height || pos.y + size >= ~~half_window_height do collided = true;
dude_aabb = dude_get_aabb(dude);
}
can_move_y = !collided;
- pos.y -= vel.y;
+ pos.y -= vel.y * dt;
}
dude_get_aabb :: proc (use dude: ^Dude) -> AABB {
use package core
use package aabb
+use package vecmath
#private_file
QUAD_TREE_MAX_POINTS :: 4;
}
quadtree_insert :: proc (use qt: ^QuadTree($T), t: ^T, alloc := context.allocator) -> bool {
- pos := t.pos; // T is expected to have a 'pos' element.
+ pos: V2f = t.pos; // T is expected to have a 'pos' element.
if !aabb_contains(region, pos) do return false;
if (v_tex_pos.x < 0.0) {
fragColor = v_col;
} else {
- fragColor = v_col * texture(tex, v_tex_pos);
+ vec4 t_col = texture(tex, v_tex_pos);
+ if (t_col == vec4(1.0, 0.0, 1.0, 1.0)) {
+ fragColor = vec4(0.0, 0.0, 0.0, 0.0);
+ } else {
+ fragColor = v_col * texture(tex, v_tex_pos);
+ }
}
}
atlas src/globals.onyx /^atlas : Atlas$/
atlas_apply_to_quad src/gfx/atlas.onyx /^atlas_apply_to_quad :: proc (use atlas: ^Atlas, id: i32, quad: ^Quad) {$/
atlas_create src/gfx/atlas.onyx /^atlas_create :: proc (tex: ^Texture) -> Atlas {$/
-atlas_lookup src/gfx/atlas.onyx /^atlas_lookup :: proc (use atlas: ^Atlas, id: i32) -> AtlasSprite {$/
+atlas_lookup src/gfx/atlas.onyx /^atlas_lookup :: proc (use atlas: ^Atlas, id: i32, offset := 0) -> AtlasSprite {$/
atlas_map src/gfx/atlas.onyx /^atlas_map :: proc (use atlas: ^Atlas, id: i32, sprite: AtlasSprite) {$/
attachShader /usr/share/onyx/core/js/webgl.onyx /^attachShader :: proc (program: GLProgram, shader: GLShader) -> GLProgram #foreign "gl" "attachShader" ---$/
bezier_curve src/font.onyx /^bezier_curve :: proc (t: f32, ps: [] V2f) -> V2f {$/
drawElementsInstanced /usr/share/onyx/core/js/webgl.onyx /^drawElementsInstanced :: proc (mode: GLenum, count: GLsizei, type: GLenum, offset: GLint, instanceCount: GLsizei) #foreign "gl" "drawElementsInstanced" ---$/
draw_quad src/main.onyx /^draw_quad :: proc (use rc: ^RenderContext, quad: ^Quad) {$/
draw_rect src/main.onyx /^draw_rect :: proc (use rc: ^RenderContext, x: f32, y: f32, w: f32, h: f32) {$/
+draw_text src/gfx/font.onyx /^draw_text :: proc (renderer: ^RenderContext, s: string, pos: V2f, scale := 1.0f) {$/
draw_textured_rect src/main.onyx /^draw_textured_rect :: proc (use rc: ^RenderContext, x: f32, y: f32, w: f32, h: f32, tx: f32, ty: f32, tw: f32, th: f32) {$/
dude_create_random src/main.onyx /^dude_create_random :: proc () -> Dude {$/
dude_get_aabb src/main.onyx /^dude_get_aabb :: proc (use dude: ^Dude) -> AABB {$/
dude_tree src/globals.onyx /^dude_tree : QuadTree(Dude)$/
-dude_try_move src/main.onyx /^dude_try_move :: proc (use dude: ^Dude, other_dudes: ^QuadTree(Dude)) {$/
-dude_update src/main.onyx /^dude_update :: proc (use dude: ^Dude, other_dudes: ^QuadTree(Dude)) {$/
+dude_try_move src/main.onyx /^dude_try_move :: proc (use dude: ^Dude, dt: f32, other_dudes: ^QuadTree(Dude)) {$/
+dude_update src/main.onyx /^dude_update :: proc (use dude: ^Dude, dt: f32, other_dudes: ^QuadTree(Dude)) {$/
dudes src/globals.onyx /^dudes : [..] Dude$/
enable /usr/share/onyx/core/js/webgl.onyx /^enable :: proc (cap: GLenum) #foreign "gl" "enable" ---$/
enableVertexAttribArray /usr/share/onyx/core/js/webgl.onyx /^enableVertexAttribArray :: proc (index: GLuint) #foreign "gl" "enableVertexAttribArray" ---$/
key_down src/input.onyx /^key_down :: proc (use state: ^InputState, key: Key) -> bool {$/
key_just_down src/input.onyx /^key_just_down :: proc (use state: ^InputState, key: Key) -> bool {$/
key_up src/input.onyx /^key_up :: proc (use state: ^InputState, key: Key) -> bool {$/
+last_time src/main.onyx /^last_time := 0;$/
lineWidth /usr/share/onyx/core/js/webgl.onyx /^lineWidth :: proc (width: GLfloat) #foreign "gl" "lineWidth" ---$/
lines_intersect src/vecmath.onyx /^lines_intersect :: proc (p1: V2($T), q1: V2(T), p2: V2(T), q2: V2(T)) -> bool {$/
linkProgram /usr/share/onyx/core/js/webgl.onyx /^linkProgram :: proc (program: GLProgram) #foreign "gl" "linkProgram" ---$/
link_program src/utils/gl.onyx /^link_program :: proc (vertex_shader: gl.GLShader, frag_shader: gl.GLShader) -> gl.GLProgram {$/
+loop src/main.onyx /^loop :: proc () #export {$/
main src/main.onyx /^main :: proc (args: [] cstring) {$/
max_f32 /usr/share/onyx/core/intrinsics.onyx /^max_f32 :: proc (lhs: f32, rhs: f32) -> f32 #intrinsic ---$/
max_f64 /usr/share/onyx/core/intrinsics.onyx /^max_f64 :: proc (lhs: f64, rhs: f64) -> f64 #intrinsic ---$/
min_poly /usr/share/onyx/core/math.onyx /^min_poly :: proc (a: $T, b: T) -> T {$/
nearest_f32 /usr/share/onyx/core/intrinsics.onyx /^nearest_f32 :: proc (val: f32) -> f32 #intrinsic ---$/
nearest_f64 /usr/share/onyx/core/intrinsics.onyx /^nearest_f64 :: proc (val: f64) -> f64 #intrinsic ---$/
-new_frame_callback src/main.onyx /^new_frame_callback :: proc () #export {$/
null /usr/share/onyx/core/builtin.onyx /^null :: cast(rawptr) 0;$/
or_i32 /usr/share/onyx/core/intrinsics.onyx /^or_i32 :: proc (lhs: i32, rhs: i32) -> i32 #intrinsic ---$/
or_i64 /usr/share/onyx/core/intrinsics.onyx /^or_i64 :: proc (lhs: i64, rhs: i64) -> i64 #intrinsic ---$/
uniformMatrix2 /usr/share/onyx/core/js/webgl.onyx /^uniformMatrix2 :: proc (loc: GLUniformLocation, transpose: GLboolean, value: GLMat2) #foreign "gl" "uniformMatrix2" ---$/
uniformMatrix3 /usr/share/onyx/core/js/webgl.onyx /^uniformMatrix3 :: proc (loc: GLUniformLocation, transpose: GLboolean, value: GLMat3) #foreign "gl" "uniformMatrix3" ---$/
uniformMatrix4 /usr/share/onyx/core/js/webgl.onyx /^uniformMatrix4 :: proc (loc: GLUniformLocation, transpose: GLboolean, value: GLMat4) #foreign "gl" "uniformMatrix4" ---$/
-update src/main.onyx /^update :: proc () {$/
+update src/main.onyx /^update :: proc (dt: f32) {$/
useProgram /usr/share/onyx/core/js/webgl.onyx /^useProgram :: proc (program: GLProgram) #foreign "gl" "useProgram" ---$/
v2_add src/vecmath.onyx /^v2_add :: proc (a: V2($T), b: V2(T)) -> V2(T) {$/
v2_equal src/vecmath.onyx /^v2_equal :: proc (a: V2($T), b: V2(T)) -> bool {$/