Viewer is ready to go, I think

This commit is contained in:
2021-01-22 17:35:23 -05:00
parent 351b923d68
commit b0440a4e12
11 changed files with 234 additions and 34 deletions

View File

@@ -65,6 +65,11 @@ void AnimQueue::set_plane(const std::string &p) {
last.plane_ = p;
}
const std::string &AnimQueue::get_graphic() const {
const AnimStep &last = steps_.back();
return last.graphic_;
}
const std::string &AnimQueue::get_plane() const {
const AnimStep &last = steps_.back();
return last.plane_;

View File

@@ -87,7 +87,8 @@ public:
void set_graphic(const std::string &g);
void set_plane(const std::string &p);
// Get the final resting place.
// Get the final resting place after all animations are complete.
const std::string &get_graphic() const;
const std::string &get_plane() const;
const util::XYZ &get_xyz() const;
@@ -95,5 +96,27 @@ public:
void set_size_limit(int n);
};
class AnimView {
private:
std::string graphic_;
std::string plane_;
util::XYZ xyz_;
bool updated_;
public:
const std::string &get_graphic() { return graphic_; }
const std::string &get_plane() { return plane_; }
const util::XYZ &get_xyz() { return xyz_; }
bool updated() { return updated_; }
void update_from(const AnimQueue &queue) {
graphic_ = queue.get_graphic();
plane_ = queue.get_plane();
xyz_ = queue.get_xyz();
updated_ = true;
}
void set_updated(bool u) { updated_ = u; }
};
#endif // ANIMQUEUE_HPP

View File

@@ -14,7 +14,7 @@
#include <string>
#include "luastack.hpp"
#include "util.hpp"
#include "world.hpp"
#include "viewer.hpp"
#include "traceback.hpp"
@@ -177,7 +177,7 @@ static void dotty(lua_State *L)
int main(int argc, char **argv)
{
LUAJIT_VERSION_SYM(); // Linker-enforced version check.
World w;
dotty(w.get_lua_state());
Viewer v;
dotty(v.get_lua_state());
return 0;
}

View File

@@ -176,8 +176,8 @@ int PlaneMap::total_cells() const {
return total;
}
PlaneMap::EltVec PlaneMap::scan_radius(const std::string &plane, double x, double y, double radius) const {
PlaneMap::EltVec result;
PlaneMap::IdVec PlaneMap::scan_radius(const std::string &plane, double x, double y, double radius) const {
PlaneMap::IdVec result;
auto piter = planes_.find(plane);
if (piter != planes_.end()) {
const Plane &p = piter->second;
@@ -189,7 +189,7 @@ PlaneMap::EltVec PlaneMap::scan_radius(const std::string &plane, double x, doubl
if (liter != p.end()) {
for (PlaneItem *client : liter->second) {
if (util::distance_squared(client->x(), client->y(), x, y) <= radsq) {
result.push_back(client);
result.push_back(client->id());
}
}
}
@@ -207,6 +207,7 @@ LuaDefine(unittests_planemap, "c") {
PlaneMap pm;
PlaneItem pia, pib;
PlaneMap::EltVec elts;
PlaneMap::IdVec ids;
// Simple test.
LuaAssert(L, rect_cell_range(-7*SC, -15*SC, 87*SC, 21*SC).equal(-7, -15, 87, 21));
@@ -306,13 +307,19 @@ LuaDefine(unittests_planemap, "c") {
// Insert the four elements, then test the scan function.
pm.track(&pib);
pia.set_id(123);
pib.set_id(456);
pib.set_pos("bar", 1100.0, 1000.0, 0.0);
elts = pm.scan_radius("bar", 1000.0, 1000.0, 1.0);
LuaAssert(L, elts.size() == 1);
elts = pm.scan_radius("bar", 1000.0, 1000.0, 99.9);
LuaAssert(L, elts.size() == 1);
elts = pm.scan_radius("bar", 1000.0, 1000.0, 100.0);
LuaAssert(L, elts.size() == 2);
ids = pm.scan_radius("bar", 1000.0, 1000.0, 1.0);
LuaAssert(L, ids.size() == 1);
LuaAssert(L, ids[0] == 123);
ids = pm.scan_radius("bar", 1000.0, 1000.0, 99.9);
LuaAssert(L, ids.size() == 1);
LuaAssert(L, ids[0] == 123);
ids = pm.scan_radius("bar", 1000.0, 1000.0, 100.0);
LuaAssert(L, ids.size() == 2);
LuaAssert(L, ids[0] == 123);
LuaAssert(L, ids[1] == 456);
return 0;
}

View File

@@ -86,11 +86,16 @@ private:
PlaneMap *pmap_;
std::string plane_;
double x_, y_, z_;
int64_t id_;
public:
PlaneItem();
~PlaneItem();
// You may modify the ID at any time.
void set_id(int64_t id) { id_ = id; }
int64_t id() const { return id_; }
const std::string &plane() const { return plane_; }
const double x() const { return x_; }
const double y() const { return y_; }
@@ -111,10 +116,11 @@ private:
void insert(const std::string &plane, int64_t cell, PlaneItem *client);
public:
using IdVec = std::vector<int64_t>;
PlaneMap();
~PlaneMap();
void track(PlaneItem *item);
EltVec 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) const;
private:
// unit testing stuff.

View File

@@ -0,0 +1,88 @@
#include "viewer.hpp"
Viewer::Viewer() {
world_.reset(new World);
world_->init_standalone();
}
Viewer::~Viewer() {
}
int64_t Viewer::get_player_id() {
return 1;
}
void Viewer::update_view() {
// Get ready to delete views that aren't in use.
//
for (auto pair : anim_view_) {
pair.second.set_updated(false);
}
// Update the player's AnimView first.
//
Tangible *player = world_->tangible_get(1);
AnimView *player_view = &anim_view_[1];
player_view->update_from(player->anim_queue_);
// Find out where's the center of the world.
//
std::string plane = player_view->get_plane();
util::XYZ xyz = player_view->get_xyz();
// Get a list of everything near the player.
//
tangibles_ = world_->scan_radius(plane, xyz.x, xyz.y, 100.0);
// Update AnimViews for every tangible near the player.
//
for (int64_t id : tangibles_) {
Tangible *tan = world_->tangible_get(id);
assert (tan != nullptr);
anim_view_[id].update_from(tan->anim_queue_);
}
// Delete any AnimView that was not updated.
//
for (auto iter = anim_view_.begin(); iter != anim_view_.end(); ) {
if (iter->second.updated()) {
iter++;
} else {
iter = anim_view_.erase(iter);
}
}
}
const std::vector<int64_t> &Viewer::get_tangibles_near_player() {
return tangibles_;
}
AnimView *Viewer::get_animation_view(int64_t id) {
auto iter = anim_view_.find(id);
if (iter == anim_view_.end()) {
return nullptr;
} else {
return &iter->second;
}
}
// Get the menu of the specified tangible.
//
std::vector<std::string> Viewer::get_menu(int64_t id) {
std::vector<std::string> 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::choose_menu_item(int64_t id, const std::string &item) {
}
void Viewer::advance_clock() {
};

View File

@@ -1,19 +1,39 @@
#ifndef VIEWER_HPP
#define VIEWER_HPP
class Viewer {
public:
// Initialize a standalone game.
//
void init_standalone();
#include "world.hpp"
#include "animqueue.hpp"
#include <vector>
#include <string>
#include <unordered_map>
#include <memory>
class Viewer {
private:
std::unique_ptr<World> world_;
std::vector<int64_t> tangibles_;
std::unordered_map<int64_t, AnimView> anim_view_;
public:
Viewer();
~Viewer();
// Get the lua state for interaction.
//
lua_State *get_lua_state() { return world_->get_lua_state(); }
// Get the player ID of the current player.
//
int64_t get_player_id();
// Update the view.
//
void update_view();
// Get a list of the tangibles in viewing radius of the player.
//
std::vector<int64_t> get_tangibles_near_player();
const std::vector<int64_t> &get_tangibles_near_player();
// Get the animation viewer of the specified tangible.
//

View File

@@ -38,27 +38,54 @@ World::World() {
// Initialize the SourceDB
source_db_.initialize(lua_state_);
source_db_.rebuild();
}
// Do an initial lua source update and then environment rebuild.
void Tangible::be_a_player() {
if (id_player_pool_ == nullptr) {
id_player_pool_.reset(new IdPlayerPool(&world_->id_global_pool_));
}
}
void World::init_standalone() {
// Load the lua source from disk then rebuild the environment.
source_db_.update();
source_db_.rebuild();
// Run unit tests.
source_db_.run_unittests();
// Create the player tangible.
Tangible *player = tangible_make(lua_state_, 1, false);
player->be_a_player();
}
Tangible *World::tangible_make(lua_State *L) {
std::vector<int64_t> World::scan_radius(const std::string &plane, float x, float y, float radius) {
return plane_map_.scan_radius(plane, x, y, radius);
}
Tangible *World::tangible_get(int64_t id) {
auto iter = tangibles_.find(id);
if (iter == tangibles_.end()) {
return nullptr;
} else {
return &iter->second;
}
}
Tangible *World::tangible_make(lua_State *L, int64_t id, bool pushdb) {
LuaVar tangibles, metatab;
LuaRet database;
LuaStack LS(L, tangibles, database, metatab);
// Get a fresh ID.
int64_t id = id_global_pool_.alloc_id_for_thread(L);
// Allocate an ID if we don't already have one.
if (id == 0) id = id_global_pool_.alloc_id_for_thread(L);
// Create the C++ part of the structure.
Tangible *t = &tangibles_[id];
assert(t->world_ == nullptr);
t->world_ = this;
t->plane_item_.set_id(id);
plane_map_.track(&t->plane_item_);
// Create the tangible's database and metatable.
@@ -77,6 +104,7 @@ Tangible *World::tangible_make(lua_State *L) {
// LS.setfield(metatab, "__metatable", LuaNil);
LS.result();
if (!pushdb) lua_pop(L, 1);
return t;
}
@@ -101,6 +129,6 @@ LuaDefine(tangible_get, "c") {
}
LuaDefine(tangible_make, "c") {
World::fetch(L)->tangible_make(L);
World::fetch(L)->tangible_make(L, 0, true);
return 1;
}

View File

@@ -21,17 +21,23 @@ public:
// Always points back to the world model.
World *world_;
// Animation queue and plane item.
// Animation queue.
//
// To update the position of this tangible, first add an animation in which
// the tangible moves, then call plane_item.set_pos_from(anim_queue_).
PlaneItem plane_item_;
AnimQueue anim_queue_;
// Plane Item.
//
// The PlaneItem also contains this tangible's ID.
// To move this Tangible, update the anim_queue first, then update
// this plane_item_ from the anim_queue.
PlaneItem plane_item_;
// Player ID pool
//
// Note: this is only allocated if this Tangible is a player.
std::unique_ptr<IdPlayerPool> id_player_pool_;
void be_a_player();
};
class World {
@@ -66,18 +72,34 @@ public:
//
~World();
// Initialize for single-player mode.
//
void init_standalone();
// get_lua_state
//
// Get the lua interpreter associated with this world model.
//
lua_State *get_lua_state() { return lua_state_; }
// Make a tangible with a generated ID.
// scan_near
//
// Pushes the database onto the lua stack and returns the tangible pointer.
// Get a list of the tangibles near the specified player ID.
//
Tangible *tangible_make(lua_State *L);
std::vector<int64_t> scan_radius(const std::string &plane, float x, float y, float radius);
// Make a tangible.
//
// If the ID is zero, allocates an ID using the thread's ID allocator. If
// pushdb is true, pushes the tangible's database onto the lua stack.
// Otherwise, leaves the lua stack untouched.
//
Tangible *tangible_make(lua_State *L, int64_t id, bool pushdb);
// Get a pointer to the specified tangible.
//
Tangible *tangible_get(int64_t id);
// Delete a tangible with the specified ID.
//
// If the tangible doesn't exist, does nothing.