summary refs log tree commit diff stats
path: root/src/entityfactory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/entityfactory.cpp')
-rw-r--r--src/entityfactory.cpp229
1 files changed, 153 insertions, 76 deletions
diff --git a/src/entityfactory.cpp b/src/entityfactory.cpp index 6fb86ca..b80fe99 100644 --- a/src/entityfactory.cpp +++ b/src/entityfactory.cpp
@@ -3,103 +3,180 @@
3#include "muxer.h" 3#include "muxer.h"
4#include <cstdio> 4#include <cstdio>
5#include <map> 5#include <map>
6#include <list>
6#include "components/static_image.h" 7#include "components/static_image.h"
7#include "components/simple_collider.h" 8#include "components/simple_collider.h"
8#include "components/physics_body.h" 9#include "components/physics_body.h"
10#include "components/ai.h"
9#include "game.h" 11#include "game.h"
10 12
11struct EntityData { 13void parseEntityAIData(AI& ai, xmlNodePtr node, const std::map<std::string, int>& items)
12 char* sprite;
13 char* action;
14 bool hasPhysics;
15 int width;
16 int height;
17};
18
19static std::map<std::string, EntityData> factories;
20
21std::shared_ptr<Entity> EntityFactory::createNamedEntity(const std::string name)
22{ 14{
23 auto it = factories.find(name); 15 xmlChar* key;
24 EntityData data = factories[name];
25 if (it == factories.end())
26 {
27 xmlDocPtr doc = xmlParseFile(("entities/" + name + ".xml").c_str());
28 if (doc == nullptr)
29 {
30 fprintf(stderr, "Error reading entity %s\n", name.c_str());
31 exit(-1);
32 }
33
34 xmlNodePtr top = xmlDocGetRootElement(doc);
35 if (top == nullptr)
36 {
37 fprintf(stderr, "Empty entity %s\n", name.c_str());
38 exit(-1);
39 }
40
41 if (xmlStrcmp(top->name, (const xmlChar*) "entity-def"))
42 {
43 fprintf(stderr, "Invalid entity definition %s\n", name.c_str());
44 exit(-1);
45 }
46 16
47 for (xmlNodePtr node = top->xmlChildrenNode; node != NULL; node = node->next) 17 for (xmlNodePtr aiNode = node->xmlChildrenNode; aiNode != NULL; aiNode = aiNode->next)
18 {
19 if (!xmlStrcmp(aiNode->name, (xmlChar*) "move"))
48 { 20 {
49 if (!xmlStrcmp(node->name, (const xmlChar*) "sprite")) 21 MoveAIAction::Direction dir;
22 int len;
23 int speed;
24
25 key = xmlGetProp(aiNode, (xmlChar*) "direction");
26 if (key == 0) exit(2);
27 if (!xmlStrcmp(key, (xmlChar*) "left"))
50 { 28 {
51 xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); 29 dir = MoveAIAction::Direction::Left;
52 data.sprite = (char*) calloc(xmlStrlen(key)+1, sizeof(char)); 30 } else if (!xmlStrcmp(key, (xmlChar*) "right"))
53 strcpy(data.sprite, (char*) key);
54 xmlFree(key);
55 } else if (!xmlStrcmp(node->name, (const xmlChar*) "action"))
56 { 31 {
57 xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); 32 dir = MoveAIAction::Direction::Right;
58 data.action = (char*) calloc(xmlStrlen(key)+1, sizeof(char)); 33 } else if (!xmlStrcmp(key, (xmlChar*) "up"))
59 strcpy(data.action, (char*) key);
60 xmlFree(key);
61 } else if (!xmlStrcmp(node->name, (const xmlChar*) "size"))
62 { 34 {
63 xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); 35 dir = MoveAIAction::Direction::Up;
64 data.hasPhysics = true; 36 } else if (!xmlStrcmp(key, (xmlChar*) "down"))
65 sscanf((char*) key, "%d,%d", &data.width, &data.height); 37 {
66 xmlFree(key); 38 dir = MoveAIAction::Direction::Down;
39 } else {
40 exit(2);
41 }
42 xmlFree(key);
43
44 key = xmlGetProp(aiNode, (xmlChar*) "length");
45 if (key != 0)
46 {
47 len = atoi((char*) key);
48 } else {
49 key = xmlGetProp(aiNode, (xmlChar*) "length-var");
50 if (key == 0) exit(2);
51 std::string varName = (char*) key;
52 len = items.at(varName);
53 }
54 xmlFree(key);
55
56 key = xmlGetProp(aiNode, (xmlChar*) "speed");
57 if (key != 0)
58 {
59 speed = atoi((char*) key);
60 } else {
61 key = xmlGetProp(aiNode, (xmlChar*) "speed-var");
62 if (key == 0) exit(2);
63 std::string varName = (char*) key;
64 speed = items.at(varName);
65 }
66 xmlFree(key);
67
68 ai.addAction(std::make_shared<MoveAIAction>(dir, len, speed));
69 } else if (!xmlStrcmp(aiNode->name, (xmlChar*) "switch"))
70 {
71 key = xmlGetProp(aiNode, (xmlChar*) "item");
72 if (key == 0) exit(2);
73 std::string switchItem = (char*) key;
74 xmlFree(key);
75
76 for (xmlNodePtr switchNode = aiNode->xmlChildrenNode; switchNode != NULL; switchNode = switchNode->next)
77 {
78 if (!xmlStrcmp(switchNode->name, (xmlChar*) "case"))
79 {
80 key = xmlGetProp(switchNode, (xmlChar*) "value");
81 if (key == 0) exit(2);
82 int caseValue = atoi((char*) key);
83 xmlFree(key);
84
85 if (items.at(switchItem) == caseValue)
86 {
87 parseEntityAIData(ai, switchNode, items);
88 }
89 }
67 } 90 }
68 } 91 }
69
70 xmlFreeDoc(doc);
71
72 factories[name] = data;
73 } 92 }
74 93}
75 auto entity = std::make_shared<Entity>(); 94
76 95std::shared_ptr<Entity> EntityFactory::createNamedEntity(const std::string name, const std::map<std::string, int>& items)
77 if (data.sprite) 96{
97 xmlDocPtr doc = xmlParseFile("res/entities.xml");
98 if (doc == nullptr)
78 { 99 {
79 auto component = std::make_shared<StaticImageComponent>(data.sprite); 100 fprintf(stderr, "Error reading entities\n");
80 entity->addComponent(component); 101 exit(-1);
81 } 102 }
82 103
83 if (data.action) 104 xmlNodePtr top = xmlDocGetRootElement(doc);
105 if (top == nullptr)
84 { 106 {
85 if (!strcmp(data.action, "save")) 107 fprintf(stderr, "Empty entities file\n");
86 { 108 exit(-1);
87 auto component = std::make_shared<SimpleColliderComponent>([&] (Game& game, Entity&) { 109 }
88 playSound("res/Pickup_Coin23.wav", 0.25); 110
89 111 if (xmlStrcmp(top->name, (const xmlChar*) "entities"))
90 game.saveGame(); 112 {
91 }); 113 fprintf(stderr, "Invalid entities definition\n");
92 entity->addComponent(component); 114 exit(-1);
93 }
94 } 115 }
95 116
96 if (data.hasPhysics) 117 auto entity = std::make_shared<Entity>();
118
119 xmlChar* key;
120 for (xmlNodePtr node = top->xmlChildrenNode; node != NULL; node = node->next)
97 { 121 {
98 auto component = std::make_shared<PhysicsBodyComponent>(); 122 if (!xmlStrcmp(node->name, (xmlChar*) "entity"))
99 entity->addComponent(component); 123 {
100 124 key = xmlGetProp(node, (xmlChar*) "id");
101 entity->size = std::make_pair(data.width, data.height); 125 if (key == 0) exit(-1);
126 std::string entityID = (char*) key;
127 xmlFree(key);
128
129 if (entityID == name)
130 {
131 key = xmlGetProp(node, (xmlChar*) "sprite");
132 if (key == 0) exit(-1);
133 auto spriteComponent = std::make_shared<StaticImageComponent>((char*) key);
134 entity->addComponent(spriteComponent);
135 xmlFree(key);
136
137 auto physicsComponent = std::make_shared<PhysicsBodyComponent>();
138 entity->addComponent(physicsComponent);
139
140 key = xmlGetProp(node, (xmlChar*) "width");
141 if (key == 0) exit(-1);
142 entity->size.first = atoi((char*) key);
143 xmlFree(key);
144
145 key = xmlGetProp(node, (xmlChar*) "height");
146 if (key == 0) exit(-1);
147 entity->size.second = atoi((char*) key);
148 xmlFree(key);
149
150 bool addAI = false;
151 auto aiComponent = std::make_shared<AIComponent>();
152
153 for (xmlNodePtr entityNode = node->xmlChildrenNode; entityNode != NULL; entityNode = entityNode->next)
154 {
155 if (!xmlStrcmp(entityNode->name, (xmlChar*) "ai"))
156 {
157 addAI = true;
158
159 xmlChar* chanceKey = xmlGetProp(entityNode, (xmlChar*) "chance");
160 if (chanceKey == 0) exit(2);
161 int chance = atoi((char*) chanceKey);
162 xmlFree(chanceKey);
163
164 AI& ai = aiComponent->emplaceAI(chance);
165 parseEntityAIData(ai, entityNode, items);
166 }
167 }
168
169 if (addAI)
170 {
171 entity->addComponent(aiComponent);
172 }
173
174 break;
175 }
176 }
102 } 177 }
178
179 xmlFreeDoc(doc);
103 180
104 return entity; 181 return entity;
105} 182}