diff --git a/luprex/Makefile b/luprex/Makefile index 54ad7c25..d6bbcbae 100644 --- a/luprex/Makefile +++ b/luprex/Makefile @@ -10,6 +10,7 @@ CPP_FILES=\ cpp/idalloc.cpp\ cpp/globaldb.cpp\ cpp/table.cpp\ + cpp/gui.cpp\ cpp/animqueue.cpp\ cpp/source.cpp\ cpp/world.cpp\ diff --git a/luprex/cpp/animqueue.cpp b/luprex/cpp/animqueue.cpp index b9bffa3f..3767bcae 100644 --- a/luprex/cpp/animqueue.cpp +++ b/luprex/cpp/animqueue.cpp @@ -78,43 +78,6 @@ const util::XYZ &AnimQueue::get_xyz() const { return last.xyz_; } -void AnimView::update_from(const AnimQueue &queue) { - id_ = queue.get_id(); - graphic_ = queue.get_graphic(); - plane_ = queue.get_plane(); - xyz_ = queue.get_xyz(); - updated_ = true; -} - -AnimView *AnimViewMap::get_one(int64_t id) { - auto iter = find(id); - if (iter == end()) { - return nullptr; - } else { - return &iter->second; - } -} - -void AnimViewMap::clear_updated_bits() { - for (auto pair : *this) { - pair.second.updated_ = false; - } -} - -void AnimViewMap::delete_non_updated() { - for (auto iter = begin(); iter != end(); ) { - if (iter->second.updated_) { - iter++; - } else { - iter = erase(iter); - } - } -} - -void AnimViewMap::update_one(const AnimQueue &queue) { - operator[](queue.get_id()).update_from(queue); -} - LuaDefine(unittests_animqueue, "c") { // Check initial state. AnimQueue aq; diff --git a/luprex/cpp/animqueue.hpp b/luprex/cpp/animqueue.hpp index d1fb265a..516caf27 100644 --- a/luprex/cpp/animqueue.hpp +++ b/luprex/cpp/animqueue.hpp @@ -77,7 +77,7 @@ private: int64_t id_; int size_limit_; std::deque steps_; -public: +public: AnimQueue(); int64_t get_id() const { return id_; } void set_id(int64_t id) { id_ = id; } @@ -100,35 +100,5 @@ public: void set_size_limit(int n); }; -class AnimView { - friend class AnimViewMap; -private: - int64_t id_; - std::string graphic_; - std::string plane_; - util::XYZ xyz_; - bool updated_; // Used by AnimViewMap. -public: - AnimView() : id_(0), updated_(true) {} - - int64_t get_id() const { return id_; } - const std::string &get_graphic() const { return graphic_; } - const std::string &get_plane() const { return plane_; } - const util::XYZ &get_xyz() const { return xyz_; } - - void update_from(const AnimQueue &queue); -}; - -// AnimViewMap: a unordered_map from tangible ID to AnimView. Adds a few -// methods for garbage collection and updating. -// -class AnimViewMap : public std::unordered_map { -public: - AnimView *get_one(int64_t id); - void clear_updated_bits(); - void delete_non_updated(); - void update_one(const AnimQueue &queue); -}; - #endif // ANIMQUEUE_HPP diff --git a/luprex/cpp/gui.cpp b/luprex/cpp/gui.cpp new file mode 100644 index 00000000..c5477553 --- /dev/null +++ b/luprex/cpp/gui.cpp @@ -0,0 +1,12 @@ +#include "gui.hpp" + +LuaDefineType(Gui); + +void Gui::add_menu_item(const std::string &id, const std::string &label) { + GuiElt elt; + elt.type_ = GuiElt::TYPE_MENU_ITEM; + elt.id_ = id; + elt.label_ = label; + elts_.push_back(elt); +} + diff --git a/luprex/cpp/gui.hpp b/luprex/cpp/gui.hpp new file mode 100644 index 00000000..fab78180 --- /dev/null +++ b/luprex/cpp/gui.hpp @@ -0,0 +1,39 @@ +#ifndef GUI_HPP +#define GUI_HPP + +#include +#include +#include "luastack.hpp" + +class GuiElt { + friend class Gui; +public: + enum Type { + TYPE_MENU_ITEM, + }; +private: + Type type_; + std::string id_; + std::string label_; + + GuiElt() {} +public: + ~GuiElt() {} + Type type() const { return type_; } + const std::string &id() const { return id_; } + const std::string &label() const { return label_; } +}; + +class Gui { +public: + using EltVec = std::vector; +private: + EltVec elts_; +public: + const EltVec &elts() const { return elts_; } + void clear() { elts_.clear(); } + void add_menu_item(const std::string &id, const std::string &label); +}; + +#endif // GUI_HPP + diff --git a/luprex/cpp/planemap.cpp b/luprex/cpp/planemap.cpp index e5da06ca..3baa673e 100644 --- a/luprex/cpp/planemap.cpp +++ b/luprex/cpp/planemap.cpp @@ -176,8 +176,11 @@ int PlaneMap::total_cells() const { return total; } -PlaneMap::IdVec PlaneMap::scan_radius(const std::string &plane, double x, double y, double radius) const { +PlaneMap::IdVec PlaneMap::scan_radius(const std::string &plane, double x, double y, double radius, int64_t prepend) const { PlaneMap::IdVec result; + if (prepend != 0) { + result.push_back(prepend); + } auto piter = planes_.find(plane); if (piter != planes_.end()) { const Plane &p = piter->second; @@ -189,7 +192,9 @@ PlaneMap::IdVec PlaneMap::scan_radius(const std::string &plane, double x, double if (liter != p.end()) { for (PlaneItem *client : liter->second) { if (util::distance_squared(client->x(), client->y(), x, y) <= radsq) { - result.push_back(client->id()); + if (client->id() != prepend) { + result.push_back(client->id()); + } } } } @@ -310,13 +315,13 @@ LuaDefine(unittests_planemap, "c") { pia.set_id(123); pib.set_id(456); pib.set_pos("bar", 1100.0, 1000.0, 0.0); - ids = pm.scan_radius("bar", 1000.0, 1000.0, 1.0); + ids = pm.scan_radius("bar", 1000.0, 1000.0, 1.0, 0); LuaAssert(L, ids.size() == 1); LuaAssert(L, ids[0] == 123); - ids = pm.scan_radius("bar", 1000.0, 1000.0, 99.9); + ids = pm.scan_radius("bar", 1000.0, 1000.0, 99.9, 0); LuaAssert(L, ids.size() == 1); LuaAssert(L, ids[0] == 123); - ids = pm.scan_radius("bar", 1000.0, 1000.0, 100.0); + ids = pm.scan_radius("bar", 1000.0, 1000.0, 100.0, 0); LuaAssert(L, ids.size() == 2); LuaAssert(L, ids[0] == 123); LuaAssert(L, ids[1] == 456); diff --git a/luprex/cpp/planemap.hpp b/luprex/cpp/planemap.hpp index a9ca4bfc..a5a25747 100644 --- a/luprex/cpp/planemap.hpp +++ b/luprex/cpp/planemap.hpp @@ -120,7 +120,7 @@ public: PlaneMap(); ~PlaneMap(); void track(PlaneItem *item); - IdVec scan_radius(const std::string &plane, double x, double y, double radius) const; + IdVec scan_radius(const std::string &plane, double x, double y, double radius, int64_t prepend) const; private: // unit testing stuff. diff --git a/luprex/cpp/textgame.cpp b/luprex/cpp/textgame.cpp index 714e69d1..952b7fca 100644 --- a/luprex/cpp/textgame.cpp +++ b/luprex/cpp/textgame.cpp @@ -8,6 +8,7 @@ #include #include "luastack.hpp" #include "util.hpp" +#include "gui.hpp" #include "viewer.hpp" #include "traceback.hpp" #include "textgame.hpp" @@ -81,11 +82,10 @@ void TextGame::do_view_command(const StringVec &cmd) { std::cerr << "v command (view) takes no arguments" << std::endl; return; } - viewer_.update_view_map(); - for (auto viewpair : viewer_.get_view_map()) { - int64_t id = viewpair.first; - AnimView &view = viewpair.second; - std::cerr << id << ": " << view.get_graphic() << " " << view.get_xyz() << std::endl; + for (int64_t id : viewer_.get_near()) { + const Tangible *tan = viewer_.tangible_get(id); + const AnimQueue &aq = tan->anim_queue_; + std::cerr << id << ": " << aq.get_graphic() << " " << aq.get_plane() << " " << aq.get_xyz() << std::endl; } } @@ -99,8 +99,13 @@ void TextGame::do_menu_command(const StringVec &cmd) { std::cerr << "m command (menu) expects a tangible ID or defaults to 1" << std::endl; return; } - - std::cerr << "Menu command (id " << id << ") not implemented yet." << std::endl; + gui_id_ = id; + viewer_.update_gui(id, &gui_); + int index = 0; + for (const GuiElt &elt : gui_.elts()) { + std::cerr << index << " " << elt.label() << std::endl; + index += 1; + } } void TextGame::do_choose_command(const StringVec &cmd) { @@ -114,11 +119,20 @@ void TextGame::do_choose_command(const StringVec &cmd) { std::cerr << "Choose command (index " << index << ") not implemented yet." << std::endl; } +void TextGame::do_quit_command(const StringVec &cmd) { + if (cmd.size() != 1) { + std::cerr << "q command (quit) takes no arguments" << std::endl; + return; + } + exit(0); +} + void TextGame::do_command(const StringVec &words) { switch (words[0][0]) { case 'v': do_view_command(words); break; case 'm': do_menu_command(words); break; case 'c': do_choose_command(words); break; + case 'q': do_quit_command(words); break; default: std::cerr << "Unknown command: " << words[0] << std::endl; } diff --git a/luprex/cpp/textgame.hpp b/luprex/cpp/textgame.hpp index 9e7b9fed..a4739e62 100644 --- a/luprex/cpp/textgame.hpp +++ b/luprex/cpp/textgame.hpp @@ -10,13 +10,13 @@ private: using StringVec = LuaConsole::StringVec; Viewer viewer_; LuaConsole console_; - int64_t menu_id_; - std::vector menu_; - + Gui gui_; + int64_t gui_id_; void do_view_command(const StringVec &cmd); void do_menu_command(const StringVec &cmd); void do_choose_command(const StringVec &cmd); + void do_quit_command(const StringVec &cmd); void do_lua(const std::string &exp); void do_command(const StringVec &exp); diff --git a/luprex/cpp/viewer.cpp b/luprex/cpp/viewer.cpp index 6b706ceb..100d0e0a 100644 --- a/luprex/cpp/viewer.cpp +++ b/luprex/cpp/viewer.cpp @@ -13,15 +13,12 @@ int64_t Viewer::get_player_id() { return 1; } -// Get the menu of the specified tangible. -// -std::vector Viewer::get_menu(int64_t id) { - std::vector result; - result.push_back("north"); - result.push_back("south"); - result.push_back("east"); - result.push_back("west"); - result.push_back("build"); - result.push_back("destroy"); - return result; +void Viewer::update_gui(int64_t id, Gui *gui) { + gui->add_menu_item("north", "north"); + gui->add_menu_item("south", "south"); + gui->add_menu_item("east", "east"); + gui->add_menu_item("west", "west"); + gui->add_menu_item("build", "build"); + gui->add_menu_item("destroy", "destroy"); } + diff --git a/luprex/cpp/viewer.hpp b/luprex/cpp/viewer.hpp index 3f6d27dd..5696d7d4 100644 --- a/luprex/cpp/viewer.hpp +++ b/luprex/cpp/viewer.hpp @@ -3,6 +3,7 @@ #include "world.hpp" #include "animqueue.hpp" +#include "gui.hpp" #include #include #include @@ -10,7 +11,6 @@ class Viewer { private: std::unique_ptr world_; - AnimViewMap view_map_; public: Viewer(); @@ -24,17 +24,21 @@ public: // int64_t get_player_id(); - // Update the view map. + // Get the list of tangibles near the player. // - void update_view_map() { world_->update_view_map(&view_map_, 1, 100); } + std::vector get_near() { return world_->get_near(1, 100); } + + // Get the specified tangible. + // + const Tangible *tangible_get(int64_t id) { return world_->tangible_get(id); } - // Get the view map. + // Update the GUI for the specified sprite. // - AnimViewMap &get_view_map() { return view_map_; } - - // Get the menu of the specified tangible. + // The gui passed in can be either a newly-created empty GUI, + // which will be populated, or a GUI object retained from + // the previous frame, which will be updated. // - std::vector get_menu(int64_t id); + void update_gui(int64_t id, Gui *g); }; #endif // VIEWER_HPP diff --git a/luprex/cpp/world.cpp b/luprex/cpp/world.cpp index 795c8ec9..a401fe3f 100644 --- a/luprex/cpp/world.cpp +++ b/luprex/cpp/world.cpp @@ -76,23 +76,14 @@ Tangible *World::tangible_get(int64_t id) { } } -void World::update_view_map(AnimViewMap *vm, int64_t player_id, float radius) { - vm->clear_updated_bits(); - - // Update the player's AnimView first. - vm->update_one(tangible_get(player_id)->anim_queue_); - const AnimView *player_view = vm->get_one(player_id); - +std::vector World::get_near(int64_t player_id, float radius) { + Tangible *player = tangible_get(player_id); + // Find out where's the center of the world. - std::string plane = player_view->get_plane(); - util::XYZ xyz = player_view->get_xyz(); - - // Update AnimViews for every tangible near the player. - for (int64_t id : plane_map_.scan_radius(plane, xyz.x, xyz.y, 100.0)) { - vm->update_one(tangible_get(id)->anim_queue_); - } - - vm->delete_non_updated(); + std::string plane = player->anim_queue_.get_plane(); + util::XYZ xyz = player->anim_queue_.get_xyz(); + + return plane_map_.scan_radius(plane, xyz.x, xyz.y, radius, player_id); } Tangible *World::tangible_make(lua_State *L, int64_t id, bool pushdb) { diff --git a/luprex/cpp/world.hpp b/luprex/cpp/world.hpp index 495d034b..fbc4786a 100644 --- a/luprex/cpp/world.hpp +++ b/luprex/cpp/world.hpp @@ -82,12 +82,11 @@ public: // lua_State *get_lua_state() { return lua_state_; } - // update_view_map + // get_near // - // Update the view map with information about all the tangibles near - // the specified player. + // Get a list of the tangibles that are near the player. // - void update_view_map(AnimViewMap *vm, int64_t player_id, float radius); + std::vector get_near(int64_t player_id, float radius); // Make a tangible. //