From e4d2ed3627462da9490b91884b4be48a6def5b2a Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Wed, 24 Nov 2021 22:44:52 -0600 Subject: [PATCH] added asset loader to snake program --- misc/onyx/heartbreak_graphics.onyx | 9 ++-- src/gfx.c | 9 ++++ tests/snake.onyx | 77 ++++++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 8 deletions(-) diff --git a/misc/onyx/heartbreak_graphics.onyx b/misc/onyx/heartbreak_graphics.onyx index f8c97bb..77cac2a 100644 --- a/misc/onyx/heartbreak_graphics.onyx +++ b/misc/onyx/heartbreak_graphics.onyx @@ -3,7 +3,7 @@ package heartbreak.graphics // State setClearColor :: (r, g, b: f32, a: f32 = 1) -> void #foreign "heartbreak" "graphics_set_clear_color" --- -setColor :: (r, g, b: f32, a: f32 = 1) -> void #foreign "heartbreak" "graphics_set_color" --- +setColor :: (r, g, b: f32, a: f32 = 1) -> void #foreign "heartbreak" "graphics_set_color" --- setLineWidth :: (width: i32) -> void #foreign "heartbreak" "graphics_set_line_width" --- // @@ -36,7 +36,8 @@ pop :: () -> void #foreign "heartbreak" "graphics_pop" --- // // Images // -Image :: #type i64 +Image :: #distinct i64 +#operator == macro (a, b: Image) => cast(i64) a == cast(i64) b; newImage :: (path: str) -> Image #foreign "heartbreak" "graphics_image_load" --- drawImage :: (img: Image, x, y: f32, w: f32 = -1, h: f32 = -1) -> void #foreign "heartbreak" "graphics_image_draw" --- @@ -101,7 +102,9 @@ drawQuad :: macro (quad: Quad, x, y: f32, w: f32 = -1, h: f32 = -1) { // // Fonts // -Font :: #type i64 +Font :: #distinct i64 +#operator != macro (a, b: Font) => cast(i64) a != cast(i64) b; +#operator == macro (a, b: Font) => cast(i64) a == cast(i64) b; newFont :: (path: str, size: i32) -> Font #foreign "heartbreak" "graphics_font_load" --- setFont :: (font: Font = 0) -> void #foreign "heartbreak" "graphics_font_set" --- diff --git a/src/gfx.c b/src/gfx.c index fd074b2..f630fae 100644 --- a/src/gfx.c +++ b/src/gfx.c @@ -494,7 +494,14 @@ void gfx_immediate_renderer_shear(ImmediateRenderer *ir, f32 kx, f32 ky) { // Image* gfx_image_load(ImmediateRenderer *ir, const char* filename) { Image* img = malloc(sizeof(Image)); + img->img_data = stbi_load(filename, &img->width, &img->height, &img->channels, 4); + if (img->img_data == NULL) { + free(img); + logprint(ERROR, "Failed to load image '%s'.", filename); + return NULL; + } + img->magic_number = 0xdeadbeefdeadbeef; glGenTextures(1, &img->texture); @@ -528,9 +535,11 @@ void gfx_image_bind(ImmediateRenderer *ir, Image* img, u32 texture_unit) { } void gfx_image_unbind(ImmediateRenderer *ir) { + if (ir->active_image == NULL) return; if (ir->tris_vertex_count > 0) gfx_immediate_renderer_flush(ir); ir->active_image = NULL; + glUseProgram(ir->tris_shader.program); glUniform1f(ir->tris_shader.texture_enabled_uniform, 0); } diff --git a/tests/snake.onyx b/tests/snake.onyx index 7a3d48c..f16e05c 100644 --- a/tests/snake.onyx +++ b/tests/snake.onyx @@ -2,6 +2,55 @@ use package core +assets : struct { + ["./tests/player.png"] + player: hb.graphics.Image; + + ["./assets/fonts/mononoki-Regular Nerd Font Complete Mono.ttf", 72] + title_font: hb.graphics.Font; +} + +load_assets :: (assets: any) { + ptr_asset_info := cast(^type_info.Type_Info_Pointer) type_info.get_type_info(assets.type); + assert(ptr_asset_info.kind == .Pointer, "Loading assets only works for pointers to strucutres."); + asset_info := cast(^type_info.Type_Info_Struct) type_info.get_type_info(ptr_asset_info.to); + assert(asset_info.kind == .Struct, "Loading assets only works for pointers to strucutres."); + + asset_store := cast(^u8) *cast(^rawptr) assets.data; + + for ^asset: asset_info.members { + switch asset.type { + case hb.graphics.Image { + path := *(cast(^str) array.first(asset.tags, (t) => t.type == str).data); + img := hb.graphics.newImage(path); + + if img == 0 { + println("Failed to load image"); + continue; + } + + @TODO // Add settings like scaling, filters, etc. + + *cast(^hb.graphics.Image) (asset_store + asset.offset) = img; + } + + case hb.graphics.Font { + path := *(cast(^str) array.first(asset.tags, (t) => t.type == str).data); + size := *(cast(^i32) array.first(asset.tags, (t) => t.type == i32).data); + + font := hb.graphics.newFont(path, ~~size); + + if font == 0 { + println("Failed to load font"); + continue; + } + + *cast(^hb.graphics.Font) (asset_store + asset.offset) = font; + } + } + } +} + Vec2 :: struct (T: type_expr) { x, y: T; @@ -74,7 +123,7 @@ snake_draw :: (use this: ^Snake, cell_size: f32) { GameState :: enum { MainMenu; Playing; Paused; Lost; } -state := GameState.Playing; +state := GameState.MainMenu; the_snake: Snake; the_food: Vec2i; @@ -82,6 +131,8 @@ the_food: Vec2i; load :: () { hb.window.setTitle("Snake 🐍"); + load_assets(^assets); + the_snake = snake_make(.{ 0, 0 }); the_food = .{ 10, 10 }; } @@ -98,6 +149,13 @@ update :: (dt: f32) { hb.window.setShouldClose(true); } + if state == .MainMenu { + if hb.input.keyIsDown(.Space) { + state = .Playing; + return; + } + } + if state != .Playing do return; #persist last_left_down := false; @@ -142,17 +200,26 @@ draw :: () { ww, wh := hb.window.getDimensions(); + centered_text :: macro (text: str, y: f32) { + width := hb.graphics.getTextWidth(text); + hb.graphics.print(text, (~~ww - width) / 2, y); + } + switch state { case .MainMenu { - title := "Snake!"; - title_width := hb.graphics.getTextWidth(title); - hb.graphics.print(title, (~~ww - title_width) / 2, 100); + hb.graphics.setFont(assets.title_font); + hb.graphics.setColor(0.2, 0.2, 0.2); + centered_text("Snake!", 100); + + hb.graphics.setFont(); + centered_text("Option 1", 200); + centered_text("Option 2", 240); } case .Playing { draw_game(); - #if false { + #if true { hb.graphics.setColor(1, 0, 0); fps_buffer: [20] u8; fps_str := conv.str_format(fps_buffer, "FPS: {}", cast(i32) hb.timer.getFPS()); -- 2.25.1