]> code.bitgloo.com Git - clyne/gamedev.git/commitdiff
particles, rain
authorClyne Sullivan <tullivan99@gmail.com>
Fri, 6 Jan 2017 13:51:53 +0000 (08:51 -0500)
committerClyne Sullivan <tullivan99@gmail.com>
Fri, 6 Jan 2017 13:51:53 +0000 (08:51 -0500)
12 files changed:
include/common.hpp
include/particle.hpp [new file with mode: 0644]
include/texture.hpp
include/weather.hpp [new file with mode: 0644]
include/world.hpp
main.cpp
src/engine.cpp
src/inventory.cpp
src/particle.cpp [new file with mode: 0644]
src/texture.cpp
src/world.cpp
xml/!town.xml

index 19af420e13342514198d917d9685313e034a2fe2..71039c7403889c372709a39f2397769903dbb474 100644 (file)
@@ -91,11 +91,11 @@ struct vec2 {
        }
 
        template<typename T>
-       const vec2 operator+(const T &n) {
+       vec2 operator+(T n) const {
                return vec2 (x + n, y + n);
        }
 
-       const vec2 operator+(const vec2 &v) {
+       vec2 operator+(const vec2 &v) {
                return vec2 (x + v.x, y + v.y);
        }
 
diff --git a/include/particle.hpp b/include/particle.hpp
new file mode 100644 (file)
index 0000000..d9aa29f
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef PARTICLE_HPP_
+#define PARTICLE_HPP_
+
+#include <common.hpp>
+
+#include <list>
+
+#include <entityx/entityx.h>
+
+enum class ParticleType : char {
+       Drop,
+       Confetti
+};
+
+struct Particle {
+       vec2 location;
+       vec2 velocity;
+       ParticleType type;
+       int timeLeft;
+
+       Particle(vec2 p, ParticleType t = ParticleType::Drop)
+               : location(p), type(t), timeLeft(3000) {} // TODO times
+} __attribute__ ((packed));
+
+class ParticleSystem : public entityx::System<ParticleSystem> {
+private:
+       std::vector<Particle> parts;
+       bool max;
+
+public:
+       ParticleSystem(int count = 1024, bool m = false);
+
+       void add(const vec2& pos, const ParticleType& type);
+       void addMultiple(const int& count, const ParticleType& type, std::function<vec2(void)> f);
+
+       void render(void) const; 
+       void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override;
+
+       int getCount(void) const;
+};
+
+#endif // PARTICLE_HPP_
index e9082b3967697a1cb1b51d2c0ff7f65200fb88ee..878955e524388373f48ff504a760538e54bdd435 100644 (file)
@@ -91,6 +91,7 @@ namespace Colors {
        extern ColorTex white; /**< A solid white texture. */
        extern ColorTex black; /**< A solid black texture. */
        extern ColorTex red;   /**< A solid red texture. */
+       extern ColorTex blue;  /**< A solid blue texture. */
 
        /**
         * Creates the colors.
diff --git a/include/weather.hpp b/include/weather.hpp
new file mode 100644 (file)
index 0000000..f7b53f1
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef WEATHER_HPP_
+#define WEATHER_HPP_
+
+#include <entityx/entityx.h>
+
+#include <common.hpp>
+#include <particle.hpp>
+
+/**
+ * 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 Weather : unsigned char {
+       Sunny = 0, /**< Sunny */
+       Rainy,     /**< Rain */
+       Snowy,     /**< Snow */
+       count
+};
+
+constexpr const char *weatherStrings[] = {
+       "Sunny",
+       "Rainy",
+       "Snowy"
+};
+
+class WeatherSystem : public entityx::System<WeatherSystem> {
+private:
+       Weather weather;
+
+public:
+       WeatherSystem(Weather w = Weather::Sunny)
+               : weather(w) {}
+
+       void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override {
+               (void)en;
+               (void)ev;
+               (void)dt;
+
+               static auto& partSystem = *game::engine.getSystem<ParticleSystem>();
+
+               switch (weather) {
+               case Weather::Sunny:
+                       break;
+               case Weather::Rainy:
+                       partSystem.add(vec2(offset.x - game::SCREEN_WIDTH / 2 + randGet() % game::SCREEN_WIDTH,
+                               offset.y + game::SCREEN_HEIGHT / 2 + 100),
+                               ParticleType::Drop);
+                       break; // TODO
+               case Weather::Snowy:
+                       break; // TODO
+               default:
+                       break;
+               }
+       }
+
+       inline void setWeather(const std::string& w) {
+               for (int i = 0; i < static_cast<int>(Weather::count); i++) {
+                       if (w == weatherStrings[i]) {
+                               weather = static_cast<Weather>(i);
+                               return;
+                       }
+               }
+       }
+};
+
+#endif // WEATHER_HPP_
index 8864d305b9c65723028dedb6768315d388f2d838..14c64d04c354b0d89124b81c523ff114a8ca811c 100644 (file)
@@ -27,37 +27,17 @@ enum class WorldBGType : unsigned int {
        Forest = 0      /**< A forest 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 {
-       None = 0,       /**< None (sunny) */
-       Rain,           /**< Rain */
-       Snowy           /**< Snow */
-};
-
-/**
- * Strings to represent each type of weather.
- */
-constexpr const char* WorldWeatherString[3] = {
-       "None",
-       "Rainy",
-       "Snowy"
-};
-
 /**
  * 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 {
+struct WorldData {
     bool          grassUnpressed; /**< squishes grass if false */
     float         grassHeight[2]; /**< height of the two grass blades */
     float         groundHeight;   /**< height of the 'line' */
     unsigned char groundColor;    /**< a value that affects the ground's color */
-} WorldData;
+} __attribute__ ((packed));
 
 /**
  * Defines how many game ticks it takes to go from day to night or vice versa.
@@ -129,11 +109,6 @@ private:
         */
        WorldData2 world;
 
-       /**
-        * The current state of weather in the world.
-        */
-       WorldWeather weather;
-
        /**
         * SDL's object for handling the background music.
         */
@@ -176,22 +151,16 @@ public:
        inline float getWidth(void) const
        { return world.startX * -2.0f; }
 
+       float isAboveGround(const vec2& p) const;
+
        void receive(const BGMToggleEvent &bte);
 
        void update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt) override;
        void render(void);
 
-       inline const std::string getWeatherStr(void) const
-       { return WorldWeatherString[static_cast<int>(weather)]; }
-
-       inline const WorldWeather& getWeatherId(void) const
-       { return weather; }
-
        inline const std::string& getXMLFile(void) const
        { return currentXMLFile; }
 
-       void setWeather(const std::string &s);
-
        void detect(entityx::TimeDelta dt);
 
        void goWorldLeft(Position& p);
index 17499f71a644e22c83ee7d0713c949bd19eca2c4..2e33a83ff513fc252a4ba67566bae08639d3edc5 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -25,6 +25,7 @@ using namespace tinyxml2;
 #include <world.hpp>
 #include <render.hpp>
 #include <ui.hpp>
+#include <particle.hpp>
 
 /**
  * The currently used folder to look for XML files in.
@@ -311,6 +312,7 @@ void render() {
 
        // draw the world and player
        game::engine.getSystem<WorldSystem>()->render();
+       game::engine.getSystem<ParticleSystem>()->render();
 
        // draw the player's inventory
        //player->inv->draw();
@@ -327,9 +329,10 @@ void render() {
        if (ui::debug) {
                auto pos = game::engine.getSystem<PlayerSystem>()->getPosition();
                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());
+                   "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());
        }
 
        // draw the menu
index 48e384d394d206ac18d16c81a26d9c0f38e9b787..aa0db73f7efe3ec563937767748ae3665160b70f 100644 (file)
@@ -8,6 +8,8 @@
 #include <components.hpp>
 #include <player.hpp>
 #include <quest.hpp>
+#include <particle.hpp>
+#include <weather.hpp>
 
 Engine::Engine(void)
     : shouldRun(true), systems(game::entities, game::events)
@@ -30,6 +32,9 @@ void Engine::init(void) {
        systems.add<MovementSystem>();
        systems.add<DialogSystem>();
 
+       systems.add<ParticleSystem>();
+       systems.add<WeatherSystem>();
+
     systems.configure();
 
     ui::initSounds();
@@ -57,6 +62,8 @@ void Engine::update(entityx::TimeDelta dt)
        systems.update<WorldSystem>(dt);
     systems.update<PlayerSystem>(dt);
        //systems.update<QuestSystem>(dt); // doesn't do anything
+       systems.update<WeatherSystem>(dt);
+       systems.update<ParticleSystem>(dt);
 }
 
 
index fb999ea54ca20588d35a0ddc3ac47cffdd321908..480c8032df25240138d9bdf22439fbab46cca3a1 100644 (file)
@@ -27,16 +27,19 @@ void InventorySystem::update(entityx::EntityManager &en, entityx::EventManager &
     (void)ev;
     (void)dt;
 
-    vec2 start = vec2(offset.x, 100);// - game::SCREEN_WIDTH / 2 + 20, game::SCREEN_HEIGHT - 40);
+       // TODO TODO TODO TODO until we do something
+       return;
+
+    //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();
+    /*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.unuse();*/
 }
 
 void InventorySystem::receive(const KeyDownEvent &kde)
diff --git a/src/particle.cpp b/src/particle.cpp
new file mode 100644 (file)
index 0000000..8090e2d
--- /dev/null
@@ -0,0 +1,99 @@
+#include <particle.hpp>
+
+#include <engine.hpp>
+#include <render.hpp>
+#include <world.hpp>
+
+ParticleSystem::ParticleSystem(int count, bool m)
+       : max(m)
+{
+       parts.reserve(count);
+}
+
+void ParticleSystem::add(const vec2& pos, const ParticleType& type)
+{
+       // TODO enforce max
+       //if (max && parts.size() >= std::end(parts))
+       //      return;
+
+       parts.emplace_back(pos, type);
+}
+
+void ParticleSystem::addMultiple(const int& count, const ParticleType& type, std::function<vec2(void)> f)
+{
+       int togo = count;
+       while (togo-- > 0)
+               parts.emplace_back(f(), type);
+}
+
+void ParticleSystem::render(void) const
+{
+       static const GLfloat tex[12] = {
+               0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0
+       };
+
+       Render::worldShader.use();
+       Render::worldShader.enable();
+       Colors::blue.use();
+
+       for (const auto& p : parts) {
+               GLfloat coord[18] = {
+                       p.location.x, p.location.y, -1,
+                       p.location.x, p.location.y + 5, -1,
+                       p.location.x + 5, p.location.y + 5, -1,
+                       p.location.x + 5, p.location.y + 5, -1,
+                       p.location.x + 5, p.location.y, -1,
+                       p.location.x, p.location.y, -1
+               };
+
+               glVertexAttribPointer(Render::worldShader.coord, 3, GL_FLOAT, GL_FALSE, 0, coord);
+               glVertexAttribPointer(Render::worldShader.tex, 2, GL_FLOAT, GL_FALSE, 0, tex);
+               glDrawArrays(GL_TRIANGLES, 0, 6);
+       }
+
+       Render::worldShader.disable();
+       Render::worldShader.unuse();
+}
+
+void ParticleSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt)
+{
+       (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;
+
+               // update timers
+               p.timeLeft -= dt;
+               if (p.timeLeft <= 0)
+                       parts.erase(part);
+
+               // update movement
+               switch (p.type) {
+               case ParticleType::Drop:
+                       if (p.velocity.y > -.5)
+                               p.velocity.y -= 0.001f;
+                       break;
+               case ParticleType::Confetti:
+                       break;
+               }
+
+               // really update movement
+               p.location.x += p.velocity.x * dt;
+               p.location.y += p.velocity.y * dt;
+
+               // world collision
+               auto height = worldSystem.isAboveGround(p.location);
+               if (height != 0)
+                       p.location.y = height + 5, p.velocity.y = randGet() % 10 / 40.0f;
+       }
+}
+
+int ParticleSystem::getCount(void) const
+{
+       return parts.size();
+}
+
index 640b06e1af24a21a2eaba1238a9b71413421e0da..da39ec053c2037fdf0f73d24ca6fcfcf40ca1471 100644 (file)
@@ -8,11 +8,13 @@ namespace Colors
        ColorTex white;
        ColorTex black;
        ColorTex red;
+       ColorTex blue;
 
        void init(void) {
                white = ColorTex(Color(255, 255, 255));
-               black = ColorTex(Color(0, 0, 0));
-               red = ColorTex(Color(255, 0, 0));
+               black = ColorTex(Color(0,   0,   0  ));
+               red   = ColorTex(Color(255, 0,   0  ));
+               blue  = ColorTex(Color(0,   0,   255));
        }
 }
 
index b10edacbc1650e9294d66239f1473e11b03ac093..6cce2b0cfc7fae6f99352670027456bc8a9b80f4 100644 (file)
@@ -21,6 +21,7 @@ using namespace std::literals::chrono_literals;
 #include <engine.hpp>
 #include <components.hpp>
 #include <player.hpp>
+#include <weather.hpp>
 
 // local library headers
 #include <tinyxml2.h>
@@ -74,12 +75,10 @@ const unsigned int GRASS_HEIGHT = HLINES(4);
 std::string currentXML;
 
 // pathnames of images for world themes
-using StyleList = std::array<std::string, 9>;
-
+using StyleList = std::array<std::string, 8>;
 static const std::vector<StyleList> bgPaths = {
        { // Forest
-               "bg.png",                               // daytime background
-               "bgn.png",                              // nighttime background
+               "bg.png",                               // sky/background
                "bgFarMountain.png",    // layer 1 (furthest)
                "forestTileFar.png",    // layer 2
                "forestTileBack.png",   // layer 3
@@ -154,6 +153,15 @@ void WorldSystem::generate(int width)
     world.startX = HLINES(width * -0.5);
 }
 
+float WorldSystem::isAboveGround(const vec2& p) const
+{
+       int line = std::clamp(static_cast<int>((p.x - world.startX) / game::HLINE),
+               0, static_cast<int>(world.data.size()));
+
+       const auto& gh = world.data[line].groundHeight;
+       return p.y >= gh ? 0 : gh;
+}
+
 static Color ambient;
 
 bool WorldSystem::save(void)
@@ -279,7 +287,8 @@ void WorldSystem::load(const std::string& file)
 
                // weather tag
                else if (tagName == "weather") {
-                       setWeather(wxml->GetText());
+                       game::engine.getSystem<WeatherSystem>()->setWeather(wxml->GetText());
+                       //setWeather(wxml->GetText());
                }
 
                // link tags
@@ -641,7 +650,7 @@ loadWorldFromXMLNoSave(std::string path) {
 }*/
 
 WorldSystem::WorldSystem(void)
-       : weather(WorldWeather::None), bgmObj(nullptr) {}
+       : bgmObj(nullptr) {}
 
 WorldSystem::~WorldSystem(void)
 {
@@ -664,10 +673,6 @@ void WorldSystem::render(void)
     // world width in pixels
        int width = HLINES(world.data.size());
 
-    // used for alpha values of background textures
-    int alpha;
-
-
        static bool ambientUpdaterStarted = false;
        if (!ambientUpdaterStarted) {
                ambientUpdaterStarted = true;
@@ -686,34 +691,12 @@ void WorldSystem::render(void)
                thAmbient.detach();
        }
 
-
-       switch (weather) {
-       case WorldWeather::Snowy:
-               alpha = 150;
-               break;
-       case WorldWeather::Rain:
-               alpha = 0;
-               break;
-       default:
-               alpha = 255 - worldShade * 4;
-               break;
-       }
-
        // shade value for GLSL
        float shadeAmbient = std::max(0.0f, static_cast<float>(-worldShade) / 50 + 0.5f); // 0 to 1.5f
 
        if (shadeAmbient > 0.9f)
                shadeAmbient = 1;
 
-    // draw background images.
-    GLfloat tex_coord[] = { 0.0f, 1.0f,
-                            1.0f, 1.0f,
-                            1.0f, 0.0f,
-
-                            1.0f, 0.0f,
-                            0.0f, 0.0f,
-                            0.0f, 1.0f,};
-
        // TODO scroll backdrop
        GLfloat bgOff = game::time::getTickCount() / static_cast<float>(DAY_CYCLE * 2);
 
@@ -755,16 +738,6 @@ void WorldSystem::render(void)
         offset.x - backgroundOffset.x - 5, offset.y - backgroundOffset.y, 9.9f
        };
 
-    GLfloat fron_tex_coord[] = {
-               offset.x - backgroundOffset.x - 5, offset.y + backgroundOffset.y, 9.8f,
-        offset.x + backgroundOffset.x + 5, offset.y + backgroundOffset.y, 9.8f,
-        offset.x + backgroundOffset.x + 5, offset.y - backgroundOffset.y, 9.8f,
-
-        offset.x + backgroundOffset.x + 5, offset.y - backgroundOffset.y, 9.8f,
-        offset.x - backgroundOffset.x - 5, offset.y - backgroundOffset.y, 9.8f,
-        offset.x - backgroundOffset.x - 5, offset.y + backgroundOffset.y, 9.8f
-       };
-
        // rendering!!
 
     glActiveTexture(GL_TEXTURE0);
@@ -785,10 +758,10 @@ void WorldSystem::render(void)
 
        makeWorldDrawingSimplerEvenThoughAndyDoesntThinkWeCanMakeItIntoFunctions(0, back_tex_coord, scrolling_tex_coord, 6);
 
-       bgTex++;
-       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);
+       // no more night bg
+       //bgTex++;
+       //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
        /*static GLuint starTex = Texture::loadTexture("assets/style/classic/bg/star.png");
@@ -1122,18 +1095,6 @@ void WorldSystem::receive(const BGMToggleEvent &bte)
        }
 }
 
-void WorldSystem::setWeather(const std::string &s)
-{
-       for (unsigned int i = 3; i--;) {
-               if (WorldWeatherString[i] == s) {
-                       weather = static_cast<WorldWeather>(i);
-                       return;
-               }
-       }
-
-       weather = WorldWeather::None;
-}
-
 void WorldSystem::update(entityx::EntityManager &en, entityx::EventManager &ev, entityx::TimeDelta dt)
 {
        (void)en;
index d98e8c65142e703a6d49cc21681b8775245efa6c..c197d8df6f627c7b59460cc1713a0b2a70cc8428 100644 (file)
@@ -4,6 +4,7 @@
 <World>
     <style background="0" bgm="assets/music/embark.wav" folder="assets/style/classic/"/>
     <generation width="320"/>
+       <weather>Rainy</weather>
     <time>6000</time>
     <link right="!town2.xml"/>
     <spawnx>-300</spawnx>