如何在用户仍然使用SFML按住键的同时在Sprite表上的两个不同部分之间来回切换

时间:2018-08-31 10:45:04

标签: c++ time sprite sfml sprite-sheet

所以我在这里的唯一目标是左右移动精灵,并且在精灵移动的同时,我想每半秒钟在精灵表的两个不同部分之间切换。

我已经尝试了所有可能想到的方法,因此我将其工作了,并且仅执行了所需功能。 (编辑:我已对其进行了更改,以尝试遵循另一位用户给出的建议。)我已经上网了,但据我所知,我找不到任何答案。我敢肯定,我忽略了某些事情,而且这很简单,但这就是为什么我需要您的输入。

我要使用的子画面的第三部分是x = 800,y = 0处朝左的动画在顶部,y = 600处朝右的动画在底部

Here is the sprite sheet I am using

第一个用于静止不动,第二行中的第二个是我要在“行走”时切换的位置

无论如何,这是我的代码:

#include "pch.h"
#include <iostream>
#include "SFML/Graphics.hpp"
#include <random>
#include <unordered_map>

enum State 
{
    Walking,
    Standing
};
enum Direction
{
    Left,
    Right
};

int main(int argc, char ** argv)
{
    /* Gregory */

    sf::Texture GregorySpriteSheet_T;
    GregorySpriteSheet_T.loadFromFile("Images/GregorySpriteSheet.png");
    sf::IntRect GregorySpriteRect(0, 600, 400, 600);
    sf::Sprite Gregory(GregorySpriteSheet_T, GregorySpriteRect);

    sf::RenderWindow renderWindow(sf::VideoMode(1600,800), "SFML 2 Demo");

    sf::Event event;



    sf::Time timePerFrame = sf::seconds(1.0f / 60.0f);
    sf::Clock deltaClock;
    sf::Time timeSinceLastUpdate = sf::Time::Zero;


    State isWalking{ Standing };
    sf::Clock walkClock;
    Direction direction = Right;




    /* RENDER WINDOW LOOP */


    while (renderWindow.isOpen())
    {

        sf::Time deltaTime = deltaClock.restart();
        timeSinceLastUpdate += deltaTime;

        while (timeSinceLastUpdate >= timePerFrame)
        {
            timeSinceLastUpdate -= timePerFrame;



            while (renderWindow.pollEvent(event))
            {
                if (event.type == sf::Event::EventType::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
                {
                    renderWindow.close();
                }


                if (event.type == sf::Event::EventType::KeyPressed)
                {
                    if (event.key.code == sf::Keyboard::Right)
                    {
                        isWalking = Walking;
                        direction = Right;
                    }

                }
                if (event.type == sf::Event::EventType::KeyReleased)
                {
                    if (event.key.code == sf::Keyboard::Right)
                    {
                        isWalking = Standing;
                    }

                }


                if (event.type == sf::Event::EventType::KeyPressed)
                {
                    if (event.key.code == sf::Keyboard::Left)
                    {
                        isWalking = Walking;
                        direction = Left;

                    }
                }
                if (event.type == sf::Event::EventType::KeyReleased)
                {
                    if (event.key.code == sf::Keyboard::Left)
                    {
                        isWalking = Standing;

                    }
                }
            }



            if (isWalking == Walking)
            {
                if (direction == Right)
                    GregorySpriteRect.top = 600;
                if (direction == Left)
                    GregorySpriteRect.top = 0;

                if (GregorySpriteRect.left == 0)
                    GregorySpriteRect.left = 400;

                if ((int(walkClock.getElapsedTime().asSeconds() / 1.5f) % 2) == 1)
                {
                    if (GregorySpriteRect.left == 400)
                        GregorySpriteRect.left == 800;
                    if (GregorySpriteRect.left == 800)
                        GregorySpriteRect.left == 400;
                    walkClock.restart();
                }
            }

            {
                using kb = sf::Keyboard;

                    if (kb::isKeyPressed(kb::Right))
                    {
                        Gregory.move(400 * timePerFrame.asSeconds(), 0.0f);
                        direction = Right;
                        isWalking = Walking;
                    }


                    if (kb::isKeyPressed(kb::Left))
                    {
                        Gregory.move(-400 * timePerFrame.asSeconds(), 0.0f);
                        direction = Left;
                        isWalking = Walking;
                    }

                    if (kb::isKeyPressed(kb::Right) && kb::isKeyPressed(kb::Left))
                    {
                        isWalking = Standing;
                    }

            }


            if (isWalking == Standing)
            {
                GregorySpriteRect.left = 0;

                if (direction == Right)
                    GregorySpriteRect.top = 600;
                if (direction == Left)
                    GregorySpriteRect.top = 0;
            }

        }




        Gregory.setTextureRect(GregorySpriteRect);

        renderWindow.clear();
        renderWindow.draw(Gregory);
        renderWindow.display();

    }
                /* END RENDER WINDOW LOOP */



}

2 个答案:

答案 0 :(得分:0)

这里是一个建议,但是有很多选择:

首先,稍微重写事件处理,以便您可以区分是第一次按住键还是随后的键。一种简单的方法是拥有一个enum State { Standing, Walking }并将其设置为您的密钥处理程序中的适当值(例如“不行走且不握住钥匙?将状态设置为行走”)

然后,当玩家开始行走时,(重新)启动一个“行走”时钟。

最后,当您实际渲染播放器时,请检查此时钟并将步行后的过期时间除以步行时间(这决定了步行帧应保持多长时间)。如果此类行走周期的数量是偶数,请使用左侧的行走小精灵,否则使用右侧的行走小精灵。

当然,这种技术很容易推广到较大的行走框架。

答案 1 :(得分:0)

所以对于将来在这里出现的任何人,我都缺少一条重要的电话:

Gregory.setTextureRect(GregorySpriteRect);

或者在我的“ if”语句中的“ if(isWalking == Walking)”下,或者在时钟下(例如我在这里所做的)。将完整的代码粘贴到下面。现在可以双向使用。不确定这有多理想,但是如果您是像我这样的业余爱好者,这应该会有所帮助。

还请注意,我已经回复了Botje回答中建议的一些更改。尽管我必须赞扬他在建议使用枚举的“行走”和“站立”以及方向指导方面给了我很大的帮助。由于浮点变量的舍入误差,我还使用了“>”运算符,而不是教授建议的“ ==”运算符。

干杯!

#include "pch.h"
#include <iostream>
#include "SFML/Graphics.hpp"
#include <random>
#include <unordered_map>

enum State 
{
    Walking,
    Standing
};
enum Direction
{
    Left,
    Right
};

int main(int argc, char ** argv)
{
    /* Gregory */

    sf::Texture GregorySpriteSheet_T;
    GregorySpriteSheet_T.loadFromFile("Images/GregorySpriteSheet.png");
    sf::IntRect GregorySpriteRect(0, 600, 400, 600);
    sf::Sprite Gregory(GregorySpriteSheet_T, GregorySpriteRect);

    sf::RenderWindow renderWindow(sf::VideoMode(1600,800), "SFML 2 Demo");

    sf::Event event;



    sf::Time timePerFrame = sf::seconds(1.0f / 60.0f);
    sf::Clock deltaClock;
    sf::Time timeSinceLastUpdate = sf::Time::Zero;


    State isWalking{ Standing };
    sf::Clock walkClock;
    Direction direction = Right;




    /* RENDER WINDOW LOOP */


    while (renderWindow.isOpen())
    {

        sf::Time deltaTime = deltaClock.restart();
        timeSinceLastUpdate += deltaTime;

        while (timeSinceLastUpdate >= timePerFrame)
        {
            timeSinceLastUpdate -= timePerFrame;



            while (renderWindow.pollEvent(event))
            {
                if (event.type == sf::Event::EventType::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
                {
                    renderWindow.close();
                }


                if (event.type == sf::Event::EventType::KeyPressed)
                {
                    if (event.key.code == sf::Keyboard::Right)
                    {
                        isWalking = Walking;
                        direction = Right;
                        GregorySpriteRect.top = 600;
                    }

                }
                if (event.type == sf::Event::EventType::KeyReleased)
                {
                    if (event.key.code == sf::Keyboard::Right)
                    {
                        isWalking = Standing;
                    }

                }


                if (event.type == sf::Event::EventType::KeyPressed)
                {
                    if (event.key.code == sf::Keyboard::Left)
                    {
                        isWalking = Walking;
                        direction = Left;
                        GregorySpriteRect.top = 0;

                    }
                }
                if (event.type == sf::Event::EventType::KeyReleased)
                {
                    if (event.key.code == sf::Keyboard::Left)
                    {
                        isWalking = Standing;
                    }
                }
            }



            if (isWalking == Walking)
            {
                if (direction == Right)
                    GregorySpriteRect.top = 600;
                else if (direction == Left)
                    GregorySpriteRect.top = 0;
                else 
                    GregorySpriteRect.top = 600;

                if (GregorySpriteRect.left == 0)
                    GregorySpriteRect.left = 400;

                if (walkClock.getElapsedTime().asSeconds() > 0.5f)
                {
                    if (GregorySpriteRect.left == 400)
                        GregorySpriteRect.left = 800;
                    else if (GregorySpriteRect.left == 800)
                        GregorySpriteRect.left = 400;
                    else
                        GregorySpriteRect.left += 0;

                    walkClock.restart();
                }

                Gregory.setTextureRect(GregorySpriteRect);

            }

            {
                using kb = sf::Keyboard;

                    if (kb::isKeyPressed(kb::Right))
                    {
                        Gregory.move(400 * timePerFrame.asSeconds(), 0.0f);
                        direction = Right;
                    }


                    if (kb::isKeyPressed(kb::Left))
                    {
                        Gregory.move(-400 * timePerFrame.asSeconds(), 0.0f);
                        direction = Left;
                    }

                    if (kb::isKeyPressed(kb::Right) && kb::isKeyPressed(kb::Left))
                    {
                        isWalking = Standing;
                        direction = Right;
                    }

            }


            if (isWalking == Standing)
            {
                GregorySpriteRect.left = 0;

                if (direction == Right)
                    GregorySpriteRect.top = 600;
                if (direction == Left)
                    GregorySpriteRect.top = 0;
            }

        }




        Gregory.setTextureRect(GregorySpriteRect);

        renderWindow.clear();
        renderWindow.draw(Gregory);
        renderWindow.display();

    }
                /* END RENDER WINDOW LOOP */



}