Sprite没有在SFML中绘制 - 从向量中存储和检索

时间:2013-12-30 10:58:03

标签: c++ vector sfml

我正在使用SFML制作一个滚动太空射击游戏。

我实现项目符号的想法是有一个以下结构的向量:

struct bullet
{
    sf::Sprite sprite;
    char frame;
};

每次用户按下某个键时,都会将一个新结构实例添加到向量中。我的想法是可以更新向量中每个对象的帧值,然后我可以使用switch语句根据它们在动画序列中的距离来更改适用于每个射弹的textureRect。

然而,这不起作用,当按下空间时,不会绘制任何内容。事件正在被触发,但由于没有错误,我无法弄清问题所在。其他一切都很完美。

拍摄功能:

void shoot(sf::Texture texture, std::vector<bullet>& onScreenBullets, sf::Sprite fighter)
{
    bullet newBullet;
    sf::Sprite bulletSprite = newBullet.sprite;
    bulletSprite.setTexture(texture);
    bulletSprite.setTextureRect(sf::IntRect(48,0,4,4));
    bulletSprite.setPosition(fighter.getPosition().x + 6, fighter.getPosition().y + 6);
    newBullet.frame = 0;
    onScreenBullets.push_back(newBullet);
}

函数调用:

while(window.pollEvent(event))
        {
            if(event.type == sf::Event::Closed)
            {
                window.close();
            }

            if(event.type == sf::Event::KeyPressed)
            {
                if(event.key.code == sf::Keyboard::Return && play == false)
                {
                    play = true;
                    clock.restart();
                }

                if(event.key.code == sf::Keyboard::Space && play == true)
                {
                    shoot(texture,onScreenBullets,fighter);
                }
            }
        }

使射弹动画化的逻辑:

for(int i = 0; i < onScreenBullets.size(); i++)
            {
                currentBullet = onScreenBullets.at(i).sprite;
                switch(onScreenBullets[i].frame)
                {
                    case 0:
                        currentBullet.setTextureRect(sf::IntRect(48,4,4,8));
                        break;
                    case 15:
                        currentBullet.setTextureRect(sf::IntRect(48,12,4,8));
                        break;
                    case 30:
                        currentBullet.setTextureRect(sf::IntRect(48,4,4,8));
                        break;
                    case 45:
                        currentBullet.setTextureRect(sf::IntRect(48,12,4,8));
                        break;
                    case 60:
                        onScreenBullets.at(i).frame = 0;
                        break;
                }

                currentBullet.move(0, -1*(projectileSpeed + scrollSpeed));
                window.draw(currentBullet);
                onScreenBullets.at(i).frame++;

                if(!currentView.intersects(currentBullet.getGlobalBounds()));
                {
                    onScreenBullets.erase(onScreenBullets.begin() + i);
                }
            }

完整来源:

#include<SFML/Graphics.hpp>
#include<iostream>
#include<string>
#include<vector>

void rollLeft(sf::Sprite& s, sf::RenderWindow& rw, int frame, char& rollDir, bool& rstatus)
{
    switch(frame)
    {
        case 0:
            s.setTextureRect(sf::IntRect(32,0,8,16));
            s.move(sf::Vector2f(-32.0f,0.0f));
            rw.draw(s);
            rw.display();
            break;

        case 4:
            s.setTextureRect(sf::IntRect(16,0,16,16));
            s.move(sf::Vector2f(-64.0f,0.0f));
            rw.draw(s);
            rw.display();
            break;

        case 8:
            s.setTextureRect(sf::IntRect(40,0,8,16));
            s.move(sf::Vector2f(-32.0f,0.0f));
            rw.draw(s);
            rw.display();
            break;

        case 12:
            s.setTextureRect(sf::IntRect(0,0,16,16));
            s.move(sf::Vector2f(-64.0f,0.0f));
            rw.draw(s);
            rw.display();
            rollDir = 'N';
            rstatus = false;
            break;

        default:
            break;
    }
}

void rollRight(sf::Sprite& s, sf::RenderWindow& rw, int frame, char& rollDir, bool& rstatus)
{
    switch(frame)
    {
        case 0:
            s.setTextureRect(sf::IntRect(40,0,8,16));
            s.move(sf::Vector2f(32.0f,0.0f));
            rw.draw(s);
            rw.display();
            break;

        case 4:
            s.setTextureRect(sf::IntRect(16,0,16,16));
            s.move(sf::Vector2f(64.0f,0.0f));
            rw.draw(s);
            rw.display();
            break;

        case 8:
            s.setTextureRect(sf::IntRect(32,0,8,16));
            s.move(sf::Vector2f(32.0f,0.0f));
            rw.draw(s);
            rw.display();
            break;

        case 12:
            s.setTextureRect(sf::IntRect(0,0,16,16));
            s.move(sf::Vector2f(64.0f,0.0f));
            rw.draw(s);
            rw.display();
            rollDir = 'N';
            rstatus = false;
            break;

        default:
            break;
    }
}

void init(sf::Text& text,sf::Sprite& fighter,sf::Sprite& barLeft,sf::Sprite&     barMiddle,sf::Sprite& barRight,sf::Sprite& marker,sf::RectangleShape& background1,
            sf::RectangleShape& background2,sf::View& view,sf::RenderWindow& window)
{
    text.setPosition(20,240);
    fighter.setPosition(304,448);
    barLeft.setPosition(72,10);
    barMiddle.setPosition(80,10);
    barRight.setPosition(560,10);
    marker.setPosition(88,10);
    background1.setPosition(0,0);
    background2.setPosition(0,-480);
    view.setCenter(320,240);
    window.setView(view);
             }

struct bullet
{
    sf::Sprite sprite;
    char frame;
};

void shoot(sf::Texture texture, std::vector<bullet>& onScreenBullets, sf::Sprite fighter)
{
    bullet newBullet;
    sf::Sprite bulletSprite = newBullet.sprite;
    bulletSprite.setTexture(texture);
    bulletSprite.setTextureRect(sf::IntRect(48,0,4,4));
    bulletSprite.setPosition(fighter.getPosition().x + 6, fighter.getPosition().y + 6);
    newBullet.frame = 0;
    onScreenBullets.push_back(newBullet);
}

int main()
{
    int frame = 0;
    char rollDir = 'N';
    bool roll,move,play,activeBackground = false;
    int timeLimit = 10000;
    int scrollSpeed = 2;
    int projectileSpeed = 5;
    std::vector<bullet> onScreenBullets;
    sf::Sprite currentBullet;
    sf::FloatRect currentView;

    sf::Time time;
    int timeInt;
    sf::Clock clock;

    sf::RenderWindow window(sf::VideoMode(640,480), "Test Window");
    window.setFramerateLimit(60);

    sf::Texture texture;
    if(!texture.loadFromFile("spritesheet.png"))
    {
        std::cout << "Error loading texture from file";
    }

    sf::Font font;
    if(!font.loadFromFile("font.ttf"))
    {
        std::cout << "Error loading font from file";
     }

    sf::Text text;
    text.setFont(font);
    text.setString("Press ENTER to start");
    text.setCharacterSize(24);
    text.setColor(sf::Color::White);

    sf::Sprite fighter;
    fighter.setTexture(texture);
    fighter.setTextureRect(sf::IntRect(0,0,16,16));
    fighter.setScale(sf::Vector2f(2,2));

    sf::Sprite barLeft,barRight,barMiddle;
    barLeft.setTexture(texture);
    barRight.setTexture(texture);
    barMiddle.setTexture(texture);

    barLeft.setTextureRect(sf::IntRect(0,16,8,16));
    barRight.setTextureRect(sf::IntRect(39,16,8,16));
    barMiddle.setTextureRect(sf::IntRect(9,16,30,16));

    barMiddle.setScale(sf::Vector2f(16,1));

    sf::Sprite marker;
    marker.setTexture(texture);
    marker.setTextureRect(sf::IntRect(0,0,16,16));
    marker.setRotation(90);

    sf::RectangleShape background1(sf::Vector2f(640,480));
    background1.setTexture(&texture);
    background1.setTextureRect(sf::IntRect(0,32,640,480));

    sf::RectangleShape background2(sf::Vector2f(640,480));
    background2.setTexture(&texture);
    background2.setTextureRect(sf::IntRect(0,32,640,480));

    sf::View view(sf::FloatRect(0,0,640,480));
    window.setView(view);

    while(window.isOpen())
    {
        sf::Event event;
        while(window.pollEvent(event))
        {
            if(event.type == sf::Event::Closed)
            {
                window.close();
            }

            if(event.type == sf::Event::KeyPressed)
            {
                if(event.key.code == sf::Keyboard::Return && play == false)
                {
                    play = true;
                    clock.restart();
                }

                if(event.key.code == sf::Keyboard::Space && play == true)
                {
                    shoot(texture,onScreenBullets,fighter);
                }
            }
        }

        if(!play)
        {
            window.clear(sf::Color::Black);
            window.draw(text);
                init(text,fighter,barLeft,barMiddle,barRight,marker,background1,background2,view,window);
            window.display();
        }

        if(play)
        {

            move = false;

            if(!roll)
            {
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::W))
                {
                    fighter.move(sf::Vector2f(0.0f,-4.0f));
                    move = true;
                }

                if(sf::Keyboard::isKeyPressed(sf::Keyboard::S))
                {
                    fighter.move(sf::Vector2f(0.0f,4.0f));
                    move = true;
                }

                if(sf::Keyboard::isKeyPressed(sf::Keyboard::A))
                {
                    fighter.move(sf::Vector2f(-4.0f,0.0f));
                    move = true;
                }

                if(sf::Keyboard::isKeyPressed(sf::Keyboard::D))
                {
                    fighter.move(sf::Vector2f(4.0f,0.0f));
                    move = true;
                }

                if(sf::Keyboard::isKeyPressed(sf::Keyboard::A) &&     sf::Keyboard::isKeyPressed(sf::Keyboard::LShift) && rollDir == 'N')
                {
                    frame = 0;
                    rollDir = 'L';
                    roll = true;
                }

                if(sf::Keyboard::isKeyPressed(sf::Keyboard::D) &&     sf::Keyboard::isKeyPressed(sf::Keyboard::LShift) && rollDir == 'N')
                {
                    frame = 0;
                    rollDir = 'R';
                    roll = true;
                }
            }

            switch(rollDir)
            {
                case 'L':
                    rollLeft(fighter,window,frame,rollDir,roll);
                    break;

                case 'R':
                    rollRight(fighter,window,frame,rollDir,roll);
                    break;
            }

            window.clear(sf::Color::Black);
            window.draw(background1);
            window.draw(background2);

            time = clock.getElapsedTime();
            timeInt = time.asMilliseconds();

            view.move(0,-1*scrollSpeed);
            window.setView(view);

            fighter.move(0,-1*scrollSpeed);
            window.draw(fighter);

            currentView.left = view.getCenter().x - view.getSize().x / 2;
            currentView.top = view.getCenter().y - view.getSize().y / 2;
            currentView.width = view.getSize().x;
            currentView.height = view.getSize().y;

            for(int i = 0; i < onScreenBullets.size(); i++)
            {
                currentBullet = onScreenBullets.at(i).sprite;
                switch(onScreenBullets[i].frame)
                {
                    case 0:
                        currentBullet.setTextureRect(sf::IntRect(48,4,4,8));
                        break;
                    case 15:
                        currentBullet.setTextureRect(sf::IntRect(48,12,4,8));
                        break;
                    case 30:
                        currentBullet.setTextureRect(sf::IntRect(48,4,4,8));
                        break;
                    case 45:
                        currentBullet.setTextureRect(sf::IntRect(48,12,4,8));
                        break;
                    case 60:
                        onScreenBullets.at(i).frame = 0;
                        break;
                }

                currentBullet.move(0, -1*(projectileSpeed + scrollSpeed));
                window.draw(currentBullet);
                onScreenBullets.at(i).frame++;

                if(!currentView.intersects(currentBullet.getGlobalBounds()));
                {
                    onScreenBullets.erase(onScreenBullets.begin() + i);
                }
            }

            barLeft.move(0,-1*scrollSpeed);
            barRight.move(0,-1*scrollSpeed);
            barMiddle.move(0,-1*scrollSpeed);
            window.draw(barLeft);
            window.draw(barRight);
            window.draw(barMiddle);

            if(int (view.getCenter().y - 240) % 480 == 0)
            {
                if(!activeBackground)
                {
                    activeBackground = true;
                    background1.move(0,-960);
                } else {
                    activeBackground = false;
                    background2.move(0,-960);
                }
            }

            marker.move(480.0f/(timeLimit/1000)/60,-1*scrollSpeed);
            window.draw(marker);

            text.move(0,-1*scrollSpeed);

            if(timeInt >= timeLimit+250)
            {
                play = false;
                text.setString("End");
            }

            window.display();
            frame++;
        }
    }
    return 0;
}

1 个答案:

答案 0 :(得分:1)

我无法完全确定问题所在,但我认为有一些问题存在:

我删掉了一点来做这个简短的事情:

void shoot(sf::Texture texture) { //creates a copy of your texture you pass

bulletSprite.setTexture(texture); //actually takes the address of your texture 

(setTexture(sf::Texture&)) <-- that's how the method probably looks like


onScreenBullets.push_back(newBullet); // I think this is okay since newBullet is bein copied into the vector so when the object runs out of scope it doesn't matter but

// here your texture object is gone now and the address your Sprite holds is not valid anymore
}

void shoot(sf::Texture texture) { //creates a copy of your texture you pass bulletSprite.setTexture(texture); //actually takes the address of your texture (setTexture(sf::Texture&)) <-- that's how the method probably looks like onScreenBullets.push_back(newBullet); // I think this is okay since newBullet is bein copied into the vector so when the object runs out of scope it doesn't matter but // here your texture object is gone now and the address your Sprite holds is not valid anymore }

Ooookay,

拍摄方法是问题

做这样的事情:

    void shoot(sf::Texture& texture, std::vector<bullet>& onScreenBullets, sf::Sprite& fighter)
    {
        bullet newBullet;
        sf::Sprite bulletSprite = newBullet.sprite; // this makes no sense
        bulletSprite.setTexture(texture); // you set the texture to the local Sprite object
        bulletSprite.setTextureRect(sf::IntRect(48,0,4,4)); // and this as well and the next line as well
        bulletSprite.setPosition(fighter.getPosition().x + 6, fighter.getPosition().y + 6);
        newBullet.frame = 0;
        onScreenBullets.push_back(newBullet); //but here you push back your struct and the sprite in the struct
//That you haven't used at all :O
}

setTexture方法: http://sfml-dev.org/documentation/2.0/classsf_1_1Sprite.php#a3729c88d88ac38c19317c18e87242560

其他一些人认为我注意到了:

  1. 使结构中的“框架”成为一个int(它不能用于char)

  2. 您的交叉方法可能已被破坏,您只需立即擦除子弹(注释掉它以查看子弹飞行)

  3. 总的来说,你经常复制子弹对象和类似的东西。我认为你需要更基本的理解。对不起; x