mirror of https://github.com/auygun/kaliber.git
Compare commits
6 Commits
67632ff144
...
709029f22c
Author | SHA1 | Date |
---|---|---|
Attila Uygun | 709029f22c | |
Attila Uygun | 8e6589ec67 | |
Attila Uygun | 69a05c00e9 | |
Attila Uygun | d7e444fa81 | |
Attila Uygun | 8a87597911 | |
Attila Uygun | 22d80d6152 |
|
@ -11,11 +11,12 @@ namespace {
|
|||
void PostTaskAndReplyRelay(Location from,
|
||||
Closure task_cb,
|
||||
Closure reply_cb,
|
||||
std::shared_ptr<TaskRunner> destination) {
|
||||
std::shared_ptr<TaskRunner> destination,
|
||||
bool front) {
|
||||
task_cb();
|
||||
|
||||
if (reply_cb)
|
||||
destination->PostTask(from, std::move(reply_cb));
|
||||
destination->PostTask(from, std::move(reply_cb), front);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -36,22 +37,28 @@ std::shared_ptr<TaskRunner> TaskRunner::GetThreadLocalTaskRunner() {
|
|||
return thread_local_task_runner;
|
||||
}
|
||||
|
||||
void TaskRunner::PostTask(Location from, Closure task) {
|
||||
void TaskRunner::PostTask(Location from, Closure task, bool front) {
|
||||
DCHECK(task) << LOCATION(from);
|
||||
|
||||
task_count_.fetch_add(1, std::memory_order_relaxed);
|
||||
std::lock_guard<std::mutex> scoped_lock(lock_);
|
||||
queue_.emplace_back(from, std::move(task));
|
||||
if (front)
|
||||
queue_.emplace_front(from, std::move(task));
|
||||
else
|
||||
queue_.emplace_back(from, std::move(task));
|
||||
}
|
||||
|
||||
void TaskRunner::PostTaskAndReply(Location from, Closure task, Closure reply) {
|
||||
void TaskRunner::PostTaskAndReply(Location from,
|
||||
Closure task,
|
||||
Closure reply,
|
||||
bool front) {
|
||||
DCHECK(task) << LOCATION(from);
|
||||
DCHECK(reply) << LOCATION(from);
|
||||
DCHECK(thread_local_task_runner) << LOCATION(from);
|
||||
|
||||
auto relay = std::bind(PostTaskAndReplyRelay, from, std::move(task),
|
||||
std::move(reply), thread_local_task_runner);
|
||||
PostTask(from, std::move(relay));
|
||||
std::move(reply), thread_local_task_runner, front);
|
||||
PostTask(from, std::move(relay), front);
|
||||
}
|
||||
|
||||
void TaskRunner::CancelTasks() {
|
||||
|
|
|
@ -18,16 +18,15 @@ namespace internal {
|
|||
// one that returns via an output parameter.
|
||||
template <typename ReturnType>
|
||||
void ReturnAsParamAdapter(std::function<ReturnType()> func,
|
||||
ReturnType* result) {
|
||||
std::shared_ptr<ReturnType> result) {
|
||||
*result = func();
|
||||
}
|
||||
|
||||
// Adapts a ReturnType* result to a callblack that expects a ReturnType.
|
||||
template <typename ReturnType>
|
||||
void ReplyAdapter(std::function<void(ReturnType)> callback,
|
||||
ReturnType* result) {
|
||||
std::shared_ptr<ReturnType> result) {
|
||||
callback(std::move(*result));
|
||||
delete result;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -45,21 +44,32 @@ class TaskRunner {
|
|||
static void CreateThreadLocalTaskRunner();
|
||||
static std::shared_ptr<TaskRunner> GetThreadLocalTaskRunner();
|
||||
|
||||
void PostTask(Location from, Closure task);
|
||||
void PostTask(Location from, Closure task, bool front = false);
|
||||
|
||||
void PostTaskAndReply(Location from, Closure task, Closure reply);
|
||||
void PostTaskAndReply(Location from,
|
||||
Closure task,
|
||||
Closure reply,
|
||||
bool front = false);
|
||||
|
||||
template <typename ReturnType>
|
||||
void PostTaskAndReplyWithResult(Location from,
|
||||
std::function<ReturnType()> task,
|
||||
std::function<void(ReturnType)> reply) {
|
||||
auto* result = new ReturnType;
|
||||
std::function<void(ReturnType)> reply,
|
||||
bool front = false) {
|
||||
auto result = std::make_shared<ReturnType>();
|
||||
return PostTaskAndReply(
|
||||
from,
|
||||
std::bind(internal::ReturnAsParamAdapter<ReturnType>, std::move(task),
|
||||
result),
|
||||
std::bind(internal::ReplyAdapter<ReturnType>, std::move(reply),
|
||||
result));
|
||||
std::bind(internal::ReplyAdapter<ReturnType>, std::move(reply), result),
|
||||
front);
|
||||
}
|
||||
|
||||
// Posts a task to delete the given object.
|
||||
template <class T>
|
||||
void Delete(Location from, std::unique_ptr<T> object) {
|
||||
std::shared_ptr<T> owned = std::move(object);
|
||||
PostTask(HERE, [owned]() {});
|
||||
}
|
||||
|
||||
void CancelTasks();
|
||||
|
|
|
@ -40,17 +40,20 @@ void ThreadPool::Shutdown() {
|
|||
threads_.clear();
|
||||
}
|
||||
|
||||
void ThreadPool::PostTask(Location from, Closure task) {
|
||||
void ThreadPool::PostTask(Location from, Closure task, bool front) {
|
||||
DCHECK((!threads_.empty()));
|
||||
|
||||
task_runner_.PostTask(from, std::move(task));
|
||||
task_runner_.PostTask(from, std::move(task), front);
|
||||
semaphore_.release();
|
||||
}
|
||||
|
||||
void ThreadPool::PostTaskAndReply(Location from, Closure task, Closure reply) {
|
||||
void ThreadPool::PostTaskAndReply(Location from,
|
||||
Closure task,
|
||||
Closure reply,
|
||||
bool front) {
|
||||
DCHECK((!threads_.empty()));
|
||||
|
||||
task_runner_.PostTaskAndReply(from, std::move(task), std::move(reply));
|
||||
task_runner_.PostTaskAndReply(from, std::move(task), std::move(reply), front);
|
||||
semaphore_.release();
|
||||
}
|
||||
|
||||
|
|
|
@ -24,16 +24,20 @@ class ThreadPool {
|
|||
|
||||
void Shutdown();
|
||||
|
||||
void PostTask(Location from, Closure task);
|
||||
void PostTask(Location from, Closure task, bool front = false);
|
||||
|
||||
void PostTaskAndReply(Location from, Closure task, Closure reply);
|
||||
void PostTaskAndReply(Location from,
|
||||
Closure task,
|
||||
Closure reply,
|
||||
bool front = false);
|
||||
|
||||
template <typename ReturnType>
|
||||
void PostTaskAndReplyWithResult(Location from,
|
||||
std::function<ReturnType()> task,
|
||||
std::function<void(ReturnType)> reply) {
|
||||
std::function<void(ReturnType)> reply,
|
||||
bool front = false) {
|
||||
task_runner_.PostTaskAndReplyWithResult(from, std::move(task),
|
||||
std::move(reply));
|
||||
std::move(reply), front);
|
||||
semaphore_.release();
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "engine/engine.h"
|
||||
#include "engine/game_factory.h"
|
||||
#include "engine/input_event.h"
|
||||
#include "engine/sound.h"
|
||||
|
||||
DECLARE_GAME_BEGIN
|
||||
DECLARE_GAME(Demo)
|
||||
|
@ -47,16 +46,38 @@ Demo::~Demo() {
|
|||
saved_data_.Save();
|
||||
}
|
||||
|
||||
bool Demo::Initialize() {
|
||||
saved_data_.Load(kSaveFileName);
|
||||
|
||||
Engine::Get().LoadCustomShader("sky_without_nebula",
|
||||
"sky_without_nebula.glsl");
|
||||
Engine::Get().LoadCustomShader("sky", "sky.glsl");
|
||||
|
||||
bool Demo::PreInitialize() {
|
||||
if (!font_.Load("PixelCaps!.ttf"))
|
||||
return false;
|
||||
|
||||
Engine::Get().SetShaderSource("sky_without_nebula",
|
||||
"sky_without_nebula.glsl");
|
||||
Engine::Get().SetShaderSource("sky", "sky.glsl");
|
||||
|
||||
Engine::Get().AsyncLoadSound("music", "Game_2_Main.mp3");
|
||||
Engine::Get().AsyncLoadSound("boss_music", "Game_2_Boss.mp3");
|
||||
|
||||
if (!enemy_.PreInitialize()) {
|
||||
LOG << "Failed to create the enemy.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!player_.PreInitialize()) {
|
||||
LOG << "Failed to create the enemy.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!menu_.PreInitialize()) {
|
||||
LOG << "Failed to create the menu.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Demo::Initialize() {
|
||||
saved_data_.Load(kSaveFileName);
|
||||
|
||||
if (!sky_.Create(false)) {
|
||||
LOG << "Could not create the sky.";
|
||||
return false;
|
||||
|
@ -87,18 +108,10 @@ bool Demo::Initialize() {
|
|||
return false;
|
||||
}
|
||||
|
||||
auto sound = std::make_unique<Sound>();
|
||||
if (!sound->Load("Game_2_Main.mp3", true))
|
||||
return false;
|
||||
|
||||
auto boss_sound = std::make_unique<Sound>();
|
||||
if (!boss_sound->Load("Game_2_Boss.mp3", true))
|
||||
return false;
|
||||
|
||||
music_.SetSound(std::move(sound));
|
||||
music_.SetSound("music");
|
||||
music_.SetMaxAplitude(0.5f);
|
||||
|
||||
boss_music_.SetSound(std::move(boss_sound));
|
||||
boss_music_.SetSound("boss_music");
|
||||
boss_music_.SetMaxAplitude(0.5f);
|
||||
|
||||
if (!saved_data_.root().get("audio", Json::Value(true)).asBool())
|
||||
|
@ -172,6 +185,7 @@ void Demo::ContextLost() {
|
|||
num_benchmark_samples_ = 0;
|
||||
avarage_fps_ = 0;
|
||||
}
|
||||
menu_.SetRendererType();
|
||||
}
|
||||
|
||||
void Demo::LostFocus() {}
|
||||
|
|
|
@ -23,14 +23,12 @@ class Demo final : public eng::Game {
|
|||
Demo();
|
||||
~Demo() final;
|
||||
|
||||
// Game interface
|
||||
bool PreInitialize() final;
|
||||
bool Initialize() final;
|
||||
|
||||
void Update(float delta_time) final;
|
||||
|
||||
void ContextLost() final;
|
||||
|
||||
void LostFocus() final;
|
||||
|
||||
void GainedFocus(bool from_interstitial_ad) final;
|
||||
|
||||
void AddScore(size_t score);
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "engine/font.h"
|
||||
#include "engine/image.h"
|
||||
#include "engine/renderer/geometry.h"
|
||||
#include "engine/sound.h"
|
||||
|
||||
#include "demo/demo.h"
|
||||
|
||||
|
@ -78,46 +77,44 @@ Enemy::Enemy() = default;
|
|||
|
||||
Enemy::~Enemy() = default;
|
||||
|
||||
bool Enemy::PreInitialize() {
|
||||
Engine::Get().SetImageSource("skull_tex", "enemy_anims_01_frames_ok.png",
|
||||
true);
|
||||
Engine::Get().SetImageSource("bug_tex", "enemy_anims_02_frames_ok.png", true);
|
||||
Engine::Get().SetImageSource("boss_tex1", "Boss_ok.png", true);
|
||||
Engine::Get().SetImageSource("boss_tex2", "Boss_ok_lvl2.png", true);
|
||||
Engine::Get().SetImageSource("boss_tex3", "Boss_ok_lvl3.png", true);
|
||||
Engine::Get().SetImageSource("target_tex", "enemy_target_single_ok.png",
|
||||
true);
|
||||
Engine::Get().SetImageSource("blast_tex", "enemy_anims_blast_ok.png", true);
|
||||
Engine::Get().SetImageSource("shield_tex", "woom_enemy_shield.png", true);
|
||||
Engine::Get().SetImageSource("crate_tex", "nuke_pack_OK.png", true);
|
||||
|
||||
for (int i = 0; i < kEnemyType_Max; ++i)
|
||||
Engine::Get().SetImageSource(
|
||||
"score_tex"s + std::to_string(i),
|
||||
std::bind(&Enemy::GetScoreImage, this, (EnemyType)i), true);
|
||||
|
||||
Engine::Get().SetShaderSource("chromatic_aberration",
|
||||
"chromatic_aberration.glsl");
|
||||
|
||||
Engine::Get().AsyncLoadSound("boss_intro", "boss_intro.mp3");
|
||||
Engine::Get().AsyncLoadSound("boss_explosion", "boss_explosion.mp3");
|
||||
Engine::Get().AsyncLoadSound("explosion", "explosion.mp3");
|
||||
Engine::Get().AsyncLoadSound("stealth", "stealth.mp3");
|
||||
Engine::Get().AsyncLoadSound("shield", "shield.mp3");
|
||||
Engine::Get().AsyncLoadSound("hit", "hit.mp3");
|
||||
Engine::Get().AsyncLoadSound("powerup-spawn", "powerup-spawn.mp3");
|
||||
Engine::Get().AsyncLoadSound("powerup-pick", "powerup-pick.mp3");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Enemy::Initialize() {
|
||||
boss_intro_sound_ = std::make_shared<Sound>();
|
||||
if (!boss_intro_sound_->Load("boss_intro.mp3", false))
|
||||
return false;
|
||||
|
||||
boss_explosion_sound_ = std::make_shared<Sound>();
|
||||
if (!boss_explosion_sound_->Load("boss_explosion.mp3", false))
|
||||
return false;
|
||||
|
||||
explosion_sound_ = std::make_shared<Sound>();
|
||||
if (!explosion_sound_->Load("explosion.mp3", false))
|
||||
return false;
|
||||
|
||||
stealth_sound_ = std::make_shared<Sound>();
|
||||
if (!stealth_sound_->Load("stealth.mp3", false))
|
||||
return false;
|
||||
|
||||
shield_on_sound_ = std::make_shared<Sound>();
|
||||
if (!shield_on_sound_->Load("shield.mp3", false))
|
||||
return false;
|
||||
|
||||
hit_sound_ = std::make_shared<Sound>();
|
||||
if (!hit_sound_->Load("hit.mp3", false))
|
||||
return false;
|
||||
|
||||
power_up_spawn_sound_ = std::make_shared<Sound>();
|
||||
if (!power_up_spawn_sound_->Load("powerup-spawn.mp3", false))
|
||||
return false;
|
||||
|
||||
power_up_pick_sound_ = std::make_shared<Sound>();
|
||||
if (!power_up_pick_sound_->Load("powerup-pick.mp3", false))
|
||||
return false;
|
||||
|
||||
if (!CreateRenderResources())
|
||||
return false;
|
||||
|
||||
boss_.SetZOrder(10);
|
||||
boss_animator_.Attach(&boss_);
|
||||
|
||||
boss_intro_.SetSound(boss_intro_sound_);
|
||||
boss_intro_.SetSound("boss_intro");
|
||||
boss_intro_.SetVariate(false);
|
||||
boss_intro_.SetSimulateStereo(false);
|
||||
|
||||
|
@ -729,29 +726,29 @@ void Enemy::SpawnUnit(EnemyType enemy_type,
|
|||
e.movement_animator.Play(Animator::kMovement, false);
|
||||
|
||||
if (e.enemy_type == kEnemyType_PowerUp) {
|
||||
e.explosion.SetSound(power_up_pick_sound_);
|
||||
e.explosion.SetSound("powerup-pick");
|
||||
|
||||
e.spawn.SetSound(power_up_spawn_sound_);
|
||||
e.spawn.SetSound("powerup-spawn");
|
||||
e.spawn.SetMaxAplitude(2.0f);
|
||||
e.spawn.Play(false);
|
||||
} else {
|
||||
e.explosion.SetSound(explosion_sound_);
|
||||
e.explosion.SetSound("explosion");
|
||||
e.explosion.SetVariate(true);
|
||||
e.explosion.SetSimulateStereo(true);
|
||||
e.explosion.SetMaxAplitude(0.9f);
|
||||
}
|
||||
|
||||
e.stealth.SetSound(stealth_sound_);
|
||||
e.stealth.SetSound("stealth");
|
||||
e.stealth.SetVariate(false);
|
||||
e.stealth.SetSimulateStereo(false);
|
||||
e.stealth.SetMaxAplitude(0.7f);
|
||||
|
||||
e.shield_on.SetSound(shield_on_sound_);
|
||||
e.shield_on.SetSound("shield");
|
||||
e.shield_on.SetVariate(false);
|
||||
e.shield_on.SetSimulateStereo(false);
|
||||
e.shield_on.SetMaxAplitude(0.5f);
|
||||
|
||||
e.hit.SetSound(hit_sound_);
|
||||
e.hit.SetSound("hit");
|
||||
e.hit.SetVariate(true);
|
||||
e.hit.SetSimulateStereo(false);
|
||||
e.hit.SetMaxAplitude(0.5f);
|
||||
|
@ -825,11 +822,11 @@ void Enemy::SpawnBoss() {
|
|||
Animator::kMovement, [&]() -> void { e.marked_for_removal = true; });
|
||||
e.score_animator.Attach(&e.score);
|
||||
|
||||
e.explosion.SetSound(boss_explosion_sound_);
|
||||
e.explosion.SetSound("boss_explosion");
|
||||
e.explosion.SetVariate(false);
|
||||
e.explosion.SetSimulateStereo(false);
|
||||
|
||||
e.hit.SetSound(hit_sound_);
|
||||
e.hit.SetSound("hit");
|
||||
e.hit.SetVariate(true);
|
||||
e.hit.SetSimulateStereo(false);
|
||||
e.hit.SetMaxAplitude(0.5f);
|
||||
|
@ -1185,30 +1182,6 @@ std::unique_ptr<Image> Enemy::GetScoreImage(EnemyType enemy_type) {
|
|||
return image;
|
||||
}
|
||||
|
||||
bool Enemy::CreateRenderResources() {
|
||||
Engine::Get().SetImageSource("skull_tex", "enemy_anims_01_frames_ok.png",
|
||||
true);
|
||||
Engine::Get().SetImageSource("bug_tex", "enemy_anims_02_frames_ok.png", true);
|
||||
Engine::Get().SetImageSource("boss_tex1", "Boss_ok.png", true);
|
||||
Engine::Get().SetImageSource("boss_tex2", "Boss_ok_lvl2.png", true);
|
||||
Engine::Get().SetImageSource("boss_tex3", "Boss_ok_lvl3.png", true);
|
||||
Engine::Get().SetImageSource("target_tex", "enemy_target_single_ok.png",
|
||||
true);
|
||||
Engine::Get().SetImageSource("blast_tex", "enemy_anims_blast_ok.png", true);
|
||||
Engine::Get().SetImageSource("shield_tex", "woom_enemy_shield.png", true);
|
||||
Engine::Get().SetImageSource("crate_tex", "nuke_pack_OK.png", true);
|
||||
|
||||
for (int i = 0; i < kEnemyType_Max; ++i)
|
||||
Engine::Get().SetImageSource(
|
||||
"score_tex"s + std::to_string(i),
|
||||
std::bind(&Enemy::GetScoreImage, this, (EnemyType)i), true);
|
||||
|
||||
Engine::Get().LoadCustomShader("chromatic_aberration",
|
||||
"chromatic_aberration.glsl");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Enemy::TranslateEnemyUnit(EnemyUnit& e, const Vector2f& delta) {
|
||||
e.sprite.Translate(delta);
|
||||
e.target.Translate(delta);
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
namespace eng {
|
||||
class Image;
|
||||
class Sound;
|
||||
} // namespace eng
|
||||
|
||||
class Enemy {
|
||||
|
@ -23,6 +22,7 @@ class Enemy {
|
|||
Enemy();
|
||||
~Enemy();
|
||||
|
||||
bool PreInitialize();
|
||||
bool Initialize();
|
||||
|
||||
void Update(float delta_time);
|
||||
|
@ -109,15 +109,6 @@ class Enemy {
|
|||
eng::Animator boss_animator_;
|
||||
eng::SoundPlayer boss_intro_;
|
||||
|
||||
std::shared_ptr<eng::Sound> boss_intro_sound_;
|
||||
std::shared_ptr<eng::Sound> boss_explosion_sound_;
|
||||
std::shared_ptr<eng::Sound> explosion_sound_;
|
||||
std::shared_ptr<eng::Sound> stealth_sound_;
|
||||
std::shared_ptr<eng::Sound> shield_on_sound_;
|
||||
std::shared_ptr<eng::Sound> hit_sound_;
|
||||
std::shared_ptr<eng::Sound> power_up_spawn_sound_;
|
||||
std::shared_ptr<eng::Sound> power_up_pick_sound_;
|
||||
|
||||
std::list<EnemyUnit> enemies_;
|
||||
|
||||
int num_enemies_killed_in_current_wave_ = 0;
|
||||
|
@ -164,8 +155,6 @@ class Enemy {
|
|||
|
||||
std::unique_ptr<eng::Image> GetScoreImage(EnemyType enemy_type);
|
||||
|
||||
bool CreateRenderResources();
|
||||
|
||||
void TranslateEnemyUnit(EnemyUnit& e, const base::Vector2f& delta);
|
||||
};
|
||||
|
||||
|
|
111
src/demo/menu.cc
111
src/demo/menu.cc
|
@ -53,7 +53,7 @@ Menu::Menu() = default;
|
|||
|
||||
Menu::~Menu() = default;
|
||||
|
||||
bool Menu::Initialize() {
|
||||
bool Menu::PreInitialize() {
|
||||
click_sound_ = std::make_shared<Sound>();
|
||||
if (!click_sound_->Load("menu_click.mp3", false))
|
||||
return false;
|
||||
|
@ -70,8 +70,59 @@ bool Menu::Initialize() {
|
|||
max_text_width_ = width;
|
||||
}
|
||||
|
||||
if (!CreateRenderResources())
|
||||
return false;
|
||||
Engine::Get().SetImageSource("menu_tex",
|
||||
std::bind(&Menu::CreateMenuImage, this), true);
|
||||
Engine::Get().SetImageSource("logo_tex0", "woom_logo_start_frames_01.png",
|
||||
true);
|
||||
Engine::Get().SetImageSource("logo_tex1", "woom_logo_start_frames_02-03.png",
|
||||
true);
|
||||
Engine::Get().SetImageSource("buttons_tex", "menu_icons.png", true);
|
||||
Engine::Get().SetImageSource("renderer_logo", "renderer_logo.png", true);
|
||||
|
||||
Engine::Get().SetImageSource(
|
||||
"version_tex",
|
||||
[]() -> std::unique_ptr<Image> {
|
||||
const Font* font = Engine::Get().GetSystemFont();
|
||||
|
||||
int w, h;
|
||||
font->CalculateBoundingBox(kVersionStr, w, h);
|
||||
|
||||
auto image = std::make_unique<Image>();
|
||||
image->Create(w, font->GetLineHeight());
|
||||
image->Clear({1, 1, 1, 0});
|
||||
|
||||
font->Print(0, 0, kVersionStr, image->GetBuffer(), image->GetWidth());
|
||||
|
||||
image->Compress();
|
||||
return image;
|
||||
},
|
||||
true);
|
||||
|
||||
Engine::Get().SetImageSource("high_score_tex",
|
||||
std::bind(&Menu::CreateHighScoreImage, this));
|
||||
Engine::Get().SetImageSource("wave_up_tex", []() -> std::unique_ptr<Image> {
|
||||
const Font& font = static_cast<Demo*>(Engine::Get().GetGame())->GetFont();
|
||||
|
||||
constexpr char btn_text[] = "[ ]";
|
||||
|
||||
int w, h;
|
||||
font.CalculateBoundingBox(btn_text, w, h);
|
||||
|
||||
auto image = std::make_unique<Image>();
|
||||
image->Create(w, h);
|
||||
image->Clear({1, 1, 1, 0});
|
||||
|
||||
font.Print(0, 0, btn_text, image->GetBuffer(), image->GetWidth());
|
||||
|
||||
image->Compress();
|
||||
return image;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Menu::Initialize() {
|
||||
Demo* game = static_cast<Demo*>(Engine::Get().GetGame());
|
||||
|
||||
for (int i = 0; i < kOption_Max; ++i) {
|
||||
items_[i].text.Create("menu_tex", {1, 4});
|
||||
|
@ -199,8 +250,6 @@ bool Menu::Initialize() {
|
|||
Engine::Get().CreateRenderer(renderer_type_.enabled()
|
||||
? RendererType::kVulkan
|
||||
: RendererType::kOpenGL);
|
||||
renderer_type_.SetEnabled(
|
||||
(Engine::Get().GetRendererType() == RendererType::kVulkan));
|
||||
},
|
||||
true, Engine::Get().GetRendererType() == RendererType::kVulkan,
|
||||
kColorFadeOut, {Vector4f{1, 1, 1, 1}, Vector4f{1, 1, 1, 1}});
|
||||
|
@ -320,6 +369,11 @@ void Menu::SetOptionEnabled(Option o, bool enable) {
|
|||
}
|
||||
}
|
||||
|
||||
void Menu::SetRendererType() {
|
||||
renderer_type_.SetEnabled(
|
||||
(Engine::Get().GetRendererType() == RendererType::kVulkan));
|
||||
}
|
||||
|
||||
void Menu::Show() {
|
||||
logo_[1].SetColor(kColorNormal);
|
||||
logo_animator_[0].SetVisible(true);
|
||||
|
@ -440,53 +494,6 @@ void Menu::Hide(Closure cb) {
|
|||
}
|
||||
}
|
||||
|
||||
bool Menu::CreateRenderResources() {
|
||||
Engine::Get().SetImageSource("menu_tex",
|
||||
std::bind(&Menu::CreateMenuImage, this));
|
||||
Engine::Get().SetImageSource("logo_tex0", "woom_logo_start_frames_01.png");
|
||||
Engine::Get().SetImageSource("logo_tex1", "woom_logo_start_frames_02-03.png");
|
||||
Engine::Get().SetImageSource("buttons_tex", "menu_icons.png");
|
||||
Engine::Get().SetImageSource("high_score_tex",
|
||||
std::bind(&Menu::CreateHighScoreImage, this));
|
||||
Engine::Get().SetImageSource("renderer_logo", "renderer_logo.png");
|
||||
|
||||
Engine::Get().SetImageSource("wave_up_tex", []() -> std::unique_ptr<Image> {
|
||||
const Font& font = static_cast<Demo*>(Engine::Get().GetGame())->GetFont();
|
||||
|
||||
constexpr char btn_text[] = "[ ]";
|
||||
|
||||
int w, h;
|
||||
font.CalculateBoundingBox(btn_text, w, h);
|
||||
|
||||
auto image = std::make_unique<Image>();
|
||||
image->Create(w, h);
|
||||
image->Clear({1, 1, 1, 0});
|
||||
|
||||
font.Print(0, 0, btn_text, image->GetBuffer(), image->GetWidth());
|
||||
|
||||
image->Compress();
|
||||
return image;
|
||||
});
|
||||
|
||||
Engine::Get().SetImageSource("version_tex", []() -> std::unique_ptr<Image> {
|
||||
const Font* font = Engine::Get().GetSystemFont();
|
||||
|
||||
int w, h;
|
||||
font->CalculateBoundingBox(kVersionStr, w, h);
|
||||
|
||||
auto image = std::make_unique<Image>();
|
||||
image->Create(w, font->GetLineHeight());
|
||||
image->Clear({1, 1, 1, 0});
|
||||
|
||||
font->Print(0, 0, kVersionStr, image->GetBuffer(), image->GetWidth());
|
||||
|
||||
image->Compress();
|
||||
return image;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<Image> Menu::CreateMenuImage() {
|
||||
const Font& font = static_cast<Demo*>(Engine::Get().GetGame())->GetFont();
|
||||
|
||||
|
|
|
@ -30,11 +30,13 @@ class Menu {
|
|||
Menu();
|
||||
~Menu();
|
||||
|
||||
bool PreInitialize();
|
||||
bool Initialize();
|
||||
|
||||
void OnInputEvent(std::unique_ptr<eng::InputEvent> event);
|
||||
|
||||
void SetOptionEnabled(Option o, bool enable);
|
||||
void SetRendererType();
|
||||
|
||||
void Show();
|
||||
void Hide(base::Closure cb = nullptr);
|
||||
|
@ -145,9 +147,6 @@ class Menu {
|
|||
|
||||
Radio starting_wave_;
|
||||
Button wave_up_;
|
||||
Button wave_down_;
|
||||
|
||||
bool CreateRenderResources();
|
||||
|
||||
std::unique_ptr<eng::Image> CreateMenuImage();
|
||||
std::unique_ptr<eng::Image> CreateHighScoreImage();
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "engine/engine.h"
|
||||
#include "engine/font.h"
|
||||
#include "engine/input_event.h"
|
||||
#include "engine/sound.h"
|
||||
|
||||
#include "demo/demo.h"
|
||||
|
||||
|
@ -29,22 +28,20 @@ Player::Player() = default;
|
|||
|
||||
Player::~Player() = default;
|
||||
|
||||
bool Player::PreInitialize() {
|
||||
Engine::Get().SetImageSource("weapon_tex", "enemy_anims_flare_ok.png", true);
|
||||
Engine::Get().SetImageSource("beam_tex", "enemy_ray_ok.png", true);
|
||||
Engine::Get().SetImageSource("nuke_symbol_tex", "nuke_frames.png", true);
|
||||
Engine::Get().SetImageSource("health_bead", "bead.png", true);
|
||||
|
||||
Engine::Get().AsyncLoadSound("laser", "laser.mp3");
|
||||
Engine::Get().AsyncLoadSound("nuke", "nuke.mp3");
|
||||
Engine::Get().AsyncLoadSound("no_nuke", "no_nuke.mp3");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Player::Initialize() {
|
||||
if (!CreateRenderResources())
|
||||
return false;
|
||||
|
||||
laser_shot_sound_ = std::make_shared<Sound>();
|
||||
if (!laser_shot_sound_->Load("laser.mp3", false))
|
||||
return false;
|
||||
|
||||
nuke_explosion_sound_ = std::make_shared<Sound>();
|
||||
if (!nuke_explosion_sound_->Load("nuke.mp3", false))
|
||||
return false;
|
||||
|
||||
no_nuke_sound_ = std::make_shared<Sound>();
|
||||
if (!no_nuke_sound_->Load("no_nuke.mp3", false))
|
||||
return false;
|
||||
|
||||
SetupWeapons();
|
||||
|
||||
Vector2f hb_pos = Engine::Get().GetScreenSize() / Vector2f(2, -2) +
|
||||
|
@ -75,12 +72,12 @@ bool Player::Initialize() {
|
|||
|
||||
nuke_symbol_animator_.Attach(&nuke_symbol_);
|
||||
|
||||
nuke_explosion_.SetSound(nuke_explosion_sound_);
|
||||
nuke_explosion_.SetSound("nuke");
|
||||
nuke_explosion_.SetVariate(false);
|
||||
nuke_explosion_.SetSimulateStereo(false);
|
||||
nuke_explosion_.SetMaxAplitude(0.8f);
|
||||
|
||||
no_nuke_.SetSound(no_nuke_sound_);
|
||||
no_nuke_.SetSound("no_nuke");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -306,7 +303,7 @@ void Player::SetupWeapons() {
|
|||
beam_animator_[i].SetBlending({1, 1, 1, 0}, 0.16f);
|
||||
beam_animator_[i].Attach(&beam_[i]);
|
||||
|
||||
laser_shot_[i].SetSound(laser_shot_sound_);
|
||||
laser_shot_[i].SetSound("laser");
|
||||
laser_shot_[i].SetVariate(true);
|
||||
laser_shot_[i].SetSimulateStereo(false);
|
||||
laser_shot_[i].SetMaxAplitude(0.4f);
|
||||
|
@ -485,12 +482,3 @@ void Player::NavigateBack() {
|
|||
Engine& engine = Engine::Get();
|
||||
static_cast<Demo*>(engine.GetGame())->EnterMenuState();
|
||||
}
|
||||
|
||||
bool Player::CreateRenderResources() {
|
||||
Engine::Get().SetImageSource("weapon_tex", "enemy_anims_flare_ok.png", true);
|
||||
Engine::Get().SetImageSource("beam_tex", "enemy_ray_ok.png", true);
|
||||
Engine::Get().SetImageSource("nuke_symbol_tex", "nuke_frames.png", true);
|
||||
Engine::Get().SetImageSource("health_bead", "bead.png", true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
|
||||
namespace eng {
|
||||
class InputEvent;
|
||||
class Sound;
|
||||
} // namespace eng
|
||||
|
||||
class Player {
|
||||
|
@ -21,6 +20,7 @@ class Player {
|
|||
Player();
|
||||
~Player();
|
||||
|
||||
bool PreInitialize();
|
||||
bool Initialize();
|
||||
|
||||
void Update(float delta_time);
|
||||
|
@ -41,10 +41,6 @@ class Player {
|
|||
int nuke_count() { return nuke_count_; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<eng::Sound> nuke_explosion_sound_;
|
||||
std::shared_ptr<eng::Sound> no_nuke_sound_;
|
||||
std::shared_ptr<eng::Sound> laser_shot_sound_;
|
||||
|
||||
eng::ImageQuad drag_sign_[2];
|
||||
eng::ImageQuad weapon_[2];
|
||||
eng::ImageQuad beam_[2];
|
||||
|
@ -101,8 +97,6 @@ class Player {
|
|||
bool ValidateDrag(int i);
|
||||
|
||||
void NavigateBack();
|
||||
|
||||
bool CreateRenderResources();
|
||||
};
|
||||
|
||||
#endif // DEMO_PLAYER_H
|
||||
|
|
|
@ -21,8 +21,8 @@ SkyQuad::~SkyQuad() = default;
|
|||
bool SkyQuad::Create(bool without_nebula) {
|
||||
without_nebula_ = without_nebula;
|
||||
scale_ = Engine::Get().GetScreenSize();
|
||||
shader_ = Engine::Get().GetCustomShader(
|
||||
without_nebula ? "sky_without_nebula" : "sky");
|
||||
shader_ =
|
||||
Engine::Get().GetShader(without_nebula ? "sky_without_nebula" : "sky");
|
||||
|
||||
color_animator_.Attach(this);
|
||||
|
||||
|
|
|
@ -5,11 +5,6 @@
|
|||
#include "engine/animatable.h"
|
||||
#include "engine/animator.h"
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace eng {
|
||||
class Shader;
|
||||
} // namespace eng
|
||||
|
|
|
@ -254,7 +254,8 @@ void AudioMixer::RenderAudio(float* output_buffer, size_t num_frames) {
|
|||
|
||||
ThreadPool::Get().PostTask(
|
||||
HERE,
|
||||
std::bind(&AudioMixer::DoStream, this, *it, flags & kLoop));
|
||||
std::bind(&AudioMixer::DoStream, this, *it, flags & kLoop),
|
||||
true);
|
||||
} else {
|
||||
DLOG << "Mixer buffer underrun!";
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "engine/renderer/texture.h"
|
||||
#include "engine/renderer/vulkan/renderer_vulkan.h"
|
||||
#include "engine/shader_source.h"
|
||||
#include "engine/sound.h"
|
||||
#include "third_party/texture_compressor/texture_compressor.h"
|
||||
|
||||
using namespace base;
|
||||
|
@ -84,6 +85,7 @@ void Engine::Run() {
|
|||
|
||||
if (!renderer_->IsInitialzed()) {
|
||||
timer_.Reset();
|
||||
input_queue_.clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -109,7 +111,7 @@ void Engine::Initialize() {
|
|||
|
||||
thread_pool_.Initialize();
|
||||
|
||||
CreateRenderer(RendererType::kVulkan);
|
||||
CreateRendererInternal(RendererType::kVulkan);
|
||||
|
||||
// Normalize viewport.
|
||||
if (GetScreenWidth() > GetScreenHeight()) {
|
||||
|
@ -134,7 +136,11 @@ void Engine::Initialize() {
|
|||
|
||||
game_ = GameFactoryBase::CreateGame("");
|
||||
CHECK(game_) << "No game found to run.";
|
||||
CHECK(game_->PreInitialize()) << "Failed to pre-initialize the game.";
|
||||
|
||||
// Create resources and let the game finalize initialization.
|
||||
CreateRenderResources();
|
||||
WaitForAsyncWork();
|
||||
CHECK(game_->Initialize()) << "Failed to initialize the game.";
|
||||
}
|
||||
|
||||
|
@ -205,33 +211,12 @@ void Engine::RemoveAnimator(Animator* animator) {
|
|||
}
|
||||
|
||||
void Engine::CreateRenderer(RendererType type) {
|
||||
if ((dynamic_cast<RendererVulkan*>(renderer_.get()) &&
|
||||
type == RendererType::kVulkan) ||
|
||||
(dynamic_cast<RendererOpenGL*>(renderer_.get()) &&
|
||||
type == RendererType::kOpenGL))
|
||||
return;
|
||||
|
||||
if (type == RendererType::kVulkan)
|
||||
renderer_ =
|
||||
std::make_unique<RendererVulkan>(std::bind(&Engine::ContextLost, this));
|
||||
else if (type == RendererType::kOpenGL)
|
||||
renderer_ =
|
||||
std::make_unique<RendererOpenGL>(std::bind(&Engine::ContextLost, this));
|
||||
else
|
||||
NOTREACHED;
|
||||
|
||||
bool result = renderer_->Initialize(platform_);
|
||||
if (!result && type == RendererType::kVulkan) {
|
||||
LOG << "Failed to initialize " << renderer_->GetDebugName() << " renderer.";
|
||||
LOG << "Fallback to OpenGL renderer.";
|
||||
CreateRenderer(RendererType::kOpenGL);
|
||||
return;
|
||||
}
|
||||
CHECK(result) << "Failed to initialize " << renderer_->GetDebugName()
|
||||
<< " renderer.";
|
||||
|
||||
CreateTextureCompressors();
|
||||
ContextLost();
|
||||
// Create a new renderer next cycle.
|
||||
TaskRunner::TaskRunner::GetThreadLocalTaskRunner()->PostTask(
|
||||
HERE, std::bind(&Engine::CreateRendererInternal, this, type));
|
||||
TaskRunner::TaskRunner::GetThreadLocalTaskRunner()->PostTask(
|
||||
HERE, std::bind(&Engine::ContextLost, this));
|
||||
input_queue_.clear();
|
||||
}
|
||||
|
||||
RendererType Engine::GetRendererType() {
|
||||
|
@ -276,14 +261,8 @@ void Engine::SetImageSource(const std::string& asset_name,
|
|||
return;
|
||||
}
|
||||
|
||||
auto& t = textures_[asset_name] = {CreateRenderResource<Texture>(),
|
||||
create_image, persistent, 0};
|
||||
|
||||
if (persistent) {
|
||||
auto image = create_image();
|
||||
if (image)
|
||||
t.texture->Update(std::move(image));
|
||||
}
|
||||
textures_[asset_name] = {std::make_unique<Texture>(renderer_.get()),
|
||||
create_image, persistent, 0};
|
||||
}
|
||||
|
||||
void Engine::RefreshImage(const std::string& asset_name) {
|
||||
|
@ -297,8 +276,6 @@ void Engine::RefreshImage(const std::string& asset_name) {
|
|||
auto image = it->second.create_image();
|
||||
if (image)
|
||||
it->second.texture->Update(std::move(image));
|
||||
else
|
||||
it->second.texture->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -310,8 +287,11 @@ Texture* Engine::AcquireTexture(const std::string& asset_name) {
|
|||
}
|
||||
|
||||
it->second.use_count++;
|
||||
if (!it->second.texture->IsValid())
|
||||
RefreshImage(it->first);
|
||||
if (!it->second.texture->IsValid()) {
|
||||
auto image = it->second.create_image();
|
||||
if (image)
|
||||
it->second.texture->Update(std::move(image));
|
||||
}
|
||||
return it->second.texture.get();
|
||||
}
|
||||
|
||||
|
@ -328,40 +308,58 @@ void Engine::ReleaseTexture(const std::string& asset_name) {
|
|||
it->second.texture->Destroy();
|
||||
}
|
||||
|
||||
void Engine::LoadCustomShader(const std::string& asset_name,
|
||||
const std::string& file_name) {
|
||||
void Engine::SetShaderSource(const std::string& asset_name,
|
||||
const std::string& file_name) {
|
||||
if (shaders_.contains(asset_name)) {
|
||||
DLOG << "Shader already exists: " << asset_name;
|
||||
return;
|
||||
}
|
||||
|
||||
auto& s = shaders_[asset_name] = {CreateRenderResource<Shader>(), file_name};
|
||||
|
||||
auto source = std::make_unique<ShaderSource>();
|
||||
if (!source->Load(file_name))
|
||||
return;
|
||||
s.shader->Create(std::move(source), quad_->vertex_description(),
|
||||
quad_->primitive(), false);
|
||||
shaders_[asset_name] = {std::make_unique<Shader>(renderer_.get()), file_name};
|
||||
}
|
||||
|
||||
Shader* Engine::GetCustomShader(const std::string& asset_name) {
|
||||
Shader* Engine::GetShader(const std::string& asset_name) {
|
||||
auto it = shaders_.find(asset_name);
|
||||
if (it == shaders_.end()) {
|
||||
DLOG << "Shader not found: " << asset_name;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!it->second.shader->IsValid()) {
|
||||
auto source = std::make_unique<ShaderSource>();
|
||||
if (source->Load(it->second.file_name))
|
||||
it->second.shader->Create(std::move(source), quad_->vertex_description(),
|
||||
quad_->primitive(), false);
|
||||
}
|
||||
|
||||
return it->second.shader.get();
|
||||
}
|
||||
|
||||
void Engine::RemoveCustomShader(const std::string& asset_name) {
|
||||
auto it = shaders_.find(asset_name);
|
||||
if (it == shaders_.end()) {
|
||||
DLOG << "Shader not found: " << asset_name;
|
||||
void Engine::AsyncLoadSound(const std::string& asset_name,
|
||||
const std::string& file_name,
|
||||
bool stream) {
|
||||
if (audio_buses_.contains(asset_name)) {
|
||||
DLOG << "AudioBus already exists: " << asset_name;
|
||||
return;
|
||||
}
|
||||
|
||||
shaders_.erase(it);
|
||||
auto sound = std::make_shared<Sound>();
|
||||
audio_buses_[asset_name] = sound;
|
||||
|
||||
++async_work_count_;
|
||||
thread_pool_.PostTaskAndReply(
|
||||
HERE, std::bind(&Sound::Load, sound, file_name, stream),
|
||||
[&]() -> void { --async_work_count_; });
|
||||
}
|
||||
|
||||
std::shared_ptr<AudioBus> Engine::GetAudioBus(const std::string& asset_name) {
|
||||
auto it = audio_buses_.find(asset_name);
|
||||
if (it == audio_buses_.end()) {
|
||||
DLOG << "AudioBus not found: " << asset_name;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::unique_ptr<InputEvent> Engine::GetNextInputEvent() {
|
||||
|
@ -564,6 +562,35 @@ void Engine::AddInputEvent(std::unique_ptr<InputEvent> event) {
|
|||
input_queue_.push_back(std::move(event));
|
||||
}
|
||||
|
||||
void Engine::CreateRendererInternal(RendererType type) {
|
||||
if ((dynamic_cast<RendererVulkan*>(renderer_.get()) &&
|
||||
type == RendererType::kVulkan) ||
|
||||
(dynamic_cast<RendererOpenGL*>(renderer_.get()) &&
|
||||
type == RendererType::kOpenGL))
|
||||
return;
|
||||
|
||||
if (type == RendererType::kVulkan)
|
||||
renderer_ =
|
||||
std::make_unique<RendererVulkan>(std::bind(&Engine::ContextLost, this));
|
||||
else if (type == RendererType::kOpenGL)
|
||||
renderer_ =
|
||||
std::make_unique<RendererOpenGL>(std::bind(&Engine::ContextLost, this));
|
||||
else
|
||||
NOTREACHED;
|
||||
|
||||
bool result = renderer_->Initialize(platform_);
|
||||
if (!result && type == RendererType::kVulkan) {
|
||||
LOG << "Failed to initialize " << renderer_->GetDebugName() << " renderer.";
|
||||
LOG << "Fallback to OpenGL renderer.";
|
||||
CreateRendererInternal(RendererType::kOpenGL);
|
||||
return;
|
||||
}
|
||||
CHECK(result) << "Failed to initialize " << renderer_->GetDebugName()
|
||||
<< " renderer.";
|
||||
|
||||
CreateTextureCompressors();
|
||||
}
|
||||
|
||||
void Engine::CreateTextureCompressors() {
|
||||
tex_comp_alpha_.reset();
|
||||
tex_comp_opaque_.reset();
|
||||
|
@ -587,6 +614,15 @@ void Engine::CreateTextureCompressors() {
|
|||
}
|
||||
|
||||
void Engine::ContextLost() {
|
||||
CreateRenderResources();
|
||||
WaitForAsyncWork();
|
||||
input_queue_.clear();
|
||||
|
||||
if (game_)
|
||||
game_->ContextLost();
|
||||
}
|
||||
|
||||
void Engine::CreateRenderResources() {
|
||||
quad_->SetRenderer(renderer_.get());
|
||||
pass_through_shader_->SetRenderer(renderer_.get());
|
||||
solid_shader_->SetRenderer(renderer_.get());
|
||||
|
@ -623,21 +659,45 @@ void Engine::ContextLost() {
|
|||
|
||||
for (auto& t : textures_) {
|
||||
t.second.texture->SetRenderer(renderer_.get());
|
||||
RefreshImage(t.first);
|
||||
if (t.second.persistent || t.second.use_count > 0) {
|
||||
++async_work_count_;
|
||||
thread_pool_.PostTaskAndReplyWithResult<std::unique_ptr<Image>>(
|
||||
HERE, t.second.create_image,
|
||||
[&,
|
||||
ptr = t.second.texture.get()](std::unique_ptr<Image> image) -> void {
|
||||
--async_work_count_;
|
||||
if (image)
|
||||
ptr->Update(std::move(image));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& s : shaders_) {
|
||||
s.second.shader->SetRenderer(renderer_.get());
|
||||
auto source = std::make_unique<ShaderSource>();
|
||||
if (source->Load(s.second.file_name))
|
||||
s.second.shader->Create(std::move(source), quad_->vertex_description(),
|
||||
quad_->primitive(), false);
|
||||
++async_work_count_;
|
||||
thread_pool_.PostTaskAndReplyWithResult<std::unique_ptr<ShaderSource>>(
|
||||
HERE,
|
||||
[file_name = s.second.file_name]() -> std::unique_ptr<ShaderSource> {
|
||||
auto source = std::make_unique<ShaderSource>();
|
||||
if (!source->Load(file_name))
|
||||
return nullptr;
|
||||
return source;
|
||||
},
|
||||
[&, ptr = s.second.shader.get()](
|
||||
std::unique_ptr<ShaderSource> source) -> void {
|
||||
--async_work_count_;
|
||||
if (source)
|
||||
ptr->Create(std::move(source), quad_->vertex_description(),
|
||||
quad_->primitive(), false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (game_)
|
||||
game_->ContextLost();
|
||||
|
||||
input_queue_.clear();
|
||||
void Engine::WaitForAsyncWork() {
|
||||
while (async_work_count_ > 0) {
|
||||
TaskRunner::GetThreadLocalTaskRunner()->RunTasks();
|
||||
platform_->Update();
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::SetStatsVisible(bool visible) {
|
||||
|
|
|
@ -19,6 +19,7 @@ class TextureCompressor;
|
|||
namespace eng {
|
||||
|
||||
class Animator;
|
||||
class AudioBus;
|
||||
class AudioMixer;
|
||||
class Drawable;
|
||||
class Font;
|
||||
|
@ -61,11 +62,6 @@ class Engine : public PlatformObserver {
|
|||
// Convert position form pixels to viewport coordinates.
|
||||
base::Vector2f ToPosition(const base::Vector2f& vec);
|
||||
|
||||
template <typename T>
|
||||
std::unique_ptr<T> CreateRenderResource() {
|
||||
return std::unique_ptr<T>(static_cast<T*>(new T(renderer_.get())));
|
||||
}
|
||||
|
||||
void SetImageSource(const std::string& asset_name,
|
||||
const std::string& file_name,
|
||||
bool persistent = false);
|
||||
|
@ -78,10 +74,14 @@ class Engine : public PlatformObserver {
|
|||
Texture* AcquireTexture(const std::string& asset_name);
|
||||
void ReleaseTexture(const std::string& asset_name);
|
||||
|
||||
void LoadCustomShader(const std::string& asset_name,
|
||||
const std::string& file_name);
|
||||
Shader* GetCustomShader(const std::string& asset_name);
|
||||
void RemoveCustomShader(const std::string& asset_name);
|
||||
void SetShaderSource(const std::string& asset_name,
|
||||
const std::string& file_name);
|
||||
Shader* GetShader(const std::string& asset_name);
|
||||
|
||||
void AsyncLoadSound(const std::string& asset_name,
|
||||
const std::string& file_name,
|
||||
bool stream = false);
|
||||
std::shared_ptr<AudioBus> GetAudioBus(const std::string& asset_name);
|
||||
|
||||
std::unique_ptr<InputEvent> GetNextInputEvent();
|
||||
|
||||
|
@ -191,9 +191,12 @@ class Engine : public PlatformObserver {
|
|||
|
||||
std::list<Animator*> animators_;
|
||||
|
||||
// Managed render resources mapped by asset name.
|
||||
// Resources mapped by asset name.
|
||||
std::unordered_map<std::string, TextureResource> textures_;
|
||||
std::unordered_map<std::string, ShaderResource> shaders_;
|
||||
std::unordered_map<std::string, std::shared_ptr<AudioBus>> audio_buses_;
|
||||
|
||||
size_t async_work_count_ = 0;
|
||||
|
||||
std::unique_ptr<ImageQuad> stats_;
|
||||
|
||||
|
@ -232,10 +235,16 @@ class Engine : public PlatformObserver {
|
|||
void GainedFocus(bool from_interstitial_ad) final;
|
||||
void AddInputEvent(std::unique_ptr<InputEvent> event) final;
|
||||
|
||||
void CreateRendererInternal(RendererType type);
|
||||
|
||||
void CreateTextureCompressors();
|
||||
|
||||
void ContextLost();
|
||||
|
||||
void CreateRenderResources();
|
||||
|
||||
void WaitForAsyncWork();
|
||||
|
||||
void SetStatsVisible(bool visible);
|
||||
std::unique_ptr<Image> PrintStats();
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "engine/platform/asset_file.h"
|
||||
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
#define STBTT_STATIC
|
||||
#include "../third_party/stb/stb_truetype.h"
|
||||
|
||||
namespace eng {
|
||||
|
|
|
@ -8,6 +8,10 @@ class Game {
|
|||
Game() = default;
|
||||
virtual ~Game() = default;
|
||||
|
||||
// Called before async-loading assets.
|
||||
virtual bool PreInitialize() = 0;
|
||||
|
||||
// Called after resources are created.
|
||||
virtual bool Initialize() = 0;
|
||||
|
||||
virtual void Update(float delta_time) = 0;
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
// This 3rd party library is written in C and uses malloc, which means that we
|
||||
// have to do the same.
|
||||
#define STBI_NO_STDIO
|
||||
#include "../third_party/stb/stb_image.h"
|
||||
|
||||
using namespace base;
|
||||
|
|
|
@ -32,7 +32,6 @@ void ImageQuad::Create(const std::string& asset_name,
|
|||
asset_name_ = asset_name;
|
||||
}
|
||||
|
||||
// TODO: typo
|
||||
void ImageQuad::Destroy() {
|
||||
if (texture_) {
|
||||
Engine::Get().ReleaseTexture(asset_name_);
|
||||
|
@ -51,7 +50,7 @@ void ImageQuad::AutoScale() {
|
|||
}
|
||||
|
||||
void ImageQuad::SetCustomShader(const std::string& asset_name) {
|
||||
custom_shader_ = Engine::Get().GetCustomShader(asset_name);
|
||||
custom_shader_ = Engine::Get().GetShader(asset_name);
|
||||
custom_uniforms_.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,8 @@ Platform::Platform() {
|
|||
shared_data_path_ = "./";
|
||||
LOG << "Shared data path: " << shared_data_path_.c_str();
|
||||
|
||||
XInitThreads();
|
||||
|
||||
bool res = CreateWindow(800, 1205);
|
||||
CHECK(res) << "Failed to create window.";
|
||||
|
||||
|
|
|
@ -44,7 +44,8 @@ RendererOpenGL::RendererOpenGL(base::Closure context_lost_cb)
|
|||
: Renderer(context_lost_cb),
|
||||
main_thread_task_runner_(TaskRunner::GetThreadLocalTaskRunner()) {}
|
||||
#else
|
||||
RendererOpenGL::RendererOpenGL() = default;
|
||||
RendererOpenGL::RendererOpenGL(base::Closure context_lost_cb)
|
||||
: Renderer(context_lost_cb) {}
|
||||
#endif // THREADED_RENDERING
|
||||
|
||||
RendererOpenGL::~RendererOpenGL() {
|
||||
|
|
|
@ -414,10 +414,7 @@ uint64_t RendererVulkan::CreateGeometry(std::unique_ptr<Mesh> mesh) {
|
|||
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT));
|
||||
task_runner_.PostTask(HERE, [&, mesh = mesh.release()]() {
|
||||
// Transfer mesh ownership to the background thread.
|
||||
std::unique_ptr<Mesh> own(mesh);
|
||||
});
|
||||
task_runner_.Delete(HERE, std::move(mesh));
|
||||
semaphore_.release();
|
||||
|
||||
return last_resource_id_;
|
||||
|
@ -506,10 +503,7 @@ void RendererVulkan::UpdateTexture(uint64_t resource_id,
|
|||
0, VK_ACCESS_SHADER_READ_BIT,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL));
|
||||
task_runner_.PostTask(HERE, [&, image = image.release()]() {
|
||||
// Transfer image ownership to the background thread.
|
||||
std::unique_ptr<Image> own(image);
|
||||
});
|
||||
task_runner_.Delete(HERE, std::move(image));
|
||||
semaphore_.release();
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,10 @@ SoundPlayer::~SoundPlayer() {
|
|||
Engine::Get().GetAudioMixer()->DestroyResource(resource_id_);
|
||||
}
|
||||
|
||||
void SoundPlayer::SetSound(const std::string& asset_name) {
|
||||
sound_ = Engine::Get().GetAudioBus(asset_name);
|
||||
}
|
||||
|
||||
void SoundPlayer::SetSound(std::shared_ptr<AudioBus> sound) {
|
||||
sound_ = sound;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define ENGINE_AUDIO_PLAYER_H
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "base/closure.h"
|
||||
|
||||
|
@ -14,6 +15,7 @@ class SoundPlayer {
|
|||
SoundPlayer();
|
||||
~SoundPlayer();
|
||||
|
||||
void SetSound(const std::string& asset_name);
|
||||
void SetSound(std::shared_ptr<AudioBus> sound);
|
||||
|
||||
void Play(bool loop, float fade_in_duration = 0);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue