]> git.localhorst.tv Git - blank.git/blob - src/app.cpp
d8f1e2147ba2589df979be0c7bbdd3402fc4eb57
[blank.git] / src / app.cpp
1 #include "app.hpp"
2
3 #include "geometry.hpp"
4
5 #include <iostream>
6 #include <stdexcept>
7
8
9 namespace blank {
10
11 Application::Application()
12 : init_sdl()
13 , init_img()
14 , init_gl()
15 , window()
16 , ctx(window.CreateContext())
17 , init_glew()
18 , program()
19 , cam()
20 , hud()
21 , world()
22 , controller(world.Player())
23 , outline()
24 , outline_visible(false)
25 , outline_transform(1.0f)
26 , running(false)
27 , place(false)
28 , remove(false)
29 , pick(false)
30 , remove_id(0)
31 , place_id(1) {
32         GLContext::EnableVSync();
33
34         world.Generate({ -4, -4, -4 }, { 5, 5, 5});
35
36         hud.Viewport(960, 600);
37         hud.Display(*world.BlockTypes()[place_id]);
38
39         glClearColor(0.0, 0.0, 0.0, 1.0);
40 }
41
42
43 void Application::Run() {
44         running = true;
45         Uint32 last = SDL_GetTicks();
46         window.GrabMouse();
47         while (running) {
48                 Uint32 now = SDL_GetTicks();
49                 int delta = now - last;
50                 Loop(delta);
51                 last = now;
52         }
53 }
54
55 void Application::Loop(int dt) {
56         HandleEvents();
57         Update(dt);
58         Render();
59 }
60
61
62 void Application::HandleEvents() {
63         SDL_Event event;
64         while (SDL_PollEvent(&event)) {
65                 switch (event.type) {
66                         case SDL_KEYDOWN:
67                         case SDL_KEYUP:
68                                 controller.HandleKeyboard(event.key);
69                                 break;
70                         case SDL_MOUSEBUTTONDOWN:
71                                 if (event.button.button == 1) {
72                                         // left
73                                         remove = true;
74                                 } else if (event.button.button == 2) {
75                                         // middle
76                                         pick = true;
77                                 } else if (event.button.button == 3) {
78                                         // right
79                                         place = true;
80                                 }
81                                 break;
82                         case SDL_MOUSEMOTION:
83                                 controller.HandleMouse(event.motion);
84                                 break;
85                         case SDL_QUIT:
86                                 running = false;
87                                 break;
88                         case SDL_WINDOWEVENT:
89                                 switch (event.window.event) {
90                                         case SDL_WINDOWEVENT_RESIZED:
91                                                 cam.Viewport(event.window.data1, event.window.data2);
92                                                 hud.Viewport(event.window.data1, event.window.data2);
93                                                 break;
94                                         default:
95                                                 break;
96                                 }
97                                 break;
98                         default:
99                                 break;
100                 }
101         }
102 }
103
104 void Application::Update(int dt) {
105         controller.Update(dt);
106         world.Update(dt);
107
108         Ray aim = controller.Aim();
109         Chunk *chunk;
110         int blkid;
111         float dist;
112         glm::vec3 normal;
113         if (world.Intersection(aim, glm::mat4(1.0f), &chunk, &blkid, &dist, &normal)) {
114                 glm::vec3 pos = Chunk::ToCoords(blkid);
115                 outline_visible = true;
116                 outline.Clear();
117                 chunk->Type(chunk->BlockAt(blkid)).FillOutlineModel(outline);
118                 outline_transform = glm::translate(chunk->Transform(world.Player().ChunkCoords()), pos);
119                 outline_transform = glm::scale(outline_transform, glm::vec3(1.0001f));
120         } else {
121                 outline_visible = false;
122         }
123
124         if (pick) {
125                 if (chunk) {
126                         place_id = chunk->BlockAt(blkid).type;
127                         hud.Display(*world.BlockTypes()[place_id]);
128                 }
129                 pick = false;
130         }
131         if (remove) {
132                 if (chunk) {
133                         chunk->BlockAt(blkid).type = remove_id;
134                         chunk->Invalidate();
135                 }
136                 remove = false;
137         }
138         if (place) {
139                 if (chunk) {
140                         Chunk *mod_chunk = chunk;
141                         glm::vec3 next_pos = Chunk::ToCoords(blkid) + normal;
142                         if (!Chunk::InBounds(next_pos)) {
143                                 mod_chunk = &world.Next(*chunk, normal);
144                                 next_pos -= normal * glm::vec3(Chunk::Extent());
145                         }
146                         mod_chunk->BlockAt(next_pos).type = place_id;
147                         mod_chunk->Invalidate();
148                 }
149                 place = false;
150         }
151 }
152
153 void Application::Render() {
154         GLContext::Clear();
155
156         program.Activate();
157
158         program.SetProjection(cam.Projection());
159         world.Render(program);
160
161         if (outline_visible) {
162                 program.SetM(outline_transform);
163                 outline.Draw();
164         }
165
166         hud.Render(program);
167
168         window.Flip();
169 }
170
171 }