]> git.localhorst.tv Git - blank.git/blob - src/app.cpp
introduce space and shift for up and down :)
[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 , move_velocity(0.003f)
20 , pitch_sensitivity(-0.0025f)
21 , yaw_sensitivity(-0.001f)
22 , cam()
23 , world()
24 , outline()
25 , outline_visible(false)
26 , outline_transform(1.0f)
27 , running(false)
28 , front(false)
29 , back(false)
30 , left(false)
31 , right(false)
32 , up(false)
33 , down(false)
34 , place(false)
35 , remove(false)
36 , pick(false)
37 , remove_id(0)
38 , place_id(1) {
39         GLContext::EnableVSync();
40
41         GLuint VertexArrayID;
42         glGenVertexArrays(1, &VertexArrayID);
43         glBindVertexArray(VertexArrayID);
44
45         cam.Position(glm::vec3(0, 4, 4));
46
47         world.Generate();
48
49         glClearColor(0.0, 0.0, 0.0, 1.0);
50 }
51
52
53 void Application::Run() {
54         running = true;
55         Uint32 last = SDL_GetTicks();
56         window.GrabMouse();
57         while (running) {
58                 Uint32 now = SDL_GetTicks();
59                 int delta = now - last;
60                 Loop(delta);
61                 last = now;
62         }
63 }
64
65 void Application::Loop(int dt) {
66         HandleEvents();
67         Update(dt);
68         Render();
69 }
70
71
72 void Application::HandleEvents() {
73         SDL_Event event;
74         while (SDL_PollEvent(&event)) {
75                 switch (event.type) {
76                         case SDL_KEYDOWN:
77                         case SDL_KEYUP:
78                                 switch (event.key.keysym.sym) {
79                                         case SDLK_w:
80                                                 front = event.key.state == SDL_PRESSED;
81                                                 break;
82                                         case SDLK_s:
83                                                 back = event.key.state == SDL_PRESSED;
84                                                 break;
85                                         case SDLK_a:
86                                                 left = event.key.state == SDL_PRESSED;
87                                                 break;
88                                         case SDLK_d:
89                                                 right = event.key.state == SDL_PRESSED;
90                                                 break;
91                                         case SDLK_q:
92                                         case SDLK_SPACE:
93                                                 up = event.key.state == SDL_PRESSED;
94                                                 break;
95                                         case SDLK_e:
96                                         case SDLK_LSHIFT:
97                                                 down = event.key.state == SDL_PRESSED;
98                                                 break;
99                                 }
100                                 break;
101                         case SDL_MOUSEBUTTONDOWN:
102                                 if (event.button.button == 1) {
103                                         // left
104                                         remove = true;
105                                 } else if (event.button.button == 2) {
106                                         // middle
107                                         pick = true;
108                                 } else if (event.button.button == 3) {
109                                         // right
110                                         place = true;
111                                 }
112                                 break;
113                         case SDL_MOUSEMOTION:
114                                 cam.RotateYaw(event.motion.xrel * yaw_sensitivity);
115                                 cam.RotatePitch(event.motion.yrel * pitch_sensitivity);
116                                 break;
117                         case SDL_QUIT:
118                                 running = false;
119                                 break;
120                         case SDL_WINDOWEVENT:
121                                 switch (event.window.event) {
122                                         case SDL_WINDOWEVENT_RESIZED:
123                                                 cam.Viewport(event.window.data1, event.window.data2);
124                                                 break;
125                                         default:
126                                                 break;
127                                 }
128                                 break;
129                         default:
130                                 break;
131                 }
132         }
133 }
134
135 void Application::Update(int dt) {
136         glm::vec3 vel;
137         if (right && !left) {
138                 vel.x = move_velocity;
139         } else if (left && !right) {
140                 vel.x = -move_velocity;
141         }
142         if (up && !down) {
143                 vel.y = move_velocity;
144         } else if (down && !up) {
145                 vel.y = -move_velocity;
146         }
147         if (back && !front) {
148                 vel.z = move_velocity;
149         } else if (front && !back) {
150                 vel.z = -move_velocity;
151         }
152         cam.OrientationVelocity(vel);
153
154         cam.Update(dt);
155
156         Ray aim = cam.Aim();
157         Chunk *chunk;
158         int blkid;
159         float dist;
160         glm::vec3 normal;
161         if (world.Intersection(aim, glm::mat4(1.0f), &chunk, &blkid, &dist, &normal)) {
162                 glm::vec3 pos = Chunk::ToCoords(blkid);
163                 outline_visible = true;
164                 outline.Clear();
165                 chunk->BlockAt(blkid).type->FillOutlineModel(outline);
166                 outline_transform = glm::translate(chunk->Transform(), pos);
167         } else {
168                 outline_visible = false;
169         }
170
171         if (pick) {
172                 if (chunk) {
173                         place_id = chunk->BlockAt(blkid).type->id;
174                 }
175                 pick = false;
176         }
177         if (remove) {
178                 if (chunk) {
179                         chunk->BlockAt(blkid).type = world.BlockTypes()[remove_id];
180                         chunk->Invalidate();
181                 }
182                 remove = false;
183         }
184         if (place) {
185                 if (chunk) {
186                         Chunk *mod_chunk = chunk;
187                         glm::vec3 next_pos = Chunk::ToCoords(blkid) + normal;
188                         if (!Chunk::InBounds(next_pos)) {
189                                 mod_chunk = &world.Next(*chunk, normal);
190                                 next_pos -= normal * Chunk::Extent();
191                         }
192                         mod_chunk->BlockAt(next_pos).type = world.BlockTypes()[place_id];
193                         mod_chunk->Invalidate();
194                 }
195                 place = false;
196         }
197 }
198
199 void Application::Render() {
200         GLContext::Clear();
201
202         program.Activate();
203
204         program.SetVP(cam.View(), cam.Projection());
205
206         for (Chunk &chunk : world.LoadedChunks()) {
207                 program.SetM(chunk.Transform());
208                 chunk.Draw();
209         }
210
211         if (outline_visible) {
212                 program.SetM(outline_transform);
213                 outline.Draw();
214         }
215
216         window.Flip();
217 }
218
219 }