Implement audio mixing
This commit is contained in:
Binary file not shown.
@@ -6,6 +6,15 @@ Room
|
||||
0D00DD0pD0
|
||||
GGGGGGGGGG
|
||||
|
||||
Room
|
||||
5555555555
|
||||
0000000000
|
||||
0000000000
|
||||
00t0000t00
|
||||
0d00000p00
|
||||
GGGGGGGGGG
|
||||
|
||||
|
||||
Room
|
||||
5555555555
|
||||
00t00p0t00
|
||||
@@ -14,6 +23,14 @@ Room
|
||||
000lggggl0
|
||||
GGGGggggGG
|
||||
|
||||
Room
|
||||
5555555555
|
||||
00t00pdt00
|
||||
000lGGGGl0
|
||||
000lggggl0
|
||||
000lggggl0
|
||||
GGGGggggGG
|
||||
|
||||
Room
|
||||
0000000000
|
||||
00t00p0t00
|
||||
@@ -22,6 +39,14 @@ Room
|
||||
0lDDDgDDDl
|
||||
GGGGGGGGGG
|
||||
|
||||
Room
|
||||
0000000000
|
||||
00t00p0t00
|
||||
0lg00g00gl
|
||||
0l000g000l
|
||||
0lDdDgDdDl
|
||||
GGGGGGGGGG
|
||||
|
||||
Room
|
||||
0000000000
|
||||
00t0000t00
|
||||
@@ -29,3 +54,11 @@ Room
|
||||
00gggggg00
|
||||
0gggggggg0
|
||||
GggggggggG
|
||||
|
||||
Room
|
||||
0000000000
|
||||
00t0000t00
|
||||
00000pd000
|
||||
00gggggg00
|
||||
0gggggggg0
|
||||
GggggggggG
|
||||
@@ -6,6 +6,14 @@ Room
|
||||
0tp00000t0
|
||||
GGGGPPPPGG
|
||||
|
||||
Room
|
||||
0000000000
|
||||
0000000000
|
||||
00t00000t0
|
||||
0000000000
|
||||
0dp0000000
|
||||
GGGGPPPPGG
|
||||
|
||||
Room
|
||||
0000000000
|
||||
0000000000
|
||||
@@ -21,3 +29,11 @@ Room
|
||||
0t000000t0
|
||||
000000p000
|
||||
GPPGPPGPPG
|
||||
|
||||
Room
|
||||
0000000000
|
||||
0000000000
|
||||
0000000000
|
||||
0t000000t0
|
||||
000d00p000
|
||||
GPPGPPGPPG
|
||||
|
||||
@@ -6,6 +6,15 @@ Room
|
||||
0000l0p000
|
||||
GGGGGGGGGG
|
||||
|
||||
Room
|
||||
0000l00000
|
||||
0000l00000
|
||||
0000l00000
|
||||
0t00l000t0
|
||||
000dldp000
|
||||
GGGGGGGGGG
|
||||
|
||||
|
||||
Room
|
||||
0000l00000
|
||||
00t0l00t00
|
||||
@@ -13,3 +22,11 @@ Room
|
||||
0l000000l0
|
||||
0l00p000l0
|
||||
GGGGGGGGGG
|
||||
|
||||
Room
|
||||
0000l00000
|
||||
00t0l00t00
|
||||
0lggggggl0
|
||||
0l000000l0
|
||||
0ld0p000l0
|
||||
GGGGGGGGGG
|
||||
@@ -6,6 +6,14 @@ Room
|
||||
0p00l00000
|
||||
GGPPlPPPGG
|
||||
|
||||
Room
|
||||
0000l00000
|
||||
0000l00000
|
||||
0000l00000
|
||||
0t00l000t0
|
||||
0p00l0d000
|
||||
GGPPlPPPGG
|
||||
|
||||
Room
|
||||
0000l00000
|
||||
0t00l000t0
|
||||
@@ -13,3 +21,11 @@ ggggggglgg
|
||||
0000000l00
|
||||
0000l0pl00
|
||||
GGPPlGGGGG
|
||||
|
||||
Room
|
||||
0000l00000
|
||||
0t00l000t0
|
||||
ggggggglgg
|
||||
0000000l00
|
||||
0d00l0pl00
|
||||
GGPPlGGGGG
|
||||
|
||||
+4
-3
@@ -3,17 +3,18 @@
|
||||
SRCS = \
|
||||
src/Alarm.cpp \
|
||||
src/App.cpp \
|
||||
src/AudioManager.cpp \
|
||||
src/Common.cpp \
|
||||
src/DigitManager.cpp \
|
||||
src/Entity.cpp \
|
||||
src/EntityManager.cpp \
|
||||
src/FileManager.cpp \
|
||||
src/FontManager.cpp \
|
||||
src/Gridmap.cpp \
|
||||
src/Main.cpp \
|
||||
src/RenderManager.cpp \
|
||||
src/RoomEntity.cpp \
|
||||
src/SpriteManager.cpp \
|
||||
src/State.cpp \
|
||||
src/SurfaceManager.cpp \
|
||||
src/FontManager.cpp \
|
||||
src/DigitManager.cpp \
|
||||
src/RoomEntity.cpp \
|
||||
src/Variable.cpp
|
||||
+10
@@ -26,6 +26,7 @@ TApp::TApp() {
|
||||
EntityManager_ = std::make_unique<TEntityManager>(*RenderManager_, 1000 / 60);
|
||||
FontManager_ = std::make_unique<TFontManager>(*SpriteManager_);
|
||||
DigitManager_ = std::make_unique<TDigitManager>(*SpriteManager_);
|
||||
AudioManager_ = std::make_unique<TAudioManager>(*FileManager_);
|
||||
}
|
||||
|
||||
TApp::~TApp() {
|
||||
@@ -43,6 +44,7 @@ void TApp::Process() {
|
||||
RenderManager_->Reset();
|
||||
EntityManager_->Run();
|
||||
RenderManager_->Run();
|
||||
AudioManager_->Run();
|
||||
}
|
||||
|
||||
int TApp::Run() {
|
||||
@@ -86,6 +88,10 @@ TDigitManager& TApp::DigitManager() {
|
||||
return *DigitManager_;
|
||||
}
|
||||
|
||||
TAudioManager& TApp::AudioManager() {
|
||||
return *AudioManager_;
|
||||
}
|
||||
|
||||
const TFileManager& TApp::FileManager() const {
|
||||
return *FileManager_;
|
||||
}
|
||||
@@ -114,4 +120,8 @@ const TDigitManager& TApp::DigitManager() const {
|
||||
return *DigitManager_;
|
||||
}
|
||||
|
||||
const TAudioManager& TApp::AudioManager() const {
|
||||
return *AudioManager_;
|
||||
}
|
||||
|
||||
} // namespace NGame
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "AudioManager.h"
|
||||
#include "DigitManager.h"
|
||||
#include "EntityManager.h"
|
||||
#include "FileManager.h"
|
||||
@@ -35,6 +36,7 @@ public:
|
||||
TSpriteManager& SpriteManager();
|
||||
TFontManager& FontManager();
|
||||
TDigitManager& DigitManager();
|
||||
TAudioManager& AudioManager();
|
||||
|
||||
const TFileManager& FileManager() const;
|
||||
const TRenderManager& RenderManager() const;
|
||||
@@ -43,6 +45,7 @@ public:
|
||||
const TSpriteManager& SpriteManager() const;
|
||||
const TFontManager& FontManager() const;
|
||||
const TDigitManager& DigitManager() const;
|
||||
const TAudioManager& AudioManager() const;
|
||||
|
||||
private:
|
||||
TApp();
|
||||
@@ -57,6 +60,7 @@ private:
|
||||
std::unique_ptr<TSpriteManager> SpriteManager_;
|
||||
std::unique_ptr<TFontManager> FontManager_;
|
||||
std::unique_ptr<TDigitManager> DigitManager_;
|
||||
std::unique_ptr<TAudioManager> AudioManager_;
|
||||
TState State_;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
#include "AudioManager.h"
|
||||
#include <cmath>
|
||||
|
||||
namespace NGame {
|
||||
|
||||
TAudioManager::TAudioManager(TFileManager& fileManager)
|
||||
: FileManager_(fileManager) {
|
||||
|
||||
SDL_AudioSpec desired;
|
||||
desired.freq = 44100;
|
||||
desired.format = AUDIO_F32;
|
||||
desired.channels = 2;
|
||||
desired.samples = 4096;
|
||||
desired.callback = NULL;
|
||||
|
||||
Device_ = SDL_OpenAudioDevice(NULL, 0, &desired, NULL, 0);
|
||||
if (!Device_) {
|
||||
throw std::runtime_error("no audio device");
|
||||
}
|
||||
|
||||
Stream_ = SDL_NewAudioStream(AUDIO_U8, 1, 22050, AUDIO_F32, 2, 44100);
|
||||
if (!Stream_) {
|
||||
throw std::runtime_error("can't create audio stream");
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < 16; ++i) {
|
||||
Channels_[i].InUse = false;
|
||||
}
|
||||
SDL_PauseAudioDevice(Device_, SDL_FALSE);
|
||||
|
||||
LastTick_ = SDL_GetTicks();
|
||||
}
|
||||
|
||||
void TAudioManager::Run() {
|
||||
std::uint32_t currentTick = SDL_GetTicks();
|
||||
|
||||
Paint(Stream_, currentTick - LastTick_);
|
||||
if (SDL_GetQueuedAudioSize(Device_) < 8192) {
|
||||
const int bytesRemaining = SDL_AudioStreamAvailable(Stream_);
|
||||
if (bytesRemaining > 0) {
|
||||
const int samplesRemaining = SDL_min(bytesRemaining, 32 * 1024);
|
||||
static Uint8 convertedBuffer[32 * 1024];
|
||||
auto bytesRead = SDL_AudioStreamGet(Stream_, convertedBuffer, samplesRemaining);
|
||||
SDL_QueueAudio(Device_, convertedBuffer, bytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
LastTick_ = currentTick;
|
||||
}
|
||||
|
||||
void TAudioManager::Play(const std::string& path) {
|
||||
TSound* sound = Load(path);
|
||||
|
||||
for (std::size_t i = 0; i < 16; i++) {
|
||||
if (Channels_[i].InUse) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Channels_[i].InUse = true;
|
||||
Channels_[i].Position = 0;
|
||||
Channels_[i].Sound = sound;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TAudioManager::Paint(SDL_AudioStream* stream, std::uint32_t ticks) {
|
||||
std::uint8_t temporary[512];
|
||||
std::size_t samples = std::min((ticks * 22050 + 999) / 1000, 512u);
|
||||
|
||||
// Mix
|
||||
for (size_t i = 0; i < samples; ++i) {
|
||||
int16_t accumulator = 0;
|
||||
|
||||
for (size_t j = 0; j < 16; j++) {
|
||||
auto& channel = Channels_[j];
|
||||
if (!channel.InUse) {
|
||||
continue;
|
||||
}
|
||||
|
||||
accumulator += channel.Sound->Data[channel.Position];
|
||||
accumulator -= 128;
|
||||
channel.Position++;
|
||||
|
||||
if (channel.Position > channel.Sound->Size) {
|
||||
channel.InUse = false;
|
||||
}
|
||||
}
|
||||
|
||||
accumulator += 128;
|
||||
if (accumulator < 0) {
|
||||
accumulator = 0;
|
||||
}
|
||||
if (accumulator > 255) {
|
||||
accumulator = 255;
|
||||
}
|
||||
|
||||
temporary[i] = accumulator;
|
||||
}
|
||||
|
||||
// Output
|
||||
if (samples > 0) {
|
||||
SDL_AudioStreamPut(stream, temporary, samples * sizeof (std::uint8_t));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
TAudioManager::TSound* TAudioManager::Load(const std::string& path) {
|
||||
auto it = Sounds_.find(path);
|
||||
if (it != Sounds_.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
TSound* newSound = new TSound;
|
||||
auto data = FileManager_.Get(path);
|
||||
SDL_RWops* rw = SDL_RWFromConstMem(data.data(), data.size());
|
||||
if (!SDL_LoadWAV_RW(rw, 1, &newSound->Spec, &newSound->Data, &newSound->Size)) {
|
||||
throw std::runtime_error("can't read WAV file " + path);
|
||||
}
|
||||
|
||||
if (newSound->Spec.channels != 1) {
|
||||
throw std::runtime_error("not mono WAV file " + path);
|
||||
}
|
||||
|
||||
if (newSound->Spec.format != AUDIO_U8) {
|
||||
throw std::runtime_error("not 8bit pcm WAV file " + path);
|
||||
}
|
||||
|
||||
if (newSound->Spec.freq != 22050) {
|
||||
throw std::runtime_error("not 22050hz WAV file " + path);
|
||||
}
|
||||
|
||||
Sounds_[path] = newSound;
|
||||
return newSound;
|
||||
}
|
||||
|
||||
} // namespace NGame
|
||||
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "FileManager.h"
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
namespace NGame {
|
||||
|
||||
class TAudioManager {
|
||||
public:
|
||||
TAudioManager(TFileManager& fileManager);
|
||||
DELETE_COPY(TAudioManager)
|
||||
|
||||
void Run();
|
||||
void Play(const std::string& sound);
|
||||
void Paint(SDL_AudioStream* stream, std::uint32_t ticks);
|
||||
|
||||
private:
|
||||
struct TSound {
|
||||
SDL_AudioSpec Spec;
|
||||
std::uint8_t* Data;
|
||||
std::uint32_t Size;
|
||||
};
|
||||
|
||||
struct TSoundChannel {
|
||||
bool InUse;
|
||||
TSound* Sound;
|
||||
std::uint32_t Position;
|
||||
};
|
||||
|
||||
private:
|
||||
TSound* Load(const std::string& sound);
|
||||
|
||||
private:
|
||||
TFileManager& FileManager_;
|
||||
TSoundChannel Channels_[16];
|
||||
std::unordered_map<std::string, TSound*> Sounds_;
|
||||
SDL_AudioDeviceID Device_;
|
||||
SDL_AudioStream* Stream_;
|
||||
std::uint32_t LastTick_;
|
||||
};
|
||||
|
||||
} // namespace NGame
|
||||
+1
-1
@@ -53,7 +53,7 @@ static void MainLoop(void) {
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
|
||||
+143
-28
@@ -120,6 +120,8 @@ TExplosionEntity::TExplosionEntity(NGame::TEntity::TId id)
|
||||
SetSize({64, 64});
|
||||
Sprite_ = NGame::TApp::Instance()->SpriteManager().Get("Sprites/Light.txt");
|
||||
Alarm_.Set(0, 50);
|
||||
|
||||
App_->AudioManager().Play("Audio/Explosion2.wav");
|
||||
}
|
||||
|
||||
void TExplosionEntity::Update(std::uint32_t delta) {
|
||||
@@ -191,10 +193,15 @@ void TMineEntity::Update(std::uint32_t delta) {
|
||||
switch (State_) {
|
||||
case Dormant:
|
||||
if (!entityManager.IsPlaceEmpty(Position() + Size() / 2 - TriggerRadius_ / 2, TriggerRadius_, HERO_GROUP)) {
|
||||
Remaining_ = rand() % 5 + 5;
|
||||
if (!(Remaining_ % 2)) {
|
||||
Remaining_ += 1;
|
||||
if (App_->State().Variable("InstantMines").Bool()) {
|
||||
Remaining_ = 1;
|
||||
} else {
|
||||
Remaining_ = rand() % 3 + 7;
|
||||
if (!(Remaining_ % 2)) {
|
||||
Remaining_ += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Alarm_.Set(0, 100);
|
||||
State_ = Active;
|
||||
}
|
||||
@@ -232,6 +239,9 @@ void TMineEntity::Alarm(NGame::TAlarm::TId id) {
|
||||
if (Remaining_) {
|
||||
--Remaining_;
|
||||
}
|
||||
if (AlternateBlink_) {
|
||||
App_->AudioManager().Play("Audio/Select.wav");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -671,8 +681,14 @@ THero::THero(NGame::TEntity::TId id)
|
||||
SetSize(NGame::Vec2i(4, 12));
|
||||
SetPosition(NGame::Vec2i(0, 0));
|
||||
SetCollisionGroup(HERO_GROUP);
|
||||
NGame::TApp::Instance()->RenderManager().EnableLight(true);
|
||||
NGame::TApp::Instance()->RenderManager().SetDefaultLightColor(0, 0, 0);
|
||||
|
||||
if (App_->State().Variable("DarkLevel").Bool()) {
|
||||
NGame::TApp::Instance()->RenderManager().EnableLight(true);
|
||||
NGame::TApp::Instance()->RenderManager().SetDefaultLightColor(0, 0, 0);
|
||||
} else {
|
||||
NGame::TApp::Instance()->RenderManager().EnableLight(false);
|
||||
NGame::TApp::Instance()->RenderManager().SetDefaultLightColor(0, 0, 0);
|
||||
}
|
||||
|
||||
Alarm_.Set(0, 100);
|
||||
|
||||
@@ -687,6 +703,9 @@ THero::THero(NGame::TEntity::TId id)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RemainingTime_ = App_->State().Variable("Time").Double();
|
||||
Grenades_ = App_->State().Variable("Grenades").Int();
|
||||
}
|
||||
|
||||
void THero::Input(SDL_Event* event) {
|
||||
@@ -781,16 +800,19 @@ void THero::Update(std::uint32_t delta) {
|
||||
Speed_.X = -100;
|
||||
}
|
||||
if (KeysPressed_[static_cast<int>(EKeys::X)]) {
|
||||
auto entity = entityManager.MakeEntityByName("GrenadeEntity");
|
||||
auto targetEntity = dynamic_cast<TGrenadeEntity*>(entity.get());
|
||||
if (Grenades_) {
|
||||
Grenades_--;
|
||||
auto entity = entityManager.MakeEntityByName("GrenadeEntity");
|
||||
auto targetEntity = dynamic_cast<TGrenadeEntity*>(entity.get());
|
||||
|
||||
targetEntity->SetPosition(Position());
|
||||
if (FaceLeft_) {
|
||||
targetEntity->SetSpeed({-300, 0});
|
||||
} else {
|
||||
targetEntity->SetSpeed({300, 0});
|
||||
targetEntity->SetPosition(Position());
|
||||
if (FaceLeft_) {
|
||||
targetEntity->SetSpeed({-300, 0});
|
||||
} else {
|
||||
targetEntity->SetSpeed({300, 0});
|
||||
}
|
||||
entityManager.UpdateCollision(entity);
|
||||
}
|
||||
entityManager.UpdateCollision(entity);
|
||||
}
|
||||
if (KeysPressed_[static_cast<int>(EKeys::Up)]) {
|
||||
auto otherIds = entityManager.CollisionList(Position(), Size(), PASSAGE_GROUP, Id());
|
||||
@@ -798,18 +820,13 @@ void THero::Update(std::uint32_t delta) {
|
||||
for (auto otherId : otherIds) {
|
||||
auto other = entityManager.Entity(otherId);
|
||||
if (dynamic_cast<TExitEntity*>(other.get())) {
|
||||
App_->State().Variable("Time").SetDouble(RemainingTime_);
|
||||
App_->State().Variable("Grenades").SetInt(Grenades_);
|
||||
entityManager.AddToDeferred("EulaMenu");
|
||||
entityManager.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (KeysPressed_[static_cast<int>(EKeys::C)]) {
|
||||
auto entity = entityManager.MakeEntityByName("FloatingTextEntity");
|
||||
auto targetEntity = dynamic_cast<TFloatingTextEntity*>(entity.get());
|
||||
targetEntity->SetText("You died, LMAO");
|
||||
targetEntity->SetColor(NGame::TFontManager::Red);
|
||||
targetEntity->SetPosition(Position());
|
||||
}
|
||||
|
||||
if (!entityManager.IsPlaceEmpty(Position(), Size(), LADDER_GROUP)) {
|
||||
if (KeysHeld_[static_cast<int>(EKeys::Up)] || KeysHeld_[static_cast<int>(EKeys::Down)]) {
|
||||
@@ -829,6 +846,7 @@ void THero::Update(std::uint32_t delta) {
|
||||
if (KeysPressed_[static_cast<int>(EKeys::Z)]) {
|
||||
Speed_.Y = -std::sqrt(2 * Gravity_ * (16 + (16 - Size().Y)));
|
||||
State_ = EState::Jump;
|
||||
App_->AudioManager().Play("Audio/jump.wav");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -972,6 +990,18 @@ void THero::Update(std::uint32_t delta) {
|
||||
}
|
||||
}
|
||||
|
||||
if (State_ != EState::Dead) {
|
||||
RemainingTime_ -= delta;
|
||||
if (RemainingTime_ < 0) {
|
||||
RemainingTime_ = 0;
|
||||
App_->AudioManager().Play("Audio/Laser.wav");
|
||||
State_ = EState::Dead;
|
||||
if (!Alarm_.IsSet(1)) {
|
||||
Alarm_.Set(1, 3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Explictly check damage sources and flick the body around the screen
|
||||
{
|
||||
auto entityList = entityManager.CollisionList(Position(), Size(), DAMAGE_GROUP, Id());
|
||||
@@ -1009,6 +1039,7 @@ void THero::Update(std::uint32_t delta) {
|
||||
}
|
||||
|
||||
if (previousState != State_) {
|
||||
App_->AudioManager().Play("Audio/Laser.wav");
|
||||
if (!Alarm_.IsSet(1)) {
|
||||
Alarm_.Set(1, 3000);
|
||||
}
|
||||
@@ -1067,7 +1098,11 @@ void THero::Update(std::uint32_t delta) {
|
||||
if (!moveResult.second.second) {
|
||||
// Fall damage
|
||||
if (App_->State().Variable("FallDamage").Bool() && (Position().Y - LastStablePosition_.Y > 40)) {
|
||||
App_->AudioManager().Play("Audio/Laser.wav");
|
||||
State_ = EState::Dead;
|
||||
if (!Alarm_.IsSet(1)) {
|
||||
Alarm_.Set(1, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
Speed_.Y = 0;
|
||||
@@ -1123,6 +1158,16 @@ void THero::Draw() const {
|
||||
auto light = SpriteManager_.Get("Sprites/Light.txt");
|
||||
SpriteManager_.Draw(light, 0, Position() - (light->Frames[0].Size * 4 / 2), {4, 4});
|
||||
|
||||
RenderManager_.SetLayer(NGame::TRenderManager::Interface);
|
||||
RenderManager_.SetColor(0, 0, 0, 128);
|
||||
RenderManager_.DrawRect({0, 0}, {320, 16}, true);
|
||||
App_->DigitManager().Draw({320 - 48 - 2, 2}, RemainingTime_, 6, 3);
|
||||
|
||||
auto itemSprite = SpriteManager_.Get("Sprites/Grenade.txt");
|
||||
for (std::size_t i = 0; i < Grenades_; i++) {
|
||||
SpriteManager_.Draw(itemSprite, 0, NGame::Vec2i(200 + i * 8, 3));
|
||||
}
|
||||
|
||||
if (!App_->State().Variable("NoCompas").Bool()) {
|
||||
auto heroCenter = RenderManager_.Camera() + RenderManager_.Size() / 2;
|
||||
auto delta = ExitPosition_ - heroCenter;
|
||||
@@ -1146,22 +1191,19 @@ void THero::Draw() const {
|
||||
index = 3;
|
||||
}
|
||||
}
|
||||
RenderManager_.SetLayer(NGame::TRenderManager::Interface);
|
||||
|
||||
screenPosition.X = std::min(std::max(screenPosition.X, 0), RenderManager_.Size().X - 16);
|
||||
screenPosition.Y = std::min(std::max(screenPosition.Y, 16), RenderManager_.Size().Y - 16);
|
||||
|
||||
auto arrow = SpriteManager_.Get("Sprites/Arrow.txt");
|
||||
SpriteManager_.Draw(arrow, index, screenPosition);
|
||||
}
|
||||
}
|
||||
|
||||
if (DisplayEnd_) {
|
||||
RenderManager_.SetLayer(NGame::TRenderManager::Interface);
|
||||
App_->FontManager().Draw(NGame::TFontManager::Red, {}, "You are dead! Press X");
|
||||
App_->FontManager().Draw(NGame::TFontManager::Red, {4, 4}, "You are dead! Press X");
|
||||
}
|
||||
|
||||
if (FadeAmount_) {
|
||||
RenderManager_.SetLayer(NGame::TRenderManager::Interface);
|
||||
if (WhiteFade_) {
|
||||
RenderManager_.SetColor(255, 255, 255, FadeAmount_);
|
||||
} else {
|
||||
@@ -1174,6 +1216,9 @@ void THero::Draw() const {
|
||||
void THero::Alarm(NGame::TAlarm::TId id) {
|
||||
if (id == 0) {
|
||||
AlternateRun_ = !AlternateRun_;
|
||||
if (AlternateRun_ && Speed_.X && State_ == EState::Normal) {
|
||||
App_->AudioManager().Play("Audio/Walk.wav");
|
||||
}
|
||||
} else if (id == 1) {
|
||||
DisplayEnd_ = true;
|
||||
}
|
||||
@@ -1268,6 +1313,14 @@ void TMainMenu::Input(SDL_Event* event) {
|
||||
switch (event->type) {
|
||||
case SDL_KEYDOWN:
|
||||
if (event->key.keysym.sym == 'x') {
|
||||
App_->AudioManager().Play("Audio/Pickup.wav");
|
||||
App_->State().Variable("Time").SetDouble(60000);
|
||||
App_->State().Variable("FallDamage").SetBool(false);
|
||||
App_->State().Variable("InstantMines").SetBool(false);
|
||||
App_->State().Variable("LimitedGrenades").SetBool(false);
|
||||
App_->State().Variable("DarkLevel").SetBool(false);
|
||||
App_->State().Variable("NoCompas").SetBool(false);
|
||||
App_->State().Variable("Grenades").SetInt(3);
|
||||
App_->EntityManager().AddToDeferred("RoomEntity");
|
||||
App_->EntityManager().Reset();
|
||||
}
|
||||
@@ -1294,12 +1347,51 @@ TEulaMenu::TEulaMenu(NGame::TEntity::TId id)
|
||||
, RenderManager_(App_->RenderManager())
|
||||
, SpriteManager_(App_->SpriteManager()) {
|
||||
RenderManager_.EnableLight(false);
|
||||
|
||||
std::vector<std::string> toDisableTo;
|
||||
|
||||
if (!App_->State().Variable("FallDamage").Bool()) {
|
||||
toDisableTo.push_back("FallDamage");
|
||||
}
|
||||
if (!App_->State().Variable("InstantMines").Bool()) {
|
||||
toDisableTo.push_back("InstantMines");
|
||||
}
|
||||
if (!App_->State().Variable("LimitedGrenades").Bool()) {
|
||||
toDisableTo.push_back("LimitedGrenades");
|
||||
}
|
||||
if (!App_->State().Variable("DarkLevel").Bool()) {
|
||||
toDisableTo.push_back("DarkLevel");
|
||||
}
|
||||
if (!App_->State().Variable("NoCompas").Bool()) {
|
||||
toDisableTo.push_back("NoCompas");
|
||||
}
|
||||
|
||||
if (!toDisableTo.empty()) {
|
||||
Choice_ = toDisableTo[rand() % toDisableTo.size()];
|
||||
}
|
||||
}
|
||||
|
||||
void TEulaMenu::Input(SDL_Event* event) {
|
||||
switch (event->type) {
|
||||
case SDL_KEYDOWN:
|
||||
if (event->key.keysym.sym == 'x') {
|
||||
if (!Choice_.empty()) {
|
||||
App_->State().Variable(Choice_).SetBool(true);
|
||||
|
||||
if (!App_->State().Variable("LimitedGrenades").Bool()) {
|
||||
App_->State().Variable("Grenades").SetInt(3);
|
||||
}
|
||||
App_->AudioManager().Play("Audio/PowerUp.wav");
|
||||
App_->State().Variable("Time").SetDouble(App_->State().Variable("Time").Double() + 30000);
|
||||
App_->EntityManager().AddToDeferred("RoomEntity");
|
||||
App_->EntityManager().Reset();
|
||||
}
|
||||
}
|
||||
else if (event->key.keysym.sym == 'c') {
|
||||
if (!App_->State().Variable("LimitedGrenades").Bool()) {
|
||||
App_->State().Variable("Grenades").SetInt(3);
|
||||
}
|
||||
App_->AudioManager().Play("Audio/Pickup.wav");
|
||||
App_->EntityManager().AddToDeferred("RoomEntity");
|
||||
App_->EntityManager().Reset();
|
||||
}
|
||||
@@ -1313,11 +1405,33 @@ void TEulaMenu::Update(std::uint32_t delta) {
|
||||
|
||||
void TEulaMenu::Draw() const {
|
||||
RenderManager_.SetLayer(NGame::TRenderManager::Interface);
|
||||
App_->FontManager().Draw(NGame::TFontManager::Gold, {}, "Press X to gain debuff and continue");
|
||||
|
||||
NGame::Vec2i position = {50, 50};
|
||||
std::string text;
|
||||
|
||||
if (Choice_.empty()) {
|
||||
text = "There is nothing that you can do";
|
||||
text += "\n\nPress C to ingore";
|
||||
App_->FontManager().Draw(NGame::TFontManager::Red, position, text);
|
||||
} else {
|
||||
if (Choice_ == "FallDamage") {
|
||||
text = "Gain 30 seconds, but there will be\nfall damage";
|
||||
} else if (Choice_ == "InstantMines") {
|
||||
text = "Gain 30 seconds, but mines will explode\ninstantly";
|
||||
} else if (Choice_ == "LimitedGrenades") {
|
||||
text = "Gain 30 seconds, but grenades will\nno longer replenish";
|
||||
} else if (Choice_ == "DarkLevel") {
|
||||
text = "Gain 30 seconds, but the cave is now\nshrouded in darkness";
|
||||
} else if (Choice_ == "NoCompas") {
|
||||
text = "Gain 30 seconds, but you lose your compass";
|
||||
}
|
||||
text += "\n\nPress X to accept or C to ingore";
|
||||
App_->FontManager().Draw(NGame::TFontManager::Gold, position, text);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TEulaMenu::Alarm(NGame::TAlarm::TId id) {
|
||||
|
||||
}
|
||||
|
||||
TIntroMenu::TIntroMenu(NGame::TEntity::TId id)
|
||||
@@ -1332,6 +1446,7 @@ void TIntroMenu::Input(SDL_Event* event) {
|
||||
switch (event->type) {
|
||||
case SDL_KEYDOWN:
|
||||
if (event->key.keysym.sym == 'x') {
|
||||
App_->AudioManager().Play("Audio/Pickup.wav");
|
||||
App_->EntityManager().AddToDeferred("MainMenu");
|
||||
App_->EntityManager().Reset();
|
||||
}
|
||||
@@ -1419,7 +1534,7 @@ TGrenadeEntity::TGrenadeEntity(NGame::TEntity::TId id)
|
||||
, SpriteManager_(App_->SpriteManager()) {
|
||||
SetSize(9);
|
||||
Sprite_ = NGame::TApp::Instance()->SpriteManager().Get("Sprites/Grenade.txt");
|
||||
Alarm_.Set(0, 3000 + rand() % 1000);
|
||||
Alarm_.Set(0, 1000 + rand() % 1000);
|
||||
Alarm_.Set(1, 100);
|
||||
}
|
||||
|
||||
|
||||
@@ -319,6 +319,8 @@ private:
|
||||
bool DisplayEnd_ = false;
|
||||
bool WhiteFade_ = false;
|
||||
std::size_t FadeAmount_ = 0;
|
||||
double RemainingTime_ = 0;
|
||||
int Grenades_ = 0;
|
||||
};
|
||||
|
||||
class TBackgroundTiler : public NGame::TEntity {
|
||||
@@ -385,6 +387,7 @@ private:
|
||||
NGame::TApp* App_;
|
||||
NGame::TSpriteManager& SpriteManager_;
|
||||
NGame::TRenderManager& RenderManager_;
|
||||
std::string Choice_;
|
||||
};
|
||||
|
||||
class TIntroMenu : public NGame::TEntity {
|
||||
|
||||
Reference in New Issue
Block a user