mirror of https://github.com/auygun/kaliber.git
Async-load support for assets
This commit is contained in:
parent
8e6589ec67
commit
709029f22c
|
@ -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);
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
@ -323,41 +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] = {std::make_unique<Shader>(renderer_.get()),
|
||||
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() {
|
||||
|
@ -560,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();
|
||||
|
@ -583,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());
|
||||
|
@ -620,24 +660,44 @@ void Engine::ContextLost() {
|
|||
for (auto& t : textures_) {
|
||||
t.second.texture->SetRenderer(renderer_.get());
|
||||
if (t.second.persistent || t.second.use_count > 0) {
|
||||
auto image = t.second.create_image();
|
||||
if (image)
|
||||
t.second.texture->Update(std::move(image));
|
||||
++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;
|
||||
|
@ -73,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();
|
||||
|
||||
|
@ -186,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_;
|
||||
|
||||
|
@ -227,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,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;
|
||||
|
|
|
@ -50,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.";
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue