added backgrounds to empty space, updated event polling to be more responsive

This commit is contained in:
Ethan 2025-03-24 18:59:16 -04:00
parent 294d75ff59
commit 268e6d6ebf
21 changed files with 269 additions and 108 deletions

Binary file not shown.

Binary file not shown.

View file

@ -47,6 +47,7 @@ add_executable (YuppleMayham
"src/gameplay/weapons/bulletmanager.cpp" "src/gameplay/weapons/bulletmanager.cpp"
"src/gameplay/scene.cpp" "src/gameplay/scene.cpp"
"src/graphics/texture.cpp" "src/graphics/texture.cpp"
"src/graphics/background.cpp"
"src/utility/resourcemanager.cpp" "src/utility/resourcemanager.cpp"
"src/utility/xmlloader.cpp" "src/utility/xmlloader.cpp"

View file

@ -27,7 +27,8 @@ public:
bool loadDebugScene(); bool loadDebugScene();
void handleInput(SDL_Event& e); void captureInput(SDL_Event& e);
void executeInputs();
void update(double deltaTime); void update(double deltaTime);
void render(); void render();
@ -38,6 +39,7 @@ public:
const unsigned getWindowHeight() const; const unsigned getWindowHeight() const;
void quit() { game_state = GAME_QUITTING; } void quit() { game_state = GAME_QUITTING; }
~Game();
private: private:
unsigned game_state = GAME_QUITTING; unsigned game_state = GAME_QUITTING;
@ -52,4 +54,4 @@ private:
std::shared_ptr<EventManager> globalEventManager; std::shared_ptr<EventManager> globalEventManager;
}; };
#endif #endif

View file

@ -2,6 +2,7 @@
#define _H_INPUT_H #define _H_INPUT_H
#include "utility/logger.h" #include "utility/logger.h"
#include <SDL_mouse.h>
#include <unordered_map> #include <unordered_map>
#include <SDL_keycode.h> #include <SDL_keycode.h>
#include <SDL_events.h> #include <SDL_events.h>
@ -46,15 +47,12 @@ protected:
mouseButtons[MOUSE_BUTTON_LEFT] = true; mouseButtons[MOUSE_BUTTON_LEFT] = true;
if (e.type == SDL_MOUSEBUTTONUP) if (e.type == SDL_MOUSEBUTTONUP)
mouseButtons[MOUSE_BUTTON_LEFT] = false; mouseButtons[MOUSE_BUTTON_LEFT] = false;
if (e.type == SDL_MOUSEMOTION)
{
mouse_state.x = static_cast<float>(e.motion.x);
mouse_state.y = static_cast<float>(e.motion.y);
// Quick fix regarding linux holding storing too many mouse events
SDL_FlushEvent(SDL_MOUSEMOTION);
}
if (e.type == SDL_MOUSEWHEEL) if (e.type == SDL_MOUSEWHEEL)
mouse_state.scroll = e.wheel.preciseY; mouse_state.scroll = e.wheel.preciseY;
if (e.type == SDL_MOUSEMOTION) {
mouse_state.x = static_cast<float>(e.motion.x);
mouse_state.y = static_cast<float>(e.motion.y);
}
} }
MouseState mouse_state; MouseState mouse_state;
std::unordered_map<Uint8, bool> mouseButtons; std::unordered_map<Uint8, bool> mouseButtons;
@ -95,11 +93,14 @@ public:
mouseScrollCommand = command; mouseScrollCommand = command;
} }
void handleInput(); void handleInput();
void executeCommands();
private: private:
GameActor* actor = nullptr; GameActor* actor = nullptr;
std::unordered_map<SDL_Keycode, CommandWithDelay> keyCommands; std::unordered_map<SDL_Keycode, CommandWithDelay> keyCommands;
std::unordered_map<Uint8, MouseCommandWithDelay> mouseCommands; std::unordered_map<Uint8, MouseCommandWithDelay> mouseCommands;
std::vector<Command*> commandQueue;
std::vector<MouseCommand*> mouseQueue;
MouseCommand* mouseMotionCommand = nullptr; MouseCommand* mouseMotionCommand = nullptr;
MouseCommand* mouseScrollCommand = nullptr; MouseCommand* mouseScrollCommand = nullptr;
}; };

View file

@ -7,6 +7,7 @@
#include <gameplay/gameactor.h> #include <gameplay/gameactor.h>
class Background;
class Entity; class Entity;
class Camera; class Camera;
class Map; class Map;
@ -61,6 +62,9 @@ private:
void hookSceneEvents(); void hookSceneEvents();
GameActor* getGameActorByID(const unsigned int ID); GameActor* getGameActorByID(const unsigned int ID);
// Non-owning pointer DO NOT DELETE, resource manager will handle that!
Background *background;
SceneType type; SceneType type;
std::shared_ptr<Map> map; std::shared_ptr<Map> map;
//std::shared_ptr<TileSet> tileSet; //std::shared_ptr<TileSet> tileSet;
@ -77,4 +81,4 @@ private:
std::shared_ptr<SceneData> sceneData; std::shared_ptr<SceneData> sceneData;
}; };
#endif //_H_SCENE_H #endif //_H_SCENE_H

View file

@ -0,0 +1,24 @@
#ifndef _H_BACKGROUND_H
#define _H_BACKGROUND_H
#include "graphics/quad.h"
#include "graphics/drawable.h"
#include "graphics/texture.h"
#include "utility/logger.h"
class Background : public Drawable
{
public:
Background(const std::string& fileName);
void draw() override;
~Background();
private:
ScreenQuad *quad;
Texture *texture;
};
#endif // _H_BACKGROUND_H

View file

@ -0,0 +1,50 @@
#ifndef _H_DRAWABLE_H
#define _H_DRAWABLE_H
#include <vector>
#include <variant>
#include <glm/glm.hpp>
#include <string>
using UniformValue = std::variant<
int,
bool,
float,
double,
glm::mat4,
glm::vec2
>;
struct Uniform {
std::string name;
UniformValue value;
};
class Drawable
{
public:
virtual void draw() = 0;
const unsigned getShaderID() const { return shaderID; }
const std::vector<Uniform>& getUniforms() { return uniforms; }
const std::vector<Uniform>& getOneShotUniforms() { return oneShotUniforms; }
void clearOneShot() { oneShotUniforms.clear(); }
void clearUniforms() { uniforms.clear(); }
protected:
unsigned shaderID;
template <typename T>
void editUniform(const std::string& name, T value)
{
uniforms.emplace_back(Uniform {name, value});
}
template <typename T>
void editUniformOnce(const std::string& name, T value)
{
oneShotUniforms.emplace_back(Uniform {name, value});
}
private:
std::vector<Uniform> uniforms;
std::vector<Uniform> oneShotUniforms;
};
#endif // _H_DRAWABLE_H

View file

@ -8,7 +8,7 @@ class Quad
{ {
public: public:
void draw(); void draw();
~Quad(); virtual ~Quad();
protected: protected:
Quad(const float* vertexData); Quad(const float* vertexData);
private: private:

View file

@ -3,12 +3,11 @@
#include <unordered_map> #include <unordered_map>
#include <memory> #include <memory>
#include <variant>
#include <string>
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include "graphics/quad.h" #include "graphics/quad.h"
#include "graphics/drawable.h"
#include "graphics/postprocess.h" #include "graphics/postprocess.h"
class ResourceManager; class ResourceManager;
@ -23,47 +22,6 @@ enum class RenderLayer {
Menu Menu
}; };
using UniformValue = std::variant<
int,
bool,
float,
double,
glm::mat4,
glm::vec2
>;
struct Uniform {
std::string name;
UniformValue value;
};
class Drawable
{
public:
virtual void draw() = 0;
const unsigned getShaderID() const { return shaderID; }
const std::vector<Uniform>& getUniforms() { return uniforms; }
const std::vector<Uniform>& getOneShotUniforms() { return oneShotUniforms; }
void clearOneShot() { oneShotUniforms.clear(); }
void clearUniforms() { uniforms.clear(); }
protected:
unsigned shaderID;
template <typename T>
void editUniform(const std::string& name, T value)
{
uniforms.emplace_back(Uniform {name, value});
}
template <typename T>
void editUniformOnce(const std::string& name, T value)
{
oneShotUniforms.emplace_back(Uniform {name, value});
}
private:
std::vector<Uniform> uniforms;
std::vector<Uniform> oneShotUniforms;
};
class Renderer class Renderer
{ {
public: public:
@ -74,14 +32,14 @@ public:
void hookEventManager(const std::weak_ptr<EventManager> eventManager); void hookEventManager(const std::weak_ptr<EventManager> eventManager);
void setProjAndViewMatrix(const glm::mat4& proj, const glm::mat4& view); void setProjAndViewMatrix(const glm::mat4& proj, const glm::mat4& view);
void addDrawable(RenderLayer renderLayer, std::shared_ptr<Drawable> drawable); void addDrawable(RenderLayer renderLayer, Drawable *drawable);
void removeDrawable(RenderLayer renderLayer, std::shared_ptr<Drawable> drawable); void removeDrawable(RenderLayer renderLayer, Drawable *drawable);
void render(); void render();
private: private:
std::unordered_map<RenderLayer, std::vector<std::shared_ptr<Drawable>>> worldLayerPool; std::unordered_map<RenderLayer, std::vector<Drawable*>> worldLayerPool;
std::unordered_map<RenderLayer, std::vector<std::shared_ptr<Drawable>>> HUDLayerPool; std::unordered_map<RenderLayer, std::vector<Drawable*>> HUDLayerPool;
std::vector<RenderLayer> renderingOrder = { std::vector<RenderLayer> renderingOrder = {
RenderLayer::Background, RenderLayer::Background,
RenderLayer::Map, RenderLayer::Map,

View file

@ -7,10 +7,15 @@
class Shader class Shader
{ {
private: protected:
bool compileAndLink(const char *vSource, const char *fSource);
std::string vertexPath;
std::string fragmentPath;
bool valid;
Shader();
public: public:
unsigned int ID; unsigned int ID;
Shader(const char* vertexPath, const char* fragmentPath); Shader(const char* vertPath, const char* fragPath);
void use() { glUseProgram(ID); } void use() { glUseProgram(ID); }
void setFloat(const std::string& name, float value); void setFloat(const std::string& name, float value);
@ -21,7 +26,15 @@ public:
void setVec2(const std::string& name, const float* value); void setVec2(const std::string& name, const float* value);
void setMatrix4f(const std::string& name, const float* value); void setMatrix4f(const std::string& name, const float* value);
~Shader(); bool isValid() { return valid; }
virtual ~Shader();
};
class GenericShader : public Shader
{
public:
GenericShader() : Shader() {};
}; };
#endif // _H_SHADER_H #endif // _H_SHADER_H

View file

@ -8,6 +8,7 @@
#include "utility/xmlloader.h" #include "utility/xmlloader.h"
#include "graphics/shader.h" #include "graphics/shader.h"
#include "graphics/sprite.h" #include "graphics/sprite.h"
#include "graphics/background.h"
#include <cassert> #include <cassert>
class Weapon; class Weapon;
@ -28,19 +29,25 @@ public:
xmlLoader->loadTileSets("maps/tilesets"); xmlLoader->loadTileSets("maps/tilesets");
xmlLoader->loadMaps("maps"); xmlLoader->loadMaps("maps");
xmlLoader->loadScenes("scenes"); xmlLoader->loadScenes("scenes");
shaders["__fallback__"] = std::make_unique<GenericShader>();
}; };
SpriteAtlas* loadSpriteAtlas (const std::string& path, float frameSize, bool isDirectional = false); // Returns a NON-OWNING pointer to a sprite atlas
Sprite* loadSpriteStatic (const std::string& path); SpriteAtlas* loadSpriteAtlas (const std::string& path, float frameSize, bool isDirectional = false);
std::shared_ptr<AIScript> loadAIScript (const std::string& path); // Returns a NON-OWNING pointer to a static sprite
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); std::shared_ptr<WeaponScript> loadWeaponScript (const std::string& path);
const unsigned loadShader (const std::string& name, const std::string& vertexPath, const std::string& fragPath); const unsigned loadShader (const std::string& name, const std::string& vertexPath, const std::string& fragPath);
std::shared_ptr<Weapon> loadWeapon (const std::string& name, const unsigned weaponShaderID, const unsigned bulletShaderID); std::shared_ptr<Weapon> loadWeapon (const std::string& name, const unsigned weaponShaderID, const unsigned bulletShaderID);
std::shared_ptr<SceneData> loadScene (const std::string& id); std::shared_ptr<SceneData> loadScene (const std::string& id);
std::shared_ptr<AnimationSet> loadAnimationSet(const std::string& name, int entityid = 0); std::shared_ptr<AnimationSet> loadAnimationSet (const std::string& name, int entityid = 0);
std::shared_ptr<TileSetData> loadTileSet (const std::string& name); std::shared_ptr<TileSetData> loadTileSet (const std::string& name);
// Returns a NON-OWNING pointer to a shader by ID
Shader* getShaderByID(unsigned int ID); Shader* getShaderByID(unsigned int ID);
void clearResources(); void clearResources();
@ -48,12 +55,13 @@ public:
~ResourceManager(); ~ResourceManager();
private: private:
std::unordered_map<std::string, std::unique_ptr<Shader>> shaders; std::unordered_map<std::string, std::unique_ptr<Shader>> shaders;
std::unordered_map<unsigned, Shader*> shaderIDs; std::unordered_map<unsigned, Shader*> shaderIDs;
std::unordered_map<std::string, std::unique_ptr<Sprite>> sprites; 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<Weapon>> weapons;
std::unordered_map<std::string, std::shared_ptr<Script>> scripts; std::unordered_map<std::string, std::shared_ptr<Script>> scripts;
std::unordered_map<std::string, std::shared_ptr<TileSetData>>tileSets; 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; //std::unordered_map<std::string, std::shared_ptr<EntityData>> entityData;
//std::unordered_map<std::string, std::shared_ptr<SceneData>> scenes; //std::unordered_map<std::string, std::shared_ptr<SceneData>> scenes;
//std::unordered_map<std::string, std::shared_ptr<MapData>> maps; //std::unordered_map<std::string, std::shared_ptr<MapData>> maps;
@ -62,4 +70,4 @@ private:
std::shared_ptr<XMLLoader> xmlLoader; std::shared_ptr<XMLLoader> xmlLoader;
}; };
#endif // _H_RESOURCEMANAGER_H #endif // _H_RESOURCEMANAGER_H

View file

@ -74,10 +74,15 @@ bool Game::loadDebugScene()
return true; return true;
} }
void Game::handleInput(SDL_Event& e) void Game::captureInput(SDL_Event& e)
{ {
inputHandler->captureInput(e); inputHandler->captureInput(e);
}
void Game::executeInputs()
{
inputHandler->handleInput(); inputHandler->handleInput();
inputHandler->executeCommands();
} }
void Game::update(double deltaTime) void Game::update(double deltaTime)
@ -102,3 +107,8 @@ void Game::render()
window->swap(); window->swap();
} }
Game::~Game()
{
resourceManager->clearResources();
}

View file

@ -1,6 +1,5 @@
#include "gameplay/input.h" #include "gameplay/input.h"
#include "utility/command.h" #include "utility/command.h"
#include "gameplay/gameactor.h"
#include <SDL_timer.h> #include <SDL_timer.h>
@ -17,7 +16,7 @@ void InputHandler::handleInput()
{ {
if (currentTime - command.lastExecution >= command.delay) if (currentTime - command.lastExecution >= command.delay)
{ {
command.cmd->execute(*actor); commandQueue.push_back(command.cmd);
command.lastExecution = currentTime; command.lastExecution = currentTime;
} }
} }
@ -29,7 +28,7 @@ void InputHandler::handleInput()
{ {
if (currentTime - command.lastExecution >= command.delay) if (currentTime - command.lastExecution >= command.delay)
{ {
command.cmd->execute(*actor, mouse_state); mouseQueue.push_back(command.cmd);
command.lastExecution = currentTime; command.lastExecution = currentTime;
} }
} }
@ -40,3 +39,16 @@ void InputHandler::handleInput()
mouseScrollCommand->execute(*actor, mouse_state); mouseScrollCommand->execute(*actor, mouse_state);
mouse_state.scroll = 0.0f; // clear mouse scroll since we have handled the event. mouse_state.scroll = 0.0f; // clear mouse scroll since we have handled the event.
} }
// Executes every captured command during the frame
void InputHandler::executeCommands()
{
for (auto& command : commandQueue) {
command->execute(*actor);
}
for (auto& mouse : mouseQueue) {
mouse->execute(*actor, mouse_state);
}
commandQueue.clear();
mouseQueue.clear();
}

View file

@ -9,6 +9,7 @@
#include "graphics/sprite.h" #include "graphics/sprite.h"
#include "graphics/animation.h" #include "graphics/animation.h"
#include "graphics/background.h"
#include "utility/component.h" #include "utility/component.h"
#include "utility/ftfont.h" #include "utility/ftfont.h"
@ -59,6 +60,11 @@ void Scene::loadDebugShooterScene()
auto bubbleShader = resourceManager->loadShader("GL_bubble", "shaders/GL_bubble.vert", "shaders/GL_bubble.frag"); auto bubbleShader = resourceManager->loadShader("GL_bubble", "shaders/GL_bubble.vert", "shaders/GL_bubble.frag");
auto weaponShader = resourceManager->loadShader("GL_pistol", "shaders/GL_pistol.vert", "shaders/GL_pistol.frag"); auto weaponShader = resourceManager->loadShader("GL_pistol", "shaders/GL_pistol.vert", "shaders/GL_pistol.frag");
if (!sceneData->bgFile.empty()) {
LOG(INFO, "Found background loading '{}'", sceneData->bgFile);
background = resourceManager->loadBackground(sceneData->bgFile);
}
// creating map from scene // creating map from scene
auto tileShader = resourceManager->loadShader("GL_tile", "shaders/GL_tile.vert", "shaders/GL_tile.frag"); auto tileShader = resourceManager->loadShader("GL_tile", "shaders/GL_tile.vert", "shaders/GL_tile.frag");
map = std::make_shared<Map>(mapData, tileShader, resourceManager); map = std::make_shared<Map>(mapData, tileShader, resourceManager);
@ -149,16 +155,19 @@ void Scene::render(std::shared_ptr<Renderer> renderer)
renderer->clear(); renderer->clear();
renderer->setProjAndViewMatrix(camera->getProjectionMatrix(), camera->getViewMatrix()); renderer->setProjAndViewMatrix(camera->getProjectionMatrix(), camera->getViewMatrix());
renderer->addDrawable(RenderLayer::Map, map); renderer->addDrawable(RenderLayer::Map, map.get());
if (background) {
renderer->addDrawable(RenderLayer::Background, static_cast<Drawable*>(background));
}
//map->draw(); //map->draw();
for (auto& [id, e] : entities) for (auto& [id, e] : entities)
{ {
//e->draw(); //e->draw();
renderer->addDrawable(RenderLayer::GameObjects, e); renderer->addDrawable(RenderLayer::GameObjects, e.get());
if (e->getHeldWeapon()) { if (e->getHeldWeapon()) {
renderer->addDrawable(RenderLayer::GameObjects, e->getHeldWeapon()); renderer->addDrawable(RenderLayer::GameObjects, e->getHeldWeapon().get());
for (const auto& bullet : e->getHeldWeapon()->getBulletManager()->getBullets()) { for (const auto& bullet : e->getHeldWeapon()->getBulletManager()->getBullets()) {
renderer->addDrawable(RenderLayer::GameObjects, bullet); renderer->addDrawable(RenderLayer::GameObjects, bullet.get());
} }
} }
} }

View file

@ -0,0 +1,23 @@
#include "graphics/background.h"
Background::Background(const std::string& fileName)
{
// This will fallback to the generic shader.
shaderID = 0;
texture = new Texture();
quad = new ScreenQuad();
if (!texture->loadTexture(fileName.c_str()))
LOG(ERROR, "Failed to load background texture: '{}'", fileName);
}
void Background::draw()
{
texture->bind();
quad->draw();
}
Background::~Background()
{
delete texture;
delete quad;
}

View file

@ -1,7 +1,5 @@
#include "graphics/quad.h" #include "graphics/quad.h"
#include <memory>
Quad::Quad(const float* vertexData) Quad::Quad(const float* vertexData)
{ {
std::memcpy(vertices, vertexData, sizeof(vertices)); std::memcpy(vertices, vertexData, sizeof(vertices));
@ -43,4 +41,4 @@ Quad::~Quad()
glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO); glDeleteBuffers(1, &EBO);
glDeleteVertexArrays(1, &VAO); glDeleteVertexArrays(1, &VAO);
} }

View file

@ -108,7 +108,7 @@ void Renderer::setProjAndViewMatrix(const glm::mat4& proj, const glm::mat4& view
glBindBuffer(GL_UNIFORM_BUFFER, 0); glBindBuffer(GL_UNIFORM_BUFFER, 0);
} }
void Renderer::addDrawable(RenderLayer renderLayer, std::shared_ptr<Drawable> drawable) void Renderer::addDrawable(RenderLayer renderLayer, Drawable *drawable)
{ {
if (renderLayer == RenderLayer::HUD || renderLayer == RenderLayer::Menu) if (renderLayer == RenderLayer::HUD || renderLayer == RenderLayer::Menu)
HUDLayerPool[renderLayer].push_back(drawable); HUDLayerPool[renderLayer].push_back(drawable);
@ -116,7 +116,7 @@ void Renderer::addDrawable(RenderLayer renderLayer, std::shared_ptr<Drawable> dr
worldLayerPool[renderLayer].push_back(drawable); worldLayerPool[renderLayer].push_back(drawable);
} }
void Renderer::removeDrawable(RenderLayer renderLayer, std::shared_ptr<Drawable> drawable) void Renderer::removeDrawable(RenderLayer renderLayer, Drawable *drawable)
{ {
auto erase = [&](auto& pool) { auto erase = [&](auto& pool) {
pool.erase(std::remove(pool.begin(), pool.end(), drawable), pool.end()); pool.erase(std::remove(pool.begin(), pool.end(), drawable), pool.end());
@ -163,17 +163,7 @@ void Renderer::renderPool(auto& layerPool)
if (item->getShaderID() != curShaderID) { if (item->getShaderID() != curShaderID) {
curShaderID = item->getShaderID(); curShaderID = item->getShaderID();
curShader = resourceManager->getShaderByID(curShaderID); curShader = resourceManager->getShaderByID(curShaderID);
curShader->use();
if (curShader) {
curShader->use();
/*
curShader->setMatrix4f("projection", glm::value_ptr(projMat));
curShader->setMatrix4f("view", glm::value_ptr(viewMat));
*/
} else {
LOG(ERROR, "Shader with ID {} not found!", curShaderID);
continue;
}
} }
if (!item->getOneShotUniforms().empty()) { if (!item->getOneShotUniforms().empty()) {
uploadUniforms(curShaderID, item->getOneShotUniforms()); uploadUniforms(curShaderID, item->getOneShotUniforms());
@ -226,7 +216,7 @@ void Renderer::sortLayerPool(auto& layerPool)
// Sort by shader id, this works to batch shaders together to avoid shader switching too much // Sort by shader id, this works to batch shaders together to avoid shader switching too much
for (auto& [_,pool] : layerPool) { for (auto& [_,pool] : layerPool) {
std::sort(pool.begin(), pool.end(), std::sort(pool.begin(), pool.end(),
[](const std::shared_ptr<Drawable>& a, const std::shared_ptr<Drawable>& b) { [](const Drawable* a, const Drawable* b) {
return a->getShaderID() < b->getShaderID(); return a->getShaderID() < b->getShaderID();
}); });
} }

View file

@ -3,7 +3,37 @@
#include "utility/logger.h" #include "utility/logger.h"
#include <cassert> #include <cassert>
Shader::Shader(const char* vertexPath, const char* fragmentPath) // Load a generic fallback shader
Shader::Shader()
{
std::string vertexSource = {
// generic vertex shader program
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec2 aTexCoord;\n"
"out vec2 texCoord;\n"
"void main()\n"
"{\n"
" texCoord = aTexCoord;\n"
" gl_Position = vec4(aPos, 1.0);\n"
"}\0"
};
std::string fragmentSource = {
// generic fragment shader program
"#version 330 core\n"
"in vec2 texCoord;\n"
"out vec4 FragColor;\n"
"uniform sampler2D sprite;\n"
"void main()\n"
"{\n"
" FragColor = texture(sprite, texCoord);\n"
"}\0"
};
compileAndLink(vertexSource.c_str(), fragmentSource.c_str());
valid = true;
}
Shader::Shader(const char* vertPath, const char* fragPath) : vertexPath(vertPath), fragmentPath(fragPath)
{ {
std::string vertexSource; std::string vertexSource;
std::string fragmentSource; std::string fragmentSource;
@ -35,7 +65,15 @@ Shader::Shader(const char* vertexPath, const char* fragmentPath)
} }
const char* vSource = vertexSource.c_str(); const char* vSource = vertexSource.c_str();
const char* fSource = fragmentSource.c_str(); const char* fSource = fragmentSource.c_str();
if (!compileAndLink(vertexSource.c_str(), fragmentSource.c_str())) {
LOG(ERROR, "Failed to compile and/or link shader! Check error details for more information.\nUsing fallback shader!", NULL);
valid = false;
}
valid = true;
}
bool Shader::compileAndLink(const char *vSource, const char *fSource)
{
unsigned int vertexid, fragmentid; unsigned int vertexid, fragmentid;
char infoLog[512]; char infoLog[512];
int success; int success;
@ -50,6 +88,7 @@ Shader::Shader(const char* vertexPath, const char* fragmentPath)
{ {
glGetShaderInfoLog(vertexid, 512, NULL, infoLog); glGetShaderInfoLog(vertexid, 512, NULL, infoLog);
LOG(ERROR, "VERTEX SHADER '{}' COMPILE ERROR\n{}", vertexPath, infoLog); LOG(ERROR, "VERTEX SHADER '{}' COMPILE ERROR\n{}", vertexPath, infoLog);
return false;
} }
//compile fragment shader //compile fragment shader
@ -62,6 +101,7 @@ Shader::Shader(const char* vertexPath, const char* fragmentPath)
{ {
glGetShaderInfoLog(fragmentid, 512, NULL, infoLog); glGetShaderInfoLog(fragmentid, 512, NULL, infoLog);
LOG(ERROR, "FRAGMENT SHADER '{}' COMPILE ERROR\n{}", fragmentPath, infoLog); LOG(ERROR, "FRAGMENT SHADER '{}' COMPILE ERROR\n{}", fragmentPath, infoLog);
return false;
} }
//create and link program with compiled shaders //create and link program with compiled shaders
@ -75,12 +115,14 @@ Shader::Shader(const char* vertexPath, const char* fragmentPath)
{ {
glGetProgramInfoLog(ID, 512, NULL, infoLog); glGetProgramInfoLog(ID, 512, NULL, infoLog);
LOG(ERROR, "PROGRAM LINKER ERROR\n{}", infoLog); LOG(ERROR, "PROGRAM LINKER ERROR\n{}", infoLog);
return false;
} }
glDeleteShader(vertexid); glDeleteShader(vertexid);
glDeleteShader(fragmentid); glDeleteShader(fragmentid);
glUniformBlockBinding(ID, glGetUniformBlockIndex(ID, "Matrices"), 0); glUniformBlockBinding(ID, glGetUniformBlockIndex(ID, "Matrices"), 0);
return true;
} }
void Shader::setFloat(const std::string& name, float value) void Shader::setFloat(const std::string& name, float value)

View file

@ -49,11 +49,13 @@ int main(int argc, char* args[])
Uint64 curCounter = SDL_GetPerformanceCounter(); Uint64 curCounter = SDL_GetPerformanceCounter();
double deltaTime = ((curCounter - lastCounter) / freq); double deltaTime = ((curCounter - lastCounter) / freq);
deltaTime = (deltaTime < 1.0) ? deltaTime : 1.0; deltaTime = (deltaTime < 1.0) ? deltaTime : 1.0;
SDL_PollEvent(&e); while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) if (e.type == SDL_QUIT)
game->quit(); game->quit();
game->handleInput(e); game->captureInput(e);
}
game->executeInputs();
game->render(); game->render();
game->update(deltaTime); game->update(deltaTime);
@ -61,6 +63,7 @@ int main(int argc, char* args[])
} }
delete game;
IMG_Quit(); IMG_Quit();
SDL_Quit(); SDL_Quit();

View file

@ -1,9 +1,9 @@
#include "utility/resourcemanager.h" #include "utility/resourcemanager.h"
#include "utility/component.h"
#include "graphics/sprite.h" #include "graphics/sprite.h"
#include "utility/script.h" #include "utility/script.h"
#include "graphics/shader.h" #include "graphics/shader.h"
#include "graphics/animation.h" #include "graphics/animation.h"
#include "graphics/background.h"
#include "gameplay/weapons/weapons.h" #include "gameplay/weapons/weapons.h"
SpriteAtlas* ResourceManager::loadSpriteAtlas(const std::string& path, float frameSize, bool isDirectional) SpriteAtlas* ResourceManager::loadSpriteAtlas(const std::string& path, float frameSize, bool isDirectional)
@ -50,6 +50,9 @@ const unsigned ResourceManager::loadShader(const std::string& name, const std::s
if (iterator != shaders.end()) if (iterator != shaders.end())
return iterator->second->ID; return iterator->second->ID;
auto shader = std::make_unique<Shader>(vertexPath.c_str(), fragPath.c_str()); auto shader = std::make_unique<Shader>(vertexPath.c_str(), fragPath.c_str());
if (!shader->isValid()) {
return shaders["__fallback__"]->ID;
}
unsigned id = shader->ID; unsigned id = shader->ID;
shaderIDs[shader->ID] = shader.get(); shaderIDs[shader->ID] = shader.get();
shaders[name] = std::move(shader); shaders[name] = std::move(shader);
@ -59,7 +62,17 @@ const unsigned ResourceManager::loadShader(const std::string& name, const std::s
Shader* ResourceManager::getShaderByID(unsigned int ID) Shader* ResourceManager::getShaderByID(unsigned int ID)
{ {
auto iterator = shaderIDs.find(ID); auto iterator = shaderIDs.find(ID);
return (iterator != shaderIDs.end() ? iterator->second : nullptr); return (iterator != shaderIDs.end() ? iterator->second : shaders["__fallback__"].get());
}
Background* ResourceManager::loadBackground(const std::string& path)
{
auto iterator = backgrounds.find(path);
if (iterator != backgrounds.end())
return iterator->second.get();
auto background = std::make_unique<Background>(path);
backgrounds[path] = std::move(background);
return backgrounds[path].get();
} }
// 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 // 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