summaryrefslogtreecommitdiff
path: root/src/main.c
blob: ce0135783f67838c9ef09be8c71cb0f23e3a7386 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include <GLFW/glfw3.h>
#include <threads.h>

#include "voxel.h"
#include "window.h"

World world;
Camera camera;

void sleep(double seconds)
{
	struct timespec req, rem;
	req.tv_sec = seconds;
	req.tv_nsec = 0;

	if (seconds < 0)
		return;

	while (thrd_sleep(&req, &rem) == thrd_error)
		req = rem;
}

/// handles rendering
VOXEL_RESULT render_main(void *)
{
	Renderer renderer;

	if (window_init_gl() != VOXEL_OK)
		return VOXEL_ERROR;

	if (renderer_init(&renderer) != VOXEL_OK)
		return VOXEL_ERROR;

	while (!window_closed()) {
		if (window.resize) {
			glViewport(0, 0, window.width, window.height);
			window.resize = false;
		}

		renderer_start(&renderer, &camera);
		world_render(&world, &renderer);
		renderer_stop(&renderer);

		window_swap();
	}

	renderer_free(&renderer);
	return VOXEL_OK;
}

#define TPS 20

/// handles game logic
VOXEL_RESULT logic_main(void *)
{
	double last_tick, next_tick;
	last_tick = 0;
	next_tick = 0;

	while (!window_closed()) {
		world_update(&world, &camera);

		next_tick = last_tick + (1.0 / TPS);
		sleep(next_tick - last_tick);
		last_tick = next_tick;
	}

	return VOXEL_OK;
}

/// handles user input
VOXEL_RESULT input_main(void *)
{
	double last_tick, next_tick;
	last_tick = 0;
	next_tick = 0;

	while (!window_closed()) {
		window_update();

		if (key_down(GLFW_KEY_ESCAPE)) {
			window.close = true;
			break;
		}

		camera_update(&camera);

		next_tick = last_tick + (1.0 / TPS);
		sleep(next_tick - last_tick);
		last_tick = next_tick;
	}

	return VOXEL_OK;
}

VOXEL_RESULT main(void)
{
	thrd_t render_thread, logic_thread, input_thread;

	if (window_init() != VOXEL_OK)
		return VOXEL_ERROR;

	camera_init(&camera);
	world_init(&world, 0);

	thrd_create(&logic_thread, logic_main, NULL);
	thrd_create(&input_thread, input_main, NULL);
	thrd_create(&render_thread, render_main, NULL);

	thrd_join(logic_thread, NULL);
	thrd_join(input_thread, NULL);
	thrd_join(render_thread, NULL);

	world_free(&world);
	window_close();

	return VOXEL_OK;
}