beefviper

XMLGameEngine - game.cpp

Sep 19th, 2020
1,057
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // game.cpp
  2. // XML Game Engine
  3. // author: beefviper
  4. // date: Sept 18, 2020
  5.  
  6. #include "game.h"
  7.  
  8. xge::Game::Game(std::string game) :
  9.     filename(game)
  10. {
  11.     initXML();
  12.     initEXPR();
  13.     initSFML();
  14. }
  15.  
  16. void xge::Game::initXML()
  17. {
  18.     tx::XMLError xmlErrorCode = xml.LoadFile(filename.c_str());
  19.     checkXMLResult(xml, xmlErrorCode);
  20.  
  21.     tx::XMLElement* xGame = getXMLRoot(xml.FirstChildElement("game"));
  22.  
  23.     tx::XMLElement* xWindow = getXMLElement(xGame, "window");
  24.  
  25.     tx::XMLElement* xVariables = getXMLElement(xGame, "variables");
  26.     tx::XMLElement* xObjects = getXMLElement(xGame, "objects");
  27.     tx::XMLElement* xStates = getXMLElement(xGame, "states");
  28.  
  29.     tx::XMLElement* xVariable = getXMLElement(xVariables, "variable");
  30.     tx::XMLElement* xObject = getXMLElement(xObjects, "object");
  31.     tx::XMLElement* xState = getXMLElement(xStates, "state");
  32.  
  33.     // load window description
  34.     windowDesc.title = getXMLAttribute(xWindow, "title");
  35.     windowDesc.width = getXMLAttributeFloat(xWindow, "width");
  36.     windowDesc.height = getXMLAttributeFloat(xWindow, "height");
  37.     windowDesc.background = getXMLAttribute(xWindow, "background");
  38.     windowDesc.fullscreen = getXMLAttribute(xWindow, "fullscreen");
  39.     windowDesc.framerate = getXMLAttributeInt(xWindow, "framerate");
  40.  
  41.     // load variables
  42.     while (xVariable != nullptr)
  43.     {
  44.         std::string vName = getXMLAttribute(xVariable, "name");
  45.         float vValue = getXMLAttributeFloat(xVariable, "value");
  46.         variables[vName] = vValue;
  47.         xVariable = xVariable->NextSiblingElement("variable");
  48.     }
  49.  
  50.     // load objects
  51.     while (xObject != nullptr)
  52.     {
  53.         std::string xName = getXMLAttribute(xObject, "name");
  54.  
  55.         tx::XMLElement* xSprite = getXMLElement(xObject, "sprite");
  56.         std::string xSrc = getXMLAttribute(xSprite, "src");
  57.  
  58.         tx::XMLElement* xPosition = getXMLElement(xObject, "position");
  59.         std::string xPosX = getXMLAttribute(xPosition, "x");
  60.         std::string xPosY = getXMLAttribute(xPosition, "y");
  61.  
  62.         tx::XMLElement* xVelocity = getXMLElement(xObject, "velocity");
  63.         std::string xVelX = getXMLAttribute(xVelocity, "x");
  64.         std::string xVelY = getXMLAttribute(xVelocity, "y");
  65.  
  66.         xge::Vector2str position{ xPosX, xPosY };
  67.         xge::Vector2str velocity{ xVelX, xVelY };
  68.  
  69.         // TODO: Add <movement> and <action> tags
  70.  
  71.         Object object;
  72.         object.init(xName, xSrc, position, velocity);
  73.         objects.push_back(object);
  74.         xObject = xObject->NextSiblingElement("object");
  75.     }
  76.  
  77.     // load states
  78.     while (xState != nullptr)
  79.     {
  80.  
  81.         std::string sName = getXMLAttribute(xState, "name");
  82.  
  83.         tx::XMLElement* sObject = getXMLElement(xState, "show");
  84.  
  85.         std::vector<std::string> sShows;
  86.  
  87.         while (sObject != nullptr)
  88.         {
  89.             std::string shName = getXMLAttribute(sObject, "object");
  90.             sShows.push_back(shName);
  91.             sObject = sObject->NextSiblingElement("show");
  92.         }
  93.  
  94.         tx::XMLElement* xInputs = getXMLElement(xState, "inputs");
  95.         tx::XMLElement* xInput = getXMLElement(xInputs, "input");
  96.  
  97.         std::map<std::string, std::string> sInputs;
  98.  
  99.         while (xInput != nullptr)
  100.         {
  101.             std::string iAction = getXMLAttribute(xInput, "action");
  102.             std::string iButton = getXMLAttribute(xInput, "button");
  103.  
  104.             sInputs[iAction] = iButton;
  105.  
  106.             xInput = xInput->NextSiblingElement("input");
  107.         }
  108.  
  109.         xge::State state;
  110.         state.init(sName, sShows, sInputs);
  111.         states.push_back(state);
  112.  
  113.         xState = xState->NextSiblingElement("state");
  114.     }
  115. }
  116.  
  117. void xge::Game::initEXPR(void)
  118. {
  119.     // TODO: Write code to parse the rest of the text fields
  120.     //      -- exprtk lib will parse text variables and expressions
  121.  
  122.     randomNumber<float> randomNumberFloat;
  123.     randomRange<float> randomRangeFloat;
  124.     shapeCircle<float> shapeCircleFloat;
  125.     shapeRectangle<float> shapeRectangleFloat;
  126.  
  127.     float recWidth{};
  128.     float recHeight{};
  129.  
  130.     exprtk::symbol_table<float> symbolTable;
  131.     symbolTable.add_function("random.number", randomNumberFloat);
  132.     symbolTable.add_function("random.range", randomRangeFloat);
  133.     symbolTable.add_function("shape.circle", shapeCircleFloat);
  134.     symbolTable.add_function("shape.rectangle", shapeRectangleFloat);
  135.     symbolTable.add_constant("screen.left", 0);
  136.     symbolTable.add_constant("screen.right", windowDesc.width);
  137.     symbolTable.add_constant("screen.width.center", windowDesc.width / 2);
  138.     symbolTable.add_constant("screen.height.center", windowDesc.height / 2);
  139.     for (auto variable : variables)
  140.     {
  141.         symbolTable.add_constant(variable.first, variable.second);
  142.     }
  143.     symbolTable.add_variable("recWidth", recWidth);
  144.     symbolTable.add_variable("recHeight", recHeight);
  145.  
  146.     exprtk::expression<float> expression;
  147.     expression.register_symbol_table(symbolTable);
  148.     exprtk::parser<float> parser;
  149.     std::string expression_str;
  150.  
  151.     for (auto& object : objects)
  152.     {
  153.         expression_str = object.sposition.x;
  154.         parser.compile(expression_str, expression);
  155.         object.position.x = expression.value();
  156.  
  157.         expression_str = object.sposition.y;
  158.         parser.compile(expression_str, expression);
  159.         object.position.y = expression.value();
  160.  
  161.         expression_str = object.svelocity.x;
  162.         parser.compile(expression_str, expression);
  163.         object.velocity.x = expression.value();
  164.  
  165.         expression_str = object.svelocity.y;
  166.         parser.compile(expression_str, expression);
  167.         object.velocity.y = expression.value();
  168.  
  169.         // TODO: finish coming up with to parse different types of assets: shape, file, data
  170.         if (object.src.compare(0, 12, "shape.circle") == 0)
  171.         {
  172.             expression_str = object.src;
  173.             parser.compile(expression_str, expression);
  174.             object.params.push_back(expression.value());
  175.         }
  176.  
  177.         else if (object.src.compare(0, 15, "shape.rectangle") == 0)
  178.         {
  179.             auto e_start = object.src.find("(") + 1;
  180.             auto e_end = object.src.find(",");
  181.             auto e_length = e_end - e_start;
  182.             expression_str = "recWidth := " + object.src.substr(e_start, e_length);
  183.             parser.compile(expression_str, expression);
  184.             expression.value();
  185.             object.params.push_back(recWidth);
  186.  
  187.             e_start = object.src.find(",") + 1;
  188.             e_end = object.src.find(")");
  189.             e_length = e_end - e_start;
  190.             expression_str = "recHeight := " + object.src.substr(e_start, e_length);
  191.             parser.compile(expression_str, expression);
  192.             expression.value();
  193.             object.params.push_back(recHeight);
  194.         }
  195.     }
  196. }
  197.  
  198. void xge::Game::initSFML(void)
  199. {
  200.     for (auto& object : objects)
  201.     {
  202.         sf::CircleShape circle;
  203.         sf::RectangleShape rectangle;
  204.         object.renderTexture = std::make_shared<sf::RenderTexture>();
  205.  
  206.         if (object.src.compare(0, 12, "shape.circle") == 0)
  207.         {
  208.             float radius = object.params.at(0);
  209.  
  210.             circle.setRadius(radius);
  211.             circle.setFillColor(sf::Color::Green);
  212.  
  213.             int width = static_cast<int>(std::ceil(circle.getLocalBounds().width));
  214.             int height = static_cast<int>(std::ceil(circle.getLocalBounds().height));
  215.  
  216.             object.renderTexture->create(width, height);
  217.  
  218.             object.renderTexture->draw(circle);
  219.         }
  220.         else if (object.src.compare(0, 15, "shape.rectangle") == 0)
  221.         {
  222.             float recWidth = object.params.at(0);
  223.             float recHeight = object.params.at(1);
  224.  
  225.             rectangle.setSize(sf::Vector2f(recWidth, recHeight));
  226.             rectangle.setFillColor(sf::Color::Magenta);
  227.  
  228.             int width = static_cast<int>(std::ceil(rectangle.getLocalBounds().width));
  229.             int height = static_cast<int>(std::ceil(rectangle.getLocalBounds().height));
  230.  
  231.             object.renderTexture->create(width, height);
  232.  
  233.             object.renderTexture->draw(rectangle);
  234.         }
  235.  
  236.         object.renderTexture->display();
  237.  
  238.         object.sprite = std::make_shared<sf::Sprite>();
  239.         object.sprite->setTexture(object.renderTexture->getTexture());
  240.         object.sprite->setPosition(object.position);
  241.     }
  242. }
  243.  
  244. void xge::Game::updateObjects(void)
  245. {
  246.     // TODO: only objects in the current state should be updating
  247.  
  248.     for (auto& object : objects)
  249.     {
  250.         object.position.x += object.velocity.x;
  251.         object.position.y += object.velocity.y;
  252.  
  253.         object.sprite->setPosition(object.position.x, object.position.y);
  254.     }
  255. }
  256.  
  257. void xge::Game::printGame(void)
  258. {
  259.     // debug -- print out window description
  260.     std::cout << "window: ";
  261.     std::cout << "title=" << windowDesc.title;
  262.     std::cout << ", width=" << windowDesc.width;
  263.     std::cout << ", height=" << windowDesc.height << std::endl;
  264.     std::cout << std::endl;
  265.  
  266.     // debug -- print out variables
  267.     for (auto variable : variables)
  268.     {
  269.         std::cout << "variable: name=" << variable.first << ", value=" << variable.second << std::endl;
  270.     }
  271.     std::cout << std::endl;
  272.  
  273.     // debug -- print out objects
  274.     for (auto object : objects)
  275.     {
  276.         std::cout << object << std::endl;
  277.         std::cout << std::endl;
  278.     }
  279.  
  280.     // debug -- print out states
  281.     for (auto state : states)
  282.     {
  283.         std::cout << "state: ";
  284.         std::cout << "name=" << state.name << ", show=";
  285.         for (auto show : state.show)
  286.         {
  287.             std::cout << show << (show != state.show.back() ? ", " : "\n");
  288.         }
  289.         for (auto input : state.input)
  290.         {
  291.             std::cout << "       action=" << input.first << ", button=" << input.second << std::endl;
  292.         }
  293.         std::cout << std::endl;
  294.     }
  295. }
  296.  
  297. xge::WindowDesc xge::Game::getWinowDesc(void)
  298. {
  299.     return windowDesc;
  300. }
  301.  
  302. std::vector<xge::Object>& xge::Game::getObjects(void)
  303. {
  304.     return objects;
  305. }
  306.  
  307. xge::Object xge::Game::getObject(std::string name)
  308. {
  309.     auto result = std::find_if(std::begin(objects), std::end(objects), [&](xge::Object& obj) { return obj.name == name; });
  310.     return *result;
  311. }
  312.  
  313. xge::State xge::Game::getCurrentState(void)
  314. {
  315.     return currentState.top();
  316. }
  317.  
  318. void xge::Game::setCurrentState(int index)
  319. {
  320.     currentState.push(states.at(index));
  321. }
  322.  
  323. void xge::Game::setObjectParam(std::string name, std::string param, float value)
  324. {
  325.     auto result = std::find_if(std::begin(objects), std::end(objects), [&](xge::Object& obj) { return obj.name == name; });
  326.     if (param == "velocity")
  327.     {
  328.         result->velocity.y = value;
  329.     }
  330. }
  331.  
RAW Paste Data