nbio/game-loop

Code

main.odin ¶
121 linesSource

1/*
2Example game loop integrated with nbio, using Raylib here.
3
4Showcases a simple async asset loader, textures are assigned a default texture at the start.
5When the texture is asked to be loaded it is done so using the event loop.
6*/
7package main
8
9import "core:nbio"
10import "core:log"
11import "core:strings"
12
13import rl "vendor:raylib"
14
15Texture :: struct {
16	path:   cstring,
17	width:  int,
18	height: int,
19	data:   rl.Texture2D,
20}
21
22Texture_Name :: enum {
23	Default,
24	Raylib_Logo,
25}
26
27g_textures := [Texture_Name]Texture{
28	.Default     = {#directory + "/missing.png", 32, 32, {}},
29	.Raylib_Logo = {#directory + "/raylib_logo.png", 256, 256, {}},
30}
31
32main :: proc() {
33	context.logger = log.create_console_logger()
34
35	nbio.acquire_thread_event_loop()
36	defer nbio.release_thread_event_loop()
37
38	rl.InitWindow(800, 600, "nbio")
39	defer rl.CloseWindow()
40
41	load_texture(&g_textures[.Default])
42
43	rl.SetTargetFPS(60)
44
45	for !rl.WindowShouldClose() {
46		// Note that it is probably not good to run your event loop bound by the frame rate.
47		// There is this cool story about GTA5, which does this, and people had to develop a mod
48		// that turned off vsync during loading screens (causing much more fps) which would speed
49		// up the event loop and make the loading screen go by much faster.
50		if err := nbio.tick(timeout=0); err != nil {
51			log.errorf("nbio.tick: %v", err)
52		}
53
54		w, h := f32(rl.GetScreenWidth()), f32(rl.GetScreenHeight())
55
56		{
57			rl.BeginDrawing()
58			defer rl.EndDrawing()
59
60			rl.ClearBackground(rl.RAYWHITE)
61
62			txt := &g_textures[.Raylib_Logo]
63			draw_texture(txt^, {w/2 - f32(txt.width)/2, h/2 - f32(txt.height)/2, f32(txt.width), f32(txt.height)}, rl.WHITE)
64
65			if rl.GuiButton({w/2 - f32(txt.width)/2, h/2 + f32(txt.height)/2, f32(txt.width), 50}, "Load texture") {
66				if rl.IsTextureReady(txt.data) {
67					rl.UnloadTexture(txt.data)
68					txt.data = {}
69				} else {
70					load_texture(txt)
71				}
72			}
73		}
74	}
75}
76
77draw_texture :: proc(txt: Texture, dest: rl.Rectangle, tint: rl.Color) {
78	txt := txt
79	if !rl.IsTextureReady(txt.data) {
80		txt.data = g_textures[.Default].data
81	}
82
83	rl.DrawTexturePro(
84		txt.data,
85		{0, 0, f32(txt.data.width), f32(txt.data.height)},
86		dest,
87		{},
88		0,
89		rl.WHITE,
90	)
91}
92
93load_texture :: proc(txt: ^Texture) {
94	assert(txt.width > 0)
95	assert(txt.height > 0)
96	assert(txt.path != nil)
97	txt.data = g_textures[.Default].data
98
99	nbio.read_entire_file(string(txt.path), txt, on_read)
100
101	on_read :: proc(txt: rawptr, buf: []byte, err: nbio.Read_Entire_File_Error) {
102		txt := (^Texture)(txt)
103		if err.value != nil {
104			log.errorf("load_texture(%q): %v: %v", txt.path, err.operation, err.value)
105			return
106		}
107
108		spath := string(txt.path)
109		i := strings.last_index(spath, ".")
110		assert(i > 0)
111		ext := spath[i:]
112
113		image := rl.LoadImageFromMemory(cstring(raw_data(ext)), raw_data(buf), i32(len(buf)))
114		txt.data = rl.LoadTextureFromImage(image)
115
116		rl.UnloadImage(image)
117		delete(buf)
118
119		log.infof("load_texture: %q loaded", txt.path)
120	}
121}

Assets 2

Declarations Used 30