From 4b4125e234cb727c70822e0a1fce0688c357741e Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Thu, 19 Mar 2015 16:15:47 -0400 Subject: Implemented a simple AI --- src/entityfactory.cpp | 229 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 153 insertions(+), 76 deletions(-) (limited to 'src/entityfactory.cpp') 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 @@ #include "muxer.h" #include #include +#include #include "components/static_image.h" #include "components/simple_collider.h" #include "components/physics_body.h" +#include "components/ai.h" #include "game.h" -struct EntityData { - char* sprite; - char* action; - bool hasPhysics; - int width; - int height; -}; - -static std::map factories; - -std::shared_ptr EntityFactory::createNamedEntity(const std::string name) +void parseEntityAIData(AI& ai, xmlNodePtr node, const std::map& items) { - auto it = factories.find(name); - EntityData data = factories[name]; - if (it == factories.end()) - { - xmlDocPtr doc = xmlParseFile(("entities/" + name + ".xml").c_str()); - if (doc == nullptr) - { - fprintf(stderr, "Error reading entity %s\n", name.c_str()); - exit(-1); - } - - xmlNodePtr top = xmlDocGetRootElement(doc); - if (top == nullptr) - { - fprintf(stderr, "Empty entity %s\n", name.c_str()); - exit(-1); - } - - if (xmlStrcmp(top->name, (const xmlChar*) "entity-def")) - { - fprintf(stderr, "Invalid entity definition %s\n", name.c_str()); - exit(-1); - } + xmlChar* key; - for (xmlNodePtr node = top->xmlChildrenNode; node != NULL; node = node->next) + for (xmlNodePtr aiNode = node->xmlChildrenNode; aiNode != NULL; aiNode = aiNode->next) + { + if (!xmlStrcmp(aiNode->name, (xmlChar*) "move")) { - if (!xmlStrcmp(node->name, (const xmlChar*) "sprite")) + MoveAIAction::Direction dir; + int len; + int speed; + + key = xmlGetProp(aiNode, (xmlChar*) "direction"); + if (key == 0) exit(2); + if (!xmlStrcmp(key, (xmlChar*) "left")) { - xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); - data.sprite = (char*) calloc(xmlStrlen(key)+1, sizeof(char)); - strcpy(data.sprite, (char*) key); - xmlFree(key); - } else if (!xmlStrcmp(node->name, (const xmlChar*) "action")) + dir = MoveAIAction::Direction::Left; + } else if (!xmlStrcmp(key, (xmlChar*) "right")) { - xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); - data.action = (char*) calloc(xmlStrlen(key)+1, sizeof(char)); - strcpy(data.action, (char*) key); - xmlFree(key); - } else if (!xmlStrcmp(node->name, (const xmlChar*) "size")) + dir = MoveAIAction::Direction::Right; + } else if (!xmlStrcmp(key, (xmlChar*) "up")) { - xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); - data.hasPhysics = true; - sscanf((char*) key, "%d,%d", &data.width, &data.height); - xmlFree(key); + dir = MoveAIAction::Direction::Up; + } else if (!xmlStrcmp(key, (xmlChar*) "down")) + { + dir = MoveAIAction::Direction::Down; + } else { + exit(2); + } + xmlFree(key); + + key = xmlGetProp(aiNode, (xmlChar*) "length"); + if (key != 0) + { + len = atoi((char*) key); + } else { + key = xmlGetProp(aiNode, (xmlChar*) "length-var"); + if (key == 0) exit(2); + std::string varName = (char*) key; + len = items.at(varName); + } + xmlFree(key); + + key = xmlGetProp(aiNode, (xmlChar*) "speed"); + if (key != 0) + { + speed = atoi((char*) key); + } else { + key = xmlGetProp(aiNode, (xmlChar*) "speed-var"); + if (key == 0) exit(2); + std::string varName = (char*) key; + speed = items.at(varName); + } + xmlFree(key); + + ai.addAction(std::make_shared(dir, len, speed)); + } else if (!xmlStrcmp(aiNode->name, (xmlChar*) "switch")) + { + key = xmlGetProp(aiNode, (xmlChar*) "item"); + if (key == 0) exit(2); + std::string switchItem = (char*) key; + xmlFree(key); + + for (xmlNodePtr switchNode = aiNode->xmlChildrenNode; switchNode != NULL; switchNode = switchNode->next) + { + if (!xmlStrcmp(switchNode->name, (xmlChar*) "case")) + { + key = xmlGetProp(switchNode, (xmlChar*) "value"); + if (key == 0) exit(2); + int caseValue = atoi((char*) key); + xmlFree(key); + + if (items.at(switchItem) == caseValue) + { + parseEntityAIData(ai, switchNode, items); + } + } } } - - xmlFreeDoc(doc); - - factories[name] = data; } - - auto entity = std::make_shared(); - - if (data.sprite) +} + +std::shared_ptr EntityFactory::createNamedEntity(const std::string name, const std::map& items) +{ + xmlDocPtr doc = xmlParseFile("res/entities.xml"); + if (doc == nullptr) { - auto component = std::make_shared(data.sprite); - entity->addComponent(component); + fprintf(stderr, "Error reading entities\n"); + exit(-1); } - - if (data.action) + + xmlNodePtr top = xmlDocGetRootElement(doc); + if (top == nullptr) { - if (!strcmp(data.action, "save")) - { - auto component = std::make_shared([&] (Game& game, Entity&) { - playSound("res/Pickup_Coin23.wav", 0.25); - - game.saveGame(); - }); - entity->addComponent(component); - } + fprintf(stderr, "Empty entities file\n"); + exit(-1); + } + + if (xmlStrcmp(top->name, (const xmlChar*) "entities")) + { + fprintf(stderr, "Invalid entities definition\n"); + exit(-1); } - if (data.hasPhysics) + auto entity = std::make_shared(); + + xmlChar* key; + for (xmlNodePtr node = top->xmlChildrenNode; node != NULL; node = node->next) { - auto component = std::make_shared(); - entity->addComponent(component); - - entity->size = std::make_pair(data.width, data.height); + if (!xmlStrcmp(node->name, (xmlChar*) "entity")) + { + key = xmlGetProp(node, (xmlChar*) "id"); + if (key == 0) exit(-1); + std::string entityID = (char*) key; + xmlFree(key); + + if (entityID == name) + { + key = xmlGetProp(node, (xmlChar*) "sprite"); + if (key == 0) exit(-1); + auto spriteComponent = std::make_shared((char*) key); + entity->addComponent(spriteComponent); + xmlFree(key); + + auto physicsComponent = std::make_shared(); + entity->addComponent(physicsComponent); + + key = xmlGetProp(node, (xmlChar*) "width"); + if (key == 0) exit(-1); + entity->size.first = atoi((char*) key); + xmlFree(key); + + key = xmlGetProp(node, (xmlChar*) "height"); + if (key == 0) exit(-1); + entity->size.second = atoi((char*) key); + xmlFree(key); + + bool addAI = false; + auto aiComponent = std::make_shared(); + + for (xmlNodePtr entityNode = node->xmlChildrenNode; entityNode != NULL; entityNode = entityNode->next) + { + if (!xmlStrcmp(entityNode->name, (xmlChar*) "ai")) + { + addAI = true; + + xmlChar* chanceKey = xmlGetProp(entityNode, (xmlChar*) "chance"); + if (chanceKey == 0) exit(2); + int chance = atoi((char*) chanceKey); + xmlFree(chanceKey); + + AI& ai = aiComponent->emplaceAI(chance); + parseEntityAIData(ai, entityNode, items); + } + } + + if (addAI) + { + entity->addComponent(aiComponent); + } + + break; + } + } } + + xmlFreeDoc(doc); return entity; } -- cgit 1.4.1