x: f32; y: f32; w: f32; h: f32;
}
-aabb_contains :: proc (r: AABB, v: V2f) -> bool {
+aabb_contains :: (r: AABB, v: V2f) -> bool {
return v.x >= r.x
&& v.x <= r.x + r.w
&& v.y >= r.y
&& v.y <= r.y + r.h;
}
-aabb_intersects :: proc (r1: AABB, r2: AABB) -> bool {
+aabb_intersects :: (r1: AABB, r2: AABB) -> bool {
return r1.x < r2.x + r2.w
&& r1.x + r1.w > r2.x
&& r1.y < r2.y + r2.h
resize : ResizeEvent;
}
-clear_event :: proc (ev: ^Event) {
- dev := cast(^DomEvent) ev;
- dev.kind = DomEventKind.None;
- dev.timestamp = 0;
+clear_event :: (ev: ^Event) {
+ ev.kind = DomEventKind.None;
+ ev.timestamp = 0;
}
-init :: proc () {
+init :: () {
event_storage.event_count = 0;
event_storage.max_events = MAX_EVENTS;
event_setup(^event_storage, sizeof Event);
}
-poll :: proc (ev: ^Event) -> bool {
+poll :: (ev: ^Event) -> bool {
if event_storage.event_count == 0 do return false;
*ev = event_storage.event_buffer[0];
}
#private_file event_storage : EventStorage;
-#private_file event_setup :: proc (event_storage: ^EventStorage, event_size: u32) #foreign "event" "setup" ---
+#private_file event_setup :: (event_storage: ^EventStorage, event_size: u32) -> void #foreign "event" "setup" ---
// Very proud of how small this function can be using slices
// However, it should be turned into a non-recursive solution
// since this runs in factorial time.
-bezier_curve :: proc (t: f32, ps: [] V2f) -> V2f {
+bezier_curve :: (t: f32, ps: [] V2f) -> V2f {
if ps.count == 1 do return ps[0];
ret := V2f.{ 0.0f, 0.0f };
pos : u32;
}
-binary_reader_create :: proc (data: [] u8, initial_pos := 0) -> BinaryReader {
+binary_reader_create :: (data: [] u8, initial_pos := 0) -> BinaryReader {
return BinaryReader.{ data = data, pos = initial_pos };
}
-#private_file seek :: proc (use br: ^BinaryReader, new_pos: u32) -> u32 {
+#private_file seek :: (use br: ^BinaryReader, new_pos: u32) -> u32 {
old_pos := pos;
pos = new_pos;
return old_pos;
}
-#private_file tell :: proc (use br: ^BinaryReader) -> u32 do return pos;
+#private_file tell :: (use br: ^BinaryReader) -> u32 do return pos;
-#private_file read_u8 :: proc (use br: ^BinaryReader) -> u8 {
+#private_file read_u8 :: (use br: ^BinaryReader) -> u8 {
ret := data[pos];
pos += 1;
return ret;
}
-#private_file read_u16 :: proc (use br: ^BinaryReader) -> u16 do return ~~(read_u8(br) << ~~8 | read_u8(br));
+#private_file read_u16 :: (use br: ^BinaryReader) -> u16 do return ~~(read_u8(br) << ~~8 | read_u8(br));
-#private_file read_u32 :: proc (use br: ^BinaryReader) -> u32 {
+#private_file read_u32 :: (use br: ^BinaryReader) -> u32 {
// Encoding is big endian
ret: u32 = 0;
ret |= cast(u32) read_u8(br) << 24;
return ret;
}
-#private_file read_i16 :: proc (use br: ^BinaryReader) -> i16 {
+#private_file read_i16 :: (use br: ^BinaryReader) -> i16 {
ret := read_u16(br);
if ret & ~~0x8000 != ~~0 do ret -= ~~(1 << 16);
return ret;
}
-#private_file read_i32 :: proc (use br: ^BinaryReader) -> i32 {
+#private_file read_i32 :: (use br: ^BinaryReader) -> i32 {
return ~~read_u32(br);
}
-#private_file read_fword :: proc (use br: ^BinaryReader) -> i16 do return read_i16(br);
+#private_file read_fword :: (use br: ^BinaryReader) -> i16 do return read_i16(br);
-#private_file read_2dot14 :: proc (use br: ^BinaryReader) -> f32 {
+#private_file read_2dot14 :: (use br: ^BinaryReader) -> f32 {
val := cast(i32) read_i16(br);
return ~~val / cast(f32) (1 << 14);
}
-#private_file read_fixed :: proc (use br: ^BinaryReader) -> f32 {
+#private_file read_fixed :: (use br: ^BinaryReader) -> f32 {
val := read_i32(br);
return ~~val / cast(f32) (1 << 16);
}
-#private_file read_string :: proc (use br: ^BinaryReader, len: i32) -> str {
+#private_file read_string :: (use br: ^BinaryReader, len: i32) -> str {
ret := data.data[pos .. pos + len];
pos += len;
return ret;
}
// NOT IMPLEMENTED
-#private_file read_date :: proc (use br: ^BinaryReader) -> u64 {
+#private_file read_date :: (use br: ^BinaryReader) -> u64 {
pos += 8;
return ~~0;
}
y : i16 = ~~0;
}
-ttf_create :: proc (ttf_data: [] u8) -> TrueTypeFont {
+ttf_create :: (ttf_data: [] u8) -> TrueTypeFont {
ttf : TrueTypeFont;
ttf.reader = binary_reader_create(ttf_data);
map.init(^ttf.table_map, TTTableInfo.{});
return ttf;
}
-ttf_read_offset_table :: proc (use ttf: ^TrueTypeFont) {
+ttf_read_offset_table :: (use ttf: ^TrueTypeFont) {
scalar_type = read_u32(^reader);
num_tables := read_u16(^reader);
search_range = read_u16(^reader);
}
}
-ttf_read_head_table :: proc (use ttf: ^TrueTypeFont) {
+ttf_read_head_table :: (use ttf: ^TrueTypeFont) {
head_table_info := map.get(^table_map, string_to_beu32("head"));
seek(^reader, head_table_info.offset);
glyph_data_format = read_i16(^reader);
}
-ttf_lookup_glyph_offset :: proc (use ttf: ^TrueTypeFont, glyph_index: i32) -> u32 {
+ttf_lookup_glyph_offset :: (use ttf: ^TrueTypeFont, glyph_index: i32) -> u32 {
loca_table_info := map.get(^table_map, string_to_beu32("loca"));
glyf_table_info := map.get(^table_map, string_to_beu32("glyf"));
}
// Result is expected to be freed
-ttf_read_glyph :: proc (use ttf: ^TrueTypeFont, glyph_index: i32) -> ^TTGlyph {
+ttf_read_glyph :: (use ttf: ^TrueTypeFont, glyph_index: i32) -> ^TTGlyph {
offset := ttf_lookup_glyph_offset(ttf, glyph_index);
glyf_table_info := map.get(^table_map, string_to_beu32("glyf"));
return glyph;
}
-ttf_glyph_destroy :: proc (glyph: ^TTGlyph) {
+ttf_glyph_destroy :: (glyph: ^TTGlyph) {
array.free(^glyph.contour_ends);
array.free(^glyph.points);
cfree(glyph);
}
#private_file
-ttf_read_simple_glyph :: proc (use ttf: ^TrueTypeFont, glyph: ^TTGlyph) {
+ttf_read_simple_glyph :: (use ttf: ^TrueTypeFont, glyph: ^TTGlyph) {
array.init(^glyph.contour_ends, ~~glyph.contour_count);
array.init(^glyph.points);
}
-ttf_glyph_count :: proc (use ttf: ^TrueTypeFont) -> u32 {
+ttf_glyph_count :: (use ttf: ^TrueTypeFont) -> u32 {
maxp_table_info := map.get(^table_map, string_to_beu32("maxp"));
old := seek(^reader, maxp_table_info.offset + 4);
defer seek(^reader, old);
return ~~read_u16(^reader);
}
-ttf_read_cmap_table :: proc (use ttf: ^TrueTypeFont) {
+ttf_read_cmap_table :: (use ttf: ^TrueTypeFont) {
cmap_table_info := map.get(^table_map, string_to_beu32("cmap"));
seek(^reader, cmap_table_info.offset);
cmap4: TTCmap4;
}
-ttf_read_cmap :: proc (use ttf: ^TrueTypeFont, offset: u32) {
+ttf_read_cmap :: (use ttf: ^TrueTypeFont, offset: u32) {
old := seek(^reader, offset);
defer seek(^reader, old);
}
}
-ttf_read_cmap0 :: proc (use ttf: ^TrueTypeFont) {
+ttf_read_cmap0 :: (use ttf: ^TrueTypeFont) {
cmap : TTCmap;
cmap.cmap0.format = TTCmapFormat.Simple;
array.push(^char_maps, cmap);
}
-ttf_read_cmap4 :: proc (use ttf: ^TrueTypeFont) {
+ttf_read_cmap4 :: (use ttf: ^TrueTypeFont) {
cmap : TTCmap;
cmap.cmap4.format = TTCmapFormat.Segmented;
imap := ^cmap.cmap4;
array.push(^char_maps, cmap);
}
-ttf_lookup_glyph_by_char :: proc (use ttf: ^TrueTypeFont, charcode: u32) -> u32 {
+ttf_lookup_glyph_by_char :: (use ttf: ^TrueTypeFont, charcode: u32) -> u32 {
potential_code := 0;
for ^cmap: char_maps {
}
#private_file
-ttf_lookup_in_cmap0 :: proc (use ttf: ^TrueTypeFont, cmap: ^TTCmap0, charcode: u32) -> u32 {
+ttf_lookup_in_cmap0 :: (use ttf: ^TrueTypeFont, cmap: ^TTCmap0, charcode: u32) -> u32 {
if charcode < 0 || charcode >= 256 do return 0;
return ~~cmap.glyph_indicies[charcode];
}
#private_file
-ttf_lookup_in_cmap4 :: proc (use ttf: ^TrueTypeFont, cmap: ^TTCmap4, charcode: u32) -> u32 {
+ttf_lookup_in_cmap4 :: (use ttf: ^TrueTypeFont, cmap: ^TTCmap4, charcode: u32) -> u32 {
if map.has(^cmap.cache, charcode) do return map.get(^cmap.cache, charcode);
index := 0;
return index;
}
-ttf_read_hhea_table :: proc (use ttf: ^TrueTypeFont) {
+ttf_read_hhea_table :: (use ttf: ^TrueTypeFont) {
hhea_table_info := map.get(^table_map, string_to_beu32("hhea"));
seek(^reader, hhea_table_info.offset);
left_side_bearing : i16;
}
-ttf_lookup_horizontal_metrics :: proc (use ttf: ^TrueTypeFont, glyph_index: u32) -> TTHorizontalMetrics {
+ttf_lookup_horizontal_metrics :: (use ttf: ^TrueTypeFont, glyph_index: u32) -> TTHorizontalMetrics {
hmtx_table_info := map.get(^table_map, string_to_beu32("hmtx"));
offset := hmtx_table_info.offset;
// Renders a grayscale image
// To be used with gl.LUMANIANCE
-ttf_render_glyph :: proc (use ttf: ^TrueTypeFont, glyph: ^TTGlyph, data: ^u8, width: u32, height: u32) {
+ttf_render_glyph :: (use ttf: ^TrueTypeFont, glyph: ^TTGlyph, data: ^u8, width: u32, height: u32) {
// Black background
for y: 0 .. height do for x: 0 .. width do data[x + y * width] = cast(u8) 255;
}
#private_file
-draw_line :: proc (data: ^u8, width: u32, height: u32, scale: f32, x0: u32, y0: u32, x1: u32, y1: u32) {
+draw_line :: (data: ^u8, width: u32, height: u32, scale: f32, x0: u32, y0: u32, x1: u32, y1: u32) {
start := V2i.{ x0, y0 };
end := V2i.{ x1, y1 };
dist := sqrt_f32(~~v2_square_dist(start, end));
}
#private_file
-draw_quadratic_line :: proc (data: ^u8, width: u32, height: u32, scale: f32, x0: u32, y0: u32, x1: u32, y1: u32, x2: u32, y2: u32) {
+draw_quadratic_line :: (data: ^u8, width: u32, height: u32, scale: f32, x0: u32, y0: u32, x1: u32, y1: u32, x2: u32, y2: u32) {
// draw_line(data, width, height, scale, x0, y0, x1, y1);
// draw_line(data, width, height, scale, x1, y1, x2, y2);
}
#private_file
-ttf_calc_table_checksum :: proc (reader: ^BinaryReader, offset: u32, length: u32) -> u32 {
+ttf_calc_table_checksum :: (reader: ^BinaryReader, offset: u32, length: u32) -> u32 {
old := seek(reader, offset);
defer seek(reader, old);
}
#private_file
-string_to_beu32 :: proc (s: str) -> u32 {
+string_to_beu32 :: (s: str) -> u32 {
return (cast(u32) s[0] << 24)
| (cast(u32) s[1] << 16)
| (cast(u32) s[2] << 8)
h : f32 = 0.0f;
}
-create :: proc (tex: ^texture.Texture) -> Atlas {
+create :: (tex: ^texture.Texture) -> Atlas {
atlas : Atlas;
atlas.texture = tex;
map.init(^atlas.texmap, AtlasSprite.{});
return atlas;
}
-map :: proc (use atlas: ^Atlas, id: i32, sprite: AtlasSprite) {
+map :: (use atlas: ^Atlas, id: i32, sprite: AtlasSprite) {
map.put(^texmap, id, sprite);
}
-lookup :: proc (use atlas: ^Atlas, id: i32, offset := 0) -> AtlasSprite {
+lookup :: (use atlas: ^Atlas, id: i32, offset := 0) -> AtlasSprite {
sprite := map.get(^texmap, id);
if offset != 0 {
return sprite;
}
-apply_to_quad :: proc (use atlas: ^Atlas, id: i32, quad: ^Quad) {
+apply_to_quad :: (use atlas: ^Atlas, id: i32, quad: ^Quad) {
sprite := map.get(^texmap, id);
quad.tex_size.x = sprite.w / ~~texture.width;
quad.tex_size.y = sprite.h / ~~texture.height;
chars := "0123456789!\"#$% ABCDEFGHIJKLMNOPQRSTUVWXYZ'()*+,abcdefghijklmnopqrstuvwxyz,-./\\,^:;<=>?[]~|_";
#private_file
-char_to_tex_offset :: proc (ch: u8) -> u32 {
+char_to_tex_offset :: (ch: u8) -> u32 {
loc := 0;
for c: chars {
if c == ch do break;
return loc;
}
-draw_text :: proc (renderer: ^RenderContext, s: str, pos: V2f, scale := 1.0f) {
+draw_text :: (renderer: ^RenderContext, s: str, pos: V2f, scale := 1.0f) {
x := pos.x;
y := pos.y;
color : Color4f32 = Color4f32.{ 0f, 0f, 0f, 0f };
}
-init :: proc (use qr: ^QuadRenderer, initial_quads := 10) #export "QUAD_INIT" {
+init :: (use qr: ^QuadRenderer, initial_quads := 10) {
vertexArray = gl.createVertexArray();
gl.bindVertexArray(vertexArray);
update_world(qr);
}
-draw :: proc (use qr: ^QuadRenderer, count := -1) {
+draw :: (use qr: ^QuadRenderer, count := -1) {
c := count;
if count == -1 do c = quad_data.count;
gl.bindVertexArray(-1);
}
-update_view :: proc (use qr: ^QuadRenderer) {
+update_view :: (use qr: ^QuadRenderer) {
proj_mat : [4 * 4] gl.GLfloat;
for ^it: proj_mat do *it = 0.0f;
gl.uniformMatrix4(u_proj_loc, true, proj_mat);
}
-update_world :: proc (use qr: ^QuadRenderer,
- scale_x := 1.0f, scale_y := 1.0f, trans_x := 0.0f, trans_y := 0.0f) {
+update_world :: (use qr: ^QuadRenderer, scale_x := 1.0f, scale_y := 1.0f, trans_x := 0.0f, trans_y := 0.0f) {
world_mat : [4 * 4] gl.GLfloat;
for ^it: world_mat do *it = 0.0f;
gl.uniformMatrix4(u_world_loc, false, world_mat);
}
-update_at_index :: proc (use qr: ^QuadRenderer, idx: i32, quad: Quad) {
+update_at_index :: (use qr: ^QuadRenderer, idx: i32, quad: Quad) {
quad_data[idx] = quad;
is_data_dirty = true;
}
-rebuffer_data :: proc (use qr: ^QuadRenderer) {
+rebuffer_data :: (use qr: ^QuadRenderer) {
if !is_data_dirty do return;
gl.bindBuffer(gl.ARRAY_BUFFER, quadBuffer);
smile : Texture;
}
-init :: proc () {
+init :: () {
textures.tilemap = create(#file_contents "res/tilemap.data", 256, 256);
textures.smile = create(#file_contents "res/smile.data", 32, 32);
}
// NOTE: This assumes that the data is raw u8 RGB packed color data.
-create :: proc (texdata: [] u8, width: i32, height: i32, data_mode := TextureDataMode.RGB) -> Texture {
+create :: (texdata: [] u8, width: i32, height: i32, data_mode := TextureDataMode.RGB) -> Texture {
tex : Texture;
tex.data = texdata;
tex.width = width;
return tex;
}
-prepare :: proc (use tex: ^Texture) {
+prepare :: (use tex: ^Texture) {
if texture_id != -1 do return;
format := gl.RGB;
gl.bindTexture(gl.TEXTURE_2D, -1);
}
-use_texture :: proc (use tex: ^Texture) {
+use_texture :: (use tex: ^Texture) {
gl.bindTexture(gl.TEXTURE_2D, texture_id);
}
};
}
-init :: proc (use state: ^InputState) {
+init :: (use state: ^InputState) {
for ^key: keys_down do *key = false;
for ^key: keys_just_down do *key = false;
for ^button: mouse.buttons_down do *button = false;
mouse.wheel_downs = 0;
}
-process_event :: proc (use state: ^InputState, ev: ^event.Event) {
+process_event :: (use state: ^InputState, ev: ^event.Event) {
use event.DomEventKind;
switch ev.kind {
}
}
-preupdate :: proc (use state: ^InputState) ---
+preupdate :: (use state: ^InputState) ---
-postupdate :: proc (use state: ^InputState) {
+postupdate :: (use state: ^InputState) {
for ^key: keys_just_down do *key = false;
for ^button: mouse.buttons_just_down do *button = false;
-key_down :: proc (use state: ^InputState, key: Key) -> bool {
+key_down :: (use state: ^InputState, key: Key) -> bool {
return keys_down[cast(u32) key];
}
-key_just_down :: proc (use state: ^InputState, key: Key) -> bool {
+key_just_down :: (use state: ^InputState, key: Key) -> bool {
return keys_just_down[cast(u32) key];
}
-key_up :: proc (use state: ^InputState, key: Key) -> bool {
+key_up :: (use state: ^InputState, key: Key) -> bool {
return !keys_down[cast(u32) key];
}
color: Color4f32 = Color4f32.{ 1.0f, 1.0f, 1.0f, 1.0f };
}
-render_context_init :: proc (use rc: ^RenderContext, qr: ^QuadRenderer = null) {
+render_context_init :: (use rc: ^RenderContext, qr: ^QuadRenderer = null) {
aqr := qr;
if aqr == null {
};
}
-draw_rect :: proc (use rc: ^RenderContext, x: f32, y: f32, w: f32, h: f32) {
+draw_rect :: (use rc: ^RenderContext, x: f32, y: f32, w: f32, h: f32) {
if curr_quad_idx >= max_quad_idx do return;
quad_renderer.update_at_index(quads, curr_quad_idx, Quad.{
curr_quad_idx += 1;
}
-draw_textured_rect :: proc (use rc: ^RenderContext, x: f32, y: f32, w: f32, h: f32, tx: f32, ty: f32, tw: f32, th: f32) {
+draw_textured_rect :: (use rc: ^RenderContext, x: f32, y: f32, w: f32, h: f32, tx: f32, ty: f32, tw: f32, th: f32) {
if curr_quad_idx >= max_quad_idx do return;
quad_renderer.update_at_index(quads, curr_quad_idx, Quad.{
curr_quad_idx += 1;
}
-draw_quad :: proc (use rc: ^RenderContext, quad: ^Quad) {
+draw_quad :: (use rc: ^RenderContext, quad: ^Quad) {
if curr_quad_idx >= max_quad_idx do return;
quad_renderer.update_at_index(quads, curr_quad_idx, *quad);
curr_quad_idx += 1;
}
-render_context_ui :: proc (use rc: ^RenderContext) {
+render_context_ui :: (use rc: ^RenderContext) {
quad_renderer.update_world(quads, 1.0f, 1.0f, ~~-half_window_width, ~~-half_window_height);
quad_renderer.rebuffer_data(quads);
quad_renderer.draw(quads, curr_quad_idx);
curr_quad_idx = 0;
}
-render_context_transformation :: proc (use rc: ^RenderContext) {
+render_context_transformation :: (use rc: ^RenderContext) {
quad_renderer.update_world(quads, scale, scale, trans_x, trans_y);
quad_renderer.rebuffer_data(quads);
quad_renderer.draw(quads, curr_quad_idx);
-poll_events :: proc () {
+poll_events :: () {
use event.DomEventKind;
ev : event.Event;
quad_scratch_buffer : [512 * 1024] u8;
simulating := true;
-update :: proc (dt: f32) {
+update :: (dt: f32) {
input.preupdate(^input_state);
defer input.postupdate(^input_state);
poll_events();
}
-draw :: proc () {
+draw :: () {
gl.clearColor(0.1f, 0.1f, 0.1f, 1.0f);
gl.clear(gl.COLOR_BUFFER_BIT);
}
-debugger :: proc () #foreign "dummy" "breakable" ---
+debugger :: () -> void #foreign "dummy" "breakable" ---
// This procedure is called asynchronously from JS every frame.
// @CLEANUP: Add local persistent variables so this can go in the loop() body.
last_time := 0;
-loop :: proc () #export {
- time_now :: proc () -> u32 #foreign "time" "now" ---;
+loop :: () -> void #export {
+ time_now :: () -> u32 #foreign "time" "now" ---;
curr_time := time_now();
if last_time == 0 do last_time = curr_time;
draw();
}
-main :: proc (args: [] cstr) {
+main :: (args: [] cstr) {
println("Setting up WebGL2 canvas...");
- time_now :: proc () -> u32 #foreign "time" "now" ---;
+ time_now :: () -> u32 #foreign "time" "now" ---;
random.set_seed(time_now());
if !gl.init("gamecanvas") {
tilemap_init(^tilemap, 250, 140);
- game_launch :: proc () #foreign "game" "launch" ---;
+ game_launch :: () -> void #foreign "game" "launch" ---;
game_launch();
}
couldnt_move_count : u16 = 0;
}
-dude_create_random :: proc () -> Dude {
+dude_create_random :: () -> Dude {
return Dude.{
entity = Entity.{
pos = V2f.{ random.float(0.0f, 1200.0f), random.float(0.0f, 1200.0f) },
};
}
-dude_update :: proc (use dude: ^Dude, dt: f32, other_dudes: ^QuadTree(Dude, $_)) {
+dude_update :: (use dude: ^Dude, dt: f32, other_dudes: ^QuadTree(Dude, $_)) {
if random.between(0, 100) < 1 || couldnt_move_count >= 2 {
vel.x = random.float(-300.0f, 300.0f);
vel.y = random.float(-300.0f, 300.0f);
}
}
-dude_try_move :: proc (use dude: ^Dude, dt: f32, other_dudes: ^QuadTree(Dude, $_)) {
+dude_try_move :: (use dude: ^Dude, dt: f32, other_dudes: ^QuadTree(Dude, $_)) {
old_pos := pos;
potential_dudes := array.make(#type ^Dude);
pos.y -= vel.y * dt;
}
-dude_get_aabb :: proc (use dude: ^Dude) -> AABB {
+dude_get_aabb :: (use dude: ^Dude) -> AABB {
return AABB.{ x = pos.x - size, y = pos.y - size, w = size * 2.0f, h = size * 2.0f };
}
b : u8 = 255;
}
-tilemap_init :: proc (use tm: ^Tilemap, w := 10, h := 10) {
+tilemap_init :: (use tm: ^Tilemap, w := 10, h := 10) {
width = w;
height = h;
memory.alloc_slice(^tiles, width * height);
for ^t: tiles do *t = Tile.{};
}
-tilemap_free :: proc (use tm: ^Tilemap) {
+tilemap_free :: (use tm: ^Tilemap) {
cfree(tiles.data);
width = 0;
height = 0;
}
-tilemap_draw :: proc (use tm: ^Tilemap, renderer: ^RenderContext) {
+tilemap_draw :: (use tm: ^Tilemap, renderer: ^RenderContext) {
x_pos := origin.x;
y_pos := origin.y;
}
}
-tilemap_get_tile :: proc (use tm: ^Tilemap, x: u32, y: u32) -> Tile {
+tilemap_get_tile :: (use tm: ^Tilemap, x: u32, y: u32) -> Tile {
if x < 0 || y < 0 || x >= width || y >= height do return Tile.{};
return tiles[x + y * width];
}
-tilemap_screen_coord_to_tile :: proc (use tm: ^Tilemap, pos: V2f) -> ^Tile {
+tilemap_screen_coord_to_tile :: (use tm: ^Tilemap, pos: V2f) -> ^Tile {
n := v2_sub(pos, origin);
tx := cast(i32) (n.x / ~~TILE_SIZE);
ty := cast(i32) (n.y / ~~TILE_SIZE);
return ^tiles[tx + ty * width];
}
-tile_to_color4f32 :: proc (t: Tile) -> Color4f32 {
+tile_to_color4f32 :: (t: Tile) -> Color4f32 {
return Color4f32.{
r = ~~cast(u32) t.r / 255.0f,
g = ~~cast(u32) t.g / 255.0f,
se: ^QuadTree(T, Points_Per_Quad) = null;
}
-quadtree_init :: proc (qt: ^QuadTree($T, $_), initial_region: AABB) {
+quadtree_init :: (qt: ^QuadTree($T, $_), initial_region: AABB) {
qt.region = initial_region;
qt.nw = null;
qt.ne = null;
for ^p: qt.points do *p = null;
}
-quadtree_free :: proc (qt: ^QuadTree($T, $_), initial := true) {
+quadtree_free :: (qt: ^QuadTree($T, $_), initial := true) {
if qt.nw != null {
quadtree_free(qt.nw, false);
quadtree_free(qt.ne, false);
}
}
-quadtree_subdivide :: proc (use qt: ^QuadTree($T, $Points_Per_Quad), a: Allocator) {
+quadtree_subdivide :: (use qt: ^QuadTree($T, $Points_Per_Quad), a: Allocator) {
if nw != null do return;
hw := region.w / ~~ 2;
quadtree_init(qt.se, AABB.{ region.x + hw, region.y + hh, hw, hh });
}
-quadtree_insert :: proc (use qt: ^QuadTree($T, $Points_Per_Quad), t: ^T, alloc := context.allocator) -> bool {
+quadtree_insert :: (use qt: ^QuadTree($T, $Points_Per_Quad), t: ^T, alloc := context.allocator) -> bool {
pos: V2f = t.pos; // T is expected to have a 'pos' element.
if !aabb_contains(region, pos) do return false;
return false;
}
-quadtree_query :: proc (use qt: ^QuadTree($T, $_), r: AABB, p: ^[..] ^T) {
+quadtree_query :: (use qt: ^QuadTree($T, $_), r: AABB, p: ^[..] ^T) {
if !aabb_intersects(region, r) do return;
// while i := 0; i < points_count {
use package core.string { make as string_make }
use package gl as gl
-compile_shader :: proc (shader_type: gl.GLenum, source: str) -> gl.GLShader {
+compile_shader :: (shader_type: gl.GLenum, source: str) -> gl.GLShader {
shader := gl.createShader(shader_type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
return shader;
}
-link_program :: proc (vertex_shader: gl.GLShader, frag_shader: gl.GLShader) -> gl.GLProgram {
+link_program :: (vertex_shader: gl.GLShader, frag_shader: gl.GLShader) -> gl.GLProgram {
program := gl.createProgram();
gl.attachShader(program, vertex_shader);
gl.attachShader(program, frag_shader);
V2f :: #type V2(f32);
V2i :: #type V2(i32);
-v2_add :: proc (a: V2($T), b: V2(T)) -> V2(T) {
+v2_add :: (a: V2($T), b: V2(T)) -> V2(T) {
ret : V2(T);
ret.x = a.x + b.x;
ret.y = a.y + b.y;
return ret;
}
-v2_sub :: proc (a: V2($T), b: V2(T)) -> V2(T) {
+v2_sub :: (a: V2($T), b: V2(T)) -> V2(T) {
ret : V2(T);
ret.x = a.x - b.x;
ret.y = a.y - b.y;
return ret;
}
-v2_mul :: proc (a: V2($T), scalar: T) -> V2(T) {
+v2_mul :: (a: V2($T), scalar: T) -> V2(T) {
ret : V2(T);
ret.x = a.x * scalar;
ret.y = a.y * scalar;
return ret;
}
-v2_lerp :: proc (t: f32, start: V2($T), end: V2(T)) -> V2(T) {
+v2_lerp :: (t: f32, start: V2($T), end: V2(T)) -> V2(T) {
ret : V2(T);
ret.x = ~~(t * ~~(end.x - start.x)) + start.x;
ret.y = ~~(t * ~~(end.y - start.y)) + start.y;
return ret;
}
-v2_square_dist :: proc (a: V2($T), b: V2(T)) -> T {
+v2_square_dist :: (a: V2($T), b: V2(T)) -> T {
return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}
-v2_equal :: proc (a: V2($T), b: V2(T)) -> bool {
+v2_equal :: (a: V2($T), b: V2(T)) -> bool {
return a.x == b.x && a.y == b.y;
}
// -1 for counter-clockwise
// 0 for colinear
// 1 for clockwise
-v2_orientation :: proc (a: V2($T), b: V2(T), c: V2(T)) -> i32 {
+v2_orientation :: (a: V2($T), b: V2(T), c: V2(T)) -> i32 {
val := (b.y - a.y) * (c.x - b.x) - (b.x - a.x) * (c.y - b.y);
if val == ~~0 do return 0;
if val > ~~0 do return 1;
}
// assumes a b and c are colinear
-v2_on_segment :: proc (a: V2($T), b: V2(T), c: V2(T)) -> bool {
+v2_on_segment :: (a: V2($T), b: V2(T), c: V2(T)) -> bool {
return b.x <= math.max(a.x, c.x)
&& b.x >= math.min(a.x, c.x)
&& b.y <= math.max(a.y, c.y)
}
-lines_intersect :: proc (p1: V2($T), q1: V2(T), p2: V2(T), q2: V2(T)) -> bool {
+lines_intersect :: (p1: V2($T), q1: V2(T), p2: V2(T), q2: V2(T)) -> bool {
o1 := v2_orientation(p1, q1, p2);
o2 := v2_orientation(p1, q1, q2);
o3 := v2_orientation(p2, q2, p1);
return false;
}
-is_inside_polygon :: proc (polygon: [] V2($T), p: V2(T)) -> bool {
+is_inside_polygon :: (polygon: [] V2($T), p: V2(T)) -> bool {
if polygon.count < 3 do return false;
extreme : V2(T);
-print_vec :: proc (v: V2($T)) {
+print_vec :: (v: V2($T)) {
print("V2(");
print(v.x);
print(", ");