--- /dev/null
- #define C(x) std::cout << x << std::endl
+/** @file common.h
+ * @brief Common items needed by most other files.
+ *
+ * This file contains headers, variables and functions that are needed in
+ * most other files included in this project.
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+// holy moly
+#include <iostream>
+#include <cstdlib>
+#include <string>
+#include <vector>
+#include <string>
+#include <fstream>
+#include <thread>
+#include <mutex>
+#include <future>
+#include <math.h>
+#include <threadpool.hpp>
+#include <algorithm>
+
+#define GLEW_STATIC
+#include <GL/glew.h>
+
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_opengl.h>
+#include <SDL2/SDL_image.h>
+#include <SDL2/SDL_mixer.h>
+
+#ifdef __WIN32__
+typedef unsigned int uint;
+#undef near
+#endif
+
+/**
+ * This flag lets the compiler know that we want to use shaders.
+ */
+
+#define SHADERS
- #define GAME_NAME "Independent Study v.0.6 alpha - NOW WITH more c++"
+
+template<typename N>
+N abso(N v){
+ if(v < 0){
+ return v * -1;
+ }else
+ return v;
+}
+
+template<class A>
+float averagef(A v){
+ float avg = 0;
+ for(auto &a : v){
+ avg += a;
+ }
+ avg /= v.size();
+ return avg;
+}
+
+
+extern GLuint colorIndex; // Texture.cpp?
+
+/**
+ * This structure contains a set of coordinates for ease of coding.
+ */
+
+typedef struct {
+ int x;
+ int y;
+} ivec2;
+
+typedef struct {
+ float x;
+ float y;
+} vec2;
+
+typedef struct {
+ float x;
+ float y;
+ float z;
+} vec3;
+
+typedef ivec2 dim2;
+
+/**
+ * This structure contains two sets of coordinates for ray drawing.
+ */
+
+typedef struct {
+ vec2 start;
+ vec2 end;
+} Ray;
+
+struct col {
+ float red;
+ float green;
+ float blue;
+ col operator-=(float a){
+ red-=a;
+ green-=a;
+ blue-=a;
+ return{red+a,green+a,blue+a};
+ }
+ col operator+=(float a){
+ return{red+a,green+a,blue+a};
+ }
+ col operator=(float a){
+ return{red=a,green=a,blue=a};
+ }
+};
+
+typedef col Color;
+
+/**
+ * Define the game's name (displayed in the window title).
+ */
+
++#define GAME_NAME "Independent Study v0.7 alpha - NOW WITH lights and snow and stuff"
+
+/**
+ * The desired width of the game window.
+ */
+
+extern unsigned int SCREEN_WIDTH;
+
+/**
+ * The desired height of the game window.
+ */
+
+extern unsigned int SCREEN_HEIGHT;
+
+extern bool FULLSCREEN;
+extern bool uiLoop;
+extern std::mutex mtx;
+
+/**
+ * Define the length of a single HLINE.
+ * The game has a great amount of elements that need to be drawn or detected, and having each
+ * of them use specific hard-coded numbers would be painful to debug. As a solution, this
+ * definition was made. Every item being drawn to the screen and most object detection/physic
+ * handling is done based off of this number. Increasing it will give the game a zoomed-in
+ * feel, while decreasing it will do the opposite.
+ *
+ */
+
+extern unsigned int HLINE;
+
+extern float VOLUME_MASTER;
+extern float VOLUME_MUSIC;
+extern float VOLUME_SFX;
+/**
+ * A 'wrapper' for libc's srand(), as we hope to eventually have our own random number
+ * generator.
+ */
+
+#define initRand(s) srand(s)
+
+/**
+ * A 'wrapper' for libc's rand(), as we hope to eventually have our own random number
+ * generator.
+ */
+
+#define getRand() rand()
+
+#define randGet rand
+#define randInit srand
+
+/**
+ * Included in common.h is a prototype for DEBUG_prints, which writes a formatted
+ * string to the console containing the callee's file and line number. This macro simplifies
+ * it to a simple printf call.
+ *
+ * DEBUG must be defined for this macro to function.
+ */
+
+#define DEBUG_printf( message, ...) DEBUG_prints(__FILE__, __LINE__, message, __VA_ARGS__ )
++#define C(x) std::cout << x << std::endl;
+
+/**
+ * Defines pi for calculations that need it.
+ */
+
+#define PI 3.1415926535
+
+
+/**
+ * References the variable in main.cpp, used for smoother drawing.
+ */
+
+extern unsigned int deltaTime;
+
+/**
+ * References the variable in main.cpp, used for drawing with the player.
+ */
+
+extern vec2 offset;
+
+/**
+ * Counts the number of times logic() (see main.cpp) has been called, for animating
+ * sprites.
+ */
+extern unsigned int loops;
+
+extern GLuint shaderProgram;
+
+/**
+ * Prints a formatted debug message to the console, along with the callee's file and line
+ * number.
+ */
+
+void DEBUG_prints(const char* file, int line, const char *s,...);
+
+/**
+ * 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);
+
+
+/**
+ * We've encountered many problems when attempting to create delays for triggering
+ * the logic function. As a result, we decided on using the timing libraries given
+ * by <chrono> in the standard C++ library. This function simply returns the amount
+ * of milliseconds that have passed since the epoch.
+ */
+
+#ifdef __WIN32__
+#define millis() SDL_GetTicks()
+#else
+unsigned int millis(void);
+#endif // __WIN32__
+
+int getdir(const char *dir, std::vector<std::string> &files);
+void strVectorSortAlpha(std::vector<std::string> *v);
+
+const char *readFile(const char *path);
+
+int strCreateFunc(const char *equ);
+
+template<typename N, size_t s>
+size_t arrAmt(N (&)[s]){return s;}
+
+void UserError(std::string reason);
+
+#endif // COMMON_H
--- /dev/null
- #include <tinyxml2.h>
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include <iostream>
++
+#include <SDL2/SDL_mixer.h>
- void readConfig(void);
+
- void updateConfig(void);
++#include <tinyxml2.h>
++#include <ui.hpp>
+
- void saveConfig();
+
- #endif //CONFIG_H
++namespace config {
++ void read( void );
++ void update( void );
++ void save( void );
++}
+
++#endif //CONFIG_H
--- /dev/null
- #include <Texture.hpp>
+#ifndef INVENTORY_H
+#define INVENTORY_H
+
+#include <common.hpp>
+#include <string.h>
+
++#include <texture.hpp>
+
+#define DEBUG
+
+class Item{
+public:
+ std::string name,type;
+
+ float width;
+ float height;
+ int maxStackSize;
+
+ std::string texloc;
+ Texturec *tex;
+
+ GLuint rtex(){
+ return tex->image[0];
+ }
+};
+
+struct item_t{
+ uint count;
+ uint id;
+} __attribute__((packed));
+
+class Inventory {
+private:
+ unsigned int size;
+ int os = 0;
+public:
+ std::vector<item_t> items;
+ unsigned int sel;
+ bool invOpen = false;
+ bool invOpening = false;
+ bool invHover = false;
+ bool selected = false;
+ bool mouseSel = false;
+ bool usingi = false;
+
+ Inventory(unsigned int s); // Creates an inventory of size 's'
+ ~Inventory(void); // Free's allocated memory
+
+ int addItem(std::string name,uint count);
+ int takeItem(std::string name,uint count);
+ int hasItem(std::string name);
+
+ int useItem(void);
+ bool detectCollision(vec2,vec2);
+
+ void setSelection(unsigned int s);
+ void setSelectionUp();
+ void setSelectionDown();
+
+ void draw(void); // Draws a text list of items in this inventory (should only be called for the player for now)
+};
+
+void initInventorySprites(void);
+void destroyInventory(void);
+
+const char *getItemTexturePath(std::string name);
+GLuint getItemTexture(std::string name);
+float getItemWidth(std::string name);
+float getItemHeight(std::string name);
+
+#endif // INVENTORY_H
--- /dev/null
- void singleDetect( Entity *e );
+/** @file world.h
+ * @brief The world system.
+ *
+ * This file contains the classes and variables necessary to create an in-game
+ * world.
+ */
+
+#ifndef WORLD_H
+#define WORLD_H
+
+#include <common.hpp>
+#include <entities.hpp>
+
+#define GROUND_HEIGHT_INITIAL 80
+#define GROUND_HEIGHT_MINIMUM 60
+#define GROUND_HEIGHT_MAXIMUM 110
+
+#define GROUND_HILLINESS 10
+
+/**
+ * Defines how many game ticks it takes for a day to elapse.
+ */
+
+#define DAY_CYCLE 12000
+
+/**
+ * The background type enum.
+ * This enum contains all different possibilities for world backgrounds; used
+ * in World::setBackground() to select the appropriate images.
+ */
+
+enum class WorldBGType : unsigned char {
+ Forest, /**< A forest theme. */
+ WoodHouse /**< An indoor wooden house theme. */
+};
+
+/**
+ * The weather type enum.
+ * This enum contains every type of weather currently implemented in the game.
+ * Weather is set by the world somewhere.
+ */
+
+enum class WorldWeather : unsigned char {
+ Sunny = 0, /**< Sunny/daytime */
+ Dark, /**< Nighttime */
+ Rain, /**< Rain */
+ Snowy /**< Snow */
+};
+
+/**
+ * The line structure.
+ * This structure is used to store the world's ground, stored in vertical
+ * lines. Dirt color and grass properties are also kept track of here.
+ */
+
+typedef struct {
+ bool grassUnpressed;
+ float grassHeight[2];
+ float groundHeight;
+ unsigned char groundColor;
+} WorldData;
+
+/**
+ * A value used by World::draw() for shading, ranges from -50 to 50 depending
+ * on the current time of day.
+ */
+
+extern int worldShade;
+
+/**
+ * The path to the currently loaded XML file.
+ */
+
+extern std::string currentXML;
+
+// prototype so Village can reference it
+class World;
+
+/**
+ * The light structure, used to store light coordinates and color.
+ */
+
+class Light{
+public:
+ vec2 loc; /**< Light location */
+ Color color; /**< Light color */
+ float radius; /**< Light radius */
+
+ bool belongsTo;
+ Entity *following;
+
+ bool flame;
+ float fireFlicker;
+ vec2 fireLoc;
+
+ Light(vec2 l, Color c, float r){
+ loc = l;
+ color = c;
+ radius = r;
+
+ belongsTo = false;
+ following = nullptr;
+
+ flame = false;
+ }
+
+ void makeFlame(void){
+ flame = true;
+ }
+
+ void follow(Entity *f){
+ following=f;
+ belongsTo = true;
+ }
+};
+
+
+/**
+ * The village class, used to group structures into villages.
+ */
+
+class Village {
+public:
+ std::string name;
+ vec2 start;
+ vec2 end;
+ bool in;
+ std::vector<Structures *> build;
+
+ Village(const char *meme, World *w);
+ ~Village(void){}
+};
+
+/**
+ * The world class. This class does everything a world should do.
+ */
+
+class World {
+protected:
+
+ /**
+ * The line array.
+ *
+ * This array is created through 'new' in World::generate(), with an amount
+ * of elements provided by the function.
+ */
+
+ std::vector<WorldData> worldData;
+
+ /**
+ * Starting x coordinate.
+ *
+ * This x value is the point at which line[0] should reside, can be used to
+ * calculate the width of the world.
+ */
+
+ int worldStart;
+
+ /**
+ * Handle physics for a single entity.
+ *
+ * This function handles gravity and death for an entity. The public version
+ * of this, World::detect(), handles all entities in the world as well as
+ * the player. World::singleDetect() should never be used outside of
+ * World::detect(), which is why it is declared private.
+ */
+
- virtual void generate(unsigned int width);
++ virtual void singleDetect( Entity *e );
+
+ /**
+ * Empties all entity vectors.
+ *
+ * Each entity vector is iterated through, calling delete for each entry.
+ * Once all specific vectors are cleared, the general entity vector is
+ * emptied of the pointers to those other vectors. This function should only
+ * be called in World's destructor, as there shouldn't be another reason to
+ * call this function.
+ */
+
+ void deleteEntities( void );
+
+ /**
+ * Number of lines in the world.
+ *
+ * While this number is helpful for knowing the world's width, it is kept
+ * private for security reasons. To compensate for this,
+ * World::getTheWidth() is provided (see below).
+ */
+
+ unsigned int lineCount;
+
+ /**
+ * An array of star coordinates.
+ */
+
+ std::vector<vec2> star;
+
+ /**
+ * The Texturec object that holds the background sprites for this world.
+ */
+
+ Texturec *bgTex;
+
+ /**
+ * Defines the set of background images that should be used for this world.
+ */
+
+ WorldBGType bgType;
+
+ /**
+ * The Mix_Music object that holds the background soundtrack for the world.
+ */
+
+ Mix_Music *bgmObj;
+
+ /**
+ * The file path of the song wished to be loaded by bgmObj.
+ */
+
+ std::string bgm;
+
+ std::vector<std::string> bgFiles;
+ std::vector<std::string> bgFilesIndoors;
+
+public:
+
+ /**
+ * The filename of the XML file for the world to the left; NULL if no world
+ * is present.
+ */
+
+ std::string toLeft;
+
+ /**
+ * The filename of the XML file for the world to the right; NULL if no world
+ * is present.
+ */
+
+ std::string toRight;
+
+ /**
+ * Sets what XML file to use for loading the world to the left.
+ */
+
+ std::string setToLeft( std::string file );
+
+ /**
+ * Sets what XML file to use for loading the world to the right.
+ */
+
+ std::string setToRight( std::string file );
+
+ /**
+ * A vector of pointers to every NPC, Structure, Mob, and Object in this
+ * world.
+ */
+
+ std::vector<Entity *> entity;
+
+ /**
+ * A vector of all NPCs in this world.
+ */
+
+ std::vector<NPC *> npc;
+ std::vector<Merchant *> merchant;
+
+ /**
+ * A vector of all Structures in this world.
+ */
+
+ std::vector<Structures *> build;
+
+ /**
+ * A vector of all Mobs in this world.
+ */
+
+ std::vector<Mob *> mob;
+
+ /**
+ * A vector of all Objects in this world.
+ */
+
+ std::vector<Object *> object;
+
+ /**
+ * A vector of all particles in this world.
+ */
+
+ std::vector<Particles> particles;
+
+
+ std::vector<Village *> village;
+
+ /**
+ * A vector of all light elements in this world.
+ */
+
+ std::vector<Light> light;
+
+ /**
+ * Vector of all building textures for the current world style
+ */
+
+ std::vector<std::string> sTexLoc;
+
+ /**
+ * NULLifies pointers and allocates necessary memory. This should be
+ * followed by some combination of setBackground(), setBGM(), or
+ * generate().
+ */
+
+ World( void );
+
+ /**
+ * Frees resources taken by the world.
+ */
+
+ virtual ~World(void);
+
+ /**
+ * Adds a structure to the world, with the specified subtype and
+ * coordinates. `inside` is a file name for the IndoorWorld XML file that
+ * this structure will lead to; if NULL the player won't be able to enter
+ * the structure.
+ */
+
+ void addStructure(BUILD_SUB subtype,float x,float y, std::string tex, std::string inside);
+
+ /**
+ * Adds a Mob to the world with the specified type and coordinates.
+ */
+
+ void addMob(int type,float x,float y);
+
+ /**
+ * Adds a Mob to the world with a handler function that can be called by
+ * certain mobs to trigger events.
+ */
+
+ void addMob(int t,float x,float y,void (*hey)(Mob *));
+
+ /**
+ * Adds an NPC to the world with the specified coordinates.
+ */
+
+ void addNPC(float x,float y);
+
+ /**
+ * Adds a Merchant to the world at the specified coordinates.
+ */
+
+ void addMerchant(float x, float y);
+
+ /**
+ * Adds an object to the world with the specified item id and coordinates.
+ * If `pickupDialog` is not NULL, that string will display in a dialog box
+ * upon object interaction.
+ */
+
+ void addObject( std::string in, std::string pickupDialog, float x, float y);
+
+ /**
+ * Adds a particle to the world with the specified coordinates, dimensions,
+ * velocity, color and duration (time to live).
+ */
+
+ void addParticle(float x, float y, float w, float h, float vx, float vy, Color color, int d);
+ void addParticle(float x, float y, float w, float h, float vx, float vy, Color color, int d, bool gravity );
+
+ /**
+ * Adds a light to the world with the specified coordinates and color.
+ */
+
+ void addLight(vec2 xy, Color color);
+
+ /**
+ * Updates the coordinates of everything in the world that has coordinates
+ * and a velocity. The provided delta time is used for smoother updating.
+ */
+
+ void update( Player *p, unsigned int delta );
+
+ /**
+ * Generate a world of the provided width. Worlds are drawn centered on the
+ * y-axis, so the reachable coordinates on the world would be from negative
+ * half-width to positive half-width.
+ */
+
- void generate(unsigned int width); // Generates a flat world of width 'width'
++ void generate(unsigned int width);
+
+ /**
+ * Sets the background theme, collecting the required textures into a
+ * Texturec object.
+ */
+
+ void setBackground(WorldBGType bgt);
+
+ /**
+ * Sets the background music for the world, required for the world to be
+ * playable.
+ */
+
+ void setBGM(std::string path);
+
+ /**
+ * Sets the worlds style folder
+ */
+
+ void setStyle(std::string pre);
+
+ /**
+ * Plays/stops this world's BGM. If `prev` is not NULL, that world's BGM
+ * will be faded out followed by the fading in of this world's BGM.
+ */
+
+ void bgmPlay(World *prev) const;
+
+ /**
+ * Draw the world and entities based on the player's coordinates.
+ */
+
+ virtual void draw(Player *p);
+
+ /**
+ * Handles collision between the entities and the world, as well as entity
+ * death.
+ */
+
+ void detect(Player *p);
+
+ /**
+ * Attempts to let the player enter the left-linked world specified by
+ * `toLeft`. Returns the world to the left if the movement is possible,
+ * otherwise returns this world.
+ */
+
+ World *goWorldLeft(Player *p);
+ bool goWorldLeft( NPC *e );
+
+ /**
+ * Attempts to let the player enter the right-linked world specified by
+ * `toRight`. Returns the world to the right if the movement is possible,
+ * otherwise returns this world.
+ */
+
+ World *goWorldRight(Player *p);
+
+ /**
+ * This function looks for any structure the player is standing in front of
+ * that also have an inside world. Returns the inside world if those
+ * conditions are met, otherwise returns this world.
+ */
+
+ World *goInsideStructure(Player *p);
+
+ /**
+ * Adds a hole between the specified y coordinates. If the player falls in
+ * this hole the game will exit.
+ */
+
+ void addHole(unsigned int start,unsigned int end);
+
+ /**
+ * Adds a hill to the world, given the peak's coordinates and how wide the
+ * hill can be.
+ */
+
+ void addHill( ivec2 peak, unsigned int width );
+
+ /**
+ * Gets the world's width.
+ */
+
+ int getTheWidth(void) const;
+
+ void save(void);
+ void load(void);
+};
+
+/*
+ * IndoorWorld - Indoor settings stored in a World class
+ */
+
+class IndoorWorld : public World {
++private:
++
++ std::vector<std::vector<float>> floor;
++
++ void singleDetect( Entity *e );
++
+public:
+ IndoorWorld(void);
+ ~IndoorWorld(void);
+
++ void addFloor( unsigned int width );
++
+ void draw(Player *p); // Draws the world (ignores layers)
+};
+
+/**
+ * The arena class - creates an arena.
+ *
+ * This world, when created, expects a pointer to a Mob. This mob will be
+ * transported to a temporary world with the player, and the Mob will be
+ * killed upon exiting the arena.
+ */
+
+class Arena : public World {
+private:
+
+ /**
+ * The mob that the player is fighting.
+ */
+
+ Mob *mmob;
+
+public:
+
+ /**
+ * Creates a world with the player and mob, returning the player to the
+ * world `leave` upon exit.
+ */
+
+ Arena( World *leave, Player *p, Mob *m );
+
+ /**
+ * Frees resources taken by the arena.
+ */
+
+ ~Arena( void );
+
+ /**
+ * Attempts to exit the world, returning the player to the world they were
+ * last in.
+ */
+
+ World *exitArena( Player *p );
+};
+
+std::string getWorldWeatherStr( WorldWeather ww );
+
+/**
+ * Loads the player into the world created by the given XML file. If a world is
+ * already loaded it will be saved before the transition is made.
+ */
+
+World *loadWorldFromXML(std::string path);
+
+/**
+ * Loads the player into the XML-scripted world, but does not save data from the
+ * previous world if one was loaded.
+ */
+
+World *loadWorldFromXMLNoSave(std::string path);
+
+World *loadWorldFromPtr( World *ptr );
+
+#endif // WORLD_H
--- /dev/null
-#include <quest.h>\r
-#include <entities.h>\r
+ #include <algorithm>\r
+ \r
-\r
++#include <quest.hpp>\r
++#include <entities.hpp>\r
+ \r
+ extern Player *player;\r
+ \r
+ int QuestHandler::assign(std::string title,std::string desc,std::string req){\r
+ Quest tmp;\r
+ char *tok;\r
+ \r
+ tmp.title = title;\r
+ tmp.desc = desc;\r
+ \r
+ tok = strtok( &req[0], "\n\r\t," );\r
+ tmp.need.emplace_back( "", 0 );\r
+ \r
+ while ( tok ) {\r
+ if ( !tmp.need.back().first.empty() ) {\r
+ tmp.need.back().second = atoi( tok );\r
+ tmp.need.emplace_back( "", 0 );\r
+ } else\r
+ tmp.need.back().first = tok;\r
+ \r
+ tok = strtok( NULL, "\n\r\t," );\r
+ }\r
+ \r
+ tmp.need.pop_back();\r
+ current.push_back( tmp );\r
+ \r
+ return 0;\r
+ }\r
+ \r
+ int QuestHandler::drop(std::string title){\r
+ current.erase( std::remove_if( current.begin(),\r
+ current.end(),\r
+ [&](Quest q){ return q.title == title; }),\r
+ current.end() );\r
+ \r
+ return 0;\r
+ }\r
+ \r
+ int QuestHandler::finish(std::string t){\r
+ for ( auto c = current.begin(); c != current.end(); c++ ) {\r
+ if ( (*c).title == t ) {\r
+ for ( auto &n : (*c).need ) {\r
+ if ( player->inv->hasItem( n.first ) < n.second )\r
+ return 0;\r
+ }\r
+ \r
+ for ( auto &n : (*c).need )\r
+ player->inv->takeItem( n.first, n.second );\r
+ current.erase( c );\r
+ return 1;\r
+ }\r
+ }\r
+ \r
+ return 0;\r
+ }\r
+ \r
+ bool QuestHandler::hasQuest(std::string t){\r
+ for ( auto &c : current ) {\r
+ if ( c.title == t )\r
+ return true;\r
+ }\r
+ \r
+ return false;\r
+ }\r
--- /dev/null
-#include <texture.h>
+ #include <algorithm>
+ #include <string>
+
++#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;
+
+ struct index_t {
+ Color color;
+ int indexx;
+ int indexy;
+ };
+
+ /**
+ * 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.
+ */
+
+ static std::vector<texture_t> LoadedTexture;
+
+ namespace Texture{
+ Color pixels[8][4];
+
+ GLuint loadTexture(std::string fileName){
+ SDL_Surface *image;
+ GLuint object = 0;
+
+ // check if texture is already loaded
+ for(auto &t : LoadedTexture){
+ if(t.name == fileName){
+
+ #ifdef DEBUG
+ DEBUG_printf("Reusing loaded texture for %s\n", fileName.c_str());
+ #endif // DEBUG
+
+ return t.tex;
+ }
+ }
+
+ // load SDL_surface of texture
+ if(!(image = IMG_Load(fileName.c_str())))
+ return 0;
+
+ #ifdef DEBUG
+ DEBUG_printf("Loaded image file: %s\n", fileName.c_str());
+ #endif // DEBUG
+
+ /*
+ * Load texture through OpenGL.
+ */
+
+ 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);
+
+ 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
+ );
+
+ // add texture to LoadedTexture
+ LoadedTexture.push_back(texture_t{fileName,object,{image->w,image->h}});
+
+ // free the SDL_Surface
+ SDL_FreeSurface(image);
+
+ return object;
+ }
+
+ dim2 imageDim(std::string fileName){
+ for(auto &t : LoadedTexture){
+ if(t.name == fileName)
+ return t.dim;
+ }
+ return {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){
+ //std::cout << float(i.indexy) << "," << float(i.indexx) << std::endl;
+ 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++){
+ //std::cout << y << "," << x << ":" << pixels[y][x].red << "," << pixels[y][x].green << "," << pixels[y][x].blue << std::endl;
+ 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));
+ //std::cout << buff << std::endl;
+ if(buff < shit){
+ shit = buff;
+ buf[0] = y;
+ buf[1] = x;
+ }
+ //
+ //std::cout << shit << std::endl;
+ }
+ }
+ ind.push_back({c, (int)buf[1], (int)buf[0]});
+ //std::cout << float(buf[1]) << ", " << float(buf[0]) << std::endl;
+ return {float(buf[1]),float(buf[0])};
+ }
+ }
+
+ Texturec::Texturec(uint amt, ...){
+ va_list fNames;
+ texState = 0;
+ va_start(fNames, amt);
+ for(unsigned int i = 0; i < amt; i++)
+ image.push_back( Texture::loadTexture(va_arg(fNames, char *)) );
+ va_end(fNames);
+ }
+
+ Texturec::Texturec( std::initializer_list<std::string> l )
+ {
+ texState = 0;
+ std::for_each( l.begin(), l.end(), [&](std::string s){ image.push_back( Texture::loadTexture( s ) ); });
+ }
+
+ 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 ) ); });
+ }
+
+ Texturec::Texturec(uint amt,const char **paths){
+ texState = 0;
+ for(unsigned int i = 0; i < amt; i++)
+ image.push_back( Texture::loadTexture(paths[i]) );
+ }
+
+ Texturec::~Texturec(){
+ }
+
+ void Texturec::bind(unsigned int bn){
+ texState = bn;
+ glBindTexture(GL_TEXTURE_2D,image[(int)texState]);
+ }
+
+ void Texturec::bindNext(){
+ bind(++texState);
+ }
+
+ void Texturec::bindPrev(){
+ bind(--texState);
+ }