diff options
-rw-r--r-- | include/brice.hpp | 39 | ||||
-rw-r--r-- | include/common.hpp | 35 | ||||
-rw-r--r-- | include/components.hpp | 41 | ||||
-rw-r--r-- | include/config.hpp | 51 | ||||
-rw-r--r-- | include/engine.hpp | 58 | ||||
-rw-r--r-- | include/gametime.hpp | 36 | ||||
-rw-r--r-- | include/player.hpp | 44 | ||||
-rw-r--r-- | include/save_util.hpp | 36 | ||||
-rw-r--r-- | include/shader_utils.hpp | 17 | ||||
-rw-r--r-- | include/texture.hpp | 232 | ||||
-rw-r--r-- | include/ui.hpp | 8 | ||||
-rw-r--r-- | include/ui_quest.hpp | 19 | ||||
-rw-r--r-- | include/world.hpp | 10 | ||||
-rw-r--r-- | main.cpp | 406 | ||||
-rw-r--r-- | src/brice.cpp | 6 | ||||
-rw-r--r-- | src/common.cpp | 39 | ||||
-rw-r--r-- | src/components.cpp | 200 | ||||
-rw-r--r-- | src/engine.cpp | 2 | ||||
-rw-r--r-- | src/inventory.cpp | 7 | ||||
-rw-r--r-- | src/texture.cpp | 314 | ||||
-rw-r--r-- | src/ui.cpp | 500 | ||||
-rw-r--r-- | src/ui_menu.cpp | 25 | ||||
-rw-r--r-- | src/world.cpp | 71 |
23 files changed, 1011 insertions, 1185 deletions
diff --git a/include/brice.hpp b/include/brice.hpp index dc3ea96..1c4eccf 100644 --- a/include/brice.hpp +++ b/include/brice.hpp @@ -1,20 +1,59 @@ +/** + * @file brice.hpp + * @brief A system for saving player information. + */ + #ifndef BRICE_H_ #define BRICE_H_ #include <string> namespace game { + + /** + * Allows the player to jump, if set to true. + */ extern bool canJump; + + /** + * Allows the player to sprint, if set to true. + */ extern bool canSprint; + /** + * Gets a value from the saved brice and returns it. + * @param id the id of the value + * @return the string value + */ std::string getValue(const std::string& id); + /** + * Sets a value in the brice, creating it if it doesn't exist. + * @param id the id of the value + * @param value the value + * @return true if the value was updated, not created + */ bool setValue(const std::string& id, const std::string& value); + /** + * Resets the brice to it's default values. + * Note: these are hardcoded into the program. + */ void briceClear(void); + + /** + * Saves the brice to it's file (brice.dat). + */ void briceSave(void); + + /** + * Loads the brice from it's file (brice.dat). + */ void briceLoad(void); + /** + * Reloads the brice. + */ void briceUpdate(void); } diff --git a/include/common.hpp b/include/common.hpp index 861905a..19af420 100644 --- a/include/common.hpp +++ b/include/common.hpp @@ -43,11 +43,8 @@ // game library includes #include <config.hpp> - - // windows stuff #ifdef __WIN32__ -typedef unsigned int uint; #undef near #endif @@ -77,12 +74,9 @@ typedef ivec2 dim2; * Creates a coordinate out of floating point integers. */ struct vec2 { - float x; /**< The x coordinate */ - float y; /**< The y coordinate */ + float x; + float y; - /** - * Constructs a vec2 with the specified coordinates. - */ vec2(float _x = 0.0f, float _y = 0.0f) : x(_x), y(_y) {} @@ -105,11 +99,14 @@ struct vec2 { return vec2 (x + v.x, y + v.y); } - template<typename T> - const vec2 operator*(const T &n) { + vec2 operator*(const float&n) const { return vec2 (x * n, y * n); } + vec2 operator/(const float& n) const { + return vec2 (x / n, y / n); + } + // std::swap can't work due to being packed inline void swapX(vec2 &v) { @@ -122,6 +119,10 @@ struct vec2 { y = v.y, v.y = t; } + std::string toString(void) const { + return "(" + std::to_string(x) + ", " + std::to_string(y) + ")"; + } + } __attribute__ ((packed)); /** @@ -188,8 +189,6 @@ public: } }; -extern GLuint colorIndex; - /** * The amount of game ticks that should occur each second. */ @@ -263,17 +262,6 @@ extern vec2 offset; */ void DEBUG_prints(const char* file, int line, const char *s,...); -// TODO make sure we don't use these. Then burn them. -/** - * Sets color using glColor3ub(), but handles potential overflow. - */ -void safeSetColor(int r,int g,int b); - -/** - * Sets color using glColor4ub(), but handles potential overflow. - */ -void safeSetColorA(int r,int g,int b,int a); - unsigned int millis(void); // reads the names of files in a directory into the given string vector @@ -283,7 +271,6 @@ int getdir(std::string dir, std::vector<std::string> &files); void strVectorSortAlpha(std::vector<std::string> *v); // reads the given file into a buffer and returns a pointer to the buffer -const char *readFile(const char *path); std::string readFile(const std::string& path); std::vector<std::string> readFileA(const std::string& path); diff --git a/include/components.hpp b/include/components.hpp index 2a8680d..5c067dd 100644 --- a/include/components.hpp +++ b/include/components.hpp @@ -125,32 +125,35 @@ struct Solid { }; struct SpriteData { - - SpriteData(std::string path, vec2 offset): - offset(offset) { - pic = Texture::loadTexture(path); - size = Texture::imageDim(path); + + SpriteData(std::string path, vec2 off): + offset(off) { + tex = Texture(path); + size = tex.getDim(); + size_tex = vec2(1.0, 1.0); offset_tex.x = offset.x/size.x; offset_tex.y = offset.y/size.y; } - SpriteData(std::string path, vec2 offset, vec2 size): - offset(offset), size(size) { - pic = Texture::loadTexture(path); - vec2 tmpsize = Texture::imageDim(path); + SpriteData(std::string path, vec2 off, vec2 si): + size(si), offset(off) { + tex = Texture(path); + vec2 tmpsize = tex.getDim(); size_tex.x = size.x/tmpsize.x; size_tex.y = size.y/tmpsize.y; + offset_tex.x = offset.x/tmpsize.x; offset_tex.y = offset.y/tmpsize.y; } - GLuint pic; + Texture tex; + vec2 size; vec2 offset; + vec2 offset_tex; - vec2 size; vec2 size_tex; }; @@ -168,7 +171,7 @@ struct Sprite { Sprite(bool left = false) : faceLeft(left) {} - std::vector<std::pair<SpriteData, vec2>> getSprite() { + Frame getSprite() { return sprite; } @@ -210,15 +213,17 @@ struct Sprite { } for (auto &s : sprite) { + const auto& size = s.first.tex.getDim(); + if (s.second.x < st.x) st.x = s.second.x; if (s.second.y < st.y) st.y = s.second.y; - if (s.second.x + s.first.size.x > dim.x) - dim.x = s.second.x + s.first.size.x; - if (s.second.y + s.first.size.y > dim.y) - dim.y = s.second.y + s.first.size.y; + if (s.second.x + size.x > dim.x) + dim.x = s.second.x + size.x; + if (s.second.y + size.y > dim.y) + dim.y = s.second.y + size.y; } return dim; @@ -321,9 +326,9 @@ public: class RenderSystem : public entityx::System<RenderSystem> { private: std::string loadTexString; - std::atomic<GLuint> loadTexResult; + Texture loadTexResult; public: - GLuint loadTexture(const std::string& file); + Texture loadTexture(const std::string& file); void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override; }; diff --git a/include/config.hpp b/include/config.hpp index bc9d052..e17df24 100644 --- a/include/config.hpp +++ b/include/config.hpp @@ -1,23 +1,72 @@ +/** + * @file config.hpp + * @brief Functions for loading/saving game settings. + */ + #ifndef CONFIG_H #define CONFIG_H #include <string> namespace game { + /** + * The size of an HLINE, according to the save file. + * This is the default "unit of measurement" in the game. Drawing scales to + * this, and it is used in game logic. + */ extern unsigned int HLINE; + + /** + * The width of the screen, in pixels. + */ extern unsigned int SCREEN_WIDTH; + + /** + * The height of the screen, in pixels. + */ extern unsigned int SCREEN_HEIGHT; - extern bool FULLSCREEN; + + /** + * The window is fullscreen if this is true. + */ + extern bool FULLSCREEN; namespace config { + /** + * The current volume level of the master channel. + * Volumes are percentages, 0 to 100. + */ extern float VOLUME_MASTER; + + /** + * Volume level of the background music (BGM). + */ extern float VOLUME_MUSIC; + + /** + * Volume level of game sound effects. + */ extern float VOLUME_SFX; + /** + * The path of the folder to load world XML files from. + */ extern std::string xmlFolder; + /** + * Reads the settings file (config/settings.xml) into the game. + * Default values are hardcoded in (see src/config.cpp). + */ void read(void); + + /** + * Updates settings with the current values. + */ void update(void); + + /** + * Saves the current settings to the settings file. + */ void save(void); } } diff --git a/include/engine.hpp b/include/engine.hpp index 1c5f510..2b03696 100644 --- a/include/engine.hpp +++ b/include/engine.hpp @@ -1,8 +1,13 @@ +/** + * @file engine.hpp + * @brief The main game engine, and functions to assist it. + */ + #ifndef ENGINE_HPP_ #define ENGINE_HPP_ #include <entityx/entityx.h> -#include "entityx/deps/Dependencies.h" +#include <entityx/deps/Dependencies.h> #include <texture.hpp> #include <components.hpp> @@ -10,28 +15,56 @@ //game::engine::Systems->add<entityx::deps::Dependency<Visible, Sprite>>(); +/** + * @class Engine + * The main game engine class. Only one instance of this should be created, it + * handles everything game-related. + */ class Engine : public entityx::Receiver<Engine> { public: + /** + * A flag to indicate if a thread should continue to run. + */ bool shouldRun; + /** + * Handles game systems. + */ entityx::SystemManager systems; explicit Engine(void); + /** + * Initializes the game engine, and all systems used within it. + */ void init(void); + + /** + * Updates all rendering systems. + * @param dt the delta time + */ void render(entityx::TimeDelta dt); void resetRender(entityx::TimeDelta dt); + + /** + * Updates all logic systems. + * @param dt the delta time + */ void update(entityx::TimeDelta dt); + /** + * A shortcut to get a system, for calling system-specific functions. + * Takes the type of the desired system. + */ template<typename T> inline T* getSystem(void) { return dynamic_cast<T*>(systems.system<T>().get()); } - /*void configure(entityx::EventManager &ev) { - (void)ev; - }*/ - + /** + * A handler for the game ending event. + * @param gee game end event data + */ inline void receive(const GameEndEvent &gee) { shouldRun = !(gee.really); } @@ -39,16 +72,27 @@ public: namespace game { + /** + * Handles all game events. + */ extern entityx::EventManager events; + + /** + * Handles entity data. + */ extern entityx::EntityManager entities; + /** + * An instance of the main game engine. + */ extern Engine engine; + /** + * Ends the game. + */ inline void endGame(void) { events.emit<GameEndEvent>(); } - - extern SpriteLoader sprite_l; } diff --git a/include/gametime.hpp b/include/gametime.hpp index a809ef9..988533a 100644 --- a/include/gametime.hpp +++ b/include/gametime.hpp @@ -1,16 +1,52 @@ +/** + * @file gametime.hpp + * @brief Handles time related operations + */ + #ifndef GAMETIME_H_ #define GAMETIME_H_ namespace game { namespace time { + /** + * Sets the game's tick count to the desired amount. + * @param t desired tick count + */ void setTickCount(unsigned int t); + + /** + * Gets the current tick count. + * @return the tick count + */ unsigned int getTickCount(void); + + /** + * Calculates and returns the delta time. + * @return the delta time + */ unsigned int getDeltaTime(void); + /** + * Increments the game's tick count. + */ void tick(void); + + /** + * Increments the game's tick count by the given amount of ticks. + * @param ticks the number of ticks to add + */ void tick(unsigned int ticks); + + /** + * Determines if a tick has passed since the last call to this function. + * @return if a tick has passed + */ bool tickHasPassed(void); + /** + * Handles time updating. + * This should be called from the game's main loop. + */ void mainLoopHandler(void); } } diff --git a/include/player.hpp b/include/player.hpp index 59d6368..85dc821 100644 --- a/include/player.hpp +++ b/include/player.hpp @@ -1,3 +1,8 @@ +/** + * @file player.hpp + * @brief The player system + */ + #ifndef PLAYER_HPP_ #define PLAYER_HPP_ @@ -8,8 +13,15 @@ #include <components.hpp> #include <common.hpp> +/** + * The constant velocity the player is given when moved with the arrow keys. + */ constexpr const float PLAYER_SPEED_CONSTANT = 0.15f; +/** + * @class PlayerSystem + * Controls a player, with keyboard and stuff. + */ class PlayerSystem : public entityx::System<PlayerSystem>, public entityx::Receiver<PlayerSystem> { private: entityx::Entity player; @@ -23,18 +35,50 @@ public: PlayerSystem(void) : moveLeft(false), moveRight(false), speed(1.0f) {} + /** + * Creates the player, adding it to the entity system. + */ void create(void); + /** + * Configures events for use with the entity system. + */ void configure(entityx::EventManager&); + /** + * Updates the player, mainly the player's velocity. + */ void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override; + /** + * Handles key up events for the player. + * @param kue key up event data + */ void receive(const KeyUpEvent&); + + /** + * Handles key down events for the player. + * @param kde key down event data + */ void receive(const KeyDownEvent&); + /** + * Gets the player's position. + * @return the player's position + */ vec2 getPosition(void) const; + + /** + * Sets the player's X coordinate. + * @param x the x coordinate to give the player + */ inline void setX(const float& x) { player.component<Position>().get()->x = x; } + + /** + * Gets the width of the player. + * @return the player's width, according to its sprite + */ inline float getWidth(void) const { return game::entities.component<Solid>(player.id())->width; } }; diff --git a/include/save_util.hpp b/include/save_util.hpp deleted file mode 100644 index 3d5cf54..0000000 --- a/include/save_util.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef SAVE_UTIL_H_ -#define SAVE_UTIL_H_ - -/* - * Save macros. - */ - -#define E_SAVE_COORDS { xmle->SetAttribute("x", loc.x); xmle->SetAttribute("y", loc.y); } - -#define E_SAVE_HEALTH xmle->SetAttribute("health", health); - -/* - * Load macos. - */ - -#define E_LOAD_COORDS(yy) { float n; \ - if (xmle->QueryFloatAttribute("x", &n) == XML_NO_ERROR) \ - spawn(n, yy); \ - else \ - spawn(xmle->FloatAttribute("spawnx"), 100); \ - \ - if (xmle->QueryFloatAttribute("y", &n) == XML_NO_ERROR) \ - loc.y = n; } - -#define E_LOAD_HEALTH { float n; \ - \ - if (xmle->QueryFloatAttribute("maxHealth", &n) != XML_NO_ERROR) \ - maxHealth = 1; \ - \ - if (xmle->QueryFloatAttribute("health", &n) == XML_NO_ERROR) \ - health = n; \ - else \ - health = maxHealth; } - - -#endif // SAVE_UTIL_H_ diff --git a/include/shader_utils.hpp b/include/shader_utils.hpp index 243b3d4..06ac318 100644 --- a/include/shader_utils.hpp +++ b/include/shader_utils.hpp @@ -1,8 +1,11 @@ /** + * @file shader_utils.hpp + * @brief Utilities to use to handle GLSL shaders. * From the OpenGL Programming wikibook: http://en.wikibooks.org/wiki/OpenGL_Programming * This file is in the public domain. * Contributors: Sylvain Beucler, Guus Sliepen */ + #ifndef _CREATE_SHADER_H #define _CREATE_SHADER_H @@ -11,12 +14,12 @@ #include <SDL2/SDL.h> -extern char* file_read(const char* filename); -extern void print_log(GLuint object); -extern GLuint create_shader(const char* filename, GLenum type); -extern GLuint create_program(const char* vertexfile, const char *fragmentfile); -extern GLint get_attrib(GLuint program, const char *name); -extern GLint get_uniform(GLuint program, const char *name); -extern void print_opengl_info(); +char* file_read(const char* filename); +void print_log(GLuint object); +GLuint create_shader(const char* filename, GLenum type); +GLuint create_program(const char* vertexfile, const char *fragmentfile); +GLint get_attrib(GLuint program, const char *name); +GLint get_uniform(GLuint program, const char *name); +void print_opengl_info(); #endif diff --git a/include/texture.hpp b/include/texture.hpp index ad5211c..e9082b3 100644 --- a/include/texture.hpp +++ b/include/texture.hpp @@ -1,11 +1,10 @@ -/** @file Texture.h +/** + * @file Texture.h * @brief Defines a method for loading textures. - * * This file gives facilities for easily loading and binding textures. */ - -#ifndef TEXTURE_H -#define TEXTURE_H +#ifndef TEXTURE_HPP_ +#define TEXTURE_HPP_ #include <common.hpp> @@ -16,137 +15,142 @@ #define DEBUG /** - * Texture functions are given a namespace for better organization. + * @class Texture + * Handles a single texture, loaded from the given file. */ -namespace Texture { +class Texture { +private: + std::string name; /**< The name (path) of the loaded file. */ + GLuint tex; /**< The GLuint for the loaded texture. */ + vec2 dim; /**< The dimensions of the loaded texture. */ +public: /** - * Loads a texture from the given file name, returning the GLuint used for - * later referencing of the texture. + * Attempts to create a texture. + * Either: + * - Creates an empty class (no arguments given) + * - Load a texture from the given file, crashing if file not found + * - Fills the class with the given values + * @param file the path to the desired texture + * @param t the GLuint for the texture, if known + * @param v the size of the texture, if known */ + Texture(const std::string& file = "", const GLuint& t = 0xFFFFF, const vec2& v = vec2(0, 0)); - GLuint loadTexture(std::string fileName); - GLuint genColor(Color c); + /** + * Gets the name (path) of the loaded texture. + * @return the texture's name + */ + const std::string& getName(void) const; - void freeTextures(void); + /** + * Gets the dimensions of the loaded texture. + * @return the texture's dimensions + */ + const vec2& getDim(void) const; - void initColorIndex(); - vec2 getIndex(Color c); - vec2 imageDim(std::string fileName); -} + /** + * Binds the texture, so it may be used for rendering. + */ + inline void use(void) const + { glBindTexture(GL_TEXTURE_2D, tex); } -class SpriteLoader { -private: - std::unordered_map<uint64_t, GLuint> sprites; - std::unordered_map<std::string, uint64_t> spritesLoc; - - uint64_t freeID = 0; - uint64_t increaseID() { - uint64_t id_t = 0; - while (1) { - try { - sprites.at(id_t); - } catch (const std::out_of_range& oor) { - freeID = id_t; - return freeID; - } - id_t++; - } - } -public: - uint64_t loadSprite(std::string s) { - uint64_t tex_e = 0; - try { - tex_e = spritesLoc.at(s); - } catch (const std::out_of_range& oor) { - sprites.emplace(increaseID(), Texture::loadTexture (s)); - spritesLoc.emplace(s, freeID); - return freeID; - } - return tex_e; - } - - GLuint getSprite(uint64_t id) { - return sprites.at(id); - } + /** + * Frees GPU resources for the loaded texture. + */ + inline void destroy(void) + { glDeleteTextures(1, &tex), tex = 0xFFFFF; } + + /** + * Checks if a texture is currently loaded in this class. + * @return true if there is not a loaded texture + */ + inline bool isEmpty(void) const + { return (tex == 0xFFFFF); } }; /** - * DRAFT texture iterator? + * @class ColorTex + * Creates a single-pixel texture of the given color. */ -class TextureIterator { -private: - std::vector<std::pair<GLuint, std::string>> textures; - std::vector<std::pair<GLuint, std::string>>::iterator position; +class ColorTex : public Texture { public: - TextureIterator(void) { - position = std::begin(textures); - } - ~TextureIterator(void) { - textures.clear(); - } - TextureIterator(const std::vector<std::string> &l) { - for (const auto &s : l) - textures.emplace_back(Texture::loadTexture(s), s); - - position = std::begin(textures); - } - void operator++(int) noexcept { - if (++position < std::end(textures)) - glBindTexture(GL_TEXTURE_2D, (*position).first); - else - position = std::end(textures) - 1; - } - void operator--(int) noexcept { - if (--position >= std::begin(textures)) - glBindTexture(GL_TEXTURE_2D, (*position).first); - else - position = std::begin(textures); - } - void operator()(const int &index) { - if (index < 0 || index > static_cast<int>(textures.size())) - throw std::invalid_argument("texture index out of range"); - - position = std::begin(textures) + index; - glBindTexture(GL_TEXTURE_2D, (*position).first); - } - const std::string& getTexturePath(const int &index) { - if (index < 0 || index > static_cast<int>(textures.size())) - throw std::invalid_argument("texture index out of range"); - - return textures[index].second; - } - const vec2 getTextureDim(void) { - return Texture::imageDim((*position).second); - } + ColorTex(void); + + /** + * Creates a texture of the given color. + * @param color the desired color + */ + ColorTex(const Color& color); }; /** - * The Texturec class. - * - * This class can handle an array of textures and allows easy binding of those - * textures. + * A collection of preloaded colors, to save resources. */ +namespace Colors { + extern ColorTex white; /**< A solid white texture. */ + extern ColorTex black; /**< A solid black texture. */ + extern ColorTex red; /**< A solid red texture. */ -class Texturec{ + /** + * Creates the colors. + */ + void init(void); +} + +/** + * @class TextureIterator + * Keeps a collection of textures for easy usage/looping. + */ +class TextureIterator { private: - unsigned int texState; + /** + * The set of textures to loop through. + */ + std::vector<Texture> textures; + /** + * The current position in the texture array. + * @see textures + */ + std::vector<Texture>::iterator position; public: + TextureIterator(void) + : position(std::begin(textures)) {} + ~TextureIterator(void) {} - std::vector<GLuint> image; - std::vector<std::string> texLoc; - - Texturec(uint amt, ...); - Texturec(uint amt,const char **paths); - Texturec(std::vector<std::string>vec); - Texturec(std::initializer_list<std::string> l); - - ~Texturec(); + /** + * Constructs a set of textures from the given list. + * @param l the list of textures + */ + TextureIterator(const std::vector<std::string> &l); + /** + * Shifts to the next texture in the array, stopping at the end if we're there. + * Also binds the texture. + */ + void operator++(int) noexcept; - void bindNext(); - void bindPrev(); - void bind(unsigned int); + /** + * Shifts back in the array, staying at the beginning if we're there. + * Also binds the texture. + */ + void operator--(int) noexcept; + /** + * Goes to the given index in the list. + * @param index the index to use + */ + void operator()(const int &index); + /** + * Gets the dimensions of the currently selected texture. + * @return the texture's dimensions + */ + inline const vec2& getTextureDim(void) + { return position->getDim(); } }; -#endif //TEXTURE_H +/** + * Frees all loaded textures, rendering them all useless. + */ +void unloadTextures(void); + +#endif //TEXTURE_HPP_ diff --git a/include/ui.hpp b/include/ui.hpp index 8d517c7..519d259 100644 --- a/include/ui.hpp +++ b/include/ui.hpp @@ -39,8 +39,8 @@ ** The UI namespace ** --------------------------------------------------------------------------*/ -void setControl(unsigned int index, SDL_Keycode key); -SDL_Keycode getControl(unsigned int index); +void setControl(int index, SDL_Keycode key); +SDL_Keycode getControl(int index); #include <entityx/entityx.h> @@ -92,7 +92,7 @@ namespace ui { void setFontFace(const char *ttf); void setFontSize(unsigned int size); - void setFontColor(unsigned char r,unsigned char g,unsigned char b, unsigned char a); + void setFontColor(int r, int g, int b, int a); void setFontZ(float z); /* @@ -145,8 +145,6 @@ namespace ui { void drawFade(void); void fadeUpdate(void); - void quitGame(); - /* * Toggle the black overlay thing. */ diff --git a/include/ui_quest.hpp b/include/ui_quest.hpp index 8582b67..d770011 100644 --- a/include/ui_quest.hpp +++ b/include/ui_quest.hpp @@ -1,3 +1,8 @@ +/** + * @file ui_quest.hpp + * @brief Handles UI elements related to quests. + */ + #ifndef UI_QUEST_HPP_ #define UI_QUEST_HPP_ @@ -6,12 +11,20 @@ namespace ui { namespace quest { + /** + * A flag to determine if the UI should be drawn. + */ bool _toggle = false; - void toggle(void) { - _toggle ^= true; - } + /** + * Toggles displaying of the UI. + */ + inline void toggle(void) + { _toggle ^= true; } + /** + * Draws the quest UI to the screen, if enabled. + */ void draw(void) { static unsigned int textWrap = 40; diff --git a/include/world.hpp b/include/world.hpp index 5c021bf..8864d30 100644 --- a/include/world.hpp +++ b/include/world.hpp @@ -60,13 +60,6 @@ typedef struct { } WorldData; /** - * Alters how bright world elements are drawn. - * This value is based off of the current time of day (tick count), set in - * main.cpp. - */ -extern int worldShade; - -/** * Defines how many game ticks it takes to go from day to night or vice versa. * Technically a half day cycle... */ @@ -108,8 +101,7 @@ struct WorldData2 { // Indoor variables bool indoor; /**< Set to true if this is an indoor world. */ - float indoorWidth; /**< The width of the indoor texture (house). */ - GLuint indoorTex; /**< The texture to draw (house). */ + Texture indoorTex; /**< The house's inside texture. */ std::string outdoor; /**< The file name of the outdoor world. */ vec2 outdoorCoords; /**< The coordinates the player should spawn to when exiting. */ @@ -1,81 +1,66 @@ -/* ---------------------------------------------------------------------------- -** The main file, home of the main loop. -** --------------------------------------------------------------------------*/ -// ... -/* ---------------------------------------------------------------------------- -** Includes section -** --------------------------------------------------------------------------*/ - -#include <brice.hpp> - -#include <entityx/entityx.h> +/** + * @file main.cpp + * The main file, where it all happens. + */ -#include <window.hpp> -#include <render.hpp> -#include <engine.hpp> +// standard library includes +#include <fstream> +#include <mutex> +#include <chrono> +using namespace std::literals::chrono_literals; // local library includes +#include <entityx/entityx.h> #include <tinyxml2.h> using namespace tinyxml2; -// local game includes -#include <common.hpp> +// our own includes +#include <brice.hpp> #include <config.hpp> -#include <world.hpp> -#include <ui.hpp> +#include <common.hpp> +#include <engine.hpp> #include <gametime.hpp> #include <player.hpp> +#include <window.hpp> +#include <world.hpp> +#include <render.hpp> +#include <ui.hpp> -#include <fstream> -#include <mutex> -#include <chrono> - -using namespace std::literals::chrono_literals; - -/* ---------------------------------------------------------------------------- -** Variables section -** --------------------------------------------------------------------------*/ - -// the currently used folder to grab XML files +/** + * The currently used folder to look for XML files in. + */ std::string xmlFolder; -// the current menu +/** + * The current menu, if any are open (TODO why is this here) + */ Menu *currentMenu; -// keeps a simple palette of colors for single-color draws -GLuint colorIndex; - -// the mouse's texture -GLuint mouseTex; - -// the center of the screen +/** + * The current center of the screen, updated in main render. + */ vec2 offset; -/* - * fps contains the game's current FPS, debugY contains the player's - * y coordinates, updated at a certain interval. These are used in - * the debug menu (see below). +/** + * The current FPS of the game. */ +static unsigned int fps = 0; -static unsigned int fps=0; -//static float debugY=0; - -// handles all logic operations -void logic(void); - -// handles all rendering operations void render(void); -/******************************************************************************* -** MAIN ************************************************************************ -********************************************************************************/ - +/** + * The main program. + * Init, load, run. Die. + */ int main(int argc, char *argv[]) { static bool worldReset = false, worldDontReallyRun = false; std::string worldActuallyUseThisXMLFile; - // handle command line arguments + // + // get command line arguments, if any + // + if (argc > 1) { for (int i = 1; i < argc; i++) { std::string s = argv[i]; @@ -89,49 +74,69 @@ int main(int argc, char *argv[]) } } + // + // init the main game engine + // + game::engine.init(); + // used three times below + auto worldSys = game::engine.getSystem<WorldSystem>(); + // // initialize GLEW + // + #ifndef __WIN32__ glewExperimental = GL_TRUE; #endif - GLenum err; - if ((err = glewInit()) != GLEW_OK) - UserError(std::string("GLEW was not able to initialize! Error: ") + reinterpret_cast<const char *>(glewGetErrorString(err))); + auto glewError = glewInit(); + if (glewError != GLEW_OK) + UserError(std::string("GLEW was not able to initialize! Error: ") + + reinterpret_cast<const char *>(glewGetErrorString(glewError))); + + // + // start the random number generator (TODO our own?) + // - // start the random number generator randInit(millis()); - // 'basic' OpenGL setup + // + // some basic OpenGL setup stuff + // + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetSwapInterval(1); // v-sync - SDL_ShowCursor(SDL_DISABLE); // hide the mouse + // enable v-sync (TODO but 1000 fps?) + SDL_GL_SetSwapInterval(1); + // hide the cursor + SDL_ShowCursor(SDL_DISABLE); + // switch to pixel grid glViewport(0, 0, game::SCREEN_WIDTH, game::SCREEN_HEIGHT); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glClearColor(1,1,1,1); - - // TODO - Texture::initColorIndex(); + glClearColor(1, 1, 1, 1); + // // initialize shaders - std::cout << "Initializing shaders!\n"; + // - // create shaders + std::cout << "Initializing shaders!\n"; Render::initShaders(); + Colors::init(); + + // + // load some saved data + // - // load up some fresh hot brice game::briceLoad(); game::briceUpdate(); // load sprites used in the inventory menu. See src/inventory.cpp //initInventorySprites(); - // load mouse texture, and other inventory textures - mouseTex = Texture::loadTexture("assets/goodmouse.png"); - // get a world + // + if (xmlFolder.empty()) xmlFolder = "xml/"; @@ -143,69 +148,58 @@ int main(int argc, char *argv[]) // alphabetically sort files strVectorSortAlpha(&xmlFiles); + // kill the world if needed if (worldReset) { - for (const auto &xf : xmlFiles) { - if (xf[0] != '.') { - XMLDocument xmld; - auto file = xmlFolder + xf; - xmld.LoadFile(file.c_str()); - - auto xmle = xmld.FirstChildElement("World"); - - if (xmle == nullptr) { - xmle = xmld.FirstChildElement("IndoorWorld"); - - if (xmle == nullptr) - continue; - } - - xmle = xmle->FirstChildElement(); - while (xmle) { - xmle->DeleteAttribute("x"); - xmle->DeleteAttribute("y"); - xmle->DeleteAttribute("health"); - xmle->DeleteAttribute("alive"); - xmle->DeleteAttribute("dindex"); - xmle = xmle->NextSiblingElement(); - } - - xmld.SaveFile(file.c_str(), false); - } - } - + // TODO TODO TODO we do xml/*.dat now... game::briceClear(); - - std::ofstream pdat ("xml/.main.dat", std::ios::out); - pdat.close(); } + // either load the given XML, or find one if (!worldActuallyUseThisXMLFile.empty()) { - game::engine.getSystem<WorldSystem>()->load(worldActuallyUseThisXMLFile); + worldSys->load(worldActuallyUseThisXMLFile); } else { // load the first valid XML file for the world for (const auto &xf : xmlFiles) { if (xf[0] != '.') { // read it in std::cout << "File to load: " << xf << '\n'; - game::engine.getSystem<WorldSystem>()->load(xf); + worldSys->load(xf); break; } } } + // + // initialize ui + // + ui::menu::init(); + ///////////////////////////// + // // + // actually start the game // + // // + ///////////////////////////// if (!worldDontReallyRun) { - // the main loop, in all of its gloriousness.. + // the main loop, in all of its gloriousness... std::thread thMain ([&] { const bool &run = game::engine.shouldRun; while (run) { game::time::mainLoopHandler(); - if (game::time::tickHasPassed()) - logic(); + if (game::time::tickHasPassed()) { + // calculate the world shading value + extern int worldShade; // TODO kill + worldShade = 50 * sin((game::time::getTickCount() + (DAY_CYCLE / 2)) / (DAY_CYCLE / PI)); + + // update fades + ui::fadeUpdate(); + + // increment game ticker + game::time::tick(); + } game::engine.update(game::time::getDeltaTime()); @@ -217,74 +211,88 @@ int main(int argc, char *argv[]) std::thread thDebug ([&] { const bool &run = game::engine.shouldRun; while (run) { - fps = 1000 / game::time::getDeltaTime(); -// debugY = player->loc.y; - + fps = 1000 / game::time::getDeltaTime(); // TODO really? std::this_thread::sleep_for(1s); } }); + // thre render loop, renders const bool &run = game::engine.shouldRun; while (run) { render(); game::engine.resetRender(0); } + // on game end, get back together thMain.join(); thDebug.join(); - //game::engine.getSystem<WorldSystem>()->thAmbient.join(); + //game::engine.getSystem<WorldSystem>()->thAmbient.join(); // segfault or something } - // put away the brice for later + // + // put away the brice for later, save world + // + game::briceSave(); + worldSys->save(); + + // + // close things, free stuff, yada yada + // - // free library resources Mix_HaltMusic(); Mix_CloseAudio(); -// destroyInventory(); ui::destroyFonts(); - Texture::freeTextures(); - - // close up the game stuff - game::engine.getSystem<WorldSystem>()->save(); + unloadTextures(); game::engine.getSystem<WindowSystem>()->die(); + // + // goodbye + // + return 0; // Calls everything passed to atexit } void render() { - const auto SCREEN_WIDTH = game::SCREEN_WIDTH; - const auto SCREEN_HEIGHT = game::SCREEN_HEIGHT; + static const Texture mouseTex ("assets/goodmouse.png"); + static const glm::mat4 view = glm::lookAt( + glm::vec3(0.0f, 0.0f, 0.0f), // pos + glm::vec3(0.0f, 0.0f, -10.0f), // looking at + glm::vec3(0.0f, 1.0f, 0.0f) // up vector + ); + + static const auto& SCREEN_WIDTH2 = game::SCREEN_WIDTH / 2.0f; + static const auto& SCREEN_HEIGHT2 = game::SCREEN_HEIGHT / 2.0f; + + // + // set the ortho + // auto ps = game::engine.getSystem<PlayerSystem>(); auto ploc = ps->getPosition(); offset.x = ploc.x + ps->getWidth() / 2; const auto& worldWidth = game::engine.getSystem<WorldSystem>()->getWidth(); - if (worldWidth < (int)SCREEN_WIDTH) + if (worldWidth < (int)SCREEN_WIDTH2 * 2) offset.x = 0; - else if (offset.x - SCREEN_WIDTH / 2 < worldWidth * -0.5f) - offset.x = ((worldWidth * -0.5f) + SCREEN_WIDTH / 2); - else if (offset.x + SCREEN_WIDTH / 2 > worldWidth * 0.5f) - offset.x = ((worldWidth * 0.5f) - SCREEN_WIDTH / 2); + else if (offset.x - SCREEN_WIDTH2 < worldWidth * -0.5f) + offset.x = ((worldWidth * -0.5f) + SCREEN_WIDTH2); + else if (offset.x + SCREEN_WIDTH2 > worldWidth * 0.5f) + offset.x = ((worldWidth * 0.5f) - SCREEN_WIDTH2); // ortho y snapping - offset.y = std::max(ploc.y /*+ player->height / 2*/, SCREEN_HEIGHT / 2.0f); + offset.y = std::max(ploc.y /*+ player->height / 2*/, SCREEN_HEIGHT2); // "setup" - glm::mat4 projection = glm::ortho(floor(offset.x - SCREEN_WIDTH / 2), // left - floor(offset.x + SCREEN_WIDTH / 2), // right - floor(offset.y - SCREEN_HEIGHT / 2), // bottom - floor(offset.y + SCREEN_HEIGHT / 2), // top + glm::mat4 projection = glm::ortho(floor(offset.x - SCREEN_WIDTH2), // left + floor(offset.x + SCREEN_WIDTH2), // right + floor(offset.y - SCREEN_HEIGHT2), // bottom + floor(offset.y + SCREEN_HEIGHT2), // top static_cast<decltype(floor(10.0f))>(10.0), // near static_cast<decltype(floor(10.0f))>(-10.0)); // far - glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), // pos - glm::vec3(0.0f, 0.0f, -10.0f), // looking at - glm::vec3(0.0f, 1.0f, 0.0f)); // up vector - glm::mat4 ortho = projection * view; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -318,30 +326,10 @@ void render() { // draw the debug overlay if desired if (ui::debug) { auto pos = game::engine.getSystem<PlayerSystem>()->getPosition(); - ui::putText(offset.x - SCREEN_WIDTH / 2, (offset.y + SCREEN_HEIGHT / 2) - ui::fontSize, - "loc: (%+.2f, %+.2f)\noffset: (%+.2f, %+.2f)\nfps: %d\nticks: %d\nxml: %s", - pos.x, - pos.y, - offset.x, - offset.y, - fps, - game::time::getTickCount(), - game::engine.getSystem<WorldSystem>()->getXMLFile().c_str() - ); - /*ui::putText(offset.x-SCREEN_WIDTH/2, (offset.y+SCREEN_HEIGHT/2)-ui::fontSize, - "fps: %d\ngrounded:%d\nresolution: %ux%u\nentity cnt: %d\nloc: (%+.2f, %+.2f)\nticks: %u\nvolume: %f\nweather: %s\nxml: %s", - fps, - 0,//player->ground, - SCREEN_WIDTH, // Window dimensions - SCREEN_HEIGHT, // - 0,//currentWorld->entity.size(),// Size of entity array - 0,//player->loc.x, // The player's x coordinate - debugY, // The player's y coordinate - game::time::getTickCount(), - game::config::VOLUME_MASTER, - game::engine.getSystem<WorldSystem>()->getWeatherStr().c_str(), - ""//currentXML.c_str() - );*/ + ui::putText(offset.x - SCREEN_WIDTH2, (offset.y + SCREEN_HEIGHT2) - ui::fontSize, + "loc: %s\noffset: %s\nfps: %d\nticks: %d\nxml: %s", + pos.toString().c_str(), offset.toString().c_str(), fps, + game::time::getTickCount(), game::engine.getSystem<WorldSystem>()->getXMLFile().c_str()); } // draw the menu @@ -351,108 +339,8 @@ void render() { // draw the mouse Render::textShader.use(); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, mouseTex); + mouseTex.use(); Render::useShader(&Render::textShader); Render::drawRect(vec2(ui::mouse.x, ui::mouse.y - 64), vec2(ui::mouse.x + 64, ui::mouse.y), -9.9); Render::textShader.unuse(); } - -void logic(){ -// static bool NPCSelected = false; -// static bool ObjectSelected = false; - - // exit the game if the player falls out of the world - /*if (player->loc.y < 0) - game::endGame();*/ - - /*if (player->inv->usingi) { - for (auto &e : currentWorld->entity) { - if (player->inv->usingi && !e->isHit() && - player->inv->detectCollision(vec2 { e->loc.x, e->loc.y }, vec2 { e->loc.x + e->width, e->loc.y + e->height})) { - e->takeHit(25, 10); - break; - } - } - player->inv->usingi = false; - }*/ - - /*for (auto &e : currentWorld->entity) { - if (e->isAlive() && ((e->type == NPCT) || (e->type == MERCHT) || (e->type == OBJECTT))) { - if (e->type == OBJECTT && ObjectSelected) { - e->near = false; - continue; - } else if (e->canMove) { - if (!currentWorld->goWorldLeft(dynamic_cast<NPC *>(e))) - currentWorld->goWorldRight(dynamic_cast<NPC *>(e)); - e->wander((rand() % 120 + 30)); - if (NPCSelected) { - e->near = false; - continue; - } - } - - if(e->isInside(ui::mouse) && player->isNear(e)) { - e->near = true; - if (e->type == OBJECTT) - ObjectSelected = true; - else - NPCSelected = true; - - if ((SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_RIGHT)) && !ui::dialogBoxExists) { - if (ui::mouse.x < player->loc.x && player->right) - player->left = true, player->right = false; - else if(ui::mouse.x > player->loc.x && player->left) - player->right = true, player->left = false; - e->interact(); - } - } else { - e->near = false; - } - } else if (e->type == MOBT) { - e->near = player->isNear(e); - e->wander(); - } - }*/ - - // calculate the world shading value - worldShade = 50 * sin((game::time::getTickCount() + (DAY_CYCLE / 2)) / (DAY_CYCLE / PI)); - - // update fades - ui::fadeUpdate(); - - // create weather particles if necessary - /*auto weather = game::engine.getSystem<WorldSystem>()->getWeatherId(); - auto worldWidth = game::engine.getSystem<WorldSystem>()->getWidth(); - if (weather == WorldWeather::Rain) { - for (unsigned int r = (randGet() % 25) + 11; r--;) { - currentWorld->addParticle(randGet() % worldWidth - (worldWidth / 2), - offset.y + game::SCREEN_HEIGHT / 2, - HLINES(1.25), // width - HLINES(1.25), // height - randGet() % 7 * .01 * (randGet() % 2 == 0 ? -1 : 1), // vel.x - (4 + randGet() % 6) * .05, // vel.y - { 0, 0, 255 }, // RGB color - 2500, // duration (ms) - (1 << 0) | (1 << 1) // gravity and bounce - ); - } - } else if (weather == WorldWeather::Snowy) { - for (unsigned int r = (randGet() % 25) + 11; r--;) { - currentWorld->addParticle(randGet() % worldWidth - (worldWidth / 2), - offset.y + game::SCREEN_HEIGHT / 2, - HLINES(1.25), // width - HLINES(1.25), // height - .0001 + randGet() % 7 * .01 * (randGet() % 2 == 0 ? -1 : 1), // vel.x - (4 + randGet() % 6) * -.03, // vel.y - { 255, 255, 255 }, // RGB color - 5000, // duration (ms) - 0 // no gravity, no bounce - ); - } - }*/ - - // increment game ticker - game::time::tick(); - //NPCSelected = false; - //ObjectSelected = false; -} diff --git a/src/brice.cpp b/src/brice.cpp index 5e7237f..53b1431 100644 --- a/src/brice.cpp +++ b/src/brice.cpp @@ -58,9 +58,9 @@ namespace game { } void briceLoad(void) { - const char *data = readFile("brice.dat"); + auto data = readFile("brice.dat"); - if (data == nullptr) { + if (data.empty()) { briceClear(); data = readFile("brice.dat"); } @@ -74,8 +74,6 @@ namespace game { brice.emplace(std::make_pair(datas[i], datas[i + 1])); } } - - delete[] data; } void briceUpdate(void) { diff --git a/src/common.cpp b/src/common.cpp index 098cd84..6539a05 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -51,22 +51,6 @@ void DEBUG_prints(const char* file, int line, const char *s,...) va_end(args); } -void safeSetColor(int r, int g, int b) -{ - r = static_cast<int>(fmax(fmin(r, 255), 0)); - g = static_cast<int>(fmax(fmin(g, 255), 0)); - b = static_cast<int>(fmax(fmin(b, 255), 0)); - glColor3ub(r, g, b); -} - -void safeSetColorA(int r,int g,int b,int a) { - r = static_cast<int>(fmax(fmin(r, 255), 0)); - g = static_cast<int>(fmax(fmin(g, 255), 0)); - b = static_cast<int>(fmax(fmin(b, 255), 0)); - a = static_cast<int>(fmax(fmin(a, 255), 0)); - glColor4ub(r, g, b, a); -} - int getdir(std::string dir, std::vector<std::string> &files) { #ifndef __WIN32__ @@ -119,27 +103,6 @@ void strVectorSortAlpha(std::vector<std::string> *v) } while (change); } -const char *readFile(const char *path) -{ - std::ifstream in (path,std::ios::in); - unsigned int size; - GLchar *buf; - - if (!in.is_open()) { -// UserError("Error reading file " + (std::string)path + "!"); - return nullptr; - } - - in.seekg(0,in.end); - buf = new GLchar[(size = in.tellg()) + 1]; - in.seekg(0,in.beg); - in.read(buf,size); - buf[size] = '\0'; - - in.close(); - return buf; -} - std::string readFile(const std::string& path) { std::ifstream in (path, std::ios::in); @@ -149,7 +112,7 @@ std::string readFile(const std::string& path) UserError("Error reading file " + path); in.seekg(0, in.end); - buffer.reserve(in.tellg()); + buffer.resize(in.tellg()); in.seekg(0, in.beg); in.read(&buffer[0], buffer.size()); diff --git a/src/components.cpp b/src/components.cpp index 323dfc8..7322208 100644 --- a/src/components.cpp +++ b/src/components.cpp @@ -10,6 +10,8 @@ #include <brice.hpp> #include <quest.hpp> +#include <atomic> + static std::vector<std::string> randomDialog (readFileA("assets/dialog_en-us")); void MovementSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) @@ -19,13 +21,11 @@ void MovementSystem::update(entityx::EntityManager &en, entityx::EventManager &e position.x += direction.x * dt; position.y += direction.y * dt; - if (entity.has_component<Animate>() && entity.has_component<Sprite>()) { - if (direction.x) { - entity.component<Animate>()->nextFrame(entity.component<Sprite>()->sprite); - } else { - entity.component<Animate>()->firstFrame(entity.component<Sprite>()->sprite); - } - } + /*if (entity.has_component<Animate>() && entity.has_component<Sprite>()) { + auto animate = entity.component<Animate>(); + entity.component<Sprite>()->sprite = + (direction.x != 0) ? animate->nextFrame() : animate->firstFrame(); + }*/ if (entity.has_component<Dialog>() && entity.component<Dialog>()->talking) { direction.x = 0; } else { @@ -59,11 +59,11 @@ void PhysicsSystem::update(entityx::EntityManager &en, entityx::EventManager &ev }); } -GLuint RenderSystem::loadTexture(const std::string& file) +Texture RenderSystem::loadTexture(const std::string& file) { loadTexString = file; - loadTexResult = 0xFFFF; - while (loadTexResult == 0xFFFF) + loadTexResult = Texture(); + while (loadTexResult.isEmpty()) std::this_thread::sleep_for(std::chrono::milliseconds(1)); return loadTexResult; } @@ -73,7 +73,7 @@ void RenderSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, (void)ev; if (!loadTexString.empty()) { - loadTexResult = Texture::loadTexture(loadTexString); + loadTexResult = Texture(loadTexString); loadTexString.clear(); } @@ -85,8 +85,7 @@ void RenderSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, float its = 0; for (auto &S : sprite.sprite) { auto sp = S.first; - float width = HLINES(S.first.size.x); - float height = HLINES(S.first.size.y); + auto size = sp.size * game::HLINE; vec2 drawOffset(HLINES(S.second.x), HLINES(S.second.y)); vec2 loc(pos.x + drawOffset.x, pos.y + drawOffset.y); @@ -99,23 +98,19 @@ void RenderSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, sp.offset_tex.x, sp.offset_tex.y}; if(sprite.faceLeft) { - glm::mat4 scale = glm::scale(glm::mat4(1.0f), glm::vec3(-1.0f,1.0f,1.0f)); - glm::mat4 translate = glm::translate(glm::mat4(1.0f), glm::vec3(0-width-pos.x*2, 0.0f, 0.0f)); + glm::mat4 translate = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f - size.x - pos.x * 2.0f, 0.0f, 0.0f)); glm::mat4 mov = scale * translate; glUniformMatrix4fv(Render::worldShader.uniform[WU_transform], 1, GL_FALSE, glm::value_ptr(mov)); - - } else { - } GLfloat coords[] = {loc.x, loc.y, visible.z + its, - loc.x + width, loc.y, visible.z + its, - loc.x + width, loc.y + height, visible.z + its, + loc.x + size.x, loc.y, visible.z + its, + loc.x + size.x, loc.y + size.y, visible.z + its, - loc.x + width, loc.y + height, visible.z + its, - loc.x, loc.y + height, visible.z + its, + loc.x + size.x, loc.y + size.y, visible.z + its, + loc.x, loc.y + size.y, visible.z + its, loc.x, loc.y, visible.z + its}; @@ -126,7 +121,7 @@ void RenderSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, glUniform4f(Render::worldShader.uniform[WU_tex_color], 1.0, flashAmt, flashAmt, 1.0); }*/ - glBindTexture(GL_TEXTURE_2D, S.first.pic); + sp.tex.use(); glUniform1i(Render::worldShader.uniform[WU_texture], 0); Render::worldShader.enable(); @@ -162,97 +157,100 @@ void DialogSystem::receive(const MouseClickEvent &mce) { game::entities.each<Position, Solid, Dialog, Name>( [&](entityx::Entity e, Position &pos, Solid &dim, Dialog &d, Name &name) { + static std::atomic_bool dialogRun; (void)e; (void)d; if (((mce.position.x > pos.x) & (mce.position.x < pos.x + dim.width)) && ((mce.position.y > pos.y) & (mce.position.y < pos.y + dim.height))) { - std::thread([&] { - std::string questAssignedText; - int newIndex; - - auto exml = game::engine.getSystem<WorldSystem>()->getXML()->FirstChildElement("Dialog"); - - if (e.has_component<Direction>()) - d.talking = true; - - if (d.index == 9999) { - ui::dialogBox(name.name, "", false, randomDialog[d.rindex % randomDialog.size()]); - ui::waitForDialog(); - } else if (exml != nullptr) { - while (exml->StrAttribute("name") != name.name) - exml = exml->NextSiblingElement(); - - exml = exml->FirstChildElement("text"); - while (exml->IntAttribute("id") != d.index) - exml = exml->NextSiblingElement(); - - auto oxml = exml->FirstChildElement("set"); - if (oxml != nullptr) { - do game::setValue(oxml->StrAttribute("id"), oxml->StrAttribute("value")); - while ((oxml = oxml->NextSiblingElement())); - game::briceUpdate(); - } - - auto qxml = exml->FirstChildElement("quest"); - if (qxml != nullptr) { - const char *qname; - auto qsys = game::engine.getSystem<QuestSystem>(); - - do { - // assign quest - qname = qxml->Attribute("assign"); - if (qname != nullptr) { - questAssignedText = qname; - auto req = qxml->GetText(); - qsys->assign(qname, qxml->StrAttribute("desc"), req ? req : ""); - } - - // check / finish quest - else { - qname = qxml->Attribute("check"); + if (!dialogRun.load()) { + std::thread([&] { + std::string questAssignedText; + int newIndex; + + auto exml = game::engine.getSystem<WorldSystem>()->getXML()->FirstChildElement("Dialog"); + dialogRun.store(true); + + if (e.has_component<Direction>()) + d.talking = true; + + if (d.index == 9999) { + ui::dialogBox(name.name, "", false, randomDialog[d.rindex % randomDialog.size()]); + ui::waitForDialog(); + } else if (exml != nullptr) { + while (exml->StrAttribute("name") != name.name) + exml = exml->NextSiblingElement(); + + exml = exml->FirstChildElement("text"); + while (exml->IntAttribute("id") != d.index) + exml = exml->NextSiblingElement(); + + auto oxml = exml->FirstChildElement("set"); + if (oxml != nullptr) { + do game::setValue(oxml->StrAttribute("id"), oxml->StrAttribute("value")); + while ((oxml = oxml->NextSiblingElement())); + game::briceUpdate(); + } + + auto qxml = exml->FirstChildElement("quest"); + if (qxml != nullptr) { + const char *qname; + auto qsys = game::engine.getSystem<QuestSystem>(); + + do { + // assign quest + qname = qxml->Attribute("assign"); if (qname != nullptr) { - if (qname != nullptr && qsys->hasQuest(qname) && qsys->finish(qname) == 0) { - d.index = 9999; - } else { - ui::dialogBox(name.name, "", false, "Finish my quest u nug"); - ui::waitForDialog(); - return; - } - // oldidx = d.index; - // d.index = qxml->UnsignedAttribute("fail"); - // goto COMMONAIFUNC; + questAssignedText = qname; + auto req = qxml->GetText(); + qsys->assign(qname, qxml->StrAttribute("desc"), req ? req : ""); } - } - } while((qxml = qxml->NextSiblingElement())); - } - auto cxml = exml->FirstChildElement("content"); - const char *content; - if (cxml == nullptr) { - content = randomDialog[d.rindex % randomDialog.size()].c_str(); - } else { - content = cxml->GetText() - 1; - while (*++content && isspace(*content)); + // check / finish quest + else { + qname = qxml->Attribute("check"); + if (qname != nullptr) { + if (qname != nullptr && qsys->hasQuest(qname) && qsys->finish(qname) == 0) { + d.index = 9999; + } else { + ui::dialogBox(name.name, "", false, "Finish my quest u nug"); + ui::waitForDialog(); + return; + } + // oldidx = d.index; + // d.index = qxml->UnsignedAttribute("fail"); + // goto COMMONAIFUNC; + } + } + } while((qxml = qxml->NextSiblingElement())); + } + + auto cxml = exml->FirstChildElement("content"); + const char *content; + if (cxml == nullptr) { + content = randomDialog[d.rindex % randomDialog.size()].c_str(); + } else { + content = cxml->GetText() - 1; + while (*++content && isspace(*content)); + } + + ui::dialogBox(name.name, "", false, content); + ui::waitForDialog(); + + if (!questAssignedText.empty()) + ui::passiveImportantText(5000, ("Quest assigned:\n\"" + questAssignedText + "\"").c_str()); + + if (exml->QueryIntAttribute("nextid", &newIndex) == XML_NO_ERROR) + d.index = newIndex; } - ui::dialogBox(name.name, "", false, content); - ui::waitForDialog(); - - if (!questAssignedText.empty()) - ui::passiveImportantText(5000, ("Quest assigned:\n\"" + questAssignedText + "\"").c_str()); - - if (exml->QueryIntAttribute("nextid", &newIndex) == XML_NO_ERROR) - d.index = newIndex; - } - - d.talking = false; - }).detach(); - + d.talking = false; + dialogRun.store(false); + }).detach(); } } - ); + }); } void DialogSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) diff --git a/src/engine.cpp b/src/engine.cpp index 7287f7d..48e384d 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -63,7 +63,7 @@ void Engine::update(entityx::TimeDelta dt) namespace game { entityx::EventManager events; entityx::EntityManager entities (events); - SpriteLoader sprite_l; + //SpriteLoader sprite_l; Engine engine; } diff --git a/src/inventory.cpp b/src/inventory.cpp index 91e81da..fb999ea 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -7,7 +7,7 @@ constexpr const char* ICON_TEX_FILE_PATH = "config/invIcons.txt"; -static std::vector<GLuint> iconTextures; +static std::vector<Texture> iconTextures; void InventorySystem::configure(entityx::EventManager &ev) { @@ -18,7 +18,7 @@ void InventorySystem::loadIcons(void) { iconTextures.clear(); auto icons = readFileA(ICON_TEX_FILE_PATH); for (const auto& s : icons) - iconTextures.push_back(Texture::loadTexture(s)); + iconTextures.push_back(s); } void InventorySystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) @@ -27,14 +27,13 @@ void InventorySystem::update(entityx::EntityManager &en, entityx::EventManager & (void)ev; (void)dt; - static auto color = Texture::genColor(Color(0, 0, 0)); vec2 start = vec2(offset.x, 100);// - game::SCREEN_WIDTH / 2 + 20, game::SCREEN_HEIGHT - 40); //std::cout << start.x << ' ' << start.y << std::endl; Render::textShader.use(); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, color); + Colors::black.use(); Render::useShader(&Render::textShader); Render::drawRect(start, start + 20, -9.9f); Render::textShader.unuse(); diff --git a/src/texture.cpp b/src/texture.cpp index a232e0e..640b06e 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -3,265 +3,139 @@ #include <texture.hpp> -/** - * A structure for keeping track of loaded textures. - */ - -typedef struct { - std::string name; /**< The file path of the texture. */ - GLuint tex; /**< The GLuint for the loaded texture. */ - dim2 dim; /**< The dimensions of the texture. */ -} texture_t; +namespace Colors +{ + ColorTex white; + ColorTex black; + ColorTex red; + + void init(void) { + white = ColorTex(Color(255, 255, 255)); + black = ColorTex(Color(0, 0, 0)); + red = ColorTex(Color(255, 0, 0)); + } +} -struct index_t { - Color color; - int indexx; - int indexy; -}; +void loadTexture(const std::string& file, Texture& texture); -// convert any type to octal -template <typename T> -uint toOctal(T toConvert) +Texture::Texture(const std::string& file, const GLuint& t, const vec2& v) + : name(file), tex(t), dim(v) { - int n = 0; - uint t = 0; - while (toConvert > 0) { - t += (pow(10, n++)) * (static_cast<int>(toConvert) % 8); - toConvert /= 8; - } - return t; + if (t == 0xFFFFF && !file.empty()) + loadTexture(file, *this); } -/** - * A vector of all loaded textures. - * - * Should a texture be asked to be loaded twice, loadTexture() can reference - * this array and reuse GLuint's to save memory. - */ +const std::string& Texture::getName(void) const +{ + return name; +} -static std::vector<texture_t> LoadedTexture; +const vec2& Texture::getDim(void) const +{ + return dim; +} -namespace Texture{ - Color pixels[8][4]; +ColorTex::ColorTex(void) +{ + Texture(); +} - GLuint loadTexture(std::string fileName) { - SDL_Surface *image; +ColorTex::ColorTex(const Color& color) +{ + unsigned char data[4] = { + static_cast<unsigned char>(color.red), + static_cast<unsigned char>(color.green), + static_cast<unsigned char>(color.blue), + static_cast<unsigned char>(color.alpha), + }; + + GLuint object; + glActiveTexture(GL_TEXTURE0); + glGenTextures(1, &object); // Turns "object" into a texture + glBindTexture(GL_TEXTURE_2D, object); // Binds "object" to the top of the stack + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + Texture("", object, vec2()); +} - // check if texture is already loaded - for(auto &t : LoadedTexture) { - if (t.name == fileName) { +static std::vector<Texture> loadedTextures; -#ifdef DEBUG - DEBUG_printf("Reusing loaded texture for %s\n", fileName.c_str()); -#endif // DEBUG - - return t.tex; - } - } +void loadTexture(const std::string& file, Texture& texture) +{ + auto preloaded = + std::find_if(std::begin(loadedTextures), std::end(loadedTextures), + [&file](const Texture& t) { return (t.getName() == file); }); - // load SDL_surface of texture - if (!(image = IMG_Load(fileName.c_str()))) - return 0; + if (preloaded == std::end(loadedTextures)) { + auto image = IMG_Load(file.c_str()); + if (image == nullptr) + UserError("File not found: " + file); #ifdef DEBUG - DEBUG_printf("Loaded image file: %s\n", fileName.c_str()); + DEBUG_printf("Loaded image file: %s\n", file.c_str()); #endif // DEBUG - /* - * Load texture through OpenGL. - */ + // load texture through OpenGL GLuint object; glGenTextures(1, &object); // Turns "object" into a texture glBindTexture(GL_TEXTURE_2D, object); // Binds "object" to the top of the stack - glPixelStoref(GL_UNPACK_ALIGNMENT,1); - + glPixelStoref(GL_UNPACK_ALIGNMENT, 1); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Sets the "min" filter glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // The the "max" filter of the stack glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // Wrap the texture to the matrix glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // - glTexImage2D(GL_TEXTURE_2D, // Sets the texture to the image file loaded above - 0, - GL_RGBA, - image->w, - image->h, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - image->pixels - ); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image->w, image->h, 0, + GL_RGBA, GL_UNSIGNED_BYTE, image->pixels); + + // add texture to loadedTextures + loadedTextures.emplace_back(file, object, vec2(image->w, image->h)); - // add texture to LoadedTexture - LoadedTexture.push_back(texture_t{fileName,object,{image->w,image->h}}); + texture = loadedTextures.back(); // free the SDL_Surface SDL_FreeSurface(image); - - return object; - } - - GLuint genColor(Color c) - { - std::string out; - - // add the red - out += static_cast<int>(c.red); - - // add the green - out += static_cast<int>(c.green); - - // add the blue - out += static_cast<int>(c.blue); - - // add the alpha - out += static_cast<int>(c.alpha); - - GLuint object; - - glActiveTexture(GL_TEXTURE0); - glGenTextures(1,&object); // Turns "object" into a texture - glBindTexture(GL_TEXTURE_2D,object); // Binds "object" to the top of the stack - //glPixelStorei(GL_UNPACK_ALIGNMENT,1); - - //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Sets the "min" filter - //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // The the "max" filter of the stack - - //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // Wrap the texture to the matrix - //glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // - - glTexImage2D(GL_TEXTURE_2D, // Sets the texture to the image file loaded above - 0, // level - GL_RGBA, // internal format - 1, // width - 1, // height - 0, // border - GL_RGBA, // image format - GL_UNSIGNED_BYTE, // type - out.data() // source - ); - - return object; - } - - vec2 imageDim(std::string fileName) { - for(auto &t : LoadedTexture) { - if (t.name == fileName) - return vec2(t.dim.x, t.dim.y); - } - return vec2(0,0); - } - - void freeTextures(void) { - while(!LoadedTexture.empty()) { - glDeleteTextures(1, &LoadedTexture.back().tex); - LoadedTexture.pop_back(); - } - } - - #define CINDEX_WIDTH (8*4*3) - void initColorIndex() { - unsigned int i; - GLubyte *buffer; - GLfloat *bufferf; - - buffer = new GLubyte[CINDEX_WIDTH]; - bufferf = new GLfloat[CINDEX_WIDTH]; - - colorIndex = loadTexture("assets/colorIndex.png"); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, colorIndex); - glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer); - - for(i = 0; i < CINDEX_WIDTH; i++) - bufferf[i] = (float)buffer[i] / 255.0f; - - i = 0; - for(unsigned int y = 0; y < 8; y++) { - for(unsigned int x = 0; x < 4; x++) { - if (i >= CINDEX_WIDTH) { - delete[] buffer; - delete[] bufferf; - return; - } - pixels[y][x].red = buffer[i++]; - pixels[y][x].green = buffer[i++]; - pixels[y][x].blue = buffer[i++]; - } - } - delete[] buffer; - delete[] bufferf; - } - - //sqrt((255-145)^2+(90-145)^2+(0-0)^2); - std::vector<index_t>ind; - vec2 getIndex(Color c) { - for(auto &i : ind) { - if (c.red == i.color.red && c.green == i.color.green && c.blue == i.color.blue) { - return {float(i.indexx), float(i.indexy)}; - } - } - uint buf[2]; - float buff = 999; - float shit = 999; - for(uint y = 0; y < 8; y++) { - for(uint x = 0; x < 4; x++) { - buff = sqrt(pow((pixels[y][x].red- c.red), 2)+ - pow((pixels[y][x].green-c.green),2)+ - pow((pixels[y][x].blue- c.blue), 2)); - if (buff < shit) { - shit = buff; - buf[0] = y; - buf[1] = x; - } - } - } - ind.push_back({c, (int)buf[1], (int)buf[0]}); - return {float(buf[1]),float(buf[0])}; + } else { + texture = *preloaded; } } -Texturec::Texturec(uint amt, ...) { - va_list fNames; - texState = 0; - va_start(fNames, amt); - for (unsigned int i = 0; i < amt; i++) { - std::string l = va_arg(fNames, char *); - image.push_back(Texture::loadTexture(l)); - texLoc.push_back(l); - } - va_end(fNames); -} -Texturec::Texturec(std::initializer_list<std::string> l) +TextureIterator::TextureIterator(const std::vector<std::string> &l) { - texState = 0; - std::for_each(l.begin(), l.end(), [&](std::string s) { image.push_back(Texture::loadTexture(s)); texLoc.push_back(s);}); + for (const auto& s : l) + textures.emplace_back(s); + position = std::begin(textures); } -Texturec::Texturec(std::vector<std::string>v) { - texState = 0; - std::for_each(v.begin(), v.end(), [&](std::string s) { image.push_back(Texture::loadTexture(s)); texLoc.push_back(s);}); +void TextureIterator::operator++(int) noexcept +{ + if (++position >= std::end(textures)) + position = std::end(textures) - 1; + position->use(); } -Texturec::Texturec(uint amt,const char **paths) { - texState = 0; - for (unsigned int i = 0; i < amt; i++) { - image.push_back(Texture::loadTexture(paths[i])); - texLoc.push_back(paths[i]); - } +void TextureIterator::operator--(int) noexcept +{ + if (--position < std::begin(textures)) + position = std::begin(textures); + position->use(); } -Texturec::~Texturec() { -} +void TextureIterator::operator()(const int &index) +{ + if (index < 0 || index > static_cast<int>(textures.size())) + throw std::invalid_argument("texture index out of range"); -void Texturec::bind(unsigned int bn) { - texState = bn; - glBindTexture(GL_TEXTURE_2D,image[(int)texState]); + position = std::begin(textures) + index; + position->use(); } -void Texturec::bindNext() { - bind(++texState); -} -void Texturec::bindPrev() { - bind(--texState); +void unloadTextures(void) +{ + while (!loadedTextures.empty()) { + loadedTextures.back().destroy(); + loadedTextures.pop_back(); + } } + @@ -20,14 +20,14 @@ std::array<SDL_Keycode, 6> controlMap = { SDLK_w, SDLK_a, SDLK_d, SDLK_LSHIFT, SDLK_LCTRL, SDLK_e }; -void setControl(unsigned int index, SDL_Keycode key) +void setControl(int index, SDL_Keycode key) { controlMap[index] = key; } -SDL_Keycode getControl(unsigned int index) +SDL_Keycode getControl(int index) { - if (index >= controlMap.size()) + if (index >= static_cast<int>(controlMap.size())) return 0; return controlMap[index]; @@ -57,7 +57,7 @@ static bool ft24loaded = false; static auto *ftdat = &ftdat16; static auto *ftex = &ftex16; -static unsigned char fontColor[4] = {255,255,255,255}; +static Color fontColor (255, 255, 255, 255); /* * Variables for dialog boxes / options. @@ -87,57 +87,45 @@ Mix_Chunk *sanic; static GLuint pageTex = 0; static bool pageTexReady = false; -void loadFontSize(unsigned int size, std::vector<GLuint> &tex, std::vector<FT_Info> &dat) +void loadFontSize(int size, std::vector<GLuint> &tex, std::vector<FT_Info> &dat) { FT_Set_Pixel_Sizes(ftf,0,size); - /* - * Pre-render 'all' the characters. - */ - + // pre-render 'all' the characters glDeleteTextures(93, tex.data()); glGenTextures(93, tex.data()); // Generate new texture name/locations? - for(char i=33;i<126;i++) { - - /* - * Load the character from the font family file. - */ - - if (FT_Load_Char (ftf, i, FT_LOAD_RENDER)) + for (char i = 33; i < 126; i++) { + // load the character from the font family file + if (FT_Load_Char(ftf, i, FT_LOAD_RENDER)) UserError("Error! Unsupported character " + i); - /* - * Transfer the character's bitmap (?) to a texture for rendering. - */ - - glBindTexture(GL_TEXTURE_2D,tex[i-33]); - glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S ,GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T ,GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER ,GL_LINEAR ); - glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER ,GL_LINEAR ); - glPixelStorei(GL_UNPACK_ALIGNMENT,1); - - /* - * The just-created texture will render red-on-black if we don't do anything to it, so - * here we create a buffer 4 times the size and transform the texture into an RGBA array, - * making it white-on-black. - */ - - - std::vector<uint32_t> buf (ftf->glyph->bitmap.width * ftf->glyph->bitmap.rows, 0xFFFFFFFF); - - for(unsigned int j = buf.size(); j--;) - buf[j] ^= !ftf->glyph->bitmap.buffer[j] ? buf[j] : 0; - - dat[i - 33].wh.x = ftf->glyph->bitmap.width; - dat[i - 33].wh.y = ftf->glyph->bitmap.rows; - dat[i - 33].bl.x = ftf->glyph->bitmap_left; - dat[i - 33].bl.y = ftf->glyph->bitmap_top; - dat[i - 33].ad.x = ftf->glyph->advance.x >> 6; - dat[i - 33].ad.y = ftf->glyph->advance.y >> 6; - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ftf->glyph->bitmap.width, ftf->glyph->bitmap.rows, + // transfer the character's bitmap (?) to a texture for rendering + glBindTexture(GL_TEXTURE_2D, tex[i - 33]); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER , GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER , GL_LINEAR); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + /** + * The just-created texture will render red-on-black if we don't do anything to it, so + * here we create a buffer 4 times the size and transform the texture into an RGBA array, + * making it white-on-black. + */ + auto& g = ftf->glyph; + std::vector<uint32_t> buf (g->bitmap.width * g->bitmap.rows, 0xFFFFFFFF); + for (auto j = buf.size(); j--;) + buf[j] ^= !g->bitmap.buffer[j] ? buf[j] : 0; + + auto& d = dat[i - 33]; + d.wh.x = g->bitmap.width; + d.wh.y = g->bitmap.rows; + d.bl.x = g->bitmap_left; + d.bl.y = g->bitmap_top; + d.ad.x = g->advance.x >> 6; + d.ad.y = g->advance.y >> 6; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, g->bitmap.width, g->bitmap.rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf.data()); } } @@ -200,7 +188,7 @@ namespace ui { UserError("Couldn't initialize freetype."); #ifdef DEBUG - DEBUG_printf("Initialized FreeType2.\n",NULL); + DEBUG_printf("Initialized FreeType2.\n", nullptr); #endif // DEBUG fontSize = 0; @@ -232,6 +220,7 @@ namespace ui { #ifdef DEBUG DEBUG_printf("Using font %s\n",ttf); #endif // DEBUG + ft16loaded = false; ft24loaded = false; } @@ -241,42 +230,24 @@ namespace ui { */ void setFontSize(unsigned int size) { - (void)size; - if (size == 16) { - if (!ft16loaded) { - loadFontSize(fontSize = size, ftex16, ftdat16); - ft16loaded = true; - } - ftex = &ftex16; - ftdat = &ftdat16; - fontSize = 16; - } else if (size == 24) { - if (!ft24loaded) { - loadFontSize(fontSize = size, ftex24, ftdat24); - ft24loaded = true; - } - ftex = &ftex24; - ftdat = &ftdat24; - fontSize = 24; + auto& loaded = (size == 16) ? ft16loaded : ft24loaded; + auto& tex = (size == 16) ? ftex16 : ftex24; + auto& dat = (size == 16) ? ftdat16 : ftdat24; + + if (!loaded) { + loadFontSize(fontSize = size, tex, dat); + loaded = true; } + ftex = &tex; + ftdat = &dat; + fontSize = size; } /* * Set a color for font rendering (default: white). - */ - - void setFontColor(unsigned char r,unsigned char g,unsigned char b) { - fontColor[0]=r; - fontColor[1]=g; - fontColor[2]=b; - fontColor[3]=255; - } - - void setFontColor(unsigned char r,unsigned char g,unsigned char b, unsigned char a) { - fontColor[0]=r; - fontColor[1]=g; - fontColor[2]=b; - fontColor[3]=a; + */ + void setFontColor(int r, int g, int b, int a = 255) { + fontColor = Color(r, g, b, a); } /* @@ -288,65 +259,53 @@ namespace ui { /* * Draws a character at the specified coordinates, aborting if the character is unknown. - */ - + */ vec2 putChar(float xx,float yy,char c){ - vec2 c1,c2; - + const auto& ch = (*ftdat)[c - 33]; int x = xx, y = yy; - /* - * Get the width and height of the rendered character. - */ - - c1={(float)floor(x)+(*ftdat)[c-33].bl.x, - (float)floor(y)+(*ftdat)[c-33].bl.y}; - c2=(*ftdat)[c-33].wh; - - /* - * Draw the character: - */ + // get dimensions of the rendered character + vec2 c1 = { + static_cast<float>(floor(x) + ch.bl.x), + static_cast<float>(floor(y) + ch.bl.y) + }; + const auto& c2 = ch.wh; + // draw the character glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,(*ftex)[c-33]); + glBindTexture(GL_TEXTURE_2D, (*ftex)[c - 33]); glUniform1i(Render::textShader.uniform[WU_texture], 0); glUniform4f(Render::textShader.uniform[WU_tex_color], 1.0f, 1.0f, 1.0f, 1.0f); - //glDisable(GL_DEPTH_TEST); - Render::textShader.use(); Render::textShader.enable(); - GLfloat tex_coord[] = { 0.0, 1.0, //bottom left 1.0, 1.0, //bottom right 1.0, 0.0, //top right - 1.0, 0.0, //top right 0.0, 0.0, //top left 0.0, 1.0, //bottom left - }; GLfloat text_vert[] = { c1.x, c1.y -c2.y, fontZ, //bottom left c1.x+c2.x, c1.y -c2.y, fontZ, //bottom right c1.x+c2.x, c1.y+c2.y-c2.y, fontZ, //top right - c1.x+c2.x, c1.y+c2.y-c2.y, fontZ, //top right c1.x, c1.y+c2.y-c2.y, fontZ, //top left c1.x, c1.y -c2.y, fontZ //bottom left }; glUniform4f(Render::textShader.uniform[WU_tex_color], - static_cast<float>(fontColor[0]/255), - static_cast<float>(fontColor[1]/255), - static_cast<float>(fontColor[2]/255), - static_cast<float>(fontColor[3]/255)); + static_cast<float>(fontColor.red / 255), + static_cast<float>(fontColor.green / 255), + static_cast<float>(fontColor.blue / 255), + static_cast<float>(fontColor.alpha / 255)); glVertexAttribPointer(Render::textShader.coord, 3, GL_FLOAT, GL_FALSE, 0, text_vert); - glVertexAttribPointer(Render::textShader.tex, 2, GL_FLOAT, GL_FALSE, 0, tex_coord); + glVertexAttribPointer(Render::textShader.tex, 2, GL_FLOAT, GL_FALSE, 0, tex_coord); glDrawArrays(GL_TRIANGLES, 0, 6); glUniform4f(Render::textShader.uniform[WU_tex_color], 1.0, 1.0, 1.0, 1.0); @@ -354,10 +313,8 @@ namespace ui { Render::textShader.disable(); Render::textShader.unuse(); - //glEnable(GL_DEPTH_TEST); - // return the width. - return (*ftdat)[c-33].ad; + return ch.ad; } /* @@ -368,13 +325,9 @@ namespace ui { unsigned int i = 0, nl = 1; vec2 add, o = {x, y}; - /* - * Loop on each character: - */ - + // loop on each character do { if (dialogBoxExists && i > textWrapLimit * nl) { - o.y -= fontSize * 1.05f; o.x = x; ++nl; @@ -385,14 +338,13 @@ namespace ui { } switch (s[i]) { + case '\r': + case '\t': + break; case '\n': o.y -= fontSize * 1.05f; o.x = x; break; - case '\r': - break; - case '\t': - break; case '\b': o.x -= add.x; break; @@ -407,7 +359,7 @@ namespace ui { } } while (s[++i]); - return o.x; // i.e. the string width + return o.x; // the string width } float putStringCentered(const float x, const float y, std::string s) { @@ -505,40 +457,36 @@ namespace ui { * Draw a formatted string to the specified coordinates. */ - float putText(const float x, const float y, const char *str, ...) { - va_list args; + std::string uisprintf(const char *s, va_list args) { std::unique_ptr<char[]> buf (new char[512]); + vsnprintf(buf.get(), 512, s, args); + std::string ret (buf.get()); + return ret; + } - // zero out the buffer - memset(buf.get(),0,512*sizeof(char)); - - /* - * Handle the formatted string, printing it to the buffer. - */ - + float putText(const float x, const float y, const char *str, ...) { + va_list args; + va_start(args,str); - vsnprintf(buf.get(),512,str,args); + auto s = uisprintf(str, args); va_end(args); // draw the string and return the width - return putString(x, y, buf.get()); + return putString(x, y, s); } void putTextL(vec2 c, const char *str, ...) { va_list args; - std::unique_ptr<char[]> buf (new char[512]); - memset(buf.get(), 0, 512 * sizeof(char)); va_start(args, str); - vsnprintf(buf.get(), 512, str, args); + auto s = uisprintf(str, args); va_end(args); - textToDraw.push_back(std::make_pair(c, buf.get())); + textToDraw.push_back(std::make_pair(c, s)); } void dialogBox(std::string name, std::string opt, bool passive, std::string text, ...) { - va_list dialogArgs; - std::unique_ptr<char[]> printfbuf (new char[512]); + va_list args; dialogPassive = passive; @@ -546,14 +494,14 @@ namespace ui { dialogBoxText = name + ": "; // handle the formatted string - va_start(dialogArgs, text); - vsnprintf(printfbuf.get(), 512, text.c_str(), dialogArgs); - va_end(dialogArgs); - dialogBoxText += printfbuf.get(); + va_start(args, text); + auto s = uisprintf(text.c_str(), args); + va_end(args); + + dialogBoxText += s; // setup option text dialogOptText.clear(); - dialogOptChosen = 0; if (!opt.empty()) { @@ -562,14 +510,11 @@ namespace ui { // cycle through options while (sopt) { dialogOptText.push_back(std::make_pair((std::string)sopt, vec3 {0,0,0})); - sopt = strtok(NULL,":"); + sopt = strtok(nullptr, ":"); } } - /* - * Tell draw() that the box is ready. - */ - + // tell draw() that the box is ready dialogBoxExists = true; dialogImportant = false; @@ -599,21 +544,16 @@ namespace ui { fadeIntensity = 0; } - void waitForNothing(unsigned int ms) { - unsigned int target = millis() + ms; - while (millis() < target); - } - - void importantText(const char *text,...) { - va_list textArgs; - std::unique_ptr<char[]> printfbuf (new char[512]); + void importantText(const char *text, ...) { + va_list args; dialogBoxText.clear(); - va_start(textArgs,text); - vsnprintf(printfbuf.get(),512,text,textArgs); - va_end(textArgs); - dialogBoxText = printfbuf.get(); + va_start(args, text); + auto s = uisprintf(text, args); + va_end(args); + + dialogBoxText = s; dialogBoxExists = true; dialogImportant = true; @@ -622,15 +562,15 @@ namespace ui { } void passiveImportantText(int duration, const char *text, ...) { - va_list textArgs; - std::unique_ptr<char[]> printfbuf (new char[512]); + va_list args; dialogBoxText.clear(); - va_start(textArgs,text); - vsnprintf(printfbuf.get(),512,text,textArgs); - va_end(textArgs); - dialogBoxText = printfbuf.get(); + va_start(args, text); + auto s = uisprintf(text, args); + va_end(args); + + dialogBoxText = s; dialogBoxExists = true; dialogImportant = true; @@ -667,11 +607,8 @@ namespace ui { 0,1, 0,0}; - static GLuint boxT = Texture::genColor(Color(0,0,0)); - static GLuint lineT = Texture::genColor(Color(255,255,255)); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, boxT); + Colors::black.use(); glUniform1i(Render::textShader.uniform[WU_texture], 0); Render::textShader.use(); @@ -681,7 +618,7 @@ namespace ui { glVertexAttribPointer(Render::textShader.tex, 2, GL_FLOAT, GL_FALSE, 0, box_tex); glDrawArrays(GL_TRIANGLES, 0 ,6); - glBindTexture(GL_TEXTURE_2D, lineT); + Colors::white.use(); glUniform1i(Render::textShader.uniform[WU_texture], 0); glVertexAttribPointer(Render::textShader.coord, 3, GL_FLOAT, GL_FALSE, 0, line_strip); @@ -698,13 +635,13 @@ namespace ui { void drawNiceBoxColor(vec2 c1, vec2 c2, float z, Color c) { // the textures for the box corners - static GLuint box_corner = Texture::loadTexture("assets/ui/button_corners.png"); - static GLuint box_side_top = Texture::loadTexture("assets/ui/button_top_bot_borders.png"); - static GLuint box_side = Texture::loadTexture("assets/ui/button_side_borders.png"); + static Texture boxCorner ("assets/ui/button_corners.png"); + static Texture boxSideTop ("assets/ui/button_top_bot_borders.png"); + static Texture boxSide ("assets/ui/button_side_borders.png"); // the dimensions of the corner textures - static vec2 box_corner_dim_t = Texture::imageDim("assets/ui/button_corners.png"); - static vec2 box_corner_dim = vec2(box_corner_dim_t.x / 2.0, box_corner_dim_t.y / 2.0); + static const auto& boxCornerDim = boxCorner.getDim(); + static const auto& boxCornerDim2 = boxCornerDim / 2; // the amount of bytes to skip in the OpenGL arrays (see below) auto stride = 5 * sizeof(GLfloat); @@ -714,81 +651,80 @@ namespace ui { if (c1.y > c2.y) c1.swapY(c2); // std::swap(c1.y, c2.y); // if the box is too small, we will not be able to draw it - if (c2.x - c1.x < (box_corner_dim_t.x)) return; - if (c2.y - c1.y < (box_corner_dim_t.y)) return; - + if (c2.x - c1.x < (boxCornerDim.x) || c2.y - c1.y < (boxCornerDim.y)) + return; - GLfloat box_ul[] = {c1.x, c2.y - box_corner_dim.y, z, 0.0f, 0.5f, - c1.x + box_corner_dim.x, c2.y - box_corner_dim.y, z, 0.5f, 0.5f, - c1.x + box_corner_dim.x, c2.y, z, 0.5f, 1.0f, + GLfloat box_ul[] = {c1.x, c2.y - boxCornerDim2.y, z, 0.0f, 0.5f, + c1.x + boxCornerDim2.x, c2.y - boxCornerDim2.y, z, 0.5f, 0.5f, + c1.x + boxCornerDim2.x, c2.y, z, 0.5f, 1.0f, - c1.x + box_corner_dim.x, c2.y, z, 0.5f, 1.0f, - c1.x, c2.y, z, 0.0f, 1.0f, - c1.x, c2.y - box_corner_dim.y, z, 0.0f, 0.5f}; + c1.x + boxCornerDim2.x, c2.y, z, 0.5f, 1.0f, + c1.x, c2.y, z, 0.0f, 1.0f, + c1.x, c2.y - boxCornerDim2.y, z, 0.0f, 0.5f}; - GLfloat box_ll[] = {c1.x, c1.y, z, 0.0f, 0.0f, - c1.x + box_corner_dim.x, c1.y, z, 0.5f, 0.0f, - c1.x + box_corner_dim.x, c1.y + box_corner_dim.y, z, 0.5f, 0.5f, + GLfloat box_ll[] = {c1.x, c1.y, z, 0.0f, 0.0f, + c1.x + boxCornerDim2.x, c1.y, z, 0.5f, 0.0f, + c1.x + boxCornerDim2.x, c1.y + boxCornerDim2.y, z, 0.5f, 0.5f, - c1.x + box_corner_dim.x, c1.y + box_corner_dim.y, z, 0.5f, 0.5f, - c1.x, c1.y + box_corner_dim.y, z, 0.0f, 0.5f, - c1.x, c1.y, z, 0.0f, 0.0f}; + c1.x + boxCornerDim2.x, c1.y + boxCornerDim2.y, z, 0.5f, 0.5f, + c1.x, c1.y + boxCornerDim2.y, z, 0.0f, 0.5f, + c1.x, c1.y, z, 0.0f, 0.0f}; - GLfloat box_ur[] = {c2.x - box_corner_dim.x, c2.y - box_corner_dim.y, z, 0.5f, 0.5f, - c2.x, c2.y - box_corner_dim.y, z, 1.0f, 0.5f, + GLfloat box_ur[] = {c2.x - boxCornerDim2.x, c2.y - boxCornerDim2.y, z, 0.5f, 0.5f, + c2.x, c2.y - boxCornerDim2.y, z, 1.0f, 0.5f, c2.x, c2.y, z, 1.0f, 1.0f, c2.x, c2.y, z, 1.0f, 1.0f, - c2.x - box_corner_dim.x, c2.y, z, 0.5f, 1.0f, - c2.x - box_corner_dim.x, c2.y - box_corner_dim.y, z, 0.5f, 0.5f}; + c2.x - boxCornerDim2.x, c2.y, z, 0.5f, 1.0f, + c2.x - boxCornerDim2.x, c2.y - boxCornerDim2.y, z, 0.5f, 0.5f}; - GLfloat box_lr[] = {c2.x - box_corner_dim.x, c1.y, z, 0.5f, 0.0f, + GLfloat box_lr[] = {c2.x - boxCornerDim2.x, c1.y, z, 0.5f, 0.0f, c2.x, c1.y, z, 1.0f, 0.0f, - c2.x, c1.y + box_corner_dim.y, z, 1.0f, 0.5f, + c2.x, c1.y + boxCornerDim2.y, z, 1.0f, 0.5f, - c2.x, c1.y + box_corner_dim.y, z, 1.0f, 0.5f, - c2.x - box_corner_dim.x, c1.y + box_corner_dim.y, z, 0.5f, 0.5f, - c2.x - box_corner_dim.x, c1.y, z, 0.5f, 0.0f}; + c2.x, c1.y + boxCornerDim2.y, z, 1.0f, 0.5f, + c2.x - boxCornerDim2.x, c1.y + boxCornerDim2.y, z, 0.5f, 0.5f, + c2.x - boxCornerDim2.x, c1.y, z, 0.5f, 0.0f}; - GLfloat box_l[] = {c1.x, c1.y + box_corner_dim.y, z, 0.0f, 0.0f, - c1.x + box_corner_dim.x, c1.y + box_corner_dim.y, z, 0.5f, 0.0f, - c1.x + box_corner_dim.x, c2.y - box_corner_dim.y, z, 0.5f, 1.0f, + GLfloat box_l[] = {c1.x, c1.y + boxCornerDim2.y, z, 0.0f, 0.0f, + c1.x + boxCornerDim2.x, c1.y + boxCornerDim2.y, z, 0.5f, 0.0f, + c1.x + boxCornerDim2.x, c2.y - boxCornerDim2.y, z, 0.5f, 1.0f, - c1.x + box_corner_dim.x, c2.y - box_corner_dim.y, z, 0.5f, 1.0f, - c1.x, c2.y - box_corner_dim.y, z, 0.0f, 1.0f, - c1.x, c1.y + box_corner_dim.y, z, 0.0f, 0.0f}; + c1.x + boxCornerDim2.x, c2.y - boxCornerDim2.y, z, 0.5f, 1.0f, + c1.x, c2.y - boxCornerDim2.y, z, 0.0f, 1.0f, + c1.x, c1.y + boxCornerDim2.y, z, 0.0f, 0.0f}; - GLfloat box_r[] = {c2.x - box_corner_dim.x, c1.y + box_corner_dim.y, z, 0.5f, 0.0f, - c2.x, c1.y + box_corner_dim.y, z, 1.0f, 0.0f, - c2.x, c2.y - box_corner_dim.y, z, 1.0f, 1.0f, + GLfloat box_r[] = {c2.x - boxCornerDim2.x, c1.y + boxCornerDim2.y, z, 0.5f, 0.0f, + c2.x, c1.y + boxCornerDim2.y, z, 1.0f, 0.0f, + c2.x, c2.y - boxCornerDim2.y, z, 1.0f, 1.0f, - c2.x, c2.y - box_corner_dim.y, z, 1.0f, 1.0f, - c2.x - box_corner_dim.x, c2.y - box_corner_dim.y, z, 0.5f, 1.0f, - c2.x - box_corner_dim.x, c1.y + box_corner_dim.y, z, 0.5f, 0.0f}; + c2.x, c2.y - boxCornerDim2.y, z, 1.0f, 1.0f, + c2.x - boxCornerDim2.x, c2.y - boxCornerDim2.y, z, 0.5f, 1.0f, + c2.x - boxCornerDim2.x, c1.y + boxCornerDim2.y, z, 0.5f, 0.0f}; - GLfloat box_b[] = {c1.x + box_corner_dim.x, c1.y, z, 0.0f, 0.0f, - c2.x - box_corner_dim.x, c1.y, z, 1.0f, 0.0f, - c2.x - box_corner_dim.x, c1.y + box_corner_dim.y, z, 1.0f, 0.5f, + GLfloat box_b[] = {c1.x + boxCornerDim2.x, c1.y, z, 0.0f, 0.0f, + c2.x - boxCornerDim2.x, c1.y, z, 1.0f, 0.0f, + c2.x - boxCornerDim2.x, c1.y + boxCornerDim2.y, z, 1.0f, 0.5f, - c2.x - box_corner_dim.x, c1.y + box_corner_dim.y, z, 1.0f, 0.5f, - c1.x + box_corner_dim.x, c1.y + box_corner_dim.y, z, 0.0f, 0.5f, - c1.x + box_corner_dim.x, c1.y, z, 0.0f, 0.0f}; + c2.x - boxCornerDim2.x, c1.y + boxCornerDim2.y, z, 1.0f, 0.5f, + c1.x + boxCornerDim2.x, c1.y + boxCornerDim2.y, z, 0.0f, 0.5f, + c1.x + boxCornerDim2.x, c1.y, z, 0.0f, 0.0f}; - GLfloat box_t[] = {c1.x + box_corner_dim.x, c2.y - box_corner_dim.y, z, 0.0f, 0.5f, - c2.x - box_corner_dim.x, c2.y - box_corner_dim.y, z, 1.0f, 0.5f, - c2.x - box_corner_dim.x, c2.y, z, 1.0f, 1.0f, + GLfloat box_t[] = {c1.x + boxCornerDim2.x, c2.y - boxCornerDim2.y, z, 0.0f, 0.5f, + c2.x - boxCornerDim2.x, c2.y - boxCornerDim2.y, z, 1.0f, 0.5f, + c2.x - boxCornerDim2.x, c2.y, z, 1.0f, 1.0f, - c2.x - box_corner_dim.x, c2.y, z, 1.0f, 1.0f, - c1.x + box_corner_dim.x, c2.y, z, 0.0f, 1.0f, - c1.x + box_corner_dim.x, c2.y - box_corner_dim.y, z, 0.0f, 0.5f}; + c2.x - boxCornerDim2.x, c2.y, z, 1.0f, 1.0f, + c1.x + boxCornerDim2.x, c2.y, z, 0.0f, 1.0f, + c1.x + boxCornerDim2.x, c2.y - boxCornerDim2.y, z, 0.0f, 0.5f}; - GLfloat box_f[] = {c1.x + box_corner_dim.x, c1.y + box_corner_dim.y, z, 0.5f, 0.5f, - c2.x - box_corner_dim.x, c1.y + box_corner_dim.y, z, 0.5f, 0.5f, - c2.x - box_corner_dim.x, c2.y - box_corner_dim.y, z, 0.5f, 0.5f, + GLfloat box_f[] = {c1.x + boxCornerDim2.x, c1.y + boxCornerDim2.y, z, 0.5f, 0.5f, + c2.x - boxCornerDim2.x, c1.y + boxCornerDim2.y, z, 0.5f, 0.5f, + c2.x - boxCornerDim2.x, c2.y - boxCornerDim2.y, z, 0.5f, 0.5f, - c2.x - box_corner_dim.x, c2.y - box_corner_dim.y, z, 0.5f, 0.5f, - c1.x + box_corner_dim.x, c2.y - box_corner_dim.y, z, 0.5f, 0.5f, - c1.x + box_corner_dim.x, c1.y + box_corner_dim.y, z, 0.5f, 0.5f}; + c2.x - boxCornerDim2.x, c2.y - boxCornerDim2.y, z, 0.5f, 0.5f, + c1.x + boxCornerDim2.x, c2.y - boxCornerDim2.y, z, 0.5f, 0.5f, + c1.x + boxCornerDim2.x, c1.y + boxCornerDim2.y, z, 0.5f, 0.5f}; glActiveTexture(GL_TEXTURE0); glUniform1f(Render::textShader.uniform[WU_texture], 0); @@ -797,7 +733,7 @@ namespace ui { Render::textShader.enable(); glUniform4f(Render::textShader.uniform[WU_tex_color], c.red, c.green, c.blue, c.alpha); - glBindTexture(GL_TEXTURE_2D, box_corner); + boxCorner.use(); // draw upper left corner glVertexAttribPointer(Render::textShader.coord, 3, GL_FLOAT, GL_FALSE, stride, &box_ul[0]); @@ -824,7 +760,7 @@ namespace ui { glVertexAttribPointer(Render::textShader.tex, 2, GL_FLOAT, GL_FALSE, stride, &box_f[3]); glDrawArrays(GL_TRIANGLES, 0, 6); - glBindTexture(GL_TEXTURE_2D, box_side); + boxSide.use(); // draw the left edge of the box glVertexAttribPointer(Render::textShader.coord, 3, GL_FLOAT, GL_FALSE, stride, &box_l[0]); @@ -836,7 +772,7 @@ namespace ui { glVertexAttribPointer(Render::textShader.tex, 2, GL_FLOAT, GL_FALSE, stride, &box_r[3]); glDrawArrays(GL_TRIANGLES, 0, 6); - glBindTexture(GL_TEXTURE_2D, box_side_top); + boxSideTop.use(); // draw bottom of the box glVertexAttribPointer(Render::textShader.coord, 3, GL_FLOAT, GL_FALSE, stride, &box_b[0]); @@ -871,13 +807,14 @@ namespace ui { offset.x - 300, SCREEN_HEIGHT - 600, -6.0, offset.x - 300, SCREEN_HEIGHT - 100, -6.0}; - GLfloat page_tex[] = {0.0, 0.0, - 1.0, 0.0, - 1.0, 1.0, - - 1.0, 1.0, - 0.0, 1.0, - 0.0, 0.0}; + static const GLfloat page_tex[] = { + 0.0, 0.0, + 1.0, 0.0, + 1.0, 1.0, + 1.0, 1.0, + 0.0, 1.0, + 0.0, 0.0 + }; glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, pageTex); @@ -897,7 +834,7 @@ namespace ui { rtext = typeOut(dialogBoxText); if (dialogImportant) { - setFontColor(255,255,255); + setFontColor(255, 255, 255); if (dialogPassive) { dialogPassiveTime -= game::time::getDeltaTime() * 12; if (dialogPassiveTime < 0) { @@ -924,21 +861,21 @@ namespace ui { putString(x + HLINES(2), y - fontSize - game::HLINE, rtext); for (i = 0; i < dialogOptText.size(); i++) { - float tmp; - setFontColor(255,255,255); - tmp = putStringCentered(offset.x,dialogOptText[i].second.y,dialogOptText[i].first); - dialogOptText[i].second.z = offset.x + tmp; - dialogOptText[i].second.x = offset.x - tmp; - dialogOptText[i].second.y = y - SCREEN_HEIGHT / 4 + (fontSize + game::HLINE) * (i + 1); - if (mouse.x > dialogOptText[i].second.x && - mouse.x < dialogOptText[i].second.z && - mouse.y > dialogOptText[i].second.y && - mouse.y < dialogOptText[i].second.y + 16) { // fontSize - setFontColor(255,255,0); - putStringCentered(offset.x,dialogOptText[i].second.y,dialogOptText[i].first); + auto& sec = dialogOptText[i].second; + + setFontColor(255, 255, 255); + auto tmp = putStringCentered(offset.x, sec.y,dialogOptText[i].first); + sec.z = offset.x + tmp; + sec.x = offset.x - tmp; + sec.y = y - SCREEN_HEIGHT / 4 + (fontSize + game::HLINE) * (i + 1); + if (mouse.x > sec.x && mouse.x < sec.z && + mouse.y > sec.y && mouse.y < sec.y + 16) { // fontSize + setFontColor(255, 255, 0); + putStringCentered(offset.x, sec.y, dialogOptText[i].first); } } - setFontColor(255,255,255); + + setFontColor(255, 255, 255); } static unsigned int rtext_oldsize = 0; @@ -1035,22 +972,12 @@ namespace ui { } } - void quitGame() { - dialogBoxExists = false; - currentMenu = NULL; - game::config::update(); - game::config::save(); - game::endGame(); - } - void closeBox() { dialogBoxExists = false; dialogMerchant = false; } void dialogAdvance(void) { - unsigned char i; - dialogPassive = false; dialogPassiveTime = 0; @@ -1067,17 +994,16 @@ namespace ui { return; } - for(i=0;i<dialogOptText.size();i++) { - if (mouse.x > dialogOptText[i].second.x && - mouse.x < dialogOptText[i].second.z && - mouse.y > dialogOptText[i].second.y && - mouse.y < dialogOptText[i].second.y + 16) { // fontSize + for (int i = 0; i < static_cast<int>(dialogOptText.size()); i++) { + const auto& dot = dialogOptText[i].second; + + if (mouse.x > dot.x && mouse.x < dot.z && + mouse.y > dot.y && mouse.y < dot.y + 16) { // fontSize dialogOptChosen = i + 1; - goto EXIT; + break; } } -EXIT: dialogBoxExists = false; // handle important text @@ -1088,8 +1014,8 @@ EXIT: } void drawFade(void) { - auto SCREEN_WIDTH = game::SCREEN_WIDTH; - auto SCREEN_HEIGHT = game::SCREEN_HEIGHT; + static const auto SCREEN_WIDTH2 = game::SCREEN_WIDTH / 2; + static const auto SCREEN_HEIGHT2 = game::SCREEN_HEIGHT / 2; if (!fadeIntensity) { if (fontSize != 16) @@ -1097,27 +1023,27 @@ EXIT: return; } - auto fadeTex = Texture::genColor( (fadeWhite ? Color(255, 255, 255, fadeIntensity) : - Color(0, 0, 0, fadeIntensity)) ); - - - GLfloat tex[] = {0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0, - 1.0, 1.0}; + static const GLfloat tex[] = { + 0.0, 0.0, + 1.0, 0.0, + 0.0, 1.0, + 1.0, 1.0 + }; - GLfloat backdrop[] = {offset.x - SCREEN_WIDTH / 2 - 1, offset.y - SCREEN_HEIGHT / 2, -7.9, - offset.x + SCREEN_WIDTH / 2, offset.y - SCREEN_HEIGHT / 2, -7.9, - offset.x - SCREEN_WIDTH / 2 - 1, offset.y + SCREEN_HEIGHT / 2, -7.9, - offset.x + SCREEN_WIDTH / 2, offset.y + SCREEN_HEIGHT / 2, -7.9}; + GLfloat backdrop[] = { + offset.x - SCREEN_WIDTH2 - 1, offset.y - SCREEN_HEIGHT2, -7.9, + offset.x + SCREEN_WIDTH2, offset.y - SCREEN_HEIGHT2, -7.9, + offset.x - SCREEN_WIDTH2 - 1, offset.y + SCREEN_HEIGHT2, -7.9, + offset.x + SCREEN_WIDTH2, offset.y + SCREEN_HEIGHT2, -7.9 + }; setFontZ(-8.2); glUniform1i(Render::textShader.uniform[WU_texture], 0); Render::textShader.use(); Render::textShader.enable(); - - glBindTexture(GL_TEXTURE_2D, fadeTex); + Colors::black.use(); + glUniform4f(Render::textShader.uniform[WU_tex_color], 1.0f, 1.0f, 1.0f, fadeIntensity / 255.0f); glVertexAttribPointer(Render::textShader.coord, 3, GL_FLOAT, GL_FALSE, 0, backdrop); glVertexAttribPointer(Render::textShader.tex, 2, GL_FLOAT, GL_FALSE, 0, tex); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); @@ -1126,8 +1052,6 @@ EXIT: Render::textShader.unuse(); setFontZ(-8.0); - - glDeleteTextures(1, &fadeTex); } void fadeUpdate(void) { @@ -1183,7 +1107,7 @@ EXIT: bgr[x+2] = pixels[x]; } - time_t epoch = time(NULL); + time_t epoch = time(nullptr); struct tm* timen = localtime(&epoch); std::string name = "screenshots/"; diff --git a/src/ui_menu.cpp b/src/ui_menu.cpp index 59b44e6..cbf30be 100644 --- a/src/ui_menu.cpp +++ b/src/ui_menu.cpp @@ -22,8 +22,16 @@ void Menu::gotoParent(void) } } -inline void segFault() { - (*((int *)NULL))++; +inline void segFault(void) +{ + ++*((int *)0); +} + +void quitGame(void) +{ + game::config::update(); + game::config::save(); + game::endGame(); } std::string& deleteWord(std::string& s) @@ -120,7 +128,7 @@ namespace ui { temp.button.dim = d; temp.button.color = c; temp.button.text = t; - temp.button.func = NULL; + temp.button.func = nullptr; temp.child = _child; return temp; @@ -134,7 +142,7 @@ namespace ui { temp.button.dim = d; temp.button.color = c; temp.button.text = t; - temp.button.func = NULL; + temp.button.func = nullptr; temp.child = nullptr; return temp; @@ -162,7 +170,7 @@ namespace ui { pauseMenu.items.push_back(ui::menu::createParentButton({-128,100},{256,75},{0.0f,0.0f,0.0f}, "Resume")); pauseMenu.items.push_back(ui::menu::createChildButton({-128, 0},{256,75},{0.0f,0.0f,0.0f}, "Options", &optionsMenu)); pauseMenu.items.push_back(ui::menu::createChildButton({-128,-100},{256,75},{0.0f,0.0f,0.0f}, "Controls", &controlsMenu)); - pauseMenu.items.push_back(ui::menu::createButton({-128,-200},{256,75},{0.0f,0.0f,0.0f}, "Save and Quit", ui::quitGame)); + pauseMenu.items.push_back(ui::menu::createButton({-128,-200},{256,75},{0.0f,0.0f,0.0f}, "Save and Quit", quitGame)); pauseMenu.items.push_back(ui::menu::createButton({-128,-300},{256,75},{0.0f,0.0f,0.0f}, "Segfault", segFault)); // Create the options (sound) menu @@ -236,14 +244,13 @@ namespace ui { } static float cMult = 1.0f; - static GLuint backTex = Texture::genColor(Color(0, 0, 0, 204)); - //static GLuint bsTex = Texture::genColor(Color(30, 30, 30)); + static const ColorTex back (Color(0, 0, 0, 204)); //draw the dark transparent background glColor4f(0.0f, 0.0f, 0.0f, .8f); Render::textShader.use(); - glBindTexture(GL_TEXTURE_2D, backTex); + back.use(); Render::drawRect(vec2(offset.x - SCREEN_WIDTH / 2 - 1, offset.y - (SCREEN_HEIGHT / 2)), vec2(offset.x + SCREEN_WIDTH / 2, offset.y + (SCREEN_HEIGHT / 2)), -8.5); @@ -320,7 +327,7 @@ namespace ui { cMult = 0.75f; //if we are inside the slider and click it will set the slider to that point - if (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON(SDL_BUTTON_LEFT)) { + if (SDL_GetMouseState(nullptr, nullptr) & SDL_BUTTON(SDL_BUTTON_LEFT)) { //change handle location if (m.slider.dim.y > m.slider.dim.x) { *m.slider.var = (((mouse.y-offset.y) - m.slider.loc.y)/m.slider.dim.y)*100; diff --git a/src/world.cpp b/src/world.cpp index d61ed41..6b18542 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -185,18 +185,13 @@ void WorldSystem::load(const std::string& file) entityx::Entity entity; - std::string xmlRaw; - std::string xmlPath; - // check for empty file name if (file.empty()) return; // load file data to string - xmlPath = xmlFolder + file; - auto xmlRawData = readFile(xmlPath.c_str()); - xmlRaw = xmlRawData; - delete[] xmlRawData; + auto xmlPath = xmlFolder + file; + auto xmlRaw = readFile(xmlPath); // let tinyxml parse the file if (xmlDoc.Parse(xmlRaw.data()) != XML_NO_ERROR) @@ -204,18 +199,21 @@ void WorldSystem::load(const std::string& file) // include headers auto ixml = xmlDoc.FirstChildElement("include"); - while (ixml) { + while (ixml != nullptr) { auto file = ixml->Attribute("file"); + if (file != nullptr) { DEBUG_printf("Including file: %s\n", file); - auto include = readFile((xmlFolder + file).c_str()); - xmlRaw.append(include); - delete[] include; + xmlRaw.append(readFile(xmlFolder + file)); + } else { + UserError("XML Error: <include> tag file not given"); } - ixml = ixml->NextSiblingElement(); + + break;//ixml = ixml->NextSiblingElement(); } - xmlDoc.Parse(xmlRaw.data()); + if (xmlDoc.Parse(xmlRaw.data()) != XML_NO_ERROR) + UserError("XML Error:"); // look for an opening world tag auto wxml = xmlDoc.FirstChildElement("World"); @@ -272,10 +270,11 @@ void WorldSystem::load(const std::string& file) if (!world.indoor) UserError("<house> can only be used inside <IndoorWorld>"); - world.indoorWidth = wxml->FloatAttribute("width"); - auto str = wxml->StrAttribute("texture"); - auto tex = render.loadTexture(str); - world.indoorTex = tex; + //world.indoorWidth = wxml->FloatAttribute("width"); + world.indoorTex = render.loadTexture(wxml->StrAttribute("texture")); + //auto str = wxml->StrAttribute("texture"); + //auto tex = render.loadTexture(str); + //world.indoorTex = tex; } // weather tag @@ -858,26 +857,26 @@ void WorldSystem::render(void) // draw the remaining layers for (int i = 0; i < 4; i++) { bgTex++; - auto dim = bgTex.getTextureDim(); - dim.x = HLINES(dim.x); - dim.y = HLINES(dim.y); auto xcoord = offset.x * bgDraw[i][2]; bg_items.clear(); bg_tex.clear(); + vec2 dim = bgTex.getTextureDim() * game::HLINE; + if (world.indoor && i == 3) { - glBindTexture(GL_TEXTURE_2D, world.indoorTex); + world.indoorTex.use(); const auto& startx = world.startX; + dim = world.indoorTex.getDim() * game::HLINE; - bg_items.emplace_back(startx, GROUND_HEIGHT_MINIMUM, 7 - (i * 0.1f)); - bg_items.emplace_back(startx + world.indoorWidth, GROUND_HEIGHT_MINIMUM, 7 - (i * 0.1f)); - bg_items.emplace_back(startx + world.indoorWidth, GROUND_HEIGHT_MINIMUM + dim.y, 7 - (i * 0.1f)); + bg_items.emplace_back(startx, GROUND_HEIGHT_MINIMUM, 7 - (i * 0.1f)); + bg_items.emplace_back(startx + dim.x, GROUND_HEIGHT_MINIMUM, 7 - (i * 0.1f)); + bg_items.emplace_back(startx + dim.x, GROUND_HEIGHT_MINIMUM + dim.y, 7 - (i * 0.1f)); - bg_items.emplace_back(startx + world.indoorWidth, GROUND_HEIGHT_MINIMUM + dim.y, 7 - (i * 0.1f)); - bg_items.emplace_back(startx, GROUND_HEIGHT_MINIMUM + dim.y, 7 - (i * 0.1f)); - bg_items.emplace_back(startx, GROUND_HEIGHT_MINIMUM, 7 - (i * 0.1f)); + bg_items.emplace_back(startx + dim.x, GROUND_HEIGHT_MINIMUM + dim.y, 7 - (i * 0.1f)); + bg_items.emplace_back(startx, GROUND_HEIGHT_MINIMUM + dim.y, 7 - (i * 0.1f)); + bg_items.emplace_back(startx, GROUND_HEIGHT_MINIMUM, 7 - (i * 0.1f)); } else { for (int j = world.startX; j <= -world.startX; j += dim.x) { bg_items.emplace_back(j + xcoord, GROUND_HEIGHT_MINIMUM, 7 - (i * 0.1f)); @@ -936,11 +935,11 @@ void WorldSystem::render(void) GLfloat *dirtp = &dirt[0]; for (int i = iStart; i < iEnd; i++) { - if (world.data[i].groundHeight <= 0) { // TODO holes (andy) + if (world.data[i].groundHeight <= 0) { // TODO holes (andy) TODO TODO TODO world.data[i].groundHeight = GROUND_HEIGHT_MINIMUM - 1; - glColor4ub(0, 0, 0, 255); + //glColor4ub(0, 0, 0, 255); } else { - safeSetColorA(150, 150, 150, 255); + //safeSetColorA(150, 150, 150, 255); } int ty = world.data[i].groundHeight / 64 + world.data[i].groundColor; @@ -978,7 +977,7 @@ void WorldSystem::render(void) if (!world.indoor) { bgTex++; - safeSetColorA(255, 255, 255, 255); + //safeSetColorA(255, 255, 255, 255); TODO TODO TODO static std::vector<GLfloat> grass; if (grass.size() != world.data.size() * 60) { @@ -1044,12 +1043,11 @@ void WorldSystem::render(void) // the ending pixel of the world static const float e = static_cast<float>(SCREEN_WIDTH) / 2.0f; - static const auto blackTex = Texture::genColor(Color(0, 0, 0)); static const float sheight = static_cast<float>(SCREEN_HEIGHT); if (offset.x + world.startX > s) { - glBindTexture(GL_TEXTURE_2D, blackTex); + Colors::black.use(); glUniform1f(Render::worldShader.uniform[WU_light_impact], 0.0f); auto off = offset.y - static_cast<float>(SCREEN_HEIGHT) / 2.0f; @@ -1070,7 +1068,7 @@ void WorldSystem::render(void) } if (offset.x - world.startX < e) { - glBindTexture(GL_TEXTURE_2D, blackTex); + Colors::black.use(); glUniform1f(Render::worldShader.uniform[WU_light_impact], 0.0f); auto off = offset.y - static_cast<float>(SCREEN_HEIGHT) / 2.0f; @@ -1096,10 +1094,9 @@ void WorldSystem::render(void) } else { Render::useShader(&Render::worldShader); Render::worldShader.use(); - static const GLuint rug = Texture::genColor(Color {255, 0, 0}); - glBindTexture(GL_TEXTURE_2D, rug); + Colors::red.use(); vec2 ll = vec2 {world.startX, GROUND_HEIGHT_MINIMUM}; - Render::drawRect(ll, ll + vec2 {world.indoorWidth, 4}, -3); + Render::drawRect(ll, ll + vec2(world.indoorTex.getDim().x, 4), -3); Render::worldShader.unuse(); } |