Now mostly working with GUECS but shaders are still busted. Have to find out why they stopped working.
This commit is contained in:
		
							parent
							
								
									a5f6a82611
								
							
						
					
					
						commit
						ac22a11c9f
					
				
					 27 changed files with 162 additions and 1210 deletions
				
			
		
							
								
								
									
										5
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -6,10 +6,7 @@ reset: | ||||||
| patch: | patch: | ||||||
| 	powershell "cp ./patches/process.h ./subprojects/libgit2-1.9.0/src/util/process.h" | 	powershell "cp ./patches/process.h ./subprojects/libgit2-1.9.0/src/util/process.h" | ||||||
| 
 | 
 | ||||||
| %.cpp : %.rl | build: | ||||||
| 	ragel -o $@ $< |  | ||||||
| 
 |  | ||||||
| build: lel_parser.cpp |  | ||||||
| 	meson compile -C builddir | 	meson compile -C builddir | ||||||
| 
 | 
 | ||||||
| config: | config: | ||||||
|  |  | ||||||
							
								
								
									
										66
									
								
								backend.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								backend.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | ||||||
|  | #include "backend.hpp" | ||||||
|  | #include "shaders.hpp" | ||||||
|  | #include "sound.hpp" | ||||||
|  | #include "textures.hpp" | ||||||
|  | 
 | ||||||
|  | namespace sfml { | ||||||
|  |   guecs::SpriteTexture Backend::texture_get(const string& name) { | ||||||
|  |     auto sp = textures::get(name); | ||||||
|  |     return {sp.sprite, sp.texture}; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   Backend::Backend() { | ||||||
|  |     sound::init(); | ||||||
|  |     shaders::init(); | ||||||
|  |     textures::init(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void Backend::sound_play(const string& name) { | ||||||
|  |     sound::play(name); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   void Backend::sound_stop(const string& name) { | ||||||
|  |     sound::stop(name); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   std::shared_ptr<sf::Shader> Backend::shader_get(const std::string& name) { | ||||||
|  |     return shaders::get(name); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   bool Backend::shader_updated() { | ||||||
|  |     if(shaders::updated($shaders_version)) { | ||||||
|  |       $shaders_version = shaders::version(); | ||||||
|  |       return true; | ||||||
|  |     } else { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   guecs::Theme Backend::theme() { | ||||||
|  |     guecs::Theme theme { | ||||||
|  |       .BLACK={1, 4, 2}, | ||||||
|  |       .DARK_DARK={9, 29, 16}, | ||||||
|  |       .DARK_MID={14, 50, 26}, | ||||||
|  |       .DARK_LIGHT={0, 109, 44}, | ||||||
|  |       .MID={63, 171, 92}, | ||||||
|  |       .LIGHT_DARK={161, 217, 155}, | ||||||
|  |       .LIGHT_MID={199, 233, 192}, | ||||||
|  |       .LIGHT_LIGHT={229, 245, 224}, | ||||||
|  |       .WHITE={255, 255, 255}, | ||||||
|  |       .TRANSPARENT = sf::Color::Transparent | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     theme.PADDING = 3; | ||||||
|  |     theme.BORDER_PX = 1; | ||||||
|  |     theme.TEXT_SIZE = 40; | ||||||
|  |     theme.LABEL_SIZE = 40; | ||||||
|  |     theme.FILL_COLOR = theme.DARK_DARK; | ||||||
|  |     theme.TEXT_COLOR = theme.LIGHT_LIGHT; | ||||||
|  |     theme.BG_COLOR = theme.MID; | ||||||
|  |     theme.BORDER_COLOR = theme.LIGHT_DARK; | ||||||
|  |     theme.BG_COLOR_DARK = theme.BLACK; | ||||||
|  |     theme.FONT_FILE_NAME = "assets/text.ttf"; | ||||||
|  | 
 | ||||||
|  |     return theme; | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								backend.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								backend.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | #include "guecs/ui.hpp" | ||||||
|  | 
 | ||||||
|  | namespace sfml { | ||||||
|  |   using std::string; | ||||||
|  | 
 | ||||||
|  |   class Backend : public guecs::Backend { | ||||||
|  |     int $shaders_version = 0; | ||||||
|  | 
 | ||||||
|  |   public: | ||||||
|  | 
 | ||||||
|  |     Backend(); | ||||||
|  |     guecs::SpriteTexture texture_get(const string& name); | ||||||
|  |     void sound_play(const string& name); | ||||||
|  |     void sound_stop(const string& name); | ||||||
|  |     std::shared_ptr<sf::Shader> shader_get(const std::string& name); | ||||||
|  |     bool shader_updated(); | ||||||
|  |     guecs::Theme theme(); | ||||||
|  |   }; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								color.hpp
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								color.hpp
									
										
									
									
									
								
							|  | @ -1,15 +0,0 @@ | ||||||
| #pragma once |  | ||||||
| #include <SFML/Graphics/Color.hpp> |  | ||||||
| 
 |  | ||||||
| namespace ColorValue { |  | ||||||
|   const sf::Color BLACK{1, 4, 2}; |  | ||||||
|   const sf::Color DARK_DARK{9, 29, 16}; |  | ||||||
|   const sf::Color DARK_MID{14, 50, 26}; |  | ||||||
|   const sf::Color DARK_LIGHT{0, 109, 44}; |  | ||||||
|   const sf::Color MID{63, 171, 92}; |  | ||||||
|   const sf::Color LIGHT_DARK{161, 217, 155}; |  | ||||||
|   const sf::Color LIGHT_MID{199, 233, 192}; |  | ||||||
|   const sf::Color LIGHT_LIGHT{229, 245, 224}; |  | ||||||
|   const sf::Color WHITE{255, 255, 255}; |  | ||||||
|   const sf::Color TRANSPARENT = sf::Color::Transparent; |  | ||||||
| } |  | ||||||
|  | @ -1,7 +1,6 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <string> | #include <string> | ||||||
| #include "color.hpp" |  | ||||||
| #include <array> | #include <array> | ||||||
| 
 | 
 | ||||||
| constexpr const int SCREEN_WIDTH= 1920 / 2; | constexpr const int SCREEN_WIDTH= 1920 / 2; | ||||||
|  | @ -10,15 +9,6 @@ constexpr const int SCREEN_HEIGHT= 1080 / 2; | ||||||
| constexpr const bool VSYNC=false; | constexpr const bool VSYNC=false; | ||||||
| constexpr const int FRAME_LIMIT=60; | constexpr const int FRAME_LIMIT=60; | ||||||
| 
 | 
 | ||||||
| constexpr const int GUECS_PADDING = 3; |  | ||||||
| constexpr const int GUECS_BORDER_PX = 1; |  | ||||||
| constexpr const int GUECS_FONT_SIZE = 40; |  | ||||||
| const sf::Color GUECS_FILL_COLOR = ColorValue::DARK_DARK; |  | ||||||
| const sf::Color GUECS_TEXT_COLOR = ColorValue::LIGHT_LIGHT; |  | ||||||
| const sf::Color GUECS_BG_COLOR = ColorValue::BLACK; |  | ||||||
| const sf::Color GUECS_BORDER_COLOR = ColorValue::MID; |  | ||||||
| constexpr const char *FONT_FILE_NAME="assets/text.ttf"; |  | ||||||
| 
 |  | ||||||
| #ifdef NDEBUG | #ifdef NDEBUG | ||||||
| constexpr const bool DEBUG_BUILD=false; | constexpr const bool DEBUG_BUILD=false; | ||||||
| #else | #else | ||||||
|  |  | ||||||
							
								
								
									
										3
									
								
								dbc.hpp
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								dbc.hpp
									
										
									
									
									
								
							|  | @ -5,9 +5,10 @@ | ||||||
| #include <functional> | #include <functional> | ||||||
| #include <source_location> | #include <source_location> | ||||||
| 
 | 
 | ||||||
| using std::string; |  | ||||||
| 
 | 
 | ||||||
| namespace dbc { | namespace dbc { | ||||||
|  |   using std::string; | ||||||
|  | 
 | ||||||
|   class Error { |   class Error { | ||||||
|     public: |     public: | ||||||
|       const string message; |       const string message; | ||||||
|  |  | ||||||
|  | @ -12,8 +12,10 @@ const auto ERROR = fmt::emphasis::bold | fg(fmt::color::red); | ||||||
| 
 | 
 | ||||||
| using namespace std; | using namespace std; | ||||||
| 
 | 
 | ||||||
| GameEngine::GameEngine(int hp) : starting_hp(hp) { | GameEngine::GameEngine(int hp, int max_hp) : | ||||||
|   hit_points = max_hp(); |   hit_points(hp), starting_hp(max_hp) | ||||||
|  | { | ||||||
|  | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int GameEngine::determine_damage(string &type) { | int GameEngine::determine_damage(string &type) { | ||||||
|  |  | ||||||
|  | @ -31,8 +31,8 @@ class GameEngine : DeadSimpleFSM<GameState, GameEvent> { | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   public: |   public: | ||||||
|   int starting_hp = 0; |  | ||||||
|   int hit_points = 0; |   int hit_points = 0; | ||||||
|  |   int starting_hp = 0; | ||||||
|   int hits_taken = 0; |   int hits_taken = 0; | ||||||
|   int rounds = 0; |   int rounds = 0; | ||||||
|   int deaths = 0; |   int deaths = 0; | ||||||
|  | @ -40,7 +40,7 @@ class GameEngine : DeadSimpleFSM<GameState, GameEvent> { | ||||||
|   float hp_bonus = 1.0f; |   float hp_bonus = 1.0f; | ||||||
|   bool free_death = false; |   bool free_death = false; | ||||||
| 
 | 
 | ||||||
|   GameEngine(int hp); |   GameEngine(int hp, int max_hp); | ||||||
| 
 | 
 | ||||||
|   // FOUND BUG: I was accidentally copying this and shouldn't have been
 |   // FOUND BUG: I was accidentally copying this and shouldn't have been
 | ||||||
|   GameEngine(GameEngine &g) = delete; |   GameEngine(GameEngine &g) = delete; | ||||||
|  |  | ||||||
							
								
								
									
										316
									
								
								guecs.cpp
									
										
									
									
									
								
							
							
						
						
									
										316
									
								
								guecs.cpp
									
										
									
									
									
								
							|  | @ -1,316 +0,0 @@ | ||||||
| #include "guecs.hpp" |  | ||||||
| #include "shaders.hpp" |  | ||||||
| #include "sound.hpp" |  | ||||||
| #include "config.hpp" |  | ||||||
| 
 |  | ||||||
| namespace guecs { |  | ||||||
| 
 |  | ||||||
|   void Textual::init(lel::Cell &cell, shared_ptr<sf::Font> font_ptr) { |  | ||||||
|     dbc::check(font_ptr != nullptr, "you failed to initialize this WideText"); |  | ||||||
|     if(font == nullptr) font = font_ptr; |  | ||||||
|     if(text == nullptr) text = make_shared<sf::Text>(*font, content, size); |  | ||||||
|     text->setFillColor(color); |  | ||||||
| 
 |  | ||||||
|     if(centered) { |  | ||||||
|       auto bounds = text->getLocalBounds(); |  | ||||||
|       auto text_cell = lel::center(bounds.size.x, bounds.size.y, cell); |  | ||||||
|       // this stupid / 2 is because SFML renders from baseline rather than from the claimed bounding box
 |  | ||||||
|       text->setPosition({float(text_cell.x), float(text_cell.y) - text_cell.h / 2}); |  | ||||||
|     } else { |  | ||||||
|       text->setPosition({float(cell.x + padding * 2), float(cell.y + padding * 2)}); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     text->setCharacterSize(size); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void Textual::update(std::wstring& new_content) { |  | ||||||
|     content = new_content; |  | ||||||
|     text->setString(content); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void Sprite::init(lel::Cell &cell) { |  | ||||||
|     auto sprite_texture = textures::get(name); |  | ||||||
| 
 |  | ||||||
|     sprite = make_shared<sf::Sprite>( |  | ||||||
|         *sprite_texture.texture, |  | ||||||
|         sprite_texture.sprite->getTextureRect()); |  | ||||||
| 
 |  | ||||||
|     sprite->setPosition({ |  | ||||||
|         float(cell.x + padding), |  | ||||||
|         float(cell.y + padding)}); |  | ||||||
| 
 |  | ||||||
|     auto bounds = sprite->getLocalBounds(); |  | ||||||
| 
 |  | ||||||
|     sprite->setScale({ |  | ||||||
|         float(cell.w - padding * 2) / bounds.size.x, |  | ||||||
|         float(cell.h - padding * 2) / bounds.size.y}); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void Rectangle::init(lel::Cell& cell) { |  | ||||||
|     sf::Vector2f size{float(cell.w) - padding * 2, float(cell.h) - padding * 2}; |  | ||||||
|     if(shape == nullptr) shape = make_shared<sf::RectangleShape>(size); |  | ||||||
|     shape->setPosition({float(cell.x + padding), float(cell.y + padding)}); |  | ||||||
|     shape->setFillColor(color); |  | ||||||
|     shape->setOutlineColor(border_color); |  | ||||||
|     shape->setOutlineThickness(border_px); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   void Meter::init(lel::Cell& cell) { |  | ||||||
|     bar.init(cell); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void Sound::play(bool hover) { |  | ||||||
|     if(!hover) { |  | ||||||
|       sound::play(on_click); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void Background::init() { |  | ||||||
|     sf::Vector2f size{float(w), float(h)}; |  | ||||||
|     if(shape == nullptr) shape = make_shared<sf::RectangleShape>(size); |  | ||||||
|     shape->setPosition({float(x), float(y)}); |  | ||||||
|     shape->setFillColor(color); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void Effect::init(lel::Cell &cell) { |  | ||||||
|     $shader_version = shaders::version(); |  | ||||||
|     $shader = shaders::get(name); |  | ||||||
|     $shader->setUniform("u_resolution", sf::Vector2f({float(cell.w), float(cell.h)})); |  | ||||||
|     $clock = std::make_shared<sf::Clock>(); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void Effect::step() { |  | ||||||
|     sf::Time cur_time = $clock->getElapsedTime(); |  | ||||||
|     float u_time = cur_time.asSeconds(); |  | ||||||
| 
 |  | ||||||
|     if(u_time < $u_time_end) { |  | ||||||
|       $shader->setUniform("u_duration", duration); |  | ||||||
|       $shader->setUniform("u_time_end", $u_time_end); |  | ||||||
|       $shader->setUniform("u_time", u_time); |  | ||||||
|     } else { |  | ||||||
|       $active = false; |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void Effect::run() { |  | ||||||
|     $active = true; |  | ||||||
|     sf::Time u_time = $clock->getElapsedTime(); |  | ||||||
|     $u_time_end = u_time.asSeconds() + duration; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   shared_ptr<sf::Shader> Effect::checkout_ptr() { |  | ||||||
|     if(shaders::updated($shader_version)) { |  | ||||||
|       $shader = shaders::get(name); |  | ||||||
|       $shader_version = shaders::version(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return $shader; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   UI::UI() { |  | ||||||
|     $font = make_shared<sf::Font>(Config::path_to(FONT_FILE_NAME)); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void UI::position(int x, int y, int width, int height) { |  | ||||||
|     $parser.position(x, y, width, height); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void UI::layout(std::string grid) { |  | ||||||
|     $grid = grid; |  | ||||||
|     bool good = $parser.parse($grid); |  | ||||||
|     dbc::check(good, "LEL parsing failed."); |  | ||||||
| 
 |  | ||||||
|     for(auto& [name, cell] : $parser.cells) { |  | ||||||
|       auto ent = init_entity(name); |  | ||||||
|       $world.set<lel::Cell>(ent, cell); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   DinkyECS::Entity UI::init_entity(std::string name) { |  | ||||||
|     auto entity = $world.entity(); |  | ||||||
|     // this lets you look up an entity by name
 |  | ||||||
|     $name_ents.insert_or_assign(name, entity); |  | ||||||
|     // this makes it easier to get the name during querying
 |  | ||||||
|     $world.set<CellName>(entity, {name}); |  | ||||||
|     return entity; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   DinkyECS::Entity UI::entity(std::string name) { |  | ||||||
|     dbc::check($name_ents.contains(name), |  | ||||||
|         fmt::format("GUECS entity {} does not exist. Forgot to init_entity?", name)); |  | ||||||
|     return $name_ents.at(name); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void UI::init() { |  | ||||||
|     if($world.has_the<Background>()) { |  | ||||||
|       auto& bg = $world.get_the<Background>(); |  | ||||||
|       bg.init(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     $world.query<Background>([](auto, auto& bg) { |  | ||||||
|         bg.init(); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     $world.query<lel::Cell, Rectangle>([](auto, auto& cell, auto& rect) { |  | ||||||
|       rect.init(cell); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     $world.query<lel::Cell, Effect>([](auto, auto& cell, auto& effect) { |  | ||||||
|         effect.init(cell); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     $world.query<Rectangle, Meter>([](auto, auto& bg, auto &) { |  | ||||||
|         bg.shape->setFillColor(ColorValue::BLACK); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     $world.query<lel::Cell, Meter>([](auto, auto &cell, auto& meter) { |  | ||||||
|         meter.init(cell); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     $world.query<lel::Cell, Textual>([this](auto, auto& cell, auto& text) { |  | ||||||
|       text.init(cell, $font); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     $world.query<lel::Cell, Label>([this](auto, auto& cell, auto& text) { |  | ||||||
|       text.init(cell, $font); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     $world.query<lel::Cell, Sprite>([&](auto, auto &cell, auto &sprite) { |  | ||||||
|         sprite.init(cell); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void UI::debug_layout(sf::RenderWindow& window) { |  | ||||||
|     $world.query<lel::Cell>([&](const auto, auto &cell) { |  | ||||||
|         sf::RectangleShape rect{{float(cell.w), float(cell.h)}}; |  | ||||||
|         rect.setPosition({float(cell.x), float(cell.y)}); |  | ||||||
|         rect.setFillColor(sf::Color::Transparent); |  | ||||||
|         rect.setOutlineColor(sf::Color::Red); |  | ||||||
|         rect.setOutlineThickness(2.0f); |  | ||||||
|         window.draw(rect); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void UI::render(sf::RenderWindow& window) { |  | ||||||
|     if($world.has_the<Background>()) { |  | ||||||
|       auto& bg = $world.get_the<Background>(); |  | ||||||
|       window.draw(*bg.shape); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     $world.query<Effect>([&](auto, auto& shader) { |  | ||||||
|       if(shader.$active) shader.step(); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     $world.query<Rectangle>([&](auto ent, auto& rect) { |  | ||||||
|         render_helper(window, ent, true, rect.shape); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     $world.query<lel::Cell, Meter>([&](auto ent, auto& cell, const auto &meter) { |  | ||||||
|         int pad = meter.bar.padding * 2; |  | ||||||
|         float level = std::clamp(meter.percent, 0.0f, 1.0f) * float(cell.w - pad); |  | ||||||
|         // ZED: this 6 is a border width, make it a thing
 |  | ||||||
|         meter.bar.shape->setSize({std::max(level, 0.0f), float(cell.h - pad)}); |  | ||||||
|         render_helper(window, ent, true, meter.bar.shape); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     $world.query<Sprite>([&](auto ent, auto& sprite) { |  | ||||||
|         render_helper(window, ent, false, sprite.sprite); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     $world.query<Label>([&](auto ent, auto& text) { |  | ||||||
|         render_helper(window, ent, false, text.text); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     $world.query<Textual>([&](auto ent, auto& text) { |  | ||||||
|         render_helper(window, ent, true, text.text); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   bool UI::mouse(float x, float y, bool hover) { |  | ||||||
|     int action_count = 0; |  | ||||||
| 
 |  | ||||||
|     $world.query<lel::Cell, Clickable>([&](auto ent, auto& cell, auto &clicked) { |  | ||||||
|       if((x >= cell.x && x <= cell.x + cell.w) && |  | ||||||
|           (y >= cell.y && y <= cell.y + cell.h)) |  | ||||||
|       { |  | ||||||
|         do_if<Effect>(ent, [hover](auto& effect) { |  | ||||||
|           effect.$shader->setUniform("hover", hover); |  | ||||||
|           effect.run(); |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|         do_if<Sound>(ent, [hover](auto& sound) { |  | ||||||
|             // here set that it played then only play once
 |  | ||||||
|             sound.play(hover); |  | ||||||
|         }); |  | ||||||
| 
 |  | ||||||
|         if(hover) return; // kinda gross
 |  | ||||||
| 
 |  | ||||||
|         if(auto action_data = get_if<ActionData>(ent)) { |  | ||||||
|           clicked.action(ent, action_data->data); |  | ||||||
|         } else { |  | ||||||
|           clicked.action(ent, {}); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         action_count++; |  | ||||||
|       } else { |  | ||||||
|         // via ORBLISHJ
 |  | ||||||
|         // just reset the hover trigger for all that aren't hit
 |  | ||||||
|         // then in the ^^ positive branch play it and set it played
 |  | ||||||
|       } |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     return action_count > 0; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void UI::show_sprite(string region, string sprite_name) { |  | ||||||
|     auto ent = entity(region); |  | ||||||
| 
 |  | ||||||
|     if(has<Sprite>(ent)) { |  | ||||||
|       auto& to_show = get<Sprite>(ent); |  | ||||||
|       auto sprite_texture = textures::get(sprite_name); |  | ||||||
|       to_show.sprite->setTexture(*sprite_texture.texture); |  | ||||||
|     } else { |  | ||||||
|       Sprite to_show{sprite_name}; |  | ||||||
|       auto& cell = cell_for(ent); |  | ||||||
|       to_show.init(cell); |  | ||||||
|       set<guecs::Sprite>(ent, to_show); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void UI::show_text(string region, wstring content) { |  | ||||||
|     auto ent = entity(region); |  | ||||||
| 
 |  | ||||||
|     if(auto text = get_if<Textual>(ent)) { |  | ||||||
|       text->text->setString(content); |  | ||||||
|     } else { |  | ||||||
|       auto &cell = cell_for(ent); |  | ||||||
|       Textual to_set{content, 20}; |  | ||||||
|       to_set.init(cell, $font); |  | ||||||
|       to_set.text->setFillColor(ColorValue::LIGHT_MID); |  | ||||||
|       set<Textual>(ent, to_set); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void UI::show_label(string region, wstring content) { |  | ||||||
|     auto ent = entity(region); |  | ||||||
| 
 |  | ||||||
|     if(auto text = get_if<Label>(ent)) { |  | ||||||
|       text->text->setString(content); |  | ||||||
|     } else { |  | ||||||
|       auto &cell = cell_for(ent); |  | ||||||
|       Label to_set{content, 20}; |  | ||||||
|       to_set.init(cell, $font); |  | ||||||
|       to_set.text->setFillColor(ColorValue::LIGHT_MID); |  | ||||||
|       set<Label>(ent, to_set); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   Clickable make_action(DinkyECS::World& target, Events::GUI event) { |  | ||||||
|     return {[&, event](auto ent, auto data){ |  | ||||||
|       // remember that ent is passed in from the UI::mouse handler
 |  | ||||||
|       target.send<Events::GUI>(event, ent, data); |  | ||||||
|     }}; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
							
								
								
									
										233
									
								
								guecs.hpp
									
										
									
									
									
								
							
							
						
						
									
										233
									
								
								guecs.hpp
									
										
									
									
									
								
							|  | @ -1,233 +0,0 @@ | ||||||
| #pragma once |  | ||||||
| #include "color.hpp" |  | ||||||
| #include "dinkyecs.hpp" |  | ||||||
| #include "lel.hpp" |  | ||||||
| #include <string> |  | ||||||
| #include <memory> |  | ||||||
| #include <SFML/Graphics.hpp> |  | ||||||
| #include "textures.hpp" |  | ||||||
| #include <functional> |  | ||||||
| #include "events.hpp" |  | ||||||
| #include "constants.hpp" |  | ||||||
| #include <any> |  | ||||||
| #include "shaders.hpp" |  | ||||||
| 
 |  | ||||||
| namespace guecs { |  | ||||||
|   using std::shared_ptr, std::make_shared, std::wstring, std::string; |  | ||||||
| 
 |  | ||||||
|   struct Textual { |  | ||||||
|     std::wstring content; |  | ||||||
|     unsigned int size = GUECS_FONT_SIZE; |  | ||||||
|     sf::Color color = GUECS_TEXT_COLOR; |  | ||||||
|     int padding = GUECS_PADDING; |  | ||||||
|     bool centered = false; |  | ||||||
|     shared_ptr<sf::Font> font = nullptr; |  | ||||||
|     shared_ptr<sf::Text> text = nullptr; |  | ||||||
| 
 |  | ||||||
|     void init(lel::Cell &cell, shared_ptr<sf::Font> font_ptr); |  | ||||||
|     void update(std::wstring& new_content); |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   struct Label : public Textual { |  | ||||||
|     template<typename... Args> |  | ||||||
|     Label(Args... args) : Textual(args...) |  | ||||||
|     { |  | ||||||
|       centered = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     Label() { |  | ||||||
|       centered = true; |  | ||||||
|     }; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   struct Clickable { |  | ||||||
|     /* This is actually called by UI::mouse and passed the entity ID of the
 |  | ||||||
|      * button pressed so you can interact with it in the event handler. |  | ||||||
|      */ |  | ||||||
|     std::function<void(DinkyECS::Entity ent, std::any data)> action; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   struct Sprite { |  | ||||||
|     std::string name; |  | ||||||
|     int padding = GUECS_PADDING; |  | ||||||
|     std::shared_ptr<sf::Sprite> sprite = nullptr; |  | ||||||
|     std::shared_ptr<sf::Texture> texture = nullptr; |  | ||||||
| 
 |  | ||||||
|     void init(lel::Cell &cell); |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   struct Rectangle { |  | ||||||
|     int padding = GUECS_PADDING; |  | ||||||
|     sf::Color color = GUECS_FILL_COLOR; |  | ||||||
|     sf::Color border_color = GUECS_BORDER_COLOR; |  | ||||||
|     int border_px = GUECS_BORDER_PX; |  | ||||||
|     shared_ptr<sf::RectangleShape> shape = nullptr; |  | ||||||
| 
 |  | ||||||
|     void init(lel::Cell& cell); |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   struct Meter { |  | ||||||
|     float percent = 1.0f; |  | ||||||
|     Rectangle bar{}; |  | ||||||
| 
 |  | ||||||
|     void init(lel::Cell& cell); |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   struct ActionData { |  | ||||||
|     std::any data; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   struct CellName { |  | ||||||
|     std::string name; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   struct Effect { |  | ||||||
|     float duration = 0.1f; |  | ||||||
|     std::string name{"ui_shader"}; |  | ||||||
|     float $u_time_end = 0.0; |  | ||||||
|     bool $active = false; |  | ||||||
|     std::shared_ptr<sf::Clock> $clock = nullptr; |  | ||||||
|     std::shared_ptr<sf::Shader> $shader = nullptr; |  | ||||||
|     int $shader_version = 0; |  | ||||||
| 
 |  | ||||||
|     void init(lel::Cell &cell); |  | ||||||
|     void run(); |  | ||||||
|     void step(); |  | ||||||
|     shared_ptr<sf::Shader> checkout_ptr(); |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   struct Sound { |  | ||||||
|     std::string on_click{"ui_click"}; |  | ||||||
|     void play(bool hover); |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   struct Background { |  | ||||||
|     float x = 0.0f; |  | ||||||
|     float y = 0.0f; |  | ||||||
|     float w = 0.0f; |  | ||||||
|     float h = 0.0f; |  | ||||||
|     sf::Color color = GUECS_BG_COLOR; |  | ||||||
|     shared_ptr<sf::RectangleShape> shape = nullptr; |  | ||||||
| 
 |  | ||||||
|     Background(lel::Parser& parser, sf::Color bg_color=GUECS_BG_COLOR) : |  | ||||||
|       x(parser.grid_x), |  | ||||||
|       y(parser.grid_y), |  | ||||||
|       w(parser.grid_w), |  | ||||||
|       h(parser.grid_h), |  | ||||||
|       color(bg_color) |  | ||||||
|     {} |  | ||||||
| 
 |  | ||||||
|     Background() {} |  | ||||||
| 
 |  | ||||||
|     void init(); |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   class UI { |  | ||||||
|     public: |  | ||||||
|       DinkyECS::World $world; |  | ||||||
|       std::unordered_map<std::string, DinkyECS::Entity> $name_ents; |  | ||||||
|       shared_ptr<sf::Font> $font = nullptr; |  | ||||||
|       lel::Parser $parser; |  | ||||||
|       std::string $grid = ""; |  | ||||||
| 
 |  | ||||||
|       UI(); |  | ||||||
| 
 |  | ||||||
|       void position(int x, int y, int width, int height); |  | ||||||
|       void layout(std::string grid); |  | ||||||
|       DinkyECS::Entity init_entity(std::string name); |  | ||||||
|       DinkyECS::Entity entity(std::string name); |  | ||||||
| 
 |  | ||||||
|       inline lel::CellMap& cells() { |  | ||||||
|         return $parser.cells; |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       inline DinkyECS::World& world() { |  | ||||||
|         return $world; |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       void init(); |  | ||||||
|       void render(sf::RenderWindow& window); |  | ||||||
|       bool mouse(float x, float y, bool hover); |  | ||||||
|       void debug_layout(sf::RenderWindow& window); |  | ||||||
| 
 |  | ||||||
|       template <typename Comp> |  | ||||||
|       void set(DinkyECS::Entity ent, Comp val) { |  | ||||||
|         $world.set<Comp>(ent, val); |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       template <typename Comp> |  | ||||||
|       void set_init(DinkyECS::Entity ent, Comp val) { |  | ||||||
|         dbc::check(has<lel::Cell>(ent),"WRONG! slot is missing its cell?!"); |  | ||||||
|         auto& cell = get<lel::Cell>(ent); |  | ||||||
|         val.init(cell); |  | ||||||
|         $world.set<Comp>(ent, val); |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       template <typename Comp> |  | ||||||
|       void do_if(DinkyECS::Entity ent, std::function<void(Comp &)> cb) { |  | ||||||
|         if($world.has<Comp>(ent)) { |  | ||||||
|           cb($world.get<Comp>(ent)); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       lel::Cell& cell_for(DinkyECS::Entity ent) { |  | ||||||
|         return $world.get<lel::Cell>(ent); |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       lel::Cell& cell_for(std::string name) { |  | ||||||
|         DinkyECS::Entity ent = entity(name); |  | ||||||
|         return $world.get<lel::Cell>(ent); |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       template <typename Comp> |  | ||||||
|         Comp& get(DinkyECS::Entity entity) { |  | ||||||
|           return $world.get<Comp>(entity); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|       template <typename Comp> |  | ||||||
|         std::optional<Comp> get_if(DinkyECS::Entity entity) { |  | ||||||
|           return $world.get_if<Comp>(entity); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|       template <typename Comp> |  | ||||||
|         bool has(DinkyECS::Entity entity) { |  | ||||||
|           return $world.has<Comp>(entity); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|       template <typename Comp> |  | ||||||
|         void remove(DinkyECS::Entity ent) { |  | ||||||
|           $world.remove<Comp>(ent); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|       template <typename Comp> |  | ||||||
|       void close(string region) { |  | ||||||
|         auto ent = entity(region); |  | ||||||
|         remove<Comp>(ent); |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       template<typename T> |  | ||||||
|       void render_helper(sf::RenderWindow& window, DinkyECS::Entity ent, bool is_shape, T& target) { |  | ||||||
|         sf::Shader *shader_ptr = nullptr; |  | ||||||
| 
 |  | ||||||
|         if($world.has<Effect>(ent)) { |  | ||||||
|           auto& shader = $world.get<Effect>(ent); |  | ||||||
| 
 |  | ||||||
|           if(shader.$active) { |  | ||||||
|             auto ptr = shader.checkout_ptr(); |  | ||||||
|             ptr->setUniform("is_shape", is_shape); |  | ||||||
|             // NOTE: this is needed because SFML doesn't handle shared_ptr
 |  | ||||||
|             shader_ptr = ptr.get(); |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         window.draw(*target, shader_ptr); |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       void show_sprite(string region, string sprite_name); |  | ||||||
|       void show_text(string region, wstring content); |  | ||||||
|       void show_label(string region, wstring content); |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   Clickable make_action(DinkyECS::World& target, Events::GUI event); |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
							
								
								
									
										11
									
								
								gui.cpp
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								gui.cpp
									
										
									
									
									
								
							|  | @ -13,9 +13,12 @@ | ||||||
| #include <iostream> | #include <iostream> | ||||||
| #include "sound.hpp" | #include "sound.hpp" | ||||||
| #include "shaders.hpp" | #include "shaders.hpp" | ||||||
|  | #include "constants.hpp" | ||||||
|  | #include "backend.hpp" | ||||||
| 
 | 
 | ||||||
| using std::string, std::vector; | using std::string, std::vector; | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| GUI::GUI(int timer_seconds, const std::wstring &g) : | GUI::GUI(int timer_seconds, const std::wstring &g) : | ||||||
|   $timer_seconds(timer_seconds), |   $timer_seconds(timer_seconds), | ||||||
|   $goal(g), |   $goal(g), | ||||||
|  | @ -34,7 +37,7 @@ GUI::GUI(int timer_seconds, const std::wstring &g) : | ||||||
|      "[_|_|*%(300,100)clock|_|_]" |      "[_|_|*%(300,100)clock|_|_]" | ||||||
|      "[hp_bar]"); |      "[hp_bar]"); | ||||||
| 
 | 
 | ||||||
|   $gui.world().set_the<Background>({$gui.$parser, {0,0,0,0}}); |   $gui.set<Background>($gui.MAIN, {$gui.$parser, {0,0,0,0}}); | ||||||
| 
 | 
 | ||||||
|   for(auto& [name, cell] : $gui.cells()) { |   for(auto& [name, cell] : $gui.cells()) { | ||||||
|     auto ent = $gui.entity(name); |     auto ent = $gui.entity(name); | ||||||
|  | @ -54,17 +57,17 @@ GUI::GUI(int timer_seconds, const std::wstring &g) : | ||||||
| 
 | 
 | ||||||
|   auto clock = $gui.entity("clock"); |   auto clock = $gui.entity("clock"); | ||||||
|   auto& clock_rect = $gui.get<Rectangle>(clock); |   auto& clock_rect = $gui.get<Rectangle>(clock); | ||||||
|   clock_rect.color = ColorValue::BLACK; |   clock_rect.color = THEME.BLACK; | ||||||
|   $gui.set<Label>(clock, {L"00:00:00", 60}); |   $gui.set<Label>(clock, {L"00:00:00", 60}); | ||||||
| 
 | 
 | ||||||
|   auto goal = $gui.entity("goal"); |   auto goal = $gui.entity("goal"); | ||||||
|   std::wstring msg = fmt::format(L"Complete '{}' in:", $goal); |   std::wstring msg = fmt::format(L"Complete '{}' in:", $goal); | ||||||
|   auto& goal_rect = $gui.get<Rectangle>(goal); |   auto& goal_rect = $gui.get<Rectangle>(goal); | ||||||
|   goal_rect.color = ColorValue::BLACK; |   goal_rect.color = THEME.BLACK; | ||||||
|   $gui.set<Label>(goal, {msg, 30}); |   $gui.set<Label>(goal, {msg, 30}); | ||||||
| 
 | 
 | ||||||
|   $hp_bar = $gui.entity("hp_bar"); |   $hp_bar = $gui.entity("hp_bar"); | ||||||
|   $gui.set<Meter>($hp_bar, {1.0f, {10, ColorValue::LIGHT_DARK}}); |   $gui.set<Meter>($hp_bar, {}); | ||||||
| 
 | 
 | ||||||
|   $gui.init(); |   $gui.init(); | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										6
									
								
								gui.hpp
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								gui.hpp
									
										
									
									
									
								
							|  | @ -2,7 +2,7 @@ | ||||||
| 
 | 
 | ||||||
| #include <string> | #include <string> | ||||||
| #include "game_engine.hpp" | #include "game_engine.hpp" | ||||||
| #include "guecs.hpp" | #include <guecs/ui.hpp> | ||||||
| 
 | 
 | ||||||
| using std::string; | using std::string; | ||||||
| 
 | 
 | ||||||
|  | @ -14,8 +14,8 @@ class GUI { | ||||||
|   sf::RenderWindow $window; |   sf::RenderWindow $window; | ||||||
|   guecs::UI $gui; |   guecs::UI $gui; | ||||||
|   std::wstring $status; |   std::wstring $status; | ||||||
|   DinkyECS::Entity $log; |   guecs::Entity $log; | ||||||
|   DinkyECS::Entity $hp_bar; |   guecs::Entity $hp_bar; | ||||||
|   bool $hit_error = false; |   bool $hit_error = false; | ||||||
|   std::chrono::time_point<std::chrono::system_clock> $timer_end; |   std::chrono::time_point<std::chrono::system_clock> $timer_end; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										117
									
								
								lel.cpp
									
										
									
									
									
								
							
							
						
						
									
										117
									
								
								lel.cpp
									
										
									
									
									
								
							|  | @ -1,117 +0,0 @@ | ||||||
| #include "lel.hpp" |  | ||||||
| #include <fmt/core.h> |  | ||||||
| #include "dbc.hpp" |  | ||||||
| #include <numeric> |  | ||||||
| 
 |  | ||||||
| #include "lel_parser.cpp" |  | ||||||
| 
 |  | ||||||
| namespace lel { |  | ||||||
| 
 |  | ||||||
|   Parser::Parser(int x, int y, int width, int height) : |  | ||||||
|     grid_x(x), |  | ||||||
|     grid_y(y), |  | ||||||
|     grid_w(width), |  | ||||||
|     grid_h(height), |  | ||||||
|     cur(0, 0) |  | ||||||
|   { |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   Parser::Parser() : cur(0, 0) { } |  | ||||||
| 
 |  | ||||||
|   void Parser::position(int x, int y, int width, int height) { |  | ||||||
|     grid_x = x; |  | ||||||
|     grid_y = y; |  | ||||||
|     grid_w = width; |  | ||||||
|     grid_h = height; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void Parser::id(std::string name) { |  | ||||||
|     if(name != "_") { |  | ||||||
|       dbc::check(!cells.contains(name), |  | ||||||
|           fmt::format("duplicate cell name {}", name)); |  | ||||||
|       cells.insert_or_assign(name, cur); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     cur = {cur.col + 1, cur.row}; |  | ||||||
|     auto& row = grid.back(); |  | ||||||
|     row.push_back(name); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void Parser::finalize() { |  | ||||||
|     size_t rows = grid.size(); |  | ||||||
|     int cell_height = grid_h / rows; |  | ||||||
| 
 |  | ||||||
|     for(auto& row : grid) { |  | ||||||
|       size_t columns = row.size(); |  | ||||||
|       int cell_width = grid_w / columns; |  | ||||||
|       dbc::check(cell_width > 0, "invalid cell width calc"); |  | ||||||
|       dbc::check(cell_height > 0, "invalid cell height calc"); |  | ||||||
| 
 |  | ||||||
|       for(auto& name : row) { |  | ||||||
|         if(name == "_") continue; |  | ||||||
|         auto& cell = cells.at(name); |  | ||||||
| 
 |  | ||||||
|         // ZED: getting a bit hairy but this should work
 |  | ||||||
|         if(cell.percent) { |  | ||||||
|           // when percent mode we have to take unset to 100%
 |  | ||||||
|           if(cell.max_w == 0) cell.max_w = 100; |  | ||||||
|           if(cell.max_h == 0) cell.max_h = 100; |  | ||||||
|           cell.max_w *= cell_width * 0.01; |  | ||||||
|           cell.max_h *= cell_height * 0.01; |  | ||||||
|         } else { |  | ||||||
|           if(cell.max_w == 0) cell.max_w = cell_width; |  | ||||||
|           if(cell.max_h == 0) cell.max_h = cell_height; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         cell.w = cell.expand ? std::min(cell.max_w, grid_w) : std::min(cell_width, cell.max_w); |  | ||||||
|         cell.h = cell.expand ? std::min(cell.max_h, grid_h) : std::min(cell_height, cell.max_h); |  | ||||||
| 
 |  | ||||||
|         dbc::check(cell.h > 0, fmt::format("invalid height cell {}", name)); |  | ||||||
|         dbc::check(cell.w > 0, fmt::format("invalid width cell {}", name)); |  | ||||||
| 
 |  | ||||||
|         cell.x = grid_x + (cell.col * cell_width); |  | ||||||
|         cell.y = grid_y + (cell.row * cell_height); |  | ||||||
| 
 |  | ||||||
|         // keep the midpoint since it is used a lot
 |  | ||||||
|         cell.mid_x = std::midpoint(cell.x, cell.x + cell.w); |  | ||||||
|         cell.mid_y = std::midpoint(cell.y, cell.y + cell.h); |  | ||||||
| 
 |  | ||||||
|         // perform alignments
 |  | ||||||
|         if(cell.right) cell.x += cell_width - cell.w; |  | ||||||
|         if(cell.bottom) cell.y += cell_height - cell.h; |  | ||||||
|         if(cell.center) { |  | ||||||
|           cell.x = cell.mid_x - cell.w / 2; |  | ||||||
|           cell.y = cell.mid_y - cell.h / 2; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void Parser::reset() { |  | ||||||
|     cur = {0, 0}; |  | ||||||
|     grid.clear(); |  | ||||||
|     cells.clear(); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   std::optional<std::string> Parser::hit(int x, int y) { |  | ||||||
|     for(auto& [name, cell] : cells) { |  | ||||||
|       if((x >= cell.x && x <= cell.x + cell.w) && |  | ||||||
|           (y >= cell.y && y <= cell.y + cell.h)) { |  | ||||||
|         return name; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return std::nullopt; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   Cell center(int width, int height, Cell &parent) { |  | ||||||
|     Cell copy = parent; |  | ||||||
| 
 |  | ||||||
|     copy.x = parent.mid_x - width / 2; |  | ||||||
|     copy.y = parent.mid_y - height / 2; |  | ||||||
|     copy.w = width; |  | ||||||
|     copy.h = height; |  | ||||||
| 
 |  | ||||||
|     return copy; |  | ||||||
|   } |  | ||||||
| } |  | ||||||
							
								
								
									
										57
									
								
								lel.hpp
									
										
									
									
									
								
							
							
						
						
									
										57
									
								
								lel.hpp
									
										
									
									
									
								
							|  | @ -1,57 +0,0 @@ | ||||||
| #pragma once |  | ||||||
| #include <string> |  | ||||||
| #include <unordered_map> |  | ||||||
| #include <functional> |  | ||||||
| #include <optional> |  | ||||||
| #include <vector> |  | ||||||
| #include "dbc.hpp" |  | ||||||
| 
 |  | ||||||
| namespace lel { |  | ||||||
| 
 |  | ||||||
|   struct Cell { |  | ||||||
|     int x = 0; |  | ||||||
|     int y = 0; |  | ||||||
|     int w = 0; |  | ||||||
|     int h = 0; |  | ||||||
|     int mid_x = 0; |  | ||||||
|     int mid_y = 0; |  | ||||||
|     int max_w = 0; |  | ||||||
|     int max_h = 0; |  | ||||||
|     int col = 0; |  | ||||||
|     int row = 0; |  | ||||||
|     bool right = false; |  | ||||||
|     bool bottom = false; |  | ||||||
|     bool expand = false; |  | ||||||
|     bool center = false; |  | ||||||
|     bool percent = false; |  | ||||||
| 
 |  | ||||||
|     Cell(int col, int row) : col(col), row(row) {} |  | ||||||
|     Cell() {} |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   using Row = std::vector<std::string>; |  | ||||||
|   using CellMap = std::unordered_map<std::string, Cell>; |  | ||||||
| 
 |  | ||||||
|   struct Parser { |  | ||||||
|     int grid_x = 0; |  | ||||||
|     int grid_y = 0; |  | ||||||
|     int grid_w = 0; |  | ||||||
|     int grid_h = 0; |  | ||||||
|     Cell cur; |  | ||||||
|     std::vector<Row> grid; |  | ||||||
|     CellMap cells; |  | ||||||
| 
 |  | ||||||
|     Parser(int x, int y, int width, int height); |  | ||||||
|     Parser(); |  | ||||||
| 
 |  | ||||||
|     void position(int x, int y, int width, int height); |  | ||||||
|     void id(std::string name); |  | ||||||
|     void reset(); |  | ||||||
|     bool parse(std::string input); |  | ||||||
|     void finalize(); |  | ||||||
|     std::optional<std::string> hit(int x, int y); |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   Cell center(int width, int height, Cell &parent); |  | ||||||
| } |  | ||||||
							
								
								
									
										263
									
								
								lel_parser.cpp
									
										
									
									
									
								
							
							
						
						
									
										263
									
								
								lel_parser.cpp
									
										
									
									
									
								
							|  | @ -1,263 +0,0 @@ | ||||||
| 
 |  | ||||||
| #line 1 "lel_parser.rl" |  | ||||||
| /***** !!!!!! THIS IS INCLUDED BY lel.cpp DO NOT PUT IN BUILD!!!!!! ******/ |  | ||||||
| 
 |  | ||||||
| #include "lel.hpp" |  | ||||||
| #include <fmt/core.h> |  | ||||||
| #include <iostream> |  | ||||||
| 
 |  | ||||||
| namespace lel { |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #line 42 "lel_parser.rl" |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #line 12 "lel_parser.cpp" |  | ||||||
| static const char _Parser_actions[] = { |  | ||||||
| 	0, 1, 1, 1, 2, 1, 3, 1,  |  | ||||||
| 	4, 1, 5, 1, 6, 1, 9, 1,  |  | ||||||
| 	10, 1, 11, 1, 12, 1, 13, 2,  |  | ||||||
| 	0, 7, 2, 0, 8, 2, 4, 1,  |  | ||||||
| 	2, 4, 5 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const char _Parser_key_offsets[] = { |  | ||||||
| 	0, 0, 4, 20, 33, 35, 39, 41,  |  | ||||||
| 	44, 56, 61 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const char _Parser_trans_keys[] = { |  | ||||||
| 	32, 91, 9, 13, 32, 37, 40, 42,  |  | ||||||
| 	46, 61, 94, 95, 9, 13, 60, 62,  |  | ||||||
| 	65, 90, 97, 122, 37, 40, 42, 46,  |  | ||||||
| 	61, 94, 95, 60, 62, 65, 90, 97,  |  | ||||||
| 	122, 48, 57, 41, 44, 48, 57, 48,  |  | ||||||
| 	57, 41, 48, 57, 32, 93, 95, 124,  |  | ||||||
| 	9, 13, 48, 57, 65, 90, 97, 122,  |  | ||||||
| 	32, 93, 124, 9, 13, 32, 91, 9,  |  | ||||||
| 	13, 0 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const char _Parser_single_lengths[] = { |  | ||||||
| 	0, 2, 8, 7, 0, 2, 0, 1,  |  | ||||||
| 	4, 3, 2 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const char _Parser_range_lengths[] = { |  | ||||||
| 	0, 1, 4, 3, 1, 1, 1, 1,  |  | ||||||
| 	4, 1, 1 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const char _Parser_index_offsets[] = { |  | ||||||
| 	0, 0, 4, 17, 28, 30, 34, 36,  |  | ||||||
| 	39, 48, 53 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const char _Parser_indicies[] = { |  | ||||||
| 	0, 2, 0, 1, 3, 4, 5, 6,  |  | ||||||
| 	7, 9, 7, 10, 3, 8, 10, 10,  |  | ||||||
| 	1, 4, 5, 6, 7, 9, 7, 10,  |  | ||||||
| 	8, 10, 10, 1, 11, 1, 12, 13,  |  | ||||||
| 	14, 1, 15, 1, 16, 17, 1, 18,  |  | ||||||
| 	20, 19, 21, 18, 19, 19, 19, 1,  |  | ||||||
| 	22, 23, 24, 22, 1, 25, 2, 25,  |  | ||||||
| 	1, 0 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const char _Parser_trans_targs[] = { |  | ||||||
| 	1, 0, 2, 2, 3, 4, 3, 3,  |  | ||||||
| 	3, 3, 8, 5, 3, 6, 5, 7,  |  | ||||||
| 	3, 7, 9, 8, 10, 2, 9, 10,  |  | ||||||
| 	2, 10 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const char _Parser_trans_actions[] = { |  | ||||||
| 	0, 0, 3, 0, 17, 0, 13, 5,  |  | ||||||
| 	11, 15, 21, 19, 23, 23, 0, 19,  |  | ||||||
| 	26, 0, 7, 0, 32, 29, 0, 9,  |  | ||||||
| 	1, 0 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const int Parser_start = 1; |  | ||||||
| static const int Parser_first_final = 10; |  | ||||||
| static const int Parser_error = 0; |  | ||||||
| 
 |  | ||||||
| static const int Parser_en_main = 1; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #line 45 "lel_parser.rl" |  | ||||||
| 
 |  | ||||||
| bool Parser::parse(std::string input) { |  | ||||||
|   reset(); |  | ||||||
|   int cs = 0; |  | ||||||
|   const char *start = nullptr; |  | ||||||
|   const char *begin = input.data(); |  | ||||||
|   const char *p = input.data(); |  | ||||||
|   const char *pe = p + input.size(); |  | ||||||
|   std::string tk; |  | ||||||
| 
 |  | ||||||
|    |  | ||||||
| #line 93 "lel_parser.cpp" |  | ||||||
| 	{ |  | ||||||
| 	cs = Parser_start; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| #line 56 "lel_parser.rl" |  | ||||||
|    |  | ||||||
| #line 96 "lel_parser.cpp" |  | ||||||
| 	{ |  | ||||||
| 	int _klen; |  | ||||||
| 	unsigned int _trans; |  | ||||||
| 	const char *_acts; |  | ||||||
| 	unsigned int _nacts; |  | ||||||
| 	const char *_keys; |  | ||||||
| 
 |  | ||||||
| 	if ( p == pe ) |  | ||||||
| 		goto _test_eof; |  | ||||||
| 	if ( cs == 0 ) |  | ||||||
| 		goto _out; |  | ||||||
| _resume: |  | ||||||
| 	_keys = _Parser_trans_keys + _Parser_key_offsets[cs]; |  | ||||||
| 	_trans = _Parser_index_offsets[cs]; |  | ||||||
| 
 |  | ||||||
| 	_klen = _Parser_single_lengths[cs]; |  | ||||||
| 	if ( _klen > 0 ) { |  | ||||||
| 		const char *_lower = _keys; |  | ||||||
| 		const char *_mid; |  | ||||||
| 		const char *_upper = _keys + _klen - 1; |  | ||||||
| 		while (1) { |  | ||||||
| 			if ( _upper < _lower ) |  | ||||||
| 				break; |  | ||||||
| 
 |  | ||||||
| 			_mid = _lower + ((_upper-_lower) >> 1); |  | ||||||
| 			if ( (*p) < *_mid ) |  | ||||||
| 				_upper = _mid - 1; |  | ||||||
| 			else if ( (*p) > *_mid ) |  | ||||||
| 				_lower = _mid + 1; |  | ||||||
| 			else { |  | ||||||
| 				_trans += (unsigned int)(_mid - _keys); |  | ||||||
| 				goto _match; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		_keys += _klen; |  | ||||||
| 		_trans += _klen; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	_klen = _Parser_range_lengths[cs]; |  | ||||||
| 	if ( _klen > 0 ) { |  | ||||||
| 		const char *_lower = _keys; |  | ||||||
| 		const char *_mid; |  | ||||||
| 		const char *_upper = _keys + (_klen<<1) - 2; |  | ||||||
| 		while (1) { |  | ||||||
| 			if ( _upper < _lower ) |  | ||||||
| 				break; |  | ||||||
| 
 |  | ||||||
| 			_mid = _lower + (((_upper-_lower) >> 1) & ~1); |  | ||||||
| 			if ( (*p) < _mid[0] ) |  | ||||||
| 				_upper = _mid - 2; |  | ||||||
| 			else if ( (*p) > _mid[1] ) |  | ||||||
| 				_lower = _mid + 2; |  | ||||||
| 			else { |  | ||||||
| 				_trans += (unsigned int)((_mid - _keys)>>1); |  | ||||||
| 				goto _match; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		_trans += _klen; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| _match: |  | ||||||
| 	_trans = _Parser_indicies[_trans]; |  | ||||||
| 	cs = _Parser_trans_targs[_trans]; |  | ||||||
| 
 |  | ||||||
| 	if ( _Parser_trans_actions[_trans] == 0 ) |  | ||||||
| 		goto _again; |  | ||||||
| 
 |  | ||||||
| 	_acts = _Parser_actions + _Parser_trans_actions[_trans]; |  | ||||||
| 	_nacts = (unsigned int) *_acts++; |  | ||||||
| 	while ( _nacts-- > 0 ) |  | ||||||
| 	{ |  | ||||||
| 		switch ( *_acts++ ) |  | ||||||
| 		{ |  | ||||||
| 	case 0: |  | ||||||
| #line 13 "lel_parser.rl" |  | ||||||
| 	{tk = input.substr(start - begin, p - start); } |  | ||||||
| 	break; |  | ||||||
| 	case 1: |  | ||||||
| #line 15 "lel_parser.rl" |  | ||||||
| 	{} |  | ||||||
| 	break; |  | ||||||
| 	case 2: |  | ||||||
| #line 16 "lel_parser.rl" |  | ||||||
| 	{ grid.push_back(Row()); } |  | ||||||
| 	break; |  | ||||||
| 	case 3: |  | ||||||
| #line 17 "lel_parser.rl" |  | ||||||
| 	{ cur.bottom = (*p) == '.'; } |  | ||||||
| 	break; |  | ||||||
| 	case 4: |  | ||||||
| #line 18 "lel_parser.rl" |  | ||||||
| 	{ id(input.substr(start - begin, p - start)); } |  | ||||||
| 	break; |  | ||||||
| 	case 5: |  | ||||||
| #line 19 "lel_parser.rl" |  | ||||||
| 	{ cur.col = 0; cur.row++; } |  | ||||||
| 	break; |  | ||||||
| 	case 6: |  | ||||||
| #line 20 "lel_parser.rl" |  | ||||||
| 	{ cur.right = (*p) == '>'; } |  | ||||||
| 	break; |  | ||||||
| 	case 7: |  | ||||||
| #line 21 "lel_parser.rl" |  | ||||||
| 	{cur.max_w = std::stoi(tk); } |  | ||||||
| 	break; |  | ||||||
| 	case 8: |  | ||||||
| #line 22 "lel_parser.rl" |  | ||||||
| 	{ cur.max_h = std::stoi(tk); } |  | ||||||
| 	break; |  | ||||||
| 	case 9: |  | ||||||
| #line 23 "lel_parser.rl" |  | ||||||
| 	{ cur.expand = true; } |  | ||||||
| 	break; |  | ||||||
| 	case 10: |  | ||||||
| #line 24 "lel_parser.rl" |  | ||||||
| 	{ cur.center = true; } |  | ||||||
| 	break; |  | ||||||
| 	case 11: |  | ||||||
| #line 25 "lel_parser.rl" |  | ||||||
| 	{ cur.percent = true; } |  | ||||||
| 	break; |  | ||||||
| 	case 12: |  | ||||||
| #line 35 "lel_parser.rl" |  | ||||||
| 	{ start = p; } |  | ||||||
| 	break; |  | ||||||
| 	case 13: |  | ||||||
| #line 38 "lel_parser.rl" |  | ||||||
| 	{start = p;} |  | ||||||
| 	break; |  | ||||||
| #line 211 "lel_parser.cpp" |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| _again: |  | ||||||
| 	if ( cs == 0 ) |  | ||||||
| 		goto _out; |  | ||||||
| 	if ( ++p != pe ) |  | ||||||
| 		goto _resume; |  | ||||||
| 	_test_eof: {} |  | ||||||
| 	_out: {} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| #line 57 "lel_parser.rl" |  | ||||||
| 
 |  | ||||||
|   bool good = pe - p == 0; |  | ||||||
|   if(good) { |  | ||||||
|     finalize(); |  | ||||||
|   } else { |  | ||||||
|     dbc::log("error at:"); |  | ||||||
|     std::cout << p; |  | ||||||
|   } |  | ||||||
|   return good; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
|  | @ -1,68 +0,0 @@ | ||||||
| /***** !!!!!! THIS IS INCLUDED BY lel.cpp DO NOT PUT IN BUILD!!!!!! ******/ |  | ||||||
| 
 |  | ||||||
| #include "lel.hpp" |  | ||||||
| #include <fmt/core.h> |  | ||||||
| #include <iostream> |  | ||||||
| 
 |  | ||||||
| namespace lel { |  | ||||||
| 
 |  | ||||||
| %%{ |  | ||||||
|   machine Parser; |  | ||||||
|   alphtype char; |  | ||||||
| 
 |  | ||||||
|   action token {tk = input.substr(start - begin, fpc - start); } |  | ||||||
| 
 |  | ||||||
|   action col {} |  | ||||||
|   action ltab { grid.push_back(Row()); } |  | ||||||
|   action valign { cur.bottom = fc == '.'; } |  | ||||||
|   action id { id(input.substr(start - begin, fpc - start)); } |  | ||||||
|   action row { cur.col = 0; cur.row++; } |  | ||||||
|   action align { cur.right = fc == '>'; } |  | ||||||
|   action setwidth {cur.max_w = std::stoi(tk); } |  | ||||||
|   action setheight { cur.max_h = std::stoi(tk); } |  | ||||||
|   action expand { cur.expand = true; } |  | ||||||
|   action center { cur.center = true; } |  | ||||||
|   action percent { cur.percent = true; } |  | ||||||
| 
 |  | ||||||
|   col = "|" $col; |  | ||||||
|   ltab = "[" $ltab; |  | ||||||
|   rtab = "]" $row; |  | ||||||
|   valign = ("^" | ".") $valign; |  | ||||||
|   expand = "*" $expand; |  | ||||||
|   center = "=" $center; |  | ||||||
|   percent = "%" $percent; |  | ||||||
|   halign = ("<" | ">") $align; |  | ||||||
|   number =  digit+ >{ start = fpc; } %token; |  | ||||||
|   setw = ("(" number %setwidth ("," number %setheight)? ")") ; |  | ||||||
|   modifiers = (percent | center | expand | valign | halign | setw); |  | ||||||
|   id = modifiers* ((alpha | '_')+ :>> (alnum | '_')*) >{start = fpc;} %id; |  | ||||||
|   row = space* ltab space* id space* (col space* id space*)* space* rtab space*; |  | ||||||
| 
 |  | ||||||
|   main := row+; |  | ||||||
| }%% |  | ||||||
| 
 |  | ||||||
| %% write data; |  | ||||||
| 
 |  | ||||||
| bool Parser::parse(std::string input) { |  | ||||||
|   reset(); |  | ||||||
|   int cs = 0; |  | ||||||
|   const char *start = nullptr; |  | ||||||
|   const char *begin = input.data(); |  | ||||||
|   const char *p = input.data(); |  | ||||||
|   const char *pe = p + input.size(); |  | ||||||
|   std::string tk; |  | ||||||
| 
 |  | ||||||
|   %% write init; |  | ||||||
|   %% write exec; |  | ||||||
| 
 |  | ||||||
|   bool good = pe - p == 0; |  | ||||||
|   if(good) { |  | ||||||
|     finalize(); |  | ||||||
|   } else { |  | ||||||
|     dbc::log("error at:"); |  | ||||||
|     std::cout << p; |  | ||||||
|   } |  | ||||||
|   return good; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
							
								
								
									
										29
									
								
								main.cpp
									
										
									
									
									
								
							
							
						
						
									
										29
									
								
								main.cpp
									
										
									
									
									
								
							|  | @ -1,3 +1,5 @@ | ||||||
|  | #include "backend.hpp" | ||||||
|  | #include "guecs/sfml/components.hpp" | ||||||
| #include "builder.hpp" | #include "builder.hpp" | ||||||
| #include "gui.hpp" | #include "gui.hpp" | ||||||
| #include "config.hpp" | #include "config.hpp" | ||||||
|  | @ -12,9 +14,11 @@ int main(int argc, char *argv[]) | ||||||
| { | { | ||||||
|   int opt = 0; |   int opt = 0; | ||||||
|   int timer_seconds = 60 * 60; |   int timer_seconds = 60 * 60; | ||||||
|  |   int start_hp = 100; | ||||||
|  |   int max_hp = 100; | ||||||
|   std::wstring goal{L"No Goal"}; |   std::wstring goal{L"No Goal"}; | ||||||
| 
 | 
 | ||||||
|   while((opt = getopt(argc, argv, "t:c:g:")) != -1) { |   while((opt = getopt(argc, argv, "ht:c:g:H:M:")) != -1) { | ||||||
|     switch(opt) { |     switch(opt) { | ||||||
|       case 't': |       case 't': | ||||||
|         timer_seconds = atoi(optarg) * 60; |         timer_seconds = atoi(optarg) * 60; | ||||||
|  | @ -23,18 +27,27 @@ int main(int argc, char *argv[]) | ||||||
|       case 'c': |       case 'c': | ||||||
|         Config::set_base_dir(optarg); |         Config::set_base_dir(optarg); | ||||||
|         break; |         break; | ||||||
|       case 'g': |       case 'g': { | ||||||
|         std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; |           std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; | ||||||
|         goal = converter.from_bytes(optarg); |           goal = converter.from_bytes(optarg); | ||||||
|  |         } break; | ||||||
|  |       case 'H': { | ||||||
|  |           start_hp = std::atoi(optarg); | ||||||
|  |         } break; | ||||||
|  |       case 'M': { | ||||||
|  |           max_hp = std::atoi(optarg); | ||||||
|  |         } break; | ||||||
|  |       case 'h': | ||||||
|  |         fmt::println("USAGE: ttpit [-t time] [-c config_dir] [-g goal] [-H hp] [-M max_hp]"); | ||||||
|  |         return 0; | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   sound::init(); |   sfml::Backend backend; | ||||||
|   shaders::init(); |   guecs::init(&backend); | ||||||
|   textures::init(); |  | ||||||
| 
 | 
 | ||||||
|   GameEngine game{100}; |   GameEngine game{start_hp, max_hp}; | ||||||
|   GUI gui(timer_seconds, goal); |   GUI gui(timer_seconds, goal); | ||||||
|   auto builder = Builder(gui, game); |   auto builder = Builder(gui, game); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								meson.build
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								meson.build
									
										
									
									
									
								
							|  | @ -1,7 +1,7 @@ | ||||||
| # clang might need _LIBCPP_ENABLE_CXX26_REMOVED_CODECVT | # clang might need _LIBCPP_ENABLE_CXX26_REMOVED_CODECVT | ||||||
| 
 | 
 | ||||||
| project('turings-tarpit', 'cpp', | project('turings-tarpit', 'cpp', | ||||||
|   version: '0.1.0', |   version: '0.2.0', | ||||||
|   default_options: [ |   default_options: [ | ||||||
|     'cpp_std=c++20', |     'cpp_std=c++20', | ||||||
|     'cpp_args=-D_GLIBCXX_DEBUG=1 -D_GLIBCXX_DEBUG_PEDANTIC=1', |     'cpp_args=-D_GLIBCXX_DEBUG=1 -D_GLIBCXX_DEBUG_PEDANTIC=1', | ||||||
|  | @ -69,6 +69,7 @@ sfml_network = dependency('sfml_network') | ||||||
| sfml_system = dependency('sfml_system') | sfml_system = dependency('sfml_system') | ||||||
| sfml_window = dependency('sfml_window', | sfml_window = dependency('sfml_window', | ||||||
|   default_options: ['default_library=shared']) |   default_options: ['default_library=shared']) | ||||||
|  | lel_guecs = dependency('lel_guecs') | ||||||
| 
 | 
 | ||||||
| cmake = import('cmake') | cmake = import('cmake') | ||||||
| opts = cmake.subproject_options() | opts = cmake.subproject_options() | ||||||
|  | @ -89,23 +90,22 @@ dependencies += [ | ||||||
|   flac, ogg, vorbis, vorbisfile, vorbisenc, |   flac, ogg, vorbis, vorbisfile, vorbisenc, | ||||||
|   sfml_audio, sfml_graphics, |   sfml_audio, sfml_graphics, | ||||||
|   sfml_network, sfml_system, |   sfml_network, sfml_system, | ||||||
|   sfml_window, libgit2package, efsw |   sfml_window, libgit2package, efsw, lel_guecs | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| sources = [ | sources = [ | ||||||
|     'builder.cpp', |     'builder.cpp', | ||||||
|     'config.cpp', |     'config.cpp', | ||||||
|     'dbc.cpp', |  | ||||||
|     'game_engine.cpp', |     'game_engine.cpp', | ||||||
|     'guecs.cpp', |  | ||||||
|     'gui.cpp', |     'gui.cpp', | ||||||
|     'lel.cpp', |  | ||||||
|     'matrix.cpp', |     'matrix.cpp', | ||||||
|     'rand.cpp', |     'rand.cpp', | ||||||
|     'shaders.cpp', |     'shaders.cpp', | ||||||
|     'sound.cpp', |     'sound.cpp', | ||||||
|  |     'dbc.cpp', | ||||||
|     'textures.cpp', |     'textures.cpp', | ||||||
|     'watcher.cpp', |     'watcher.cpp', | ||||||
|  |     'backend.cpp', | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| executable('ttpit', sources + [ | executable('ttpit', sources + [ | ||||||
|  | @ -119,7 +119,6 @@ executable('ttpit', sources + [ | ||||||
| executable('runtests', sources + [ | executable('runtests', sources + [ | ||||||
|   'tests/game_engine.cpp', |   'tests/game_engine.cpp', | ||||||
|   'tests/fsm.cpp', |   'tests/fsm.cpp', | ||||||
|   'tests/dbc.cpp', |  | ||||||
|   ], |   ], | ||||||
|   cpp_args: cpp_args, |   cpp_args: cpp_args, | ||||||
|   link_args: link_args, |   link_args: link_args, | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								shaders.cpp
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								shaders.cpp
									
										
									
									
									
								
							|  | @ -1,8 +1,8 @@ | ||||||
| #include "shaders.hpp" | #include "guecs/sfml/shaders.hpp" | ||||||
| #include <SFML/Graphics/Image.hpp> | #include "guecs/sfml/config.hpp" | ||||||
| #include "dbc.hpp" | #include "dbc.hpp" | ||||||
|  | #include <SFML/Graphics/Image.hpp> | ||||||
| #include <fmt/core.h> | #include <fmt/core.h> | ||||||
| #include "config.hpp" |  | ||||||
| #include <memory> | #include <memory> | ||||||
| 
 | 
 | ||||||
| namespace shaders { | namespace shaders { | ||||||
|  | @ -18,10 +18,8 @@ namespace shaders { | ||||||
| 
 | 
 | ||||||
|   bool load_shader(std::string name, nlohmann::json& settings) { |   bool load_shader(std::string name, nlohmann::json& settings) { | ||||||
|     std::string file_name = settings["file_name"]; |     std::string file_name = settings["file_name"]; | ||||||
| 
 |  | ||||||
|     auto ptr = std::make_shared<sf::Shader>(); |     auto ptr = std::make_shared<sf::Shader>(); | ||||||
|     bool good = ptr->loadFromFile(Config::path_to(file_name), |     bool good = ptr->loadFromFile(file_name, sf::Shader::Type::Fragment); | ||||||
|         sf::Shader::Type::Fragment); |  | ||||||
| 
 | 
 | ||||||
|     if(good) { |     if(good) { | ||||||
|       configure_shader_defaults(ptr); |       configure_shader_defaults(ptr); | ||||||
|  |  | ||||||
|  | @ -5,7 +5,6 @@ | ||||||
| #include <SFML/Graphics.hpp> | #include <SFML/Graphics.hpp> | ||||||
| #include <unordered_map> | #include <unordered_map> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include "matrix.hpp" |  | ||||||
| #include <nlohmann/json.hpp> | #include <nlohmann/json.hpp> | ||||||
| 
 | 
 | ||||||
| namespace shaders { | namespace shaders { | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								sound.cpp
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								sound.cpp
									
										
									
									
									
								
							|  | @ -1,7 +1,7 @@ | ||||||
| #include "sound.hpp" | #include "guecs/sfml/sound.hpp" | ||||||
|  | #include "guecs/sfml/config.hpp" | ||||||
| #include "dbc.hpp" | #include "dbc.hpp" | ||||||
| #include <fmt/core.h> | #include <fmt/core.h> | ||||||
| #include "config.hpp" |  | ||||||
| 
 | 
 | ||||||
| namespace sound { | namespace sound { | ||||||
|   static SoundManager SMGR; |   static SoundManager SMGR; | ||||||
|  | @ -28,7 +28,7 @@ namespace sound { | ||||||
| 
 | 
 | ||||||
|   void init() { |   void init() { | ||||||
|     if(!initialized) { |     if(!initialized) { | ||||||
|       Config assets("./assets/config.json"); |       Config assets("assets/config.json"); | ||||||
| 
 | 
 | ||||||
|       for(auto& el : assets["sounds"].items()) { |       for(auto& el : assets["sounds"].items()) { | ||||||
|         load(el.key(), el.value()); |         load(el.key(), el.value()); | ||||||
|  | @ -38,11 +38,10 @@ namespace sound { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   void load(const std::string& name, const std::string& sound_path) { |   void load(const std::string& name, const std::string& sound_path) { | ||||||
|     dbc::check(fs::exists(Config::path_to(sound_path)), |     dbc::check(fs::exists(sound_path), fmt::format("sound file {} does not exist", sound_path)); | ||||||
|         fmt::format("sound file {} does not exist", sound_path)); |  | ||||||
| 
 | 
 | ||||||
|     // create the buffer and keep in the buffer map
 |     // create the buffer and keep in the buffer map
 | ||||||
|     auto buffer = make_shared<sf::SoundBuffer>(Config::path_to(sound_path)); |     auto buffer = make_shared<sf::SoundBuffer>(sound_path); | ||||||
| 
 | 
 | ||||||
|     // set it on the sound and keep in the sound map
 |     // set it on the sound and keep in the sound map
 | ||||||
|     auto sound = make_shared<sf::Sound>(*buffer); |     auto sound = make_shared<sf::Sound>(*buffer); | ||||||
|  |  | ||||||
|  | @ -1,39 +0,0 @@ | ||||||
| #include <catch2/catch_test_macros.hpp> |  | ||||||
| #include "dbc.hpp" |  | ||||||
| 
 |  | ||||||
| using namespace dbc; |  | ||||||
| 
 |  | ||||||
| TEST_CASE("basic feature tests", "[utils]") { |  | ||||||
|   log("Logging a message."); |  | ||||||
| 
 |  | ||||||
|   try { |  | ||||||
|     sentinel("This shouldn't happen."); |  | ||||||
|   } catch(SentinelError) { |  | ||||||
|     log("Sentinel happened."); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   pre("confirm positive cases work", 1 == 1); |  | ||||||
|   pre("confirm positive lambda", [&]{ return 1 == 1;}); |  | ||||||
|   post("confirm positive post", 1 == 1); |  | ||||||
|   post("confirm postitive post with lamdba", [&]{ return 1 == 1;}); |  | ||||||
| 
 |  | ||||||
|   check(1 == 1, "one equals 1"); |  | ||||||
| 
 |  | ||||||
|   try { |  | ||||||
|     check(1 == 2, "this should fail"); |  | ||||||
|   } catch(CheckError err) { |  | ||||||
|     log("check fail worked"); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   try { |  | ||||||
|     pre("failing pre", 1 == 3); |  | ||||||
|   } catch(PreCondError err) { |  | ||||||
|     log("pre fail worked"); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   try { |  | ||||||
|     post("failing post", 1 == 4); |  | ||||||
|   } catch(PostCondError err) { |  | ||||||
|     log("post faile worked"); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  | @ -6,7 +6,7 @@ using namespace fmt; | ||||||
| 
 | 
 | ||||||
| TEST_CASE("game engine death cycle", "[game_engine]") { | TEST_CASE("game engine death cycle", "[game_engine]") { | ||||||
|   // test fails on purpose right now
 |   // test fails on purpose right now
 | ||||||
|   GameEngine game{4}; |   GameEngine game{4, 4}; | ||||||
| 
 | 
 | ||||||
|   for(int i = 0; i < 4; i++) { |   for(int i = 0; i < 4; i++) { | ||||||
|     game.event(GameEvent::BUILD_START); |     game.event(GameEvent::BUILD_START); | ||||||
|  | @ -36,7 +36,7 @@ TEST_CASE("game engine death cycle", "[game_engine]") { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_CASE("game can do success build", "[game_engine]") { | TEST_CASE("game can do success build", "[game_engine]") { | ||||||
|   GameEngine game{10}; |   GameEngine game{10, 10}; | ||||||
| 
 | 
 | ||||||
|   // test fails on purpose right now
 |   // test fails on purpose right now
 | ||||||
|   for(int i = 0; i < 10; i++) { |   for(int i = 0; i < 10; i++) { | ||||||
|  |  | ||||||
							
								
								
									
										45
									
								
								textures.cpp
									
										
									
									
									
								
							
							
						
						
									
										45
									
								
								textures.cpp
									
										
									
									
									
								
							|  | @ -1,8 +1,8 @@ | ||||||
| #include "textures.hpp" |  | ||||||
| #include <SFML/Graphics/Image.hpp> |  | ||||||
| #include "dbc.hpp" | #include "dbc.hpp" | ||||||
| #include <fmt/core.h> | #include "textures.hpp" | ||||||
| #include "config.hpp" | #include "config.hpp" | ||||||
|  | #include <SFML/Graphics/Image.hpp> | ||||||
|  | #include <fmt/core.h> | ||||||
| #include <memory> | #include <memory> | ||||||
| 
 | 
 | ||||||
| namespace textures { | namespace textures { | ||||||
|  | @ -15,7 +15,7 @@ namespace textures { | ||||||
|     Config assets("assets/config.json"); |     Config assets("assets/config.json"); | ||||||
| 
 | 
 | ||||||
|     for(auto& [name, settings] : assets["sprites"].items()) { |     for(auto& [name, settings] : assets["sprites"].items()) { | ||||||
|       auto texture = make_shared<sf::Texture>(Config::path_to(settings["path"])); |       auto texture = make_shared<sf::Texture>(settings["path"]); | ||||||
| 
 | 
 | ||||||
|       texture->setSmooth(assets["graphics"]["smooth_textures"]); |       texture->setSmooth(assets["graphics"]["smooth_textures"]); | ||||||
|       auto sprite = make_shared<sf::Sprite>(*texture); |       auto sprite = make_shared<sf::Sprite>(*texture); | ||||||
|  | @ -24,32 +24,18 @@ namespace textures { | ||||||
|       int height = settings["frame_height"]; |       int height = settings["frame_height"]; | ||||||
|       sprite->setTextureRect({{0,0}, {width, height}}); |       sprite->setTextureRect({{0,0}, {width, height}}); | ||||||
| 
 | 
 | ||||||
|       TMGR.sprite_textures.try_emplace(name, name, sprite, texture); |       TMGR.sprite_textures.try_emplace(name, sprite, texture); | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   void load_tiles() { |  | ||||||
|     Config assets("assets/tiles.json"); |  | ||||||
|     auto &tiles = assets.json(); |  | ||||||
| 
 |  | ||||||
|     for(auto &el : tiles.items()) { |  | ||||||
|       auto &config = el.value(); |  | ||||||
|       TMGR.surfaces.emplace_back(load_image(config["texture"])); |  | ||||||
|       wchar_t tid = config["display"]; |  | ||||||
|       int surface_i = TMGR.surfaces.size() - 1; |  | ||||||
|       TMGR.char_to_texture[tid] = surface_i; |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   void init() { |   void init() { | ||||||
|     if(!initialized) { |     if(!initialized) { | ||||||
|       load_tiles(); |  | ||||||
|       load_sprites(); |       load_sprites(); | ||||||
|       initialized = true; |       initialized = true; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   SpriteTexture get(std::string name) { |   SpriteTexture get(const std::string& name) { | ||||||
|     dbc::check(initialized, "you forgot to call textures::init()"); |     dbc::check(initialized, "you forgot to call textures::init()"); | ||||||
|     dbc::check(TMGR.sprite_textures.contains(name), |     dbc::check(TMGR.sprite_textures.contains(name), | ||||||
|         fmt::format("!!!!! texture pack does not contain {} sprite", name)); |         fmt::format("!!!!! texture pack does not contain {} sprite", name)); | ||||||
|  | @ -64,25 +50,10 @@ namespace textures { | ||||||
|     return result; |     return result; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   sf::Image load_image(std::string filename) { |   sf::Image load_image(const std::string& filename) { | ||||||
|     sf::Image texture; |     sf::Image texture; | ||||||
|     bool good = texture.loadFromFile(Config::path_to(filename)); |     bool good = texture.loadFromFile(filename); | ||||||
|     dbc::check(good, fmt::format("failed to load {}", filename)); |     dbc::check(good, fmt::format("failed to load {}", filename)); | ||||||
|     return texture; |     return texture; | ||||||
|   } |   } | ||||||
| 
 |  | ||||||
|   const uint32_t* get_surface(size_t num) { |  | ||||||
|     return (const uint32_t *)TMGR.surfaces[num].getPixelsPtr(); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   matrix::Matrix convert_char_to_texture(matrix::Matrix &tile_ids) { |  | ||||||
|     auto result = matrix::make(matrix::width(tile_ids), matrix::height(tile_ids)); |  | ||||||
| 
 |  | ||||||
|     for(matrix::each_cell it(tile_ids); it.next();) { |  | ||||||
|       wchar_t tid = tile_ids[it.y][it.x]; |  | ||||||
|       result[it.y][it.x] = TMGR.char_to_texture.at(tid); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
|   } |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
							
								
								
									
										10
									
								
								textures.hpp
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								textures.hpp
									
										
									
									
									
								
							|  | @ -5,12 +5,10 @@ | ||||||
| #include <SFML/Graphics.hpp> | #include <SFML/Graphics.hpp> | ||||||
| #include <unordered_map> | #include <unordered_map> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include "matrix.hpp" |  | ||||||
| 
 | 
 | ||||||
| namespace textures { | namespace textures { | ||||||
| 
 | 
 | ||||||
|   struct SpriteTexture { |   struct SpriteTexture { | ||||||
|     std::string name; |  | ||||||
|     std::shared_ptr<sf::Sprite> sprite = nullptr; |     std::shared_ptr<sf::Sprite> sprite = nullptr; | ||||||
|     std::shared_ptr<sf::Texture> texture = nullptr; |     std::shared_ptr<sf::Texture> texture = nullptr; | ||||||
|   }; |   }; | ||||||
|  | @ -23,11 +21,7 @@ namespace textures { | ||||||
| 
 | 
 | ||||||
|   void init(); |   void init(); | ||||||
| 
 | 
 | ||||||
|   SpriteTexture get(std::string name); |   SpriteTexture get(const std::string& name); | ||||||
| 
 | 
 | ||||||
|   sf::Image load_image(std::string filename); |   sf::Image load_image(const std::string& filename); | ||||||
| 
 |  | ||||||
|   const uint32_t* get_surface(size_t num); |  | ||||||
| 
 |  | ||||||
|   matrix::Matrix convert_char_to_texture(matrix::Matrix &from); |  | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										9
									
								
								wraps/lel-guecs.wrap
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								wraps/lel-guecs.wrap
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | [wrap-git] | ||||||
|  | directory=lel-guecs-0.2.0 | ||||||
|  | url=https://git.learnjsthehardway.com/learn-code-the-hard-way/lel-guecs.git | ||||||
|  | revision=HEAD | ||||||
|  | depth=1 | ||||||
|  | method=meson | ||||||
|  | 
 | ||||||
|  | [provide] | ||||||
|  | lel_guecs = lel_guecs_dep | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| [wrap-git] | [wrap-git] | ||||||
| directory=SFML-3.0.0 | directory=SFML-3.0.1 | ||||||
| url=https://github.com/SFML/SFML.git | url=https://github.com/SFML/SFML.git | ||||||
| revision=3.0.0 | revision=3.0.1 | ||||||
| depth=1 | depth=1 | ||||||
| method=cmake | method=cmake | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Zed A. Shaw
						Zed A. Shaw