Added spatial sound effects, fixed a bunch of memory leaks
This commit is contained in:
parent
d3ad840169
commit
93b0c0ea0d
34 changed files with 589 additions and 132 deletions
|
|
@ -26,7 +26,9 @@ SET(FT_DISABLE_ZLIB 1)
|
|||
|
||||
option(GLM_ENABLE_FAST_MATH OFF)
|
||||
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffloat-store -fexcess-precision=standard -ffp-contract=off")
|
||||
# -fsanitize=address I will forget, renable this flag no more leaks allowed!
|
||||
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -ffloat-store -fexcess-precision=standard -ffp-contract=off")
|
||||
|
||||
FetchContent_Declare(
|
||||
tracy
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -3,18 +3,18 @@
|
|||
<scene type="shooter" id="000" bg="backgrounds/blue_sky.png">
|
||||
<map name="newmap"/>
|
||||
<entities>
|
||||
<player x="7" y="5" weapon="shotgun">
|
||||
<player x="7" y="5" weapon="gun/machine">
|
||||
<animation id="character/player"/>
|
||||
</player>
|
||||
<entity x="10" y="3" weapon="pistol">
|
||||
<entity x="10" y="3" weapon="gun/pistol">
|
||||
<animation id="character/player"/>
|
||||
<script file="scripts/ai/grunt_behaviour.lua"/>
|
||||
</entity>
|
||||
<entity x="6" y="3" weapon="pistol">
|
||||
<entity x="6" y="3" weapon="gun/pistol">
|
||||
<animation id="character/tmp"/>
|
||||
<script file="scripts/ai/grunt_behaviour.lua"/>
|
||||
</entity>
|
||||
<entity x="5" y="3" weapon="pistol">
|
||||
<entity x="5" y="3" weapon="gun/pistol">
|
||||
<animation id="character/tmp"/>
|
||||
<script file="scripts/ai/grunt_behaviour.lua"/>
|
||||
</entity>
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<weapons>
|
||||
<weapon name="bubblegun" fireSpeed="100.0" maxAmmo="40000" clipSize="1000">
|
||||
<weapon id="gun/machine" fireSpeed="100.0" maxAmmo="40000" clipSize="1000">
|
||||
<bullet anim="obj/bubble">
|
||||
<spread>60</spread>
|
||||
<speed>20.0</speed>
|
||||
|
|
@ -11,9 +11,9 @@
|
|||
</bullet>
|
||||
</weapon>
|
||||
|
||||
<weapon name="shotgun" fireSpeed="1750.0" maxAmmo="64" clipSize="4">
|
||||
<weapon id="gun/shotgun" fireSpeed="1750.0" maxAmmo="64" clipSize="4">
|
||||
<script file="scripts/weapons/shotgun_script.lua"/>
|
||||
<animation id="gun/shotgun">
|
||||
<animation>
|
||||
<size x="55.0" y="55.0"/>
|
||||
<offset x="-30.0" y="0.0"/>
|
||||
</animation>
|
||||
|
|
@ -26,8 +26,8 @@
|
|||
</bullet>
|
||||
</weapon>
|
||||
|
||||
<weapon name="machine_gun" fireSpeed="50.0" maxAmmo="512" clipSize="64">
|
||||
<animation id="gun/machine">
|
||||
<weapon id="gun/machine" fireSpeed="50.0" maxAmmo="512" clipSize="64">
|
||||
<animation>
|
||||
<size x="55.0" y="55.0"/>
|
||||
<offset x="-30.0" y="0.0"/>
|
||||
</animation>
|
||||
|
|
@ -40,8 +40,8 @@
|
|||
</bullet>
|
||||
</weapon>
|
||||
|
||||
<weapon name="pistol" fireSpeed="750.0" maxAmmo="512" clipSize="21">
|
||||
<animation id="gun/pistol">
|
||||
<weapon id="gun/pistol" fireSpeed="750.0" maxAmmo="512" clipSize="21">
|
||||
<animation>
|
||||
<size x="55.0" y="55.0"/>
|
||||
<offset x="-30.0" y="0.0"/>
|
||||
</animation>
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ add_executable (YuppleMayham
|
|||
"src/sound/engine.cpp"
|
||||
"src/sound/audiostream.cpp"
|
||||
"src/sound/soundeffect.cpp"
|
||||
"src/sound/soundmanager.cpp"
|
||||
"include/thirdparty/stb_vorbis.c"
|
||||
"src/utility/data/font_data.c"
|
||||
"src/utility/ftfont.cpp"
|
||||
|
|
|
|||
|
|
@ -17,25 +17,25 @@ enum class AIState {
|
|||
Patrol
|
||||
};
|
||||
|
||||
class AI : public std::enable_shared_from_this<AI> {
|
||||
class AI {
|
||||
public:
|
||||
AI(const std::shared_ptr<GameActor>& actor, const std::shared_ptr<Raycaster>& raycaster);
|
||||
AI(GameActor* actor, std::unique_ptr<Raycaster> raycaster);
|
||||
void update();
|
||||
|
||||
void setTarget(const std::shared_ptr<GameActor>& target) { this->target = target; }
|
||||
void attachBehaviourScript(const std::shared_ptr<AIScript>& behaviour);
|
||||
void setTarget(GameActor* target) { this->target = target; }
|
||||
void attachBehaviourScript(std::unique_ptr<AIScript> behaviour);
|
||||
|
||||
AIState getState() const { return state; }
|
||||
void setState(AIState state) { this->state = state; }
|
||||
|
||||
~AI() {}
|
||||
~AI();
|
||||
|
||||
private:
|
||||
AIState state;
|
||||
std::shared_ptr<Raycaster> raycaster;
|
||||
std::shared_ptr<AIScript> behaviour;
|
||||
std::shared_ptr<GameActor> actor;
|
||||
std::shared_ptr<GameActor> target;
|
||||
std::unique_ptr<Raycaster> raycaster;
|
||||
std::unique_ptr<AIScript> behaviour;
|
||||
GameActor* actor;
|
||||
GameActor* target;
|
||||
|
||||
// cache our lua function calls
|
||||
sol::function idleFunc;
|
||||
|
|
|
|||
|
|
@ -62,12 +62,12 @@ class InputHandler : public Keyboard, public Mouse
|
|||
{
|
||||
private:
|
||||
struct CommandWithDelay{
|
||||
Command* cmd;
|
||||
std::unique_ptr<Command> cmd;
|
||||
Uint32 lastExecution;
|
||||
Uint32 delay;
|
||||
};
|
||||
struct MouseCommandWithDelay{
|
||||
MouseCommand* cmd;
|
||||
std::unique_ptr<MouseCommand> cmd;
|
||||
Uint32 lastExecution;
|
||||
Uint32 delay;
|
||||
};
|
||||
|
|
@ -80,29 +80,31 @@ public:
|
|||
this->actor = actor;
|
||||
}
|
||||
|
||||
void bindKeyCommand(SDL_Keycode key, Uint32 delay, Command* command) {
|
||||
keyCommands[key] = { command, 0, delay };
|
||||
void bindKeyCommand(SDL_Keycode key, Uint32 delay, std::unique_ptr<Command> command) {
|
||||
keyCommands[key] = { std::move(command), 0, delay };
|
||||
}
|
||||
void bindMouseCommand(Uint8 mouse, Uint32 delay, MouseCommand* command) {
|
||||
mouseCommands[mouse] = { command, 0, delay };
|
||||
void bindMouseCommand(Uint8 mouse, Uint32 delay, std::unique_ptr<MouseCommand> command) {
|
||||
mouseCommands[mouse] = { std::move(command), 0, delay };
|
||||
}
|
||||
void bindMouseMotion(MouseCommand* command) {
|
||||
mouseMotionCommand = command;
|
||||
void bindMouseMotion(std::unique_ptr<MouseCommand> command) {
|
||||
mouseMotionCommand = std::move(command);
|
||||
}
|
||||
void bindMouseScroll(MouseCommand* command) {
|
||||
mouseScrollCommand = command;
|
||||
void bindMouseScroll(std::unique_ptr<MouseCommand> command) {
|
||||
mouseScrollCommand = std::move(command);
|
||||
}
|
||||
void handleInput();
|
||||
void executeCommands();
|
||||
|
||||
~InputHandler();
|
||||
|
||||
private:
|
||||
GameActor* actor = nullptr;
|
||||
std::unordered_map<SDL_Keycode, CommandWithDelay> keyCommands;
|
||||
std::unordered_map<Uint8, MouseCommandWithDelay> mouseCommands;
|
||||
std::vector<Command*> commandQueue;
|
||||
std::vector<MouseCommand*> mouseQueue;
|
||||
MouseCommand* mouseMotionCommand = nullptr;
|
||||
MouseCommand* mouseScrollCommand = nullptr;
|
||||
std::unique_ptr<MouseCommand> mouseMotionCommand = nullptr;
|
||||
std::unique_ptr<MouseCommand> mouseScrollCommand = nullptr;
|
||||
};
|
||||
|
||||
#endif // _H_INPUT_H
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ public:
|
|||
void putaway() { wielded = false; }
|
||||
|
||||
void addComponent(std::unique_ptr<Component> component);
|
||||
void attachScript(const std::shared_ptr<WeaponScript>& script);
|
||||
void attachScript(std::unique_ptr<WeaponScript> script);
|
||||
void hookEventManager(std::weak_ptr<EventManager> eventManager);
|
||||
bool shoot();
|
||||
void reload();
|
||||
|
|
@ -69,6 +69,8 @@ public:
|
|||
|
||||
const BulletManager* getBulletManager() { return bulletManager.get(); }
|
||||
|
||||
~Weapon();
|
||||
|
||||
private:
|
||||
void adjustWeapon();
|
||||
|
||||
|
|
@ -104,7 +106,7 @@ private:
|
|||
Direction lastDir;
|
||||
|
||||
std::vector <std::unique_ptr<Component>> components;
|
||||
std::shared_ptr<WeaponScript> weaponScript;
|
||||
std::unique_ptr<WeaponScript> weaponScript;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ public:
|
|||
const TextureArray* getTextureArray() { return textures; }
|
||||
const Texture* getTexture() { return texture; }
|
||||
|
||||
~TileTextureInstance();
|
||||
|
||||
private:
|
||||
void setup() override;
|
||||
TextureArray* textures = nullptr;
|
||||
|
|
|
|||
|
|
@ -38,14 +38,14 @@ public:
|
|||
|
||||
void bind();
|
||||
|
||||
TextureData* operator[](const size_t index) {
|
||||
TextureData operator[](const size_t index) {
|
||||
try
|
||||
{
|
||||
return textures.at(index);
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
return nullptr;
|
||||
return { 0, 0 };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ private:
|
|||
|
||||
size_t numOfLayers;
|
||||
unsigned ID = 0;
|
||||
std::vector<TextureData*> textures;
|
||||
std::vector<TextureData> textures;
|
||||
int canvasWidth = 0;
|
||||
int canvasHeight = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,27 +4,35 @@
|
|||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#include <memory>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "utility/events.h"
|
||||
#include "sound/audiostream.h"
|
||||
#include "sound/soundmanager.h"
|
||||
#include "utility/resourcemanager.h"
|
||||
#include "utility/logger.h"
|
||||
|
||||
class AudioEngine
|
||||
class AudioEngine : public std::enable_shared_from_this<AudioEngine>
|
||||
{
|
||||
public:
|
||||
AudioEngine(std::weak_ptr<ResourceManager> _resource);
|
||||
|
||||
void hookEventManager(std::weak_ptr<EventManager> _events);
|
||||
void hookSceneManager(std::weak_ptr<EventManager> _events);
|
||||
void pushMusic(std::string _songName);
|
||||
void playMusic();
|
||||
void pauseMusic();
|
||||
void killMusic();
|
||||
|
||||
void poll();
|
||||
void updateListener(const glm::vec3& pos);
|
||||
|
||||
~AudioEngine();
|
||||
private:
|
||||
std::unique_ptr<AudioStream> musicPlayer;
|
||||
std::unique_ptr<SoundManager> soundManager;
|
||||
std::weak_ptr<EventManager> globalEventManager;
|
||||
std::weak_ptr<EventManager> sceneEventManager;
|
||||
std::weak_ptr<ResourceManager> resourceManager;
|
||||
ALCdevice *device;
|
||||
ALCcontext *context;
|
||||
|
|
|
|||
25
YuppleMayham/include/sound/soundmanager.h
Normal file
25
YuppleMayham/include/sound/soundmanager.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef _H_SOUNDMANAGER_H
|
||||
#define _H_SOUNDMANAGER_H
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <array>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
class SoundManager
|
||||
{
|
||||
public:
|
||||
SoundManager();
|
||||
void playSound(ALuint buffer, int priority=10, const glm::vec3& pos = glm::vec3(0));
|
||||
void pollSources();
|
||||
~SoundManager();
|
||||
private:
|
||||
struct AudioSource {
|
||||
ALuint source;
|
||||
bool inUse;
|
||||
int priority;
|
||||
};
|
||||
std::array<AudioSource, 10> sources;
|
||||
std::size_t lastUsed = 0;
|
||||
};
|
||||
|
||||
#endif // _H_SOUNDMANAGER_H
|
||||
|
|
@ -30,6 +30,14 @@ namespace UTIL
|
|||
return (pos != std::string::npos) ? id.substr(pos + 1) : id;
|
||||
};
|
||||
|
||||
constexpr auto get_generic = [](const std::string& id) {
|
||||
size_t left = 0;
|
||||
size_t right = 0;
|
||||
std::string out;
|
||||
split(id, &left, &right, &out);
|
||||
return (out + "/generic/" + get_type(id));
|
||||
};
|
||||
|
||||
void flip_surface(SDL_Surface* surface);
|
||||
std::string parsePrefix(const std::string& id);
|
||||
|
||||
|
|
|
|||
|
|
@ -145,6 +145,8 @@ public:
|
|||
void idle() override { /*unused*/ }
|
||||
TYPE getType() const override { return TYPE::AI; }
|
||||
|
||||
~AIComponent() { }
|
||||
|
||||
private:
|
||||
std::shared_ptr<AI> ai;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ public:
|
|||
xmlLoader->loadTileSets("maps/tilesets");
|
||||
xmlLoader->loadMaps("maps");
|
||||
xmlLoader->loadScenes("scenes");
|
||||
xmlLoader->loadSoundEffects("sounds");
|
||||
shaders["__fallback__"] = std::make_unique<GenericShader>();
|
||||
};
|
||||
|
||||
|
|
@ -39,8 +40,9 @@ public:
|
|||
Sprite* loadSpriteStatic (const std::string& path);
|
||||
// Returns a NON-OWNING pointer to a background
|
||||
Background* loadBackground (const std::string& path);
|
||||
std::shared_ptr<AIScript> loadAIScript (const std::string& path);
|
||||
std::shared_ptr<WeaponScript> loadWeaponScript (const std::string& path);
|
||||
const unsigned loadSoundEffect (const std::string& id);
|
||||
std::unique_ptr<AIScript> loadAIScript (const std::string& path);
|
||||
std::unique_ptr<WeaponScript> loadWeaponScript (const std::string& path);
|
||||
std::shared_ptr<Weapon> loadWeapon (const std::string& name, const unsigned weaponShaderID, const unsigned bulletShaderID);
|
||||
std::shared_ptr<AnimationSet> loadAnimationSet (const std::string& name, int entityid = 0);
|
||||
|
||||
|
|
@ -61,7 +63,7 @@ private:
|
|||
std::unordered_map<std::string, std::unique_ptr<SoundEffect>> sounds;
|
||||
std::unordered_map<std::string, std::unique_ptr<Sprite>> sprites;
|
||||
std::unordered_map<std::string, std::shared_ptr<Weapon>> weapons;
|
||||
std::unordered_map<std::string, std::shared_ptr<Script>> scripts;
|
||||
//std::unordered_map<std::string, std::string> scripts;
|
||||
std::unordered_map<std::string, std::unique_ptr<Background>> backgrounds;
|
||||
std::unordered_map<std::string, std::shared_ptr<TileSetData>> tileSets;
|
||||
//std::unordered_map<std::string, std::shared_ptr<EntityData>> entityData;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ class Script {
|
|||
public:
|
||||
sol::state lua;
|
||||
Script(const std::string& path);
|
||||
virtual ~Script() {};
|
||||
~Script();
|
||||
private:
|
||||
bool loadScript(const std::string& path) {
|
||||
auto result = lua.script_file(path);
|
||||
|
|
@ -29,6 +29,8 @@ class AIScript : public Script {
|
|||
public:
|
||||
AIScript(const std::string& path) : Script(path) { registerUserTypes(); }
|
||||
|
||||
~AIScript();
|
||||
|
||||
private:
|
||||
|
||||
void registerUserTypes() ;
|
||||
|
|
@ -37,6 +39,7 @@ private:
|
|||
class WeaponScript : public Script {
|
||||
public:
|
||||
WeaponScript(const std::string& path) : Script(path) { registerUserTypes(); }
|
||||
~WeaponScript();
|
||||
private:
|
||||
void registerUserTypes() ;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -72,13 +72,12 @@ struct SceneData {
|
|||
};
|
||||
|
||||
struct WeaponData {
|
||||
std::string name;
|
||||
std::string id;
|
||||
float fireSpeed = 250.0f;
|
||||
int clipSize = 21;
|
||||
int maxAmmo = 512;
|
||||
std::string script = "";
|
||||
std::string graphic;
|
||||
std::string animPrefix;
|
||||
bool animated = false;
|
||||
float sizeX = 50.f, sizeY = 50.f;
|
||||
float offsetX = 0.f, offsetY = 0.f;
|
||||
|
|
@ -118,6 +117,7 @@ public:
|
|||
bool loadAnimations(const char* animationFolder);
|
||||
bool loadTileSets(const char* tileSetFolder);
|
||||
bool loadMaps(const char* mapFolder);
|
||||
bool loadSoundEffects(const char* soundFolder);
|
||||
|
||||
const SceneData* getSceneData(const std::string& id) const {
|
||||
try {
|
||||
|
|
@ -137,9 +137,9 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
const WeaponData* getWeaponData(const std::string& name) const {
|
||||
const WeaponData* getWeaponData(const std::string& id) const {
|
||||
try {
|
||||
return weapons.at(name).get();
|
||||
return weapons.at(id).get();
|
||||
}
|
||||
catch (std::exception&) {
|
||||
return nullptr;
|
||||
|
|
@ -164,6 +164,15 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
const SoundData* getSoundData(const std::string& id) const {
|
||||
try {
|
||||
return sounds.at(id).get();
|
||||
}
|
||||
catch (std::exception&) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// return a full set of animations, may need further optimization.
|
||||
// one idea is when loading animations we create a seperate map that holds each set by their reference, so we can just do a simple,
|
||||
// hash table lookup.
|
||||
|
|
@ -189,6 +198,7 @@ private:
|
|||
std::unordered_map<std::string, std::unique_ptr<AnimationData>> animations;
|
||||
std::unordered_map<std::string, std::unique_ptr<MapData>> maps;
|
||||
std::unordered_map<std::string, std::unique_ptr<TileSetData>> tileSets;
|
||||
std::unordered_map<std::string, std::unique_ptr<SoundData>> sounds;
|
||||
};
|
||||
|
||||
#endif // _H_XMLLOADER_H
|
||||
|
|
|
|||
134
YuppleMayham/src/gameplay/'
Normal file
134
YuppleMayham/src/gameplay/'
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
#include "gameplay/game.h"
|
||||
#include "gameplay/input.h"
|
||||
#include "gameplay/scene.h"
|
||||
/*due for possible removal!*/
|
||||
#include "gameplay/gameactor.h"
|
||||
#include "gameplay/weapons/weapon.h"
|
||||
/*-------------------------*/
|
||||
|
||||
#include "utility/command.h"
|
||||
#include "utility/resourcemanager.h"
|
||||
#include "utility/ftfont.h"
|
||||
#include "utility/logger.h"
|
||||
|
||||
#include "graphics/glwindow.h"
|
||||
|
||||
#include "sound/engine.h"
|
||||
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <memory>
|
||||
#include <utility/events.h>
|
||||
|
||||
bool Game::init()
|
||||
{
|
||||
window = std::make_shared<GLWindow>("Yupple Mayham", 800, 600);
|
||||
|
||||
if (!window->Init())
|
||||
ERROR_LOG("Failed to init GLWindow: {}", SDL_GetError());
|
||||
|
||||
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
|
||||
ERROR_LOG("Failed to load GLLoader", NULL);
|
||||
|
||||
#if _DEBUG
|
||||
LOG_LEVEL(DEBUG);
|
||||
#else
|
||||
LOG_LEVEL(INFO);
|
||||
#endif
|
||||
|
||||
SDL_GL_SetSwapInterval(1);
|
||||
glViewport(0, 0, window->width(), window->height());
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// For now we'll init default bindings, but as we move forward controls will be set by the player and saved in controls.xml
|
||||
inputHandler = std::make_shared<InputHandler>();
|
||||
inputHandler->bindKeyCommand(SDLK_w, 0, new MoveUpCommand());
|
||||
inputHandler->bindKeyCommand(SDLK_a, 0, new MoveLeftCommand());
|
||||
inputHandler->bindKeyCommand(SDLK_s, 0, new MoveDownCommand());
|
||||
inputHandler->bindKeyCommand(SDLK_d, 0, new MoveRightCommand());
|
||||
|
||||
inputHandler->bindMouseCommand(MOUSE_BUTTON_LEFT, 100, new ShootCommand());
|
||||
inputHandler->bindMouseMotion(new FollowMouseCommand());
|
||||
inputHandler->bindMouseScroll(new CycleCommand());
|
||||
|
||||
game_state |= GAME_RUNNING;
|
||||
globalEventManager = std::make_shared<EventManager>();
|
||||
resourceManager = std::make_shared<ResourceManager>();
|
||||
renderer = std::make_shared<Renderer>(resourceManager);
|
||||
audioEngine = std::make_shared<AudioEngine>(resourceManager);
|
||||
audioEngine->hookEventManager(globalEventManager);
|
||||
/* Testing */
|
||||
audioEngine->pushMusic("music/short_song.ogg");
|
||||
audioEngine->pushMusic("music/bright.ogg");
|
||||
audioEngine->pushMusic("music/main_song.ogg");
|
||||
audioEngine->playMusic();
|
||||
/* */
|
||||
renderer->hookEventManager(globalEventManager);
|
||||
textHandler = std::make_shared<Text>();
|
||||
if (!textHandler->loadFonts("fonts"))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
const unsigned Game::getWindowWidth() const { return window->width(); }
|
||||
const unsigned Game::getWindowHeight() const { return window->height(); }
|
||||
|
||||
bool Game::loadDebugScene()
|
||||
{
|
||||
currentScene = std::make_shared<Scene>(SCENE_SHOOTER, resourceManager, globalEventManager);
|
||||
currentScene->init();
|
||||
audioEngine->hookSceneManager(currentScene->getEventManager());
|
||||
if (currentScene->getPlayer() == nullptr)
|
||||
return false;
|
||||
inputHandler->setActor(currentScene->getPlayer().get());
|
||||
return true;
|
||||
}
|
||||
|
||||
void Game::captureInput(SDL_Event& e)
|
||||
{
|
||||
inputHandler->captureInput(e);
|
||||
}
|
||||
|
||||
void Game::executeInputs()
|
||||
{
|
||||
inputHandler->handleInput();
|
||||
inputHandler->executeCommands();
|
||||
}
|
||||
|
||||
void Game::update(double deltaTime)
|
||||
{
|
||||
if (currentScene)
|
||||
currentScene->update(deltaTime);
|
||||
audioEngine->poll();
|
||||
}
|
||||
|
||||
void Game::render()
|
||||
{
|
||||
glClearColor(0.05f, 0.25f, 0.05f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
if (currentScene)
|
||||
{
|
||||
currentScene->render(renderer);
|
||||
/*Debug ammo indicator*/
|
||||
textHandler->DrawText("comic.ttf", std::to_string(currentScene->getPlayer()->getHeldWeapon()->getMagazine()), glm::vec2(10, 10), 0.5f);
|
||||
textHandler->DrawText("comic.ttf", "/", glm::vec2(50, 10), 0.5f);
|
||||
textHandler->DrawText("comic.ttf", std::to_string(currentScene->getPlayer()->getHeldWeapon()->getAmmo()), glm::vec2(90, 10), 0.5f);
|
||||
}
|
||||
|
||||
window->swap();
|
||||
}
|
||||
|
||||
void Game::quit()
|
||||
{
|
||||
game_state = GAME_QUITTING;
|
||||
}
|
||||
|
||||
Game::~Game()
|
||||
{
|
||||
if (audioEngine) {
|
||||
audioEngine->killMusic();
|
||||
}
|
||||
resourceManager->clearResources();
|
||||
}
|
||||
|
|
@ -4,18 +4,18 @@
|
|||
#include "utility/raycaster.h"
|
||||
#include "utility/script.h"
|
||||
|
||||
AI::AI(const std::shared_ptr<GameActor>& actor, const std::shared_ptr<Raycaster>& raycaster)
|
||||
: state(AIState::Idle), raycaster(raycaster), actor(actor),
|
||||
AI::AI(GameActor* actor, std::unique_ptr<Raycaster> raycaster)
|
||||
: state(AIState::Idle), raycaster(std::move(raycaster)), actor(actor),
|
||||
lastGCTime(std::chrono::high_resolution_clock::now()), GCTimeout(3)
|
||||
{}
|
||||
|
||||
void AI::attachBehaviourScript(const std::shared_ptr<AIScript>& behaviour)
|
||||
void AI::attachBehaviourScript(std::unique_ptr<AIScript> behaviour)
|
||||
{
|
||||
// passing out instance of raycaster and this AI into our scripting api
|
||||
// pay special attention each ai script has control of only their own instance of ai!
|
||||
this->behaviour = behaviour;
|
||||
this->behaviour->lua["raycaster"] = raycaster;
|
||||
this->behaviour->lua["ai"] = sol::make_reference(this->behaviour->lua, shared_from_this());
|
||||
this->behaviour = std::move(behaviour);
|
||||
this->behaviour->lua["raycaster"] = sol::make_reference(this->behaviour->lua, raycaster.get());
|
||||
this->behaviour->lua["ai"] = sol::make_reference(this->behaviour->lua, this);
|
||||
|
||||
idleFunc = this->behaviour->lua["idle"];
|
||||
patrolFunc = this->behaviour->lua["patrol"];
|
||||
|
|
@ -25,6 +25,7 @@ void AI::attachBehaviourScript(const std::shared_ptr<AIScript>& behaviour)
|
|||
void AI::update()
|
||||
{
|
||||
try {
|
||||
if (actor && target) {
|
||||
switch (state)
|
||||
{
|
||||
case AIState::Idle:
|
||||
|
|
@ -61,6 +62,7 @@ void AI::update()
|
|||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::chrono::high_resolution_clock::time_point curTime = std::chrono::high_resolution_clock::now();
|
||||
if (curTime - lastGCTime >= GCTimeout)
|
||||
{
|
||||
|
|
@ -73,3 +75,13 @@ void AI::update()
|
|||
state = AIState::Idle;
|
||||
}
|
||||
}
|
||||
|
||||
AI::~AI()
|
||||
{
|
||||
behaviour->lua["raycaster"] = sol::nil;
|
||||
behaviour->lua["ai"] = sol::nil;
|
||||
behaviour->lua["idle"] = sol::nil;
|
||||
behaviour->lua["patrol"] = sol::nil;
|
||||
behaviour->lua["alert"] = sol::nil;
|
||||
behaviour->lua.collect_gc();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <utility/events.h>
|
||||
|
||||
bool Game::init()
|
||||
|
|
@ -43,14 +44,14 @@ bool Game::init()
|
|||
|
||||
// For now we'll init default bindings, but as we move forward controls will be set by the player and saved in controls.xml
|
||||
inputHandler = std::make_shared<InputHandler>();
|
||||
inputHandler->bindKeyCommand(SDLK_w, 0, new MoveUpCommand());
|
||||
inputHandler->bindKeyCommand(SDLK_a, 0, new MoveLeftCommand());
|
||||
inputHandler->bindKeyCommand(SDLK_s, 0, new MoveDownCommand());
|
||||
inputHandler->bindKeyCommand(SDLK_d, 0, new MoveRightCommand());
|
||||
inputHandler->bindKeyCommand(SDLK_w, 0, std::make_unique<MoveUpCommand>());
|
||||
inputHandler->bindKeyCommand(SDLK_a, 0, std::make_unique<MoveLeftCommand>());
|
||||
inputHandler->bindKeyCommand(SDLK_s, 0, std::make_unique<MoveDownCommand>());
|
||||
inputHandler->bindKeyCommand(SDLK_d, 0, std::make_unique<MoveRightCommand>());
|
||||
|
||||
inputHandler->bindMouseCommand(MOUSE_BUTTON_LEFT, 100, new ShootCommand());
|
||||
inputHandler->bindMouseMotion(new FollowMouseCommand());
|
||||
inputHandler->bindMouseScroll(new CycleCommand());
|
||||
inputHandler->bindMouseCommand(MOUSE_BUTTON_LEFT, 100, std::make_unique<ShootCommand>());
|
||||
inputHandler->bindMouseMotion(std::make_unique<FollowMouseCommand>());
|
||||
inputHandler->bindMouseScroll(std::make_unique<CycleCommand>());
|
||||
|
||||
game_state |= GAME_RUNNING;
|
||||
globalEventManager = std::make_shared<EventManager>();
|
||||
|
|
@ -78,6 +79,7 @@ bool Game::loadDebugScene()
|
|||
{
|
||||
currentScene = std::make_shared<Scene>(SCENE_SHOOTER, resourceManager, globalEventManager);
|
||||
currentScene->init();
|
||||
audioEngine->hookSceneManager(currentScene->getEventManager());
|
||||
if (currentScene->getPlayer() == nullptr)
|
||||
return false;
|
||||
inputHandler->setActor(currentScene->getPlayer().get());
|
||||
|
|
@ -97,8 +99,12 @@ void Game::executeInputs()
|
|||
|
||||
void Game::update(double deltaTime)
|
||||
{
|
||||
if (currentScene)
|
||||
if (currentScene) {
|
||||
currentScene->update(deltaTime);
|
||||
if (auto player = currentScene->getPlayer())
|
||||
audioEngine->updateListener(player->getPosition());
|
||||
}
|
||||
audioEngine->poll();
|
||||
}
|
||||
|
||||
void Game::render()
|
||||
|
|
@ -121,12 +127,12 @@ void Game::render()
|
|||
void Game::quit()
|
||||
{
|
||||
game_state = GAME_QUITTING;
|
||||
if (audioEngine) {
|
||||
audioEngine->killMusic();
|
||||
}
|
||||
}
|
||||
|
||||
Game::~Game()
|
||||
{
|
||||
if (audioEngine) {
|
||||
audioEngine->killMusic();
|
||||
}
|
||||
resourceManager->clearResources();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ void InputHandler::handleInput()
|
|||
{
|
||||
if (currentTime - command.lastExecution >= command.delay)
|
||||
{
|
||||
commandQueue.push_back(command.cmd);
|
||||
commandQueue.push_back(command.cmd.get());
|
||||
command.lastExecution = currentTime;
|
||||
}
|
||||
}
|
||||
|
|
@ -28,7 +28,7 @@ void InputHandler::handleInput()
|
|||
{
|
||||
if (currentTime - command.lastExecution >= command.delay)
|
||||
{
|
||||
mouseQueue.push_back(command.cmd);
|
||||
mouseQueue.push_back(command.cmd.get());
|
||||
command.lastExecution = currentTime;
|
||||
}
|
||||
}
|
||||
|
|
@ -52,3 +52,7 @@ void InputHandler::executeCommands()
|
|||
commandQueue.clear();
|
||||
mouseQueue.clear();
|
||||
}
|
||||
|
||||
InputHandler::~InputHandler()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "graphics/animation.h"
|
||||
#include "graphics/background.h"
|
||||
|
||||
#include "utility/script.h"
|
||||
#include "utility/component.h"
|
||||
#include "utility/ftfont.h"
|
||||
#include "utility/xmlloader.h"
|
||||
|
|
@ -88,7 +89,7 @@ void Scene::loadDebugShooterScene()
|
|||
auto entitySprite = resourceManager->loadSpriteStatic(entityData.graphic);
|
||||
entity->addComponent(std::make_unique<SpriteComponent>(entitySprite));
|
||||
}
|
||||
auto defaultWeapon = resourceManager->loadWeapon("pistol", weaponShader, bubbleShader);
|
||||
auto defaultWeapon = resourceManager->loadWeapon("gun/pistol", weaponShader, bubbleShader);
|
||||
auto entityWeapon = resourceManager->loadWeapon(entityData.weapon, weaponShader, bubbleShader);
|
||||
|
||||
entity->pickupWeapon(defaultWeapon);
|
||||
|
|
@ -115,11 +116,11 @@ void Scene::loadDebugShooterScene()
|
|||
// attach ai
|
||||
if (!entityData.script.empty())
|
||||
{
|
||||
auto behaviourScript = resourceManager->loadAIScript(entityData.script);
|
||||
auto rayCaster = std::make_shared<Raycaster>(40.f, 300.f, map->getCollisionMap(), mapData->tileSize);
|
||||
auto ai = std::make_shared<AI>(entity, rayCaster);
|
||||
ai->setTarget(player);
|
||||
ai->attachBehaviourScript(behaviourScript);
|
||||
auto behaviour = resourceManager->loadAIScript(entityData.script);
|
||||
auto rayCaster = std::make_unique<Raycaster>(40.f, 300.f, map->getCollisionMap(), mapData->tileSize);
|
||||
auto ai = std::make_shared<AI>(entity.get(), std::move(rayCaster));
|
||||
ai->setTarget(player.get());
|
||||
ai->attachBehaviourScript(std::move(behaviour));
|
||||
entity->addComponent(std::make_unique<AIComponent>(ai));
|
||||
}
|
||||
}
|
||||
|
|
@ -173,6 +174,7 @@ void Scene::render(std::shared_ptr<Renderer> renderer)
|
|||
}
|
||||
|
||||
renderer->render();
|
||||
/*
|
||||
for (const auto& bullet : player->getHeldWeapon()->getBulletManager()->getBullets()) {
|
||||
DebugDrawer::getInstance().addLine(player->getCenter(), bullet->getCenter(), glm::vec4(1.f, 0.f, 0.f, 0.f));
|
||||
DEBUG_TEXT(
|
||||
|
|
@ -203,6 +205,7 @@ void Scene::render(std::shared_ptr<Renderer> renderer)
|
|||
bullet->getPhysicsComponent()->rigidBody.velocity.x,
|
||||
bullet->getPhysicsComponent()->rigidBody.velocity.y);
|
||||
}
|
||||
*/
|
||||
DebugDrawer::getInstance().draw(camera->getProjectionMatrix() * camera->getViewMatrix());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
Weapon::Weapon(const WeaponData* data, const unsigned weaponShaderID, const unsigned bulletShaderID, ResourceManager* resourceManager)
|
||||
:
|
||||
Entity (weaponShaderID),
|
||||
weaponType (data->name),
|
||||
weaponType (data->id),
|
||||
weaponSize (glm::vec2(data->sizeX, data->sizeY)),
|
||||
weaponOffset (glm::vec2(data->offsetX, data->offsetY)),
|
||||
weaponMag (data->clipSize),
|
||||
|
|
@ -39,7 +39,7 @@ Weapon::Weapon(const WeaponData* data, const unsigned weaponShaderID, const unsi
|
|||
|
||||
if (data->animated)
|
||||
{
|
||||
addComponent(std::make_unique<AnimationComponent>(resourceManager->loadAnimationSet(data->graphic, entityid)));
|
||||
addComponent(std::make_unique<AnimationComponent>(resourceManager->loadAnimationSet(data->id, entityid)));
|
||||
}
|
||||
else
|
||||
addComponent(std::make_unique<SpriteComponent>(resourceManager->loadSpriteStatic(data->graphic)));
|
||||
|
|
@ -79,7 +79,7 @@ bool Weapon::shoot()
|
|||
{
|
||||
shotsFired = true;
|
||||
if (auto event = eventManager.lock())
|
||||
event->notify<EntityFireEvent>((EntityFireEvent){entityid, fireSpeed, wielder->getPosition(), weaponType});
|
||||
event->notify<EntityFireEvent>({entityid, fireSpeed, wielder->getPosition(), weaponType});
|
||||
if (!weaponScript || !weaponScript->lua["onShoot"].valid())
|
||||
{
|
||||
// create bullet using this generated data
|
||||
|
|
@ -137,10 +137,10 @@ void Weapon::hookEventManager(std::weak_ptr<EventManager> eventManager)
|
|||
bulletManager->hookEventManager(eventManager);
|
||||
}
|
||||
|
||||
void Weapon::attachScript(const std::shared_ptr<WeaponScript>& script)
|
||||
void Weapon::attachScript(std::unique_ptr<WeaponScript> script)
|
||||
{
|
||||
weaponScript = script;
|
||||
weaponScript->lua["weapon"] = shared_from_this();
|
||||
weaponScript = std::move(script);
|
||||
weaponScript->lua["weapon"] = this;
|
||||
LOG(DEBUG, "Weapon state bound", NULL);
|
||||
}
|
||||
|
||||
|
|
@ -262,6 +262,14 @@ void Weapon::createBullet(const Weapon::BulletData& data)
|
|||
bulletManager->addBullet(bullet);
|
||||
}
|
||||
|
||||
Weapon::~Weapon()
|
||||
{
|
||||
if (weaponScript) {
|
||||
weaponScript->lua["onShoot"] = sol::nil;
|
||||
weaponScript->lua.collect_gc();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
!| SLATED FOR REMOVAL |!
|
||||
|
||||
|
|
|
|||
|
|
@ -124,3 +124,14 @@ void TileTextureInstance::draw()
|
|||
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr, numOfInstances);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
TileTextureInstance::~TileTextureInstance()
|
||||
{
|
||||
if (texture)
|
||||
delete texture;
|
||||
else if (textures)
|
||||
delete textures;
|
||||
glDeleteBuffers(1, &VBO);
|
||||
glDeleteBuffers(1, &EBO);
|
||||
glDeleteVertexArrays(1, &VAO);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ bool TextureArray::adjustCanvasSizes(std::vector<SDL_Surface*>& surfaces)
|
|||
|
||||
if (surface->w > maxWidth) maxWidth = surface->w;
|
||||
if (surface->h > maxHeight) maxHeight = surface->h;
|
||||
textures.push_back(new TextureData({ surface->w, surface->h }));
|
||||
textures.push_back(TextureData({ surface->w, surface->h }));
|
||||
}
|
||||
for (int i = 0; i < surfaces.size(); ++i)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ AudioStream::AudioStream()
|
|||
eof = true;
|
||||
paused = true;
|
||||
streamThread = std::thread(&AudioStream::stream, this);
|
||||
streamThread.detach();
|
||||
//streamThread.detach();
|
||||
}
|
||||
|
||||
std::string AudioStream::CurStreamName()
|
||||
|
|
@ -153,7 +153,7 @@ void AudioStream::stream()
|
|||
if (state != AL_PLAYING) {
|
||||
alSourcePlay(source);
|
||||
}
|
||||
while (state == AL_PLAYING) {
|
||||
while (state == AL_PLAYING && !stopThread) {
|
||||
if (paused) {
|
||||
alSourcePause(source);
|
||||
}
|
||||
|
|
@ -161,8 +161,12 @@ void AudioStream::stream()
|
|||
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
|
||||
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
|
||||
|
||||
while (processed != 0) {
|
||||
alSourceUnqueueBuffers(source, 1, &buffers[last_buffer]);
|
||||
while (processed != 0 && !stopThread) {
|
||||
ALuint unqueued;
|
||||
alSourceUnqueueBuffers(source, 1, &unqueued);
|
||||
for (int i = 0; i < 4; ++i)
|
||||
if (unqueued == buffers[i])
|
||||
last_buffer = i;
|
||||
int samples = loadNextChunk();
|
||||
if (samples == 0) {
|
||||
LOG(INFO, "Hit the end of the song!", NULL);
|
||||
|
|
@ -176,7 +180,7 @@ void AudioStream::stream()
|
|||
}
|
||||
//LOG(INFO, "Buffer index: {}", last_buffer);
|
||||
alSourceQueueBuffers(source, 1, &buffers[last_buffer]);
|
||||
last_buffer = (last_buffer + 1) % 4;
|
||||
//last_buffer = (last_buffer + 1) % 4;
|
||||
processed--;
|
||||
}
|
||||
}
|
||||
|
|
@ -185,7 +189,12 @@ void AudioStream::stream()
|
|||
|
||||
AudioStream::~AudioStream()
|
||||
{
|
||||
stopThread = true;
|
||||
if (streamThread.joinable())
|
||||
streamThread.join();
|
||||
stb_vorbis_close(file);
|
||||
std::free(data);
|
||||
alDeleteBuffers(4, buffers);
|
||||
alSourcei(source, AL_BUFFER, 0);
|
||||
alDeleteSources(1, &source);
|
||||
alDeleteBuffers(4, buffers);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "sound/engine.h"
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
AudioEngine::AudioEngine(std::weak_ptr<ResourceManager> _resource)
|
||||
{
|
||||
|
|
@ -12,6 +13,7 @@ AudioEngine::AudioEngine(std::weak_ptr<ResourceManager> _resource)
|
|||
context = alcCreateContext(device, NULL);
|
||||
alcMakeContextCurrent(context);
|
||||
musicPlayer = std::make_unique<AudioStream>();
|
||||
soundManager = std::make_unique<SoundManager>();
|
||||
resourceManager = _resource;
|
||||
alGetError();
|
||||
}
|
||||
|
|
@ -21,6 +23,34 @@ void AudioEngine::hookEventManager(std::weak_ptr<EventManager> _events)
|
|||
globalEventManager = _events;
|
||||
}
|
||||
|
||||
void AudioEngine::hookSceneManager(std::weak_ptr<EventManager> _events)
|
||||
{
|
||||
sceneEventManager = _events;
|
||||
if (auto weak = sceneEventManager.lock()) {
|
||||
std::weak_ptr<AudioEngine> weakSelf = shared_from_this();
|
||||
weak->subscribe<EntityFireEvent>([weakSelf](const EntityFireEvent& e){
|
||||
if (auto self = weakSelf.lock()) {
|
||||
if (auto res = self->resourceManager.lock()) {
|
||||
auto buf = res->loadSoundEffect(e.weaponType + "/shoot");
|
||||
if (buf != 0) {
|
||||
self->soundManager->playSound(buf, 10, e.firePosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void AudioEngine::poll()
|
||||
{
|
||||
soundManager->pollSources();
|
||||
}
|
||||
|
||||
void AudioEngine::updateListener(const glm::vec3& pos)
|
||||
{
|
||||
alListenerfv(AL_POSITION, glm::value_ptr(pos));
|
||||
}
|
||||
|
||||
void AudioEngine::pushMusic(std::string _songName)
|
||||
{
|
||||
LOG(INFO, "Loading song {}", _songName);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@ SoundEffect::SoundEffect(const std::string& filename)
|
|||
// load the whole file into a buffer, this should only be used for small sound effects. Never with music or sounds exceeding 10MB!
|
||||
bool SoundEffect::loadFile(const std::string& filename)
|
||||
{
|
||||
short *data = (short *)std::malloc(UTIL::AUDIO::CHUNK_SIZE * sizeof(short) * 2);
|
||||
short *data;
|
||||
//std::unique_ptr<short[]> data((short*)new short[UTIL::AUDIO::CHUNK_SIZE * sizeof(short) * 2]());
|
||||
//std::vector<short> data(UTIL::AUDIO::CHUNK_SIZE * sizeof(short) * 2);
|
||||
int channels, sample_rate, samples;
|
||||
|
||||
samples = stb_vorbis_decode_filename(filename.c_str(), &channels, &sample_rate, &data);
|
||||
|
|
|
|||
103
YuppleMayham/src/sound/soundmanager.cpp
Normal file
103
YuppleMayham/src/sound/soundmanager.cpp
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
#include "sound/soundmanager.h"
|
||||
#include <AL/al.h>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
SoundManager::SoundManager()
|
||||
{
|
||||
for (auto& s : sources) {
|
||||
alGenSources(1, &s.source);
|
||||
s.inUse = false;
|
||||
s.priority = 0;
|
||||
alSourcef(s.source, AL_REFERENCE_DISTANCE, 1.0f);
|
||||
alSourcef(s.source, AL_MAX_DISTANCE, 10000.f);
|
||||
alSourcef(s.source, AL_ROLLOFF_FACTOR, 1.0f);
|
||||
}
|
||||
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
|
||||
}
|
||||
|
||||
void SoundManager::playSound(ALuint buffer, int priority, const glm::vec3& pos)
|
||||
{
|
||||
std::size_t ring = lastUsed;
|
||||
AudioSource* nextBest = nullptr;
|
||||
std::size_t secIndex = 0;
|
||||
auto nextIndex = [](std::size_t i){ return (i + 1) % 10; };
|
||||
|
||||
if (!sources[ring].inUse) {
|
||||
sources[ring].inUse = true;
|
||||
sources[ring].priority = priority;
|
||||
alSourcei(sources[ring].source, AL_BUFFER, buffer);
|
||||
if (pos != glm::vec3(0)) {
|
||||
//alSourcei(sources[ring].source, AL_SOURCE_RELATIVE, 1);
|
||||
alSourcefv(sources[ring].source, AL_POSITION, glm::value_ptr(pos));
|
||||
} else {
|
||||
//alSourcei(sources[ring].source, AL_SOURCE_RELATIVE, 0);
|
||||
}
|
||||
alSourcePlay(sources[ring].source);
|
||||
lastUsed = nextIndex(lastUsed);
|
||||
return;
|
||||
}
|
||||
for (ring = nextIndex(lastUsed); ring != lastUsed; ring = nextIndex(ring)) {
|
||||
if (!sources[ring].inUse) {
|
||||
sources[ring].inUse = true;
|
||||
sources[ring].priority = priority;
|
||||
alSourcei(sources[ring].source, AL_BUFFER, buffer);
|
||||
if (pos != glm::vec3(0)) {
|
||||
//alSourcei(sources[ring].source, AL_SOURCE_RELATIVE, 1);
|
||||
alSourcefv(sources[ring].source, AL_POSITION, glm::value_ptr(pos));
|
||||
} else {
|
||||
//alSourcei(sources[ring].source, AL_SOURCE_RELATIVE, 0);
|
||||
}
|
||||
alSourcePlay(sources[ring].source);
|
||||
lastUsed = ring;
|
||||
return;
|
||||
}
|
||||
if (sources[ring].priority <= priority) {
|
||||
if (nextBest) {
|
||||
if (nextBest->priority > sources[ring].priority) {
|
||||
nextBest = &sources[ring];
|
||||
secIndex = ring;
|
||||
}
|
||||
} else {
|
||||
nextBest = &sources[ring];
|
||||
secIndex = ring;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nextBest) {
|
||||
nextBest->priority = priority;
|
||||
alSourcei(nextBest->source, AL_BUFFER, buffer);
|
||||
if (pos != glm::vec3(0)) {
|
||||
//alSourcei(nextBest->source, AL_SOURCE_RELATIVE, 1);
|
||||
alSourcefv(nextBest->source, AL_POSITION, glm::value_ptr(pos));
|
||||
} else {
|
||||
//alSourcei(nextBest->source, AL_SOURCE_RELATIVE, 0);
|
||||
}
|
||||
alSourcePlay(nextBest->source);
|
||||
lastUsed = secIndex;
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::pollSources()
|
||||
{
|
||||
for (auto& s : sources) {
|
||||
if (s.inUse) {
|
||||
ALint processed, state;
|
||||
alGetSourcei(s.source, AL_BUFFERS_PROCESSED, &processed);
|
||||
alGetSourcei(s.source, AL_SOURCE_STATE, &state);
|
||||
if (state == AL_STOPPED) {
|
||||
s.inUse = false;
|
||||
alSourcei(s.source, AL_BUFFER, 0);
|
||||
}
|
||||
//else if (state != AL_PLAYING)
|
||||
// alSourcePlay(s.source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SoundManager::~SoundManager()
|
||||
{
|
||||
for (auto& s : sources) {
|
||||
alSourcei(s.source, AL_BUFFER, 0);
|
||||
alDeleteSources(1, &s.source);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#include "utility/resourcemanager.h"
|
||||
#include "graphics/sprite.h"
|
||||
#include "util.h"
|
||||
#include "utility/script.h"
|
||||
#include "graphics/shader.h"
|
||||
#include "graphics/animation.h"
|
||||
|
|
@ -29,14 +30,14 @@ Sprite* ResourceManager::loadSpriteStatic(const std::string& path)
|
|||
return sprites[path].get();
|
||||
}
|
||||
|
||||
std::shared_ptr<AIScript> ResourceManager::loadAIScript(const std::string& path)
|
||||
std::unique_ptr<AIScript> ResourceManager::loadAIScript(const std::string& path)
|
||||
{
|
||||
return std::make_shared<AIScript>(path.c_str());
|
||||
return std::make_unique<AIScript>(path.c_str());
|
||||
}
|
||||
|
||||
std::shared_ptr<WeaponScript> ResourceManager::loadWeaponScript(const std::string& path)
|
||||
std::unique_ptr<WeaponScript> ResourceManager::loadWeaponScript(const std::string& path)
|
||||
{
|
||||
return std::make_shared<WeaponScript>(path.c_str());
|
||||
return std::make_unique<WeaponScript>(path.c_str());
|
||||
}
|
||||
|
||||
const TileSetData* ResourceManager::loadTileSet(const std::string& name)
|
||||
|
|
@ -77,15 +78,36 @@ Background* ResourceManager::loadBackground(const std::string& path)
|
|||
|
||||
// We attach our script after we create our weapon because we are passing a reference to the weapon into the script and we don't want to pass an
|
||||
// incomplete reference to our script.
|
||||
std::shared_ptr<Weapon> ResourceManager::loadWeapon(const std::string& name, const unsigned weaponShaderID, const unsigned bulletShaderID)
|
||||
std::shared_ptr<Weapon> ResourceManager::loadWeapon(const std::string& id, const unsigned weaponShaderID, const unsigned bulletShaderID)
|
||||
{
|
||||
const WeaponData* data = xmlLoader->getWeaponData(name);
|
||||
const WeaponData* data = xmlLoader->getWeaponData(id);
|
||||
if (!data) {
|
||||
LOG(ERROR, "Could not load weapon id '{}', falling back to pistol", id);
|
||||
data = xmlLoader->getWeaponData("gun/pistol");// using this as a fallback for now
|
||||
}
|
||||
auto weapon = std::make_shared<Weapon>(data, weaponShaderID, bulletShaderID, this);
|
||||
if (!data->script.empty())
|
||||
weapon->attachScript(loadWeaponScript(data->script));
|
||||
return weapon;
|
||||
}
|
||||
|
||||
const unsigned ResourceManager::loadSoundEffect(const std::string& id)
|
||||
{
|
||||
auto iterator = sounds.find(id);
|
||||
if (iterator != sounds.end())
|
||||
return iterator->second->getBuffer();
|
||||
auto soundData = xmlLoader->getSoundData(id) ;
|
||||
if (!soundData) {
|
||||
soundData = xmlLoader->getSoundData(UTIL::get_generic(id));
|
||||
LOG(WARN, "Could not load sound id: '{}' trying generic", id);
|
||||
if (!soundData)
|
||||
return 0;
|
||||
}
|
||||
auto sound = std::make_unique<SoundEffect>(soundData->path);
|
||||
sounds[id] = std::move(sound);
|
||||
return sounds[id]->getBuffer();
|
||||
}
|
||||
|
||||
const SceneData* ResourceManager::loadScene(const std::string& id)
|
||||
{
|
||||
return xmlLoader->getSceneData(id);
|
||||
|
|
|
|||
|
|
@ -108,3 +108,20 @@ Script::Script(const std::string& path)
|
|||
loadScript(path);
|
||||
|
||||
}
|
||||
|
||||
Script::~Script()
|
||||
{
|
||||
lua.collect_garbage();
|
||||
}
|
||||
|
||||
AIScript::~AIScript()
|
||||
{
|
||||
lua.collect_garbage();
|
||||
lua = sol::state{};
|
||||
}
|
||||
|
||||
WeaponScript::~WeaponScript()
|
||||
{
|
||||
lua.collect_gc();
|
||||
lua = sol::state{};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "utility/xmlloader.h"
|
||||
|
||||
#include "utility/logger.h"
|
||||
#include <filesystem>
|
||||
#include <tinyxml2.h>
|
||||
|
||||
/*
|
||||
|
|
@ -181,9 +182,9 @@ bool XMLLoader::loadWeapons(const char* weaponFolder)
|
|||
{
|
||||
// populate weapon data into this temp buffer, then push it into our list of weapons
|
||||
WeaponData data;
|
||||
const char *name, *graphic, *bulletGraphic, *script;
|
||||
const char *id, *graphic, *bulletGraphic, *script;
|
||||
// Getting top level weapon data, attribs in the weapon Node
|
||||
if (weapon->QueryStringAttribute("name", &name) != tinyxml2::XML_SUCCESS)
|
||||
if (weapon->QueryStringAttribute("id", &id) != tinyxml2::XML_SUCCESS)
|
||||
continue;
|
||||
weapon->QueryFloatAttribute("fireSpeed", &data.fireSpeed);
|
||||
weapon->QueryIntAttribute("maxAmmo", &data.maxAmmo);
|
||||
|
|
@ -199,9 +200,6 @@ bool XMLLoader::loadWeapons(const char* weaponFolder)
|
|||
if (anim)
|
||||
{
|
||||
data.animated = true;
|
||||
if (anim->QueryStringAttribute("id", &graphic) != tinyxml2::XML_SUCCESS)
|
||||
continue;
|
||||
|
||||
if (anim->ChildElementCount() != 0)
|
||||
{
|
||||
tinyxml2::XMLElement* size = anim->FirstChildElement("size");
|
||||
|
|
@ -251,9 +249,8 @@ bool XMLLoader::loadWeapons(const char* weaponFolder)
|
|||
bullet->FirstChildElement("size")->QueryFloatAttribute("y", &data.bulletSizeY) != tinyxml2::XML_SUCCESS)
|
||||
continue;
|
||||
|
||||
data.name = name;
|
||||
data.id = id;
|
||||
data.script = script;
|
||||
data.graphic = graphic;
|
||||
data.bulletGraphic = bulletGraphic;
|
||||
|
||||
tinyxml2::XMLElement* spread = bullet->FirstChildElement("spread");
|
||||
|
|
@ -272,8 +269,8 @@ bool XMLLoader::loadWeapons(const char* weaponFolder)
|
|||
modifier->QueryFloatAttribute("max", &data.modMax);
|
||||
}
|
||||
|
||||
LOG(DEBUG, "Loaded {} from {}", data.name, file.path().filename().generic_string());
|
||||
weapons.try_emplace(data.name, std::make_unique<WeaponData>(data));
|
||||
LOG(DEBUG, "Loaded {} from {}", data.id, file.path().filename().generic_string());
|
||||
weapons.try_emplace(data.id, std::make_unique<WeaponData>(data));
|
||||
}
|
||||
}
|
||||
return (!weapons.empty());
|
||||
|
|
@ -584,3 +581,35 @@ bool XMLLoader::loadMaps(const char* mapFolder)
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XMLLoader::loadSoundEffects(const char *soundFolder)
|
||||
{
|
||||
std::filesystem::path folder(soundFolder);
|
||||
if (!std::filesystem::exists(folder) || !std::filesystem::is_directory(folder))
|
||||
ERROR_LOG("Directory '{}' does not exist!", soundFolder);
|
||||
|
||||
for (auto& file : std::filesystem::directory_iterator(folder))
|
||||
{
|
||||
if (!file.path().has_extension() || !file.path().has_filename() || !file.exists() || file.is_directory())
|
||||
continue;
|
||||
|
||||
tinyxml2::XMLDocument doc;
|
||||
if (doc.LoadFile(file.path().string().c_str()) != tinyxml2::XML_SUCCESS)
|
||||
continue;
|
||||
|
||||
for (tinyxml2::XMLElement *e = doc.FirstChildElement("sound"); e != NULL; e = e->NextSiblingElement("sound")) {
|
||||
SoundData sound;
|
||||
const char *id, *path;
|
||||
if (e->QueryStringAttribute("id", &id) != tinyxml2::XML_SUCCESS ||
|
||||
e->QueryStringAttribute("path", &path) != tinyxml2::XML_SUCCESS)
|
||||
continue;
|
||||
e->QueryBoolAttribute("spatial", &sound.spatial);
|
||||
|
||||
sound.id = id;
|
||||
sound.path = path;
|
||||
|
||||
sounds.try_emplace(sound.id, std::make_unique<SoundData>(sound));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue