]> git.localhorst.tv Git - orbi.git/blob - src/app/Application.cpp
orientation for entities
[orbi.git] / src / app / Application.cpp
1 #include "Application.h"
2
3 #include "../graphics/Canvas.h"
4 #include "../graphics/Color.h"
5 #include "../world/Character.h"
6 #include "../world/Entity.h"
7 #include "../world/Tileset.h"
8 #include "../world/World.h"
9
10
11 namespace orbi {
12
13 Application::Application(Canvas &c, World &w, Tileset &t)
14 : canvas(c)
15 , world(w)
16 , tiles(t)
17 , ctrl()
18 , focus(5, 5)
19 , target(focus, 2)
20 , cam(c.Size(), focus)
21 , last(SDL_GetTicks())
22 , running(false)
23 , paused(false) {
24         cam.SetScale(tiles.TileSize());
25 }
26
27
28 void Application::Control(Entity &e) {
29         ctrl.Control(e);
30 }
31
32 void Application::Relinquish() {
33         ctrl.Relinquish();
34 }
35
36
37 void Application::Run() {
38         running = true;
39         while (running) {
40                 Uint32 now = SDL_GetTicks();
41                 int delta = now - last;
42                 Loop(delta);
43                 last = now;
44         }
45 }
46
47
48 void Application::Loop(int delta) {
49         HandleEvents();
50
51         if (delta == 0) {
52                 SDL_Delay(1);
53                 return;
54         } else if (delta > 30) {
55                 delta = 30;
56         }
57
58         if (!paused) {
59                 Update(delta);
60         }
61
62         Render();
63
64         canvas.Present();
65
66 }
67
68
69 void Application::HandleEvents() {
70         SDL_Event event;
71         while (SDL_PollEvent(&event)) {
72                 switch (event.type) {
73                         case SDL_QUIT:
74                                 running = false;
75                                 break;
76                         case SDL_WINDOWEVENT:
77                                 if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
78                                         cam.Resize(event.window.data1, event.window.data2);
79                                 }
80                                 break;
81                         case SDL_KEYDOWN:
82                                 if (!event.key.repeat) {
83                                         OnKeyDown(event.key);
84                                 }
85                                 break;
86                         case SDL_KEYUP:
87                                 if (!event.key.repeat) {
88                                         OnKeyUp(event.key);
89                                 }
90                                 break;
91                         default:
92                                 // skip event
93                                 break;
94                 }
95         }
96 }
97
98 void Application::OnKeyDown(const SDL_KeyboardEvent &e) {
99         switch (e.keysym.sym) {
100                 case SDLK_w:
101                         target.MoveUp();
102                         break;
103                 case SDLK_s:
104                         target.MoveDown();
105                         break;
106                 case SDLK_a:
107                         ctrl.MoveLeft();
108                         target.MoveLeft();
109                         break;
110                 case SDLK_d:
111                         ctrl.MoveRight();
112                         target.MoveRight();
113                         break;
114                 case SDLK_SPACE:
115                         ctrl.StartJump();
116                         break;
117                 case SDLK_p:
118                         paused = !paused;
119                         break;
120                 default:
121                         break;
122         }
123 }
124
125 void Application::OnKeyUp(const SDL_KeyboardEvent &e) {
126         switch (e.keysym.sym) {
127                 case SDLK_w:
128                         target.StopUp();
129                         break;
130                 case SDLK_s:
131                         target.StopDown();
132                         break;
133                 case SDLK_a:
134                         ctrl.StopLeft();
135                         target.StopLeft();
136                         break;
137                 case SDLK_d:
138                         ctrl.StopRight();
139                         target.StopRight();
140                         break;
141                 case SDLK_SPACE:
142                         ctrl.StopJump();
143                         break;
144                 default:
145                         break;
146         }
147 }
148
149
150 void Application::Update(int dt) {
151         const float delta = dt / 1e3;
152         for (int i = 0; i < dt; ++i) {
153                 ctrl.Update(1e-3);
154                 world.Update(1e-3);
155         }
156         target.Update(delta);
157         focus = ctrl.Controlling()
158                 ? ctrl.Controlled().vbox.Center()
159                 : target.Pos();
160         cam.Update(delta);
161
162         // testing arm rotation
163         //dynamic_cast<Character *>(*world.Entities().begin())->armAngle -= 3 * delta;
164 }
165
166
167 void Application::Render() {
168         RenderBackground();
169         RenderWorld();
170         RenderEntities();
171         RenderUI();
172 }
173
174 void Application::RenderBackground() {
175         constexpr Color background(0x00, 0x00, 0x00);
176         constexpr Color outlineColor(0x00, 0x00, 0xFA);
177
178         canvas.SetColor(background);
179         canvas.Fill();
180
181         canvas.SetColor(outlineColor);
182         canvas.Grid(cam.ToScreen(Vector<int>(0, 0)), cam.ToScale(world.Size()), cam.ToScale(world.TileSize()));
183 }
184
185 void Application::RenderWorld() {
186         const Vector<int> begin(0, 0);
187         const Vector<int> end(world.Size());
188
189         for (Vector<int> pos(begin); pos.y < end.y; ++pos.y) {
190                 for (pos.x = 0; pos.x < end.x; ++pos.x) {
191                         tiles.DrawFG(canvas, cam.ToScreen(pos), world, pos);
192                 }
193         }
194 }
195
196 void Application::RenderEntities() {
197         constexpr Color boundsColor(0xFA, 0x00, 0x00);
198         constexpr Color vboxColor(0xFA, 0xFA, 0x00);
199         constexpr Color hboxColor(0x00, 0xFA, 0x00);
200         constexpr Color dotColor(0x00, 0xFA, 0xFA);
201
202         for (const Entity *e : world.Entities()) {
203                 canvas.SetColor(boundsColor);
204                 canvas.OutlineRect(
205                         cam.ToScreen(e->bounds.LeftTop()),
206                         cam.ToScale(e->bounds.Size())
207                 );
208                 if (const Character *c = dynamic_cast<const Character *>(e)) {
209                         if (c->orient == Entity::LOOKS_LEFT) {
210                                 canvas.OutlineRectRot(
211                                         Rect<float>(
212                                                 cam.ToScreen(c->bounds.LeftTop() + c->arm.LeftTop()),
213                                                 cam.ToScale(c->arm.Size())
214                                         ),
215                                         cam.ToScreen(c->bounds.LeftTop() + c->armOrigin),
216                                         c->armAngle
217                                 );
218                                 //canvas.SetColor(dotColor);
219                                 //canvas.Cross(cam.ToScreen(c->bounds.LeftTop() + c->armOrigin), 5);
220                         } else {
221                                 canvas.OutlineRectRot(
222                                         Rect<float>(
223                                                 cam.ToScreen(c->bounds.RightTop() + MirrorY(c->arm.RightTop())),
224                                                 cam.ToScale(c->arm.Size())
225                                         ),
226                                         cam.ToScreen(c->bounds.RightTop() + MirrorY(c->armOrigin)),
227                                         -c->armAngle
228                                 );
229                                 //canvas.SetColor(dotColor);
230                                 //canvas.Cross(cam.ToScreen(c->bounds.RightTop() + MirrorY(c->armOrigin)), 5);
231                         }
232                 }
233                 canvas.SetColor(vboxColor);
234                 canvas.OutlineRect(
235                         cam.ToScreen(e->vbox.LeftTop()),
236                         cam.ToScale(e->vbox.Size())
237                 );
238                 canvas.SetColor(hboxColor);
239                 canvas.OutlineRect(
240                         cam.ToScreen(e->hbox.LeftTop()),
241                         cam.ToScale(e->hbox.Size())
242                 );
243         }
244 }
245
246 void Application::RenderUI() {
247         constexpr Color targetColor(0xFA, 0xFA, 0x00);
248
249         canvas.SetColor(targetColor);
250         canvas.Cross(cam.ToScreen(target.Pos()), 15);
251 }
252
253 }