1 #include <chaiscript/chaiscript.hpp>
2
3 class Entity
4 {
5 public:
6 int width;
7 int height;
8 int x;
9 int y;
10 std::string name;
11
12 std::function<void (Entity &)> updater;
13
Entity(const int t_width,const int t_height,const int t_x,const int t_y,std::string t_name)14 Entity(const int t_width, const int t_height, const int t_x, const int t_y, std::string t_name)
15 : width(t_width), height(t_height), x(t_x), y(t_y), name(std::move(t_name))
16 {
17 }
18 };
19
20 class Factory
21 {
22 public:
23 // we may as well pass the parameters for the entity to the factory method, this does the initialization
24 // in one step.
make_entity(const int width,const int height,const int x,const int y,const std::string & name)25 Entity *make_entity(const int width, const int height, const int x, const int y, const std::string &name)
26 {
27 auto entity = entities.insert({name, Entity{width, height, x, y, name}});
28 return &(entity.first->second);
29 }
30
get_entity(const std::string & name)31 Entity *get_entity(const std::string &name)
32 {
33 return &entities.at(name);
34 }
35
36
37 // loop over all entities and all their updater function (if it exists)
update_entities()38 void update_entities()
39 {
40 for (auto &entity : entities)
41 {
42 if (entity.second.updater) {
43 entity.second.updater(entity.second);
44 }
45 }
46 }
47
48
49 private:
50 // we cannot store the entities in a std::vector if we want to return a pointer to them,
51 // because a vector automatically resizing itself can invalidate the pointer that was returned.
52 // using a map guarantees that the memory assigned to the entity will never change, plus
53 // lets us easily look up an entity by name
54 std::map<std::string, Entity> entities;
55 };
56
main()57 int main()
58 {
59 chaiscript::ChaiScript chai;
60
61 chai.add(chaiscript::fun(&Entity::width), "width");
62 chai.add(chaiscript::fun(&Entity::height), "height");
63 chai.add(chaiscript::fun(&Entity::x), "x");
64 chai.add(chaiscript::fun(&Entity::y), "y");
65 chai.add(chaiscript::fun(&Entity::name), "name");
66 chai.add(chaiscript::fun(&Entity::updater), "updater");
67 chai.add(chaiscript::user_type<Entity>(), "Entity"); // this isn't strictly necessary but makes error messages nicer
68
69 chai.add(chaiscript::fun(&Factory::make_entity), "make_entity");
70 chai.add(chaiscript::fun(&Factory::get_entity), "get_entity");
71 chai.add(chaiscript::fun(&Factory::update_entities), "update_entities");
72 chai.add(chaiscript::user_type<Factory>(), "Factory"); // this isn't strictly necessary but makes error messages nicer
73
74
75 Factory f;
76 chai.add(chaiscript::var(&f), "f");
77
78 std::string script = R""(
79 f.make_entity(10,10,1,1,"entity1").updater = fun(e){ e.x += 1; e.y += 1 };
80 f.make_entity(10,10,10,10,"entity2").updater = fun(e){ e.x += 2; e.y += 2 };
81 f.make_entity(10,10,20,20,"entity3");
82
83 print(f.get_entity("entity1").x == 1)
84 print(f.get_entity("entity2").x == 10)
85 print(f.get_entity("entity3").x == 20)
86
87 f.update_entities(); // this runs the function objects we set in the previous lines
88 // we should now see the updated values
89
90 print(f.get_entity("entity1").x == 2)
91 print(f.get_entity("entity2").x == 12)
92 print(f.get_entity("entity3").x == 20) // this one has no updater, so it stays the same
93 )"";
94
95
96 chai.eval(script);
97
98
99
100 }
101
102
103