#include "Application.hpp"
#include "Assets.hpp"
+#include "FrameCounter.hpp"
+#include "init.hpp"
+#include "../audio/Sound.hpp"
#include "../graphics/Font.hpp"
#include "../world/BlockType.hpp"
#include "../world/Entity.hpp"
namespace blank {
-Application::Application(const Config &config)
-: init_sdl()
-, init_img()
-, init_ttf()
-, init_gl(config.doublebuf, config.multisampling)
-, window()
-, ctx(window.CreateContext())
-, init_glew()
+Application::Application(Window &win, const Config &config)
+: window(win)
+, viewport()
, assets(get_asset_path())
-, chunk_prog()
-, entity_prog()
-, sprite_prog()
-, cam()
+, audio()
+, counter()
, world(config.world)
-, interface(config.interface, assets, world)
-, test_controller(MakeTestEntity(world))
+, interface(config.interface, assets, audio, counter, world)
+, spawner(world)
, running(false) {
- if (config.vsync) {
- GLContext::EnableVSync();
- }
-
- glClearColor(0.0, 0.0, 0.0, 1.0);
+ viewport.VSync(config.vsync);
}
-Entity &Application::MakeTestEntity(World &world) {
- Entity &e = world.AddEntity();
- e.Name("test");
- e.Position({ 0.0f, 0.0f, 0.0f });
- e.Bounds({ { -0.5f, -0.5f, -0.5f }, { 0.5f, 0.5f, 0.5f } });
- e.WorldCollidable(true);
- e.SetShape(world.BlockTypes()[1].shape, { 1.0f, 1.0f, 0.0f });
- e.AngularVelocity(glm::quat(glm::vec3{ 0.00001f, 0.000006f, 0.000013f }));
- return e;
+Application::~Application() {
+ audio.StopAll();
}
}
void Application::Loop(int dt) {
+ counter.EnterFrame();
HandleEvents();
Update(dt);
Render();
+ counter.ExitFrame();
}
void Application::HandleEvents() {
+ counter.EnterHandle();
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
break;
}
}
+ counter.ExitHandle();
}
void Application::Handle(const SDL_WindowEvent &event) {
window.ReleaseMouse();
break;
case SDL_WINDOWEVENT_RESIZED:
- cam.Viewport(event.data1, event.data2);
- interface.Handle(event);
+ viewport.Resize(event.data1, event.data2);
break;
default:
- interface.Handle(event);
break;
}
}
void Application::Update(int dt) {
+ counter.EnterUpdate();
interface.Update(dt);
- test_controller.Update(dt);
+ spawner.Update(dt);
world.Update(dt);
-}
-void Application::Render() {
- GLContext::Clear();
+ glm::mat4 trans = world.Player().Transform(Chunk::Pos(0, 0, 0));
+ glm::vec3 dir(trans * glm::vec4(0.0f, 0.0f, -1.0f, 0.0f));
+ glm::vec3 up(trans * glm::vec4(0.0f, 1.0f, 0.0f, 0.0f));
+ audio.Position(world.Player().Position());
+ audio.Velocity(world.Player().Velocity());
+ audio.Orientation(dir, up);
- chunk_prog.SetProjection(cam.Projection());
- entity_prog.SetProjection(cam.Projection());
+ counter.ExitUpdate();
+}
- world.Render(chunk_prog, entity_prog);
+void Application::Render() {
+ // gl implementation may (and will probably) delay vsync blocking until
+ // the first write after flipping, which is this clear call
+ viewport.Clear();
+ counter.EnterRender();
- interface.Render(entity_prog, sprite_prog);
+ world.Render(viewport);
+ interface.Render(viewport);
+ counter.ExitRender();
window.Flip();
}
Assets::Assets(const string &base)
-: fonts(base + "fonts/") {
+: fonts(base + "fonts/")
+, sounds(base + "sounds/") {
}
return Font(full.c_str(), size);
}
+Sound Assets::LoadSound(const string &name) const {
+ string full = sounds + name + ".wav";
+ return Sound(full.c_str());
+}
+
+
+void FrameCounter::EnterFrame() noexcept {
+ last_enter = SDL_GetTicks();
+ last_tick = last_enter;
+}
+
+void FrameCounter::EnterHandle() noexcept {
+ Tick();
+}
+
+void FrameCounter::ExitHandle() noexcept {
+ current.handle = Tick();
+}
+
+void FrameCounter::EnterUpdate() noexcept {
+ Tick();
+}
+
+void FrameCounter::ExitUpdate() noexcept {
+ current.update = Tick();
+}
+
+void FrameCounter::EnterRender() noexcept {
+ Tick();
+}
+
+void FrameCounter::ExitRender() noexcept {
+ current.render = Tick();
+}
+
+void FrameCounter::ExitFrame() noexcept {
+ Uint32 now = SDL_GetTicks();
+ current.total = now - last_enter;
+ current.running = current.handle + current.update + current.render;
+ current.waiting = current.total - current.running;
+ Accumulate();
+
+ ++cur_frame;
+ if (cur_frame >= NUM_FRAMES) {
+ Push();
+ cur_frame = 0;
+ changed = true;
+ } else {
+ changed = false;
+ }
+}
+
+int FrameCounter::Tick() noexcept {
+ Uint32 now = SDL_GetTicks();
+ int delta = now - last_tick;
+ last_tick = now;
+ return delta;
+}
+
+void FrameCounter::Accumulate() noexcept {
+ sum.handle += current.handle;
+ sum.update += current.update;
+ sum.render += current.render;
+ sum.running += current.running;
+ sum.waiting += current.waiting;
+ sum.total += current.total;
+
+ max.handle = std::max(current.handle, max.handle);
+ max.update = std::max(current.update, max.update);
+ max.render = std::max(current.render, max.render);
+ max.running = std::max(current.running, max.running);
+ max.waiting = std::max(current.waiting, max.waiting);
+ max.total = std::max(current.total, max.total);
+
+ current = Frame<int>();
+}
+
+void FrameCounter::Push() noexcept {
+ peak = max;
+ avg.handle = sum.handle * factor;
+ avg.update = sum.update * factor;
+ avg.render = sum.render * factor;
+ avg.running = sum.running * factor;
+ avg.waiting = sum.waiting * factor;
+ avg.total = sum.total * factor;
+
+ sum = Frame<int>();
+ max = Frame<int>();
+}
+
}