diff options
author | Andy <drumsetmonkey@gmail.com> | 2017-01-19 09:21:12 -0500 |
---|---|---|
committer | Andy <drumsetmonkey@gmail.com> | 2017-01-19 09:21:12 -0500 |
commit | 213d9ccfbb4752d4c62d6b7e6b3f9172cdf1bccc (patch) | |
tree | 7872c6f30c8adf048a7863a33d837299c7fb0771 /src | |
parent | 19a32074595a4a2797eaeb978f8bd302f736f6a6 (diff) | |
parent | 8452b199d28bea53bf2c5e3b3d604064000fc73d (diff) |
Limb animation actually works
Diffstat (limited to 'src')
-rw-r--r-- | src/common.cpp | 71 | ||||
-rw-r--r-- | src/components.cpp | 29 | ||||
-rw-r--r-- | src/engine.cpp | 17 | ||||
-rw-r--r-- | src/gametime.cpp | 24 | ||||
-rw-r--r-- | src/inventory.cpp | 91 | ||||
-rw-r--r-- | src/old/entities.cpp.bak (renamed from src/entities.cpp.bak) | 0 | ||||
-rw-r--r-- | src/old/inventory.cpp.bak (renamed from src/inventory.cpp.bak) | 0 | ||||
-rw-r--r-- | src/old/items.cpp.bak (renamed from src/items.cpp.bak) | 0 | ||||
-rw-r--r-- | src/old/mob.cpp.bak (renamed from src/mob.cpp.bak) | 0 | ||||
-rw-r--r-- | src/old/quest.cpp.bak (renamed from src/quest.cpp.bak) | 0 | ||||
-rw-r--r-- | src/particle.cpp | 53 | ||||
-rw-r--r-- | src/render.cpp | 128 | ||||
-rw-r--r-- | src/texture.cpp | 4 | ||||
-rw-r--r-- | src/ui.cpp | 288 | ||||
-rw-r--r-- | src/window.cpp | 6 | ||||
-rw-r--r-- | src/world.cpp | 104 |
16 files changed, 490 insertions, 325 deletions
diff --git a/src/common.cpp b/src/common.cpp index 6539a05..2ec80a7 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -18,8 +18,10 @@ #endif // __WIN32__ unsigned int millis(void) { - std::chrono::system_clock::time_point now=std::chrono::system_clock::now(); - return std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count(); + using namespace std::chrono; + + auto now = system_clock::now(); + return duration_cast<milliseconds>(now.time_since_epoch()).count(); } @@ -37,7 +39,7 @@ std::vector<std::string> StringTokenizer(const std::string& str, char delim) std::string token; while (getline(is, token, delim)) - tokens.push_back(token); + tokens.emplace_back(token); return tokens; } @@ -51,56 +53,41 @@ void DEBUG_prints(const char* file, int line, const char *s,...) va_end(args); } -int getdir(std::string dir, std::vector<std::string> &files) +int getdir(std::string dir, std::list<std::string>& files) { #ifndef __WIN32__ - DIR *dp; - struct dirent *dirp; - if (!(dp = opendir(dir.c_str()))) { - std::cout <<"Error ("<<errno<<") opening "<<dir<<std::endl; - return errno; - } - while((dirp = readdir(dp))) - files.push_back(std::string(dirp->d_name)); - closedir(dp); -#else - HANDLE dirh; - WIN32_FIND_DATA file_data; + auto dp = opendir(dir.c_str()); + if (dp == nullptr) + UserError("Couldn\'t open folder: " + dir); - if ((dirh = FindFirstFile((dir + "/*").c_str(), &file_data)) == INVALID_HANDLE_VALUE) - return -1; /* No files found */ + auto dirp = readdir(dp); + while (dirp != nullptr) { + files.emplace_back(dirp->d_name); + dirp = readdir(dp); + } - do { - const std::string file_name = file_data.cFileName; - const std::string full_file_name = dir + file_name; - const bool is_directory = (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; + closedir(dp); +#else + WIN32_FIND_DATA fileData; + auto dirh = FindFirstFile((dir + "/*").c_str(), &fileData); + if (dirh == INVALID_HANDLE_VALUE) + UserError("Couldn\'t open folder: " + dir); - if (file_name[0] == '.') - continue; + do { + auto fileName = fileData.cFileName; - if (is_directory) - continue; + if (fileName[0] == '.') + continue; - files.push_back(file_name); - } while (FindNextFile(dirh, &file_data)); + if (!(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + files.emplace_back(fileName); + } while (FindNextFile(dirh, &fileData)); FindClose(dirh); #endif // __WIN32__ - return 0; -} -void strVectorSortAlpha(std::vector<std::string> *v) -{ - static bool change; - do { - change = false; - for (unsigned int i=0; i < v->size() - 1; i++) { - if (v[0][i] > v[0][i + 1]) { - std::swap(v[0][i], v[0][i + 1]); - change = true; - } - } - } while (change); + files.sort(); + return 0; } std::string readFile(const std::string& path) diff --git a/src/components.cpp b/src/components.cpp index 3096d39..b06bf84 100644 --- a/src/components.cpp +++ b/src/components.cpp @@ -12,6 +12,8 @@ #include <atomic> +using namespace std::literals::chrono_literals; + static std::vector<std::string> randomDialog (readFileA("assets/dialog_en-us")); void MovementSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) @@ -67,22 +69,22 @@ Texture RenderSystem::loadTexture(const std::string& file) loadTexString = file; loadTexResult = Texture(); while (loadTexResult.isEmpty()) - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + std::this_thread::sleep_for(1ms); return loadTexResult; } -void RenderSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) +void RenderSystem::render(void) { - (void)ev; - if (!loadTexString.empty()) { loadTexResult = Texture(loadTexString); loadTexString.clear(); } - + Render::worldShader.use(); + Render::worldShader.enable(); - en.each<Visible, Sprite, Position>([dt](entityx::Entity entity, Visible &visible, Sprite &sprite, Position &pos) { + game::entities.lock(); + game::entities.each<Visible, Sprite, Position>([](entityx::Entity entity, Visible &visible, Sprite &sprite, Position &pos) { // Verticies and shit float its = 0; @@ -134,7 +136,6 @@ void RenderSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, sp.tex.use(); glUniform1i(Render::worldShader.uniform[WU_texture], 0); - Render::worldShader.enable(); glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 0, coords); glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 0 ,tex_coord); @@ -150,12 +151,13 @@ void RenderSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, Render::worldShader.disable(); Render::worldShader.unuse(); - en.each<Visible, Position, Solid, Name>([](entityx::Entity e, Visible &v, Position &pos, Solid& dim, Name &name) { + game::entities.each<Visible, Position, Solid, Name>([](entityx::Entity e, Visible &v, Position &pos, Solid& dim, Name &name) { (void)e; (void)v; ui::setFontZ(-5.0); ui::putStringCentered(pos.x + dim.width / 2, pos.y - ui::fontSize - HLINES(0.5), name.name); }); + game::entities.unlock(); } void DialogSystem::configure(entityx::EventManager &ev) @@ -165,6 +167,7 @@ void DialogSystem::configure(entityx::EventManager &ev) void DialogSystem::receive(const MouseClickEvent &mce) { + game::entities.lock(); game::entities.each<Position, Solid, Dialog, Name>( [&](entityx::Entity e, Position &pos, Solid &dim, Dialog &d, Name &name) { static std::atomic_bool dialogRun; @@ -175,7 +178,8 @@ void DialogSystem::receive(const MouseClickEvent &mce) ((mce.position.y > pos.y) & (mce.position.y < pos.y + dim.height))) { if (!dialogRun.load()) { - std::thread([&] { + // copy entity, windows destroys the original after thread detach + std::thread([e, &pos, &dim, &d, &name] { std::string questAssignedText; int newIndex; @@ -272,6 +276,7 @@ void DialogSystem::receive(const MouseClickEvent &mce) } } }); + game::entities.unlock(); } void DialogSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) @@ -308,12 +313,12 @@ std::vector<Frame> developFrame(XMLElement* xml) std::string sname = sxml->Name(); if (sname == "src") { foffset = (sxml->Attribute("offset") != nullptr) ? - str2coord(sxml->Attribute("offset")) : vec2(0,0); + sxml->StrAttribute("offset") : vec2(0,0); fdraw = (sxml->Attribute("drawOffset") != nullptr) ? - str2coord(sxml->Attribute("drawOffset")) : vec2(0,0); + sxml->StrAttribute("drawOffset") : vec2(0,0); if (sxml->Attribute("size") != nullptr) { - fsize = str2coord(sxml->Attribute("size")); + fsize = sxml->StrAttribute("size"); sd = new SpriteData(sxml->GetText(), foffset, fsize); } else { sd = new SpriteData(sxml->GetText(), foffset); diff --git a/src/engine.cpp b/src/engine.cpp index aa0db73..d334aea 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -23,7 +23,7 @@ void Engine::init(void) { systems.add<WindowSystem>(); systems.add<RenderSystem>(); systems.add<InputSystem>(); - //systems.add<InventorySystem>(); + systems.add<InventorySystem>(); systems.add<WorldSystem>(); systems.add<PlayerSystem>(); systems.add<QuestSystem>(); @@ -38,22 +38,11 @@ void Engine::init(void) { systems.configure(); ui::initSounds(); + ui::menu::init(); game::config::update(); getSystem<PlayerSystem>()->create(); } -void Engine::render(entityx::TimeDelta dt) -{ - systems.update<RenderSystem>(dt); - //systems.update<InventorySystem>(dt); // doesn't do anything... - - ui::fadeUpdate(); -} -void Engine::resetRender(entityx::TimeDelta dt) -{ - systems.update<WindowSystem>(dt); -} - void Engine::update(entityx::TimeDelta dt) { systems.update<InputSystem>(dt); @@ -69,7 +58,7 @@ void Engine::update(entityx::TimeDelta dt) namespace game { entityx::EventManager events; - entityx::EntityManager entities (events); + LockableEntityManager entities (events); //SpriteLoader sprite_l; Engine engine; diff --git a/src/gametime.cpp b/src/gametime.cpp index 1005d84..cb736ff 100644 --- a/src/gametime.cpp +++ b/src/gametime.cpp @@ -1,15 +1,9 @@ #include <gametime.hpp> -#include <common.hpp> +#include <common.hpp> // millis static unsigned int tickCount = 0; -static float deltaTime = 1; - -// millisecond timers -static unsigned int currentTime = 0; -static unsigned int prevTime; - -static float accum = 0.0f; +static unsigned int deltaTime = 1; namespace game { namespace time { @@ -34,15 +28,19 @@ namespace game { } void mainLoopHandler(void) { - if (!currentTime) - currentTime = prevTime = millis(); + static unsigned int cur = 0, prev; - currentTime = millis(); - deltaTime = currentTime - prevTime; - prevTime = currentTime; + if (cur == 0) + cur = prev = millis(); + + cur = millis(); + deltaTime = cur - prev; + prev = cur; } bool tickHasPassed(void) { + static unsigned int accum = 0; + accum += deltaTime; if (accum > MSEC_PER_TICK) { accum = 0.0f; diff --git a/src/inventory.cpp b/src/inventory.cpp index 480c803..354db9c 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -4,21 +4,34 @@ #include <events.hpp> #include <texture.hpp> #include <render.hpp> +#include <ui.hpp> -constexpr const char* ICON_TEX_FILE_PATH = "config/invIcons.txt"; +#include <unordered_map> -static std::vector<Texture> iconTextures; +#include <tinyxml2.h> +using namespace tinyxml2; + +constexpr const char* itemsPath = "config/items.xml"; + +static std::unordered_map<std::string, Item> itemList; void InventorySystem::configure(entityx::EventManager &ev) { ev.subscribe<KeyDownEvent>(*this); } -void InventorySystem::loadIcons(void) { - iconTextures.clear(); - auto icons = readFileA(ICON_TEX_FILE_PATH); - for (const auto& s : icons) - iconTextures.push_back(s); +void InventorySystem::loadItems(void) { + XMLDocument doc; + doc.LoadFile(itemsPath); + + auto item = doc.FirstChildElement("item"); + if (item == nullptr) + UserError("No items found"); + + do { + itemList.emplace(item->StrAttribute("name"), item); + item = item->NextSiblingElement("item"); + } while (item != nullptr); } void InventorySystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) @@ -26,23 +39,67 @@ void InventorySystem::update(entityx::EntityManager &en, entityx::EventManager & (void)en; (void)ev; (void)dt; +} - // TODO TODO TODO TODO until we do something - return; +void InventorySystem::render(void) +{ + // calculate positions + items.front().loc = vec2(offset.x - 35 * items.size(), offset.y - game::SCREEN_HEIGHT / 2); + for (unsigned int i = 1; i < items.size(); i++) + items[i].loc = vec2(items[i - 1].loc.x + 70, items[i - 1].loc.y); + + // draw items + for (const auto& i : items) { + // draw the slot + Render::textShader.use(); + Render::textShader.enable(); - //vec2 start = vec2(offset.x, 100);// - game::SCREEN_WIDTH / 2 + 20, game::SCREEN_HEIGHT - 40); + Colors::black.use(); + glUniform4f(Render::textShader.uniform[WU_tex_color], 1, 1, 1, .8); + glVertexAttribPointer(Render::textShader.tex, 2, GL_FLOAT, GL_FALSE, 0, Colors::texCoord); + vec2 end = i.loc + 64; + GLfloat coords[18] = { + i.loc.x, i.loc.y, -7, end.x, i.loc.y, -7, end.x, end.y, -7, + end.x, end.y, -7, i.loc.x, end.y, -7, i.loc.x, i.loc.y, -7 + }; + glVertexAttribPointer(Render::textShader.coord, 3, GL_FLOAT, GL_FALSE, 0, coords); + glDrawArrays(GL_TRIANGLES, 0, 6); + glUniform4f(Render::textShader.uniform[WU_tex_color], 1, 1, 1, 1); - //std::cout << start.x << ' ' << start.y << std::endl; + // draw the item + if (i.item != nullptr) { + i.item->sprite.use(); + static const GLfloat tex[12] = {0,1,1,1,1,0,1,0,0,0,0,1}; + glVertexAttribPointer(Render::textShader.tex, 2, GL_FLOAT, GL_FALSE, 0, tex); + vec2 end = i.loc + i.item->sprite.getDim(); + GLfloat coords[18] = { + i.loc.x, i.loc.y, -7.1, end.x, i.loc.y, -7.1, end.x, end.y, -7.1, + end.x, end.y, -7.1, i.loc.x, end.y, -7.1, i.loc.x, i.loc.y, -7.1 + }; + glVertexAttribPointer(Render::textShader.coord, 3, GL_FLOAT, GL_FALSE, 0, coords); + glDrawArrays(GL_TRIANGLES, 0, 6); + ui::setFontZ(-7.2); + ui::putText(i.loc.x, i.loc.y, std::to_string(i.count).c_str()); + ui::setFontZ(-6); + } + } - /*Render::textShader.use(); - glActiveTexture(GL_TEXTURE0); - Colors::black.use(); - Render::useShader(&Render::textShader); - Render::drawRect(start, start + 20, -9.9f); - Render::textShader.unuse();*/ + Render::textShader.disable(); + Render::textShader.unuse(); } void InventorySystem::receive(const KeyDownEvent &kde) { (void)kde; } + +void InventorySystem::add(const std::string& name, int count) +{ + for (auto& i : items) { + if (i.count == 0) { + i.item = &itemList[name]; + i.count = count; + break; + } + } +} diff --git a/src/entities.cpp.bak b/src/old/entities.cpp.bak index 25dd379..25dd379 100644 --- a/src/entities.cpp.bak +++ b/src/old/entities.cpp.bak diff --git a/src/inventory.cpp.bak b/src/old/inventory.cpp.bak index 1b325c0..1b325c0 100644 --- a/src/inventory.cpp.bak +++ b/src/old/inventory.cpp.bak diff --git a/src/items.cpp.bak b/src/old/items.cpp.bak index 180c5fa..180c5fa 100644 --- a/src/items.cpp.bak +++ b/src/old/items.cpp.bak diff --git a/src/mob.cpp.bak b/src/old/mob.cpp.bak index e78e5cd..e78e5cd 100644 --- a/src/mob.cpp.bak +++ b/src/old/mob.cpp.bak diff --git a/src/quest.cpp.bak b/src/old/quest.cpp.bak index f19359e..f19359e 100644 --- a/src/quest.cpp.bak +++ b/src/old/quest.cpp.bak diff --git a/src/particle.cpp b/src/particle.cpp index a8fab9d..6eeec33 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -84,60 +84,61 @@ void ParticleSystem::update(entityx::EntityManager &en, entityx::EventManager &e { (void)en; (void)ev; - (void)dt; // TODO use for time to die auto& worldSystem = *game::engine.getSystem<WorldSystem>(); - for (auto part = std::begin(parts); part != std::end(parts); part++) { - auto& p = *part; + for (unsigned int i = 0; i < parts.size(); i++) { + auto& p = parts[i]; + auto& vel = p.velocity; // update timers - p.timeLeft -= dt; + if (p.timeLeft > 0) + p.timeLeft -= dt; + else + continue; // update movement switch (p.type) { case ParticleType::Drop: - if (p.velocity.y > -.6) - p.velocity.y -= 0.001f; + if (vel.y > -.6) + vel.y -= 0.001f; break; case ParticleType::Confetti: - if (p.velocity.x > -0.01 && p.velocity.x < 0.01) { - p.velocity.x = randGet() % 12 / 30.0f - 0.2f; + if (vel.x > -0.01 && vel.x < 0.01) { + vel.x = randGet() % 12 / 30.0f - 0.2f; + vel.y = -0.15f; } else { - p.velocity.x += (p.velocity.x > 0) ? -0.002f : 0.002f; + vel.x += (vel.x > 0) ? -0.002f : 0.002f; } - p.velocity.y = -0.15f; - p.timeLeft = 1000; break; case ParticleType::SmallBlast: - if (p.velocity.x == 0) { + if (vel.x == 0) { int degree = randGet() % 100; - p.velocity.x = cos(degree) / 4.0f; - p.velocity.y = sin(degree) / 4.0f; + vel.x = cos(degree) / 4.0f; + vel.y = sin(degree) / 4.0f; } else { - p.velocity.x += (p.velocity.x > 0) ? -0.001f : 0.001f; - p.velocity.y += (p.velocity.y > 0) ? -0.001f : 0.001f; - if ((p.velocity.x > -0.01 && p.velocity.x < 0.01) && - (p.velocity.y > -0.01 && p.velocity.y < 0.01)) { + vel.x += (vel.x > 0) ? -0.001f : 0.001f; + vel.y += (vel.y > 0) ? -0.001f : 0.001f; + if ((vel.x > -0.01 && vel.x < 0.01) && + (vel.y > -0.01 && vel.y < 0.01)) { p.timeLeft = 0; } } - break; case ParticleType::SmallPoof: - if (p.velocity.x == 0) { - p.velocity.y = 0.1f; - p.velocity.x = randGet() % 10 / 20.0f - 0.25f; + if (vel.x == 0) { + vel.y = 0.1f; + vel.x = randGet() % 10 / 20.0f - 0.25f; } else { - p.velocity.x += (p.velocity.x > 0) ? -0.001f : 0.001f; - p.velocity.y -= 0.0015f; + vel.x += (vel.x > 0) ? -0.001f : 0.001f; + vel.y -= 0.0015f; } break; } // really update movement - p.location.x += p.velocity.x * dt; - p.location.y += p.velocity.y * dt; + p.location.x += vel.x * dt; + p.location.y += vel.y * dt; // world collision auto height = worldSystem.isAboveGround(p.location); diff --git a/src/render.cpp b/src/render.cpp index 908b620..5cbd11e 100644 --- a/src/render.cpp +++ b/src/render.cpp @@ -1,7 +1,12 @@ #include <render.hpp> +#include <texture.hpp> + static Shader *currentShader = nullptr; +void preRender(void); +void render(const int&); + namespace Render { Shader worldShader; @@ -62,4 +67,127 @@ void drawRect(vec2 ll, vec2 ur, float z) currentShader->disable(); } +void init(void) +{ +#ifndef __WIN32__ + glewExperimental = GL_TRUE; +#endif + + auto glewError = glewInit(); + if (glewError != GLEW_OK) + UserError(std::string("GLEW was not able to initialize! Error: ") + + reinterpret_cast<const char *>(glewGetErrorString(glewError))); + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // anti-aliasing + SDL_GL_SetSwapInterval(1); // v-sync + SDL_ShowCursor(SDL_DISABLE); // hide the cursor + glViewport(0, 0, game::SCREEN_WIDTH, game::SCREEN_HEIGHT); // pixel coordinates + glEnable(GL_BLEND); // alpha enabling + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // + glClearColor(1, 1, 1, 1); // white clear color + + std::cout << "Initializing shaders!\n"; + initShaders(); + ::Colors::init(); +} + +void render(const int& fps) +{ + preRender(); + ::render(fps); +} + +} // namespace render + +#include <engine.hpp> +#include <gametime.hpp> +#include <inventory.hpp> +#include <particle.hpp> +#include <player.hpp> +#include <ui.hpp> +#include <window.hpp> +#include <world.hpp> + +#include <entityx/entityx.h> + +void preRender(void) +{ + 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_WIDTH2 * 2) + offset.x = 0; + 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_HEIGHT2); + + // "setup" + 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 ortho = projection * view; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); + + Render::worldShader.use(); + glUniformMatrix4fv(Render::worldShader.uniform[WU_ortho], 1, GL_FALSE, glm::value_ptr(ortho)); + glUniformMatrix4fv(Render::worldShader.uniform[WU_transform], 1, GL_FALSE, glm::value_ptr(glm::mat4(1.0f))); + Render::worldShader.unuse(); + + Render::textShader.use(); + glUniformMatrix4fv(Render::textShader.uniform[WU_transform], 1, GL_FALSE, glm::value_ptr(ortho)); + glUniform4f(Render::textShader.uniform[WU_tex_color], 1.0, 1.0, 1.0, 1.0); + Render::textShader.unuse(); +} + +void render(const int& fps) +{ + preRender(); + + game::engine.getSystem<WorldSystem>()->render(); + + game::engine.getSystem<ParticleSystem>()->render(); + + game::engine.getSystem<RenderSystem>()->render(); + + game::engine.getSystem<InventorySystem>()->render(); + + // draw the debug overlay if desired + if (ui::debug) { + auto pos = game::engine.getSystem<PlayerSystem>()->getPosition(); + ui::putText(offset.x - game::SCREEN_WIDTH / 2, (offset.y + game::SCREEN_HEIGHT / 2) - ui::fontSize, + "loc: %s\noffset: %s\nfps: %d\nticks: %d\npcount: %d\nxml: %s", + pos.toString().c_str(), offset.toString().c_str(), fps, + game::time::getTickCount(), game::engine.getSystem<ParticleSystem>()->getCount(), + game::engine.getSystem<WorldSystem>()->getXMLFile().c_str()); + } + + ui::drawFade(); + ui::draw(); + + game::engine.getSystem<WindowSystem>()->render(); } diff --git a/src/texture.cpp b/src/texture.cpp index b47c3c7..721e5cb 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -10,6 +10,10 @@ namespace Colors ColorTex red; ColorTex blue; + GLfloat texCoord[12] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + void init(void) { white = ColorTex(Color(255, 255, 255)); black = ColorTex(Color(0, 0, 0 )); @@ -309,7 +309,7 @@ namespace ui { 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); + glUniform4f(Render::textShader.uniform[WU_tex_color], 1.0, 1.0, 1.0, 1.0); // TODO seg faults Render::textShader.disable(); Render::textShader.unuse(); @@ -534,8 +534,10 @@ namespace ui { void waitForCover(void) { auto& fi = fadeIntensity; fi = 0; + while (fi < 255) std::this_thread::sleep_for(1ms); + fi = 255; } @@ -648,8 +650,8 @@ namespace ui { auto stride = 5 * sizeof(GLfloat); // we always want to make sure c1 is lower left and c2 is upper right - if (c1.x > c2.x) c1.swapX(c2); // std::swap(c1.x, c2.y); - if (c1.y > c2.y) c1.swapY(c2); // std::swap(c1.y, c2.y); + if (c1.x > c2.x) std::swap(c1.x, c2.x); + if (c1.y > c2.y) 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 < (boxCornerDim.x) || c2.y - c1.y < (boxCornerDim.y)) @@ -971,6 +973,18 @@ namespace ui { }*/ setFontColor(255,255,255,255); } + + if (currentMenu != nullptr) + menu::draw(); + + // draw the mouse + static const Texture mouseTex ("assets/goodmouse.png"); + Render::textShader.use(); + glActiveTexture(GL_TEXTURE0); + 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 closeBox() { @@ -1015,43 +1029,40 @@ namespace ui { } void drawFade(void) { - static const auto SCREEN_WIDTH2 = game::SCREEN_WIDTH / 2; - static const auto SCREEN_HEIGHT2 = game::SCREEN_HEIGHT / 2; - if (!fadeIntensity) { if (fontSize != 16) setFontSize(16); return; } - static const GLfloat tex[] = { - 0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0, - 1.0, 1.0 + static const GLfloat tex[12] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - 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 + vec2 p1 (offset.x - game::SCREEN_WIDTH / 2, offset.y - game::SCREEN_HEIGHT / 2); + vec2 p2 (p1.x + game::SCREEN_WIDTH, p1.y + game::SCREEN_HEIGHT); + GLfloat backdrop[18] = { + p1.x, p1.y, -7.9, + p2.x, p1.y, -7.9, + p2.x, p2.y, -7.9, + + p2.x, p2.y, -7.9, + p1.x, p2.y, -7.9, + p1.x, p1.y, -7.9 }; setFontZ(-8.2); - glUniform1i(Render::textShader.uniform[WU_texture], 0); - Render::textShader.use(); Render::textShader.enable(); + 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); + glDrawArrays(GL_TRIANGLES, 0, 6); Render::textShader.disable(); Render::textShader.unuse(); - setFontZ(-8.0); } @@ -1168,148 +1179,143 @@ namespace ui { using namespace ui; -void InputSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) +void InputSystem::receive(const MainSDLEvent& event) { - (void)en; - (void)ev; - (void)dt; - if (currentMenu != nullptr) return; - - auto SCREEN_WIDTH = game::SCREEN_WIDTH; - auto SCREEN_HEIGHT = game::SCREEN_HEIGHT; - - SDL_Event e; - - // update mouse coords - mouse.x = premouse.x + offset.x - (SCREEN_WIDTH / 2); - mouse.y = (offset.y + SCREEN_HEIGHT / 2) - premouse.y; - - while(SDL_PollEvent(&e)) { - switch(e.type) { - - // escape - quit game - case SDL_QUIT: - game::endGame(); - break; - - // window events - used for resizing and stuff - case SDL_WINDOWEVENT: - switch (e.window.event) { - case SDL_WINDOWEVENT_RESIZED: - std::cout << "Window " << e.window.windowID << " resized to: " << e.window.data1 << ", " << e.window.data2 << std::endl; - auto w = e.window.data1; - auto h = e.window.data2; - ev.emit<WindowResizeEvent>(w,h); - break; - } + + const auto& e = event.event; + auto& ev = game::events; + + switch (e.type) { + // escape - quit game + case SDL_QUIT: + game::endGame(); + break; + + // window events - used for resizing and stuff + case SDL_WINDOWEVENT: + switch (e.window.event) { + case SDL_WINDOWEVENT_RESIZED: + std::cout << "Window " << e.window.windowID << " resized to: " << e.window.data1 << ", " << e.window.data2 << std::endl; + auto w = e.window.data1; + auto h = e.window.data2; + ev.emit<WindowResizeEvent>(w,h); break; + } + break; + // mouse movement - update mouse vector + case SDL_MOUSEMOTION: + premouse.x=e.motion.x; + premouse.y=e.motion.y; + break; - // mouse movement - update mouse vector - case SDL_MOUSEMOTION: - premouse.x=e.motion.x; - premouse.y=e.motion.y; + //case SDL_MOUSEBUTTONUP: + case SDL_MOUSEBUTTONDOWN: + if (currentMenu != nullptr) break; - //case SDL_MOUSEBUTTONUP: + ev.emit<MouseClickEvent>(mouse, e.button.button); - case SDL_MOUSEBUTTONDOWN: - if (currentMenu != nullptr) - break; - - ev.emit<MouseClickEvent>(mouse, e.button.button); + // run actions? + //if ((action::make = e.button.button & SDL_BUTTON_RIGHT)) + // /*player->inv->invHover =*/ edown = false; - // run actions? - //if ((action::make = e.button.button & SDL_BUTTON_RIGHT)) - // /*player->inv->invHover =*/ edown = false; + textToDraw.clear(); - textToDraw.clear(); - - if (dialogBoxExists || pageTexReady) { - // right click advances dialog - if ((e.button.button & SDL_BUTTON_RIGHT)) - dialogAdvance(); - } else { - // left click uses item - if (e.button.button & SDL_BUTTON_LEFT) { - /*if ((ent = currentWorld->getNearMob(*player)) != nullptr) { - player->inv->currentAddInteract(ent); - } - player->inv->useCurrent();*/ + if (dialogBoxExists || pageTexReady) { + // right click advances dialog + if ((e.button.button & SDL_BUTTON_RIGHT)) + dialogAdvance(); + } else { + // left click uses item + if (e.button.button & SDL_BUTTON_LEFT) { + /*if ((ent = currentWorld->getNearMob(*player)) != nullptr) { + player->inv->currentAddInteract(ent); } - + player->inv->useCurrent();*/ } - break; - case SDL_MOUSEWHEEL: - ev.emit<MouseScrollEvent>(e.wheel.y); + } + break; + + case SDL_MOUSEWHEEL: + ev.emit<MouseScrollEvent>(e.wheel.y); + break; + + // key presses + case SDL_KEYDOWN: + ev.emit<KeyDownEvent>(SDL_KEY); + switch(SDL_KEY){ + case SDLK_t: + game::time::tick(100); + break; + } + break; + + // key release + case SDL_KEYUP: + ev.emit<KeyUpEvent>(SDL_KEY); + + if (SDL_KEY == SDLK_ESCAPE) + ui::menu::toggle(); + + if (SDL_KEY == SDLK_q) { + /*auto item = player->inv->getCurrentItem(); + if (item != nullptr) { + if (player->inv->takeItem(item->name, 1) == 0) + currentWorld->addObject(item->name, "o shit waddup", + player->loc.x + player->width / 2, player->loc.y + player->height / 2); + }*/ + } else if (SDL_KEY == SDLK_h) { + quest::toggle(); + } else switch (SDL_KEY) { + case SDLK_F3: + debug ^= true; break; - - // key presses - case SDL_KEYDOWN: - ev.emit<KeyDownEvent>(SDL_KEY); - switch(SDL_KEY){ - case SDLK_t: - game::time::tick(100); - break; - } + case SDLK_BACKSLASH: + dialogBoxExists = false; break; - /* - * KEYUP - */ - - case SDL_KEYUP: - ev.emit<KeyUpEvent>(SDL_KEY); - - if (SDL_KEY == SDLK_ESCAPE) - ui::menu::toggle(); - - if (SDL_KEY == SDLK_q) { - /*auto item = player->inv->getCurrentItem(); - if (item != nullptr) { - if (player->inv->takeItem(item->name, 1) == 0) - currentWorld->addObject(item->name, "o shit waddup", - player->loc.x + player->width / 2, player->loc.y + player->height / 2); - }*/ - } else if (SDL_KEY == SDLK_h) { - quest::toggle(); - } else switch (SDL_KEY) { - case SDLK_F3: - debug ^= true; - break; - case SDLK_BACKSLASH: - dialogBoxExists = false; - break; - case SDLK_b: - if (debug) - posFlag ^= true; - break; - case SDLK_F12: - // Make the BYTE array, factor of 3 because it's RBG. - /*static GLubyte* pixels; - pixels = new GLubyte[ 3 * SCREEN_WIDTH * SCREEN_HEIGHT]; - glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels); - takeScreenshot(pixels);*/ - - ev.emit<ScreenshotEvent>(game::SCREEN_WIDTH, game::SCREEN_HEIGHT); + case SDLK_b: + if (debug) + posFlag ^= true; + break; + case SDLK_F12: + // Make the BYTE array, factor of 3 because it's RBG. + /*static GLubyte* pixels; + pixels = new GLubyte[ 3 * SCREEN_WIDTH * SCREEN_HEIGHT]; + glReadPixels(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, pixels); + takeScreenshot(pixels);*/ - std::cout << "Took screenshot" << std::endl; - break; - case SDLK_UP: - //player->inv->setSelectionUp(); - break; - case SDLK_DOWN: - //player->inv->setSelectionDown(); - break; - default: - break; - } + ev.emit<ScreenshotEvent>(game::SCREEN_WIDTH, game::SCREEN_HEIGHT); + std::cout << "Took screenshot" << std::endl; + break; + case SDLK_UP: + //player->inv->setSelectionUp(); + break; + case SDLK_DOWN: + //player->inv->setSelectionDown(); break; default: break; } + break; + + default: + break; + } } + +void InputSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) +{ + (void)en; + (void)ev; + (void)dt; + + // update mouse coords + mouse.x = premouse.x + offset.x - (game::SCREEN_WIDTH / 2); + mouse.y = (offset.y + game::SCREEN_HEIGHT / 2) - premouse.y; +} diff --git a/src/window.cpp b/src/window.cpp index 29bd7c7..992e3c1 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -95,11 +95,7 @@ void WindowSystem::receive(const ScreenshotEvent &scr) std::cout << "Triggered\n"; } -void WindowSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) +void WindowSystem::render(void) { - (void)en; - (void)ev; - (void)dt; - SDL_GL_SwapWindow(window); } diff --git a/src/world.cpp b/src/world.cpp index 95bf576..1d29bfe 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -9,7 +9,6 @@ #include <sstream> #include <fstream> #include <memory> -#include <mutex> #include <chrono> using namespace std::literals::chrono_literals; @@ -57,9 +56,6 @@ extern std::string xmlFolder; // wait static bool waitToSwap = false; -// particle mutex -std::mutex partMutex; - // externally referenced in main.cpp int worldShade = 0; @@ -102,14 +98,6 @@ static const std::string buildPaths[] = { "brazzier.png" }; -// alpha-related values used for world drawing? nobody knows... -static const float bgDraw[4][3]={ - { 100, 240, 0.6 }, - { 150, 250, 0.4 }, - { 200, 255, 0.25 }, - { 255, 255, 0.1 } -}; - /* ---------------------------------------------------------------------------- ** Functions section ** --------------------------------------------------------------------------*/ @@ -166,7 +154,7 @@ float WorldSystem::isAboveGround(const vec2& p) const static Color ambient; bool WorldSystem::save(void) -{ +{ if (world.indoor) return false; @@ -175,6 +163,7 @@ bool WorldSystem::save(void) // signature? save << "831998 "; + game::entities.lock(); game::entities.each<Position>([&](entityx::Entity entity, Position& pos) { // save position save << "p " << pos.x << ' ' << pos.y << ' '; @@ -183,6 +172,7 @@ bool WorldSystem::save(void) if (entity.has_component<Dialog>()) save << "d " << entity.component<Dialog>()->index << ' '; }); + game::entities.unlock(); save.close(); return true; @@ -241,11 +231,12 @@ void WorldSystem::load(const std::string& file) world.toLeft = world.toRight = ""; currentXMLFile = file; + game::entities.lock(); game::entities.reset(); game::engine.getSystem<PlayerSystem>()->create(); // iterate through tags - while (wxml) { + while (wxml != nullptr) { std::string tagName = wxml->Name(); // style tag @@ -280,7 +271,7 @@ void WorldSystem::load(const std::string& file) UserError("<house> can only be used inside <IndoorWorld>"); //world.indoorWidth = wxml->FloatAttribute("width"); - world.indoorTex = render.loadTexture(wxml->StrAttribute("texture")); + (void)render;//world.indoorTex = render.loadTexture(wxml->StrAttribute("texture")); // TODO winbloze lol //auto str = wxml->StrAttribute("texture"); //auto tex = render.loadTexture(str); //world.indoorTex = tex; @@ -325,9 +316,9 @@ void WorldSystem::load(const std::string& file) vec2 coords; if (wxml->Attribute("position") != nullptr) { - coords = str2coord(wxml->StrAttribute("position")); + coords = wxml->StrAttribute("position"); } else { - coords = str2coord(abcd->StrAttribute("value")); + coords = abcd->StrAttribute("value"); } float cdat[2] = {coords.x, coords.y}; @@ -346,7 +337,7 @@ void WorldSystem::load(const std::string& file) vec2 dim; if (abcd->Attribute("value") != nullptr) - dim = str2coord(abcd->StrAttribute("value")); + dim = abcd->StrAttribute("value"); else dim = entity.component<Sprite>()->getSpriteSize(); @@ -356,9 +347,9 @@ void WorldSystem::load(const std::string& file) vec2 dir; if (wxml->Attribute("direction") != nullptr) { - dir = str2coord(wxml->StrAttribute("direction")); + dir = wxml->StrAttribute("direction"); } else if (wxml->Attribute("value") != nullptr) { - dir = str2coord(wxml->StrAttribute("value")); + dir = wxml->StrAttribute("value"); } else { dir = vec2(0,0); } @@ -480,6 +471,7 @@ void WorldSystem::load(const std::string& file) } game::events.emit<BGMToggleEvent>(); + game::entities.unlock(); } /* @@ -689,9 +681,8 @@ void WorldSystem::render(void) const auto SCREEN_WIDTH = game::SCREEN_WIDTH; const auto SCREEN_HEIGHT = game::SCREEN_HEIGHT; - const ivec2 backgroundOffset = ivec2 { - static_cast<int>(SCREEN_WIDTH) / 2, static_cast<int>(SCREEN_HEIGHT) / 2 - }; + const vector2<int> backgroundOffset + (static_cast<int>(SCREEN_WIDTH) / 2, static_cast<int>(SCREEN_HEIGHT) / 2); int iStart, iEnd, pOffset; @@ -783,7 +774,7 @@ void WorldSystem::render(void) //glUniform4f(Render::worldShader.uniform[WU_tex_color], 1.0, 1.0, 1.0, 1.3 - static_cast<float>(alpha) / 255.0f); //makeWorldDrawingSimplerEvenThoughAndyDoesntThinkWeCanMakeItIntoFunctions(0, fron_tex_coord, tex_coord, 6); - // TODO make stars dynamic + // TODO make stars dynamic (make them particles??) /*static GLuint starTex = Texture::loadTexture("assets/style/classic/bg/star.png"); const static float stardim = 24; GLfloat star_coord[star.size() * 5 * 6 + 1]; @@ -848,9 +839,12 @@ void WorldSystem::render(void) Render::worldShader.unuse(); // draw the remaining layers + static const float alphas[4] = { + 0.6, 0.4, 0.25, 0.1 + }; for (int i = 0; i < 4; i++) { bgTex++; - auto xcoord = offset.x * bgDraw[i][2]; + auto xcoord = offset.x * alphas[i]; bg_items.clear(); bg_tex.clear(); @@ -1128,32 +1122,30 @@ void WorldSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, void WorldSystem::detect(entityx::TimeDelta dt) { + game::entities.lock(); game::entities.each<Grounded, Position, Solid>( [&](entityx::Entity e, Grounded &g, Position &loc, Solid &dim) { - (void)e; - if (!g.grounded) { - // get the line the entity is on - int line = std::clamp(static_cast<int>((loc.x + dim.width / 2 - world.startX) / game::HLINE), - 0, - static_cast<int>(world.data.size())); - + (void)e; + if (!g.grounded) { + // get the line the entity is on + int line = std::clamp(static_cast<int>((loc.x + dim.width / 2 - world.startX) / game::HLINE), + 0, static_cast<int>(world.data.size())); // make sure entity is above ground - const auto& data = world.data; - if (loc.y != data[line].groundHeight) { - loc.y = data[line].groundHeight; - e.remove<Grounded>(); - } + const auto& data = world.data; + if (loc.y != data[line].groundHeight) { + loc.y = data[line].groundHeight; + e.remove<Grounded>(); } - - }); + } + }); game::entities.each<Direction, Physics>( [&](entityx::Entity e, Direction &vel, Physics &phys) { - (void)e; - // handle gravity - if (vel.y > -2.0f) - vel.y -= (GRAVITY_CONSTANT * phys.g) * dt; - }); + (void)e; + // handle gravity + if (vel.y > -2.0f) + vel.y -= (GRAVITY_CONSTANT * phys.g) * dt; + }); game::entities.each<Position, Direction, Solid>( [&](entityx::Entity e, Position &loc, Direction &vel, Solid &dim) { @@ -1163,14 +1155,14 @@ void WorldSystem::detect(entityx::TimeDelta dt) // get the line the entity is on int line = std::clamp(static_cast<int>((loc.x + dim.width / 2 - world.startX) / game::HLINE), - 0, - static_cast<int>(world.data.size())); + 0, static_cast<int>(world.data.size())); // make sure entity is above ground const auto& data = world.data; if (loc.y < data[line].groundHeight) { int dir = vel.x < 0 ? -1 : 1; - if (line + dir * 2 < static_cast<int>(data.size()) && + auto thing = line + dir * 2; + if (thing > 0 && thing < static_cast<int>(data.size()) && data[line + dir * 2].groundHeight - 30 > data[line + dir].groundHeight) { loc.x -= (PLAYER_SPEED_CONSTANT + 2.7f) * dir * 2; vel.x = 0; @@ -1195,6 +1187,7 @@ void WorldSystem::detect(entityx::TimeDelta dt) loc.x = -(static_cast<int>(world.startX)) - dim.width - game::HLINE; } }); + game::entities.unlock(); } void WorldSystem::goWorldRight(Position& p, Solid &d) @@ -1232,17 +1225,18 @@ void WorldSystem::goWorldPortal(Position& p) p.x = world.outdoorCoords.x; // ineffective, player is regen'd p.y = world.outdoorCoords.y; } else { + game::entities.lock(); game::entities.each<Position, Solid, Portal>( [&](entityx::Entity entity, Position& loc, Solid &dim, Portal &portal) { - (void)entity; - if (!(portal.toFile.empty()) && p.x > loc.x && p.x < loc.x + dim.width) { - file = portal.toFile; - world.outdoor = currentXMLFile; - world.outdoorCoords = vec2(loc.x + dim.width / 2, 100); - return; - } + (void)entity; + if (!(portal.toFile.empty()) && p.x > loc.x && p.x < loc.x + dim.width) { + file = portal.toFile; + world.outdoor = currentXMLFile; + world.outdoorCoords = vec2(loc.x + dim.width / 2, 100); + return; } - ); + }); + game::entities.unlock(); } if (!file.empty()) { |