所以我这里唯一的目标是左右移动精灵,当精灵移动时,我想每隔半秒在我的精灵表的两个不同部分之间切换。
我已经尝试了所有我能想到的东西,所以我让它保持工作,而不仅仅是实现了所需的功能。 (编辑:我试图按照另一个用户的建议改变它)我在网上看过,但据我所知,我找不到任何答案。我敢肯定有一些我忽略的东西,它很简单,但这就是我需要你输入的原因。
我要使用的精灵表的第三部分是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 */
}
这是一个建议,但有很多选择:
首先,稍微重写您的事件处理,以便您可以在第一次持有密钥和后续时间之间进行区分。一个简单的方法是使用enum State { Standing, Walking }
并将其设置为您的密钥处理程序中的适当值(例如“不行走并且密钥被保持?设置状态为行走”)
然后,当玩家开始行走时,(重新启动“墙”时钟。
最后,当你实际渲染你的玩家时,检查这个时钟并划分自步行时间以来走过的时间(这决定了应该保持一个步行帧的长度)。如果有相同数量的步行时段,请使用左步行精灵,否则使用右步行精灵。
当然,这种技术很容易推广到更大的步行框架集。
所以对于将来在这里结束的人来说,我错过了一条至关重要的路线:
Gregory.setTextureRect(GregorySpriteRect);
在“if(isWalking == Walking)”下的时钟的“if”语句中,或者在它下面(就像我在这里所做的那样)。粘贴下面的完整代码。现在适用于两个方向。不确定这是多么优越,但如果你像我这样的业余爱好者应该有所帮助。
还要注意我已经恢复了Botje的回答中提出的一些改变。虽然我必须相信他能帮助我使用enum's for Walking and Standing以及方向。由于浮点变量的舍入误差,我还使用了一个“>”运算符而不是我教授建议的“==”运算符。
干杯!
#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 */
}