c++ - 我如何使用 tinyxml 将 xml 属性转换为 C++ 类

标签 c++ visual-studio-2010 xml-parsing glfw

嘿,我正在尝试通过读取 .xml 文件中的烟花来创建烟花表演,然后该文件将遍历并启动每个烟花。

我按照 dinomage 上的教程了解如何使用 tinyxml,我了解到我可以将属性存储到 char 指针中,但我不知道如何将它们转换为 GLfloats 以将它们存储在我的类变量中。

我确实尝试过使用 atof,但是当我运行程序时,我遇到了很多错误,我猜这是因为指针只存储了我传递给我的变量的地址。

谁能指出我哪里出了问题以及我该如何解决这个问题?

更新

我发现 tinyxml 与 vs2010 不兼容,但 tinyxml 2 兼容,所以我更改了我的代码,但仍然无法加载我的属性我添加了错误检查,它打印出 xml 已加载但随后它不会加载根

代码已更新

代码:Firework.h

#ifndef FIREWORK_H
#define FIREWORK_H
#include <cstdlib>
#include <GL\GL.h>
#include <string>



const GLint particles= 50;

 class Firework

 {

 public:

            GLint x[particles];
            GLint y[particles];
            GLint VelX[particles];
            GLint VelY[particles];
            GLint Xpos;
            GLint Ypos;
            GLint Xspeed;
            GLint Yspeed;



            unsigned char red;
            unsigned char blue;
            unsigned char green;
            GLfloat alpha;
            GLfloat redStart;
            GLfloat blueStart;
            GLfloat greenStart;
            std::string hexColour;
            std::string type;

            GLint timeUntilLaunch;
            GLint startTime;
            GLint endTime;
            GLint duration;
            GLfloat particleSize;
            GLboolean hasExploded;




            GLboolean rocket, fountain;

            static const GLfloat gravity;
            static const GLfloat baseYSpeed;
            static const GLfloat maxYSpeed;

            Firework();

            void initialise();
            void move();
            void explode();




 };




#endif

烟花.ccp

#include "Firework.h"
#include "tinyxml2.h"
#include<time.h>
#include <string>
#include<iostream>
#include <vector>

using namespace std;

const GLfloat Firework::gravity = 0.05f;
const GLfloat Firework::baseYSpeed = -4.0f;
const GLfloat Firework::maxYSpeed = -4.0f;

//int QueryAttributeStatus = elem->FirstChildElement("begin")- >QueryFloatAttribute(attr,&timeUntillLaunch);





int convertFromHex(string hex)

{

    int value = 0;



    int a = 0;

    int b = hex.length() - 1;

    for (; b >= 0; a++, b--)

    {

        if (hex[b] >= '0' && hex[b] <= '9')

        {

            value += (hex[b] - '0') * (1 << (a * 4));

        }

        else

        {

            switch (hex[b])

            {

                case 'A':

                case 'a':

                    value += 10 * (1 << (a * 4));

                    break;



                case 'B':

                case 'b':

                    value += 11 * (1 << (a * 4));

                    break;



                case 'C':

                case 'c':

                    value += 12 * (1 << (a * 4));

                    break;



                case 'D':

                case 'd':

                    value += 13 * (1 << (a * 4));

                    break;



                case 'E':

                case 'e':

                    value += 14 * (1 << (a * 4));

                    break;



                case 'F':

                case 'f':

                    value += 15 * (1 << (a * 4));

                    break;



                default:

                    cout << "Error, invalid charactare '" << hex[a] << "' in hex number" << endl;

                    break;

            }

        }

    }
        return value;

}


void hextodec(string hex, vector<unsigned char>& rgb)

{

/*  
    since there is no prefix attached to hex, use this code

    string redString = hex.substr(0, 2);

    string greenString = hex.substr(2, 2);

    string blueString = hex.substr(4, 2);
*/



/*

    if the prefix # was attached to hex, use the following code

    string redString = hex.substr(1, 2);

    string greenString = hex.substr(3, 2);

    string blueString = hex.substr(5, 2);

*/





    //if the prefix 0x was attached to hex, use the following code

    string redString = hex.substr(2, 2);

    string greenString = hex.substr(4, 2);

    string blueString = hex.substr(6, 2);





    unsigned char red = (unsigned char)(convertFromHex(redString));

    unsigned char green = (unsigned char)(convertFromHex(greenString));

    unsigned char blue = (unsigned char)(convertFromHex(blueString));



    rgb[0] = red;

    rgb[1] = green;

    rgb[2] = blue;

}


Firework::Firework()
{

    initialise();

}



void Firework::initialise()
{
    tinyxml2::XMLDocument doc;
    doc.LoadFile( "fireworks.xml");
    if (!doc.LoadFile("fireworks.xml"))
    {
        std::cout<<"Failed to load file: no xml"<<endl;
    }

    else
        std::cout<<"loaded xml"<<endl;



        tinyxml2::XMLElement * root = doc.FirstChildElement();
        if (root == NULL)
        {
            std::cout<<"Failed to load file: no root element."<<endl;

        }

        else

            std::cout<<"root node loaded"<<endl;

        for (tinyxml2::XMLElement* elem = root ->FirstChildElement(); elem!=NULL; elem = elem->NextSiblingElement())
        {
            string elemName = elem->Value();
            const char* attr;

            if (elemName == "Firework")
            {
                attr = elem->Attribute("begin");
                if(attr != NULL)
                {
                    elem->QueryIntAttribute("begin",&startTime);
                }

                attr = elem->Attribute("type");
                if (attr != NULL)
                {
                    type = elem->GetText();
                    if (type != "")

                        std::cout<<"have something"<<endl; 


                }

                attr = elem ->Attribute("colour");
                if (attr !=NULL)
                {
                    hexColour= elem->GetText();
                     vector<unsigned char> rgbColor(3);

                     hextodec(hexColour,rgbColor);

                     red =int(rgbColor[0]);
                     blue = int(rgbColor[1]);
                     green= int(rgbColor[2]);


                }

                attr = elem->Attribute("duration");
                if (attr !=NULL)
                {
                    elem->QueryIntAttribute("duration", &endTime);
                }

                for (tinyxml2::XMLElement * e =elem ->FirstChildElement("Position"); e != NULL; e = e->NextSiblingElement("Position"))
                {
                    attr = e->Attribute("x");
                    if (attr != NULL)
                    {
                        Xpos = e->QueryIntAttribute("x", &Xpos);
                    }

                    attr = e->Attribute("y");
                    if (attr != NULL)
                    {
                        Ypos = e->QueryIntAttribute("y", &Ypos);
                    }
                }

                for(tinyxml2::XMLElement * v =elem ->FirstChildElement("Velocity"); v !=NULL; v = v->NextSiblingElement("Velocity"))
                {
                    attr = v -> Attribute("x");
                        if (attr != NULL)
                    {
                        Xspeed = v ->QueryIntAttribute("x", &Xspeed);
                    }

                    attr = v ->Attribute ("y");
                        if (attr !=NULL)
                    {
                        Yspeed = v ->QueryIntAttribute("y", &Yspeed);
                    }
                }
            }

        }









    //Setting initial x/y locations and speeds for each particle
    for (int loop = 0; loop < particles; loop++)
    {
        x[loop] = Xpos;
        y[loop] = Ypos;
        VelX[loop] = Xspeed;
        VelY[loop] = Yspeed;
    }

    //intiallising the colour and full alpha
    redStart   = 0.85f;//((float)rand() / (float)RAND_MAX);
    greenStart = 0.55f;//((float)rand() / (float)RAND_MAX);
    blueStart  = 0.01f;//((float)rand() / (float)RAND_MAX);

    alpha = 1.0f;

    timeUntilLaunch = startTime;
    duration = endTime;
    particleSize = 1.0f + ((float)rand()/(float)RAND_MAX)* 3.0f;

    hasExploded = false;
}

void Firework::move()
{
    for (int loop = 0; loop < particles; loop++)
    {
        if (timeUntilLaunch <= 0)
        {   
            x[loop] += VelX [loop];
            y[loop] += VelY [loop];
            VelY[loop] += Firework::gravity;
            duration --;
        }

    }
    timeUntilLaunch --;

    if (duration <= 0)
    {
        for (int loop2 = 0; loop2 < particles; loop2++)
        {
            VelX[loop2] = -4 + (rand() / (int)RAND_MAX)*8;
            VelY[loop2] = -4 + (rand() / (int)RAND_MAX)*8;
        }
         hasExploded = true;
    }
}


void Firework::explode()
{
       for (int loop = 0; loop < particles; loop++)
    {
        // Dampen the horizontal speed by 1% per frame
       VelX[loop] *= 0.99f;

        // Move the particle
        x[loop] += VelX[loop];
        y[loop] += VelY[loop];

        // Apply gravity to the particle's speed
        VelY[loop] += Firework::gravity;
    }

    // Fade out the particles (alpha is stored per firework, not per particle)
    if (alpha > 0.0f)
    {
        alpha -= 0.01f;
    }
    else // Once the alpha hits zero, then reset the firework
    {
        initialise();
    }
}

主.ccp

#include <iostream>
#include <ctime>
#include <time.h>
#include <windows.h> // *** IMPORTANT: Uncomment for Win32 systems - This must come -BEFORE- gl.h in the include list! ***
#include "GL\glfw.h"
#include "Firework.h"
#include <GL\GL.h>
#include <GL/glu.h>
#include "tinyxml2.h"


#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "lib/glfw/GLFW.lib")

 using namespace std;


 GLint windowWidth = 1024;
 GLint windowHeight = 600;
 GLint frameCount =0;
 GLint texture;

 const int FIREWORKS = 15; // Number of fireworks

 Firework fw[FIREWORKS];


 void initGL()

 {
     glfwSwapInterval(1);


     glfwSetWindowTitle("Fireworks");

     glViewport(0, 0, (GLsizei)windowWidth, (GLsizei)windowHeight);

     glMatrixMode(GL_PROJECTION);

     glLoadIdentity();

     glOrtho(0, windowWidth, windowHeight, 0, 0, 1);

     glShadeModel(GL_SMOOTH);

    // Set our clear colour to opaque black
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    // Disable depth testing (because we're working in 2D!)
    glDisable(GL_DEPTH_TEST);

    // Enable blending (we need this to be able to use an alpha component)
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    // Set the accumulation buffer clearing colour to opaque black
    glClearAccum(0.0f, 0.0f, 0.0f, 1.0f);

    glEnable(GL_POINT_SMOOTH);

}

 void drawScene()

 {
     // Take the contents of the current accumulation buffer and copy it to the colour buffer so that it entirely overwrites it
    glAccum(GL_RETURN, 1.0f);

    // Clear the accumulation buffer (don't worry, we re-grab the screen into the accumulation buffer after drawing our current frame!)
    glClear(GL_ACCUM_BUFFER_BIT);

    // Set ModelView matrix mode and reset to the default identity matrix
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // Displacement trick for exact pixelisation
    glTranslatef(0.375, 0.375, 0);

    // Draw our fireworks
    for (int loop = 0; loop < FIREWORKS; loop++)
    {
        for (int particleLoop = 0; particleLoop < particles; particleLoop++)
        {

            // Set the point size of the firework particles (this needs to be called BEFORE opening the glBegin(GL_POINTS) section!)
            glPointSize(fw[loop].particleSize);

            glBegin(GL_POINTS);
                // Set colour to yellow on the way up, then whatever colour firework should be when exploded   

            if (fw[loop].hasExploded == false)
                {
                    glColor4f(fw[loop].redStart, fw[loop].greenStart, fw[loop].blueStart, 1.0f);
                }
                else
                {
                    glColor4f(fw[loop].red, fw[loop].green, fw[loop].blue, fw[loop].alpha);
                }

                // Draw the point
                glVertex2f(fw[loop].x[particleLoop], fw[loop].y[particleLoop]);
            glEnd();
        }

        // Move the firework appropriately depending on its explosion state
        if (fw[loop].hasExploded == false && fw[loop].type=="Rocket")
        {
            fw[loop].move();
        }
        else
        {
            fw[loop].explode();
        }

 }

     glAccum(GL_ACCUM, 0.85f);

    glfwSwapBuffers();

 }


int main()
{
    int srand((unsigned)time(NULL)); // Seed the random number generator

    // Define our buffer settings
    int redBits     = 8,   greenBits = 8,    blueBits    = 8;
    int alphaBits  = 64, depthBits = 24,   stencilBits = 8;

    // Flag to keep our main loop running
    bool running = true;

    // Initialise glfw
    glfwInit();

    // Create a window
    if(!glfwOpenWindow(windowWidth, windowHeight, redBits, greenBits, blueBits, alphaBits, 0, 0, GLFW_WINDOW))
    {
        cout << "Failed to open window!" << endl;
        glfwTerminate();
        return 0;
    }

    // Call our initGL function to set up our OpenGL options
    initGL();

    while (running == true)
    {
    // Draw our scene
    drawScene();

    // Increase our frame counter
    frameCount++;

    // Exit if ESC was pressed or the window was closed
    running = glfwGetWindowParam(GLFW_OPENED);
    }

    glfwTerminate();

    return 0;
}

烟花.xml

   <?xml version="1.0" ?>
<FireworkDisplay>
  <Firework begin="1000" type="Fountain" colour="0x20FF40" duration="5000">
    <Position x="0" y="-384"/>
  </Firework>
  <Firework begin="2000" type="Fountain" colour="0x4020FF" duration="4000">
    <Position x="100" y="-384"/>
  </Firework>
  <Firework begin="3000" type="Fountain" colour="0xff5099" duration="3000">
    <Position x="-100" y="-384"/>
  </Firework>

  <Firework begin="1000" type="Rocket" colour="0xFF2020" duration="1000">
    <Position x="500" y="-384"/>
    <Velocity x="-3" y="10"/>
  </Firework>
  <Firework begin="2000" type="Rocket" colour="0xFF2020" duration="1000">
    <Position x="0" y="-384"/>
    <Velocity x="0" y="10"/>
  </Firework>
  <Firework begin="3000" type="Rocket" colour="0xFF2020" duration="1000">
    <Position x="-500" y="-384"/>
    <Velocity x="3" y="10"/>
  </Firework>

  <Firework begin="11000" type="Rocket" colour="0xFFFF20" duration="1000">
    <Position x="500" y="-384"/>
    <Velocity x="-3" y="10"/>
  </Firework>
  <Firework begin="12000" type="Rocket" colour="0xFF2020" duration="1000">
    <Position x="0" y="-384"/>
    <Velocity x="0" y="10"/>
  </Firework>
  <Firework begin="13000" type="Rocket" colour="0xFF20FF" duration="1000">
    <Position x="-500" y="-384"/>
    <Velocity x="3" y="10"/>
  </Firework>


  <Firework begin="4000" type="Fountain" colour="0xffFF40" duration="5000">
    <Position x="0" y="-384"/>
  </Firework>
  <Firework begin="5000" type="Fountain" colour="0x4020FF" duration="4000">
    <Position x="-200" y="-384"/>
  </Firework>
  <Firework begin="6000" type="Fountain" colour="0xff5099" duration="3000">
    <Position x="200" y="-384"/>
  </Firework>

  <Firework begin="7000" type="Fountain" colour="0x20FF40" duration="5000">
    <Position x="0" y="-384"/>
  </Firework>
  <Firework begin="8000" type="Fountain" colour="0x4020FF" duration="4000">
    <Position x="400" y="-384"/>
  </Firework>
  <Firework begin="9000" type="Fountain" colour="0xff5099" duration="3000">
    <Position x="-400" y="-384"/>
  </Firework>


  <Firework begin="10000" type="Fountain" colour="0xff8040" duration="1000">
    <Position x="-450" y="-384"/>
  </Firework>
  <Firework begin="10500" type="Fountain" colour="0x40ffFF" duration="1000">
    <Position x="-220" y="-384"/>
  </Firework>
  <Firework begin="11000" type="Fountain" colour="0xffff99" duration="1000">
    <Position x="0" y="-384"/>
  </Firework>
  <Firework begin="11500" type="Fountain" colour="0xff00ff" duration="1000">
    <Position x="220" y="-384"/>
  </Firework>
  <Firework begin="12000" type="Fountain" colour="0x40ffFF" duration="1000">
    <Position x="450" y="-384"/>
  </Firework>

</FireworkDisplay>

最佳答案

if (attr == "Fountain")

这是错误的。它比较指针,而不是字符串内容。使用 strcmp。检查每次出现的情况。

if ( rocket = true)

这将始终为真,因为它是一个赋值,请使用 == 代替。检查每次出现的情况。

关于c++ - 我如何使用 tinyxml 将 xml 属性转换为 C++ 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16426381/

相关文章:

c++ - 将 dll 添加到项目并使功能正常工作

perl - XML::Simple 删除根元素

c++ - 为什么不是 std::string::max_size() == std::string::allocator::max_size()

c++ - VC 2010 上带 SSL 的 libpq

c++ - std::ios_base::sync_with_stdio 如何影响流缓冲?

javascript - 在 DropDownList SelectedIndexChanged 事件上调用 JavaScript 函数 :

c++ - 引用 vector

visual-studio-2010 - Visual Studio 2010 中的属性窗口字体

java - 从单个文件中分离两个 XML

java - 解析 XML 并填充到 Map 中