- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 xcode 作为编译器并使用 SFML 作为库,用 C++ 制作一个简单的游戏。到目前为止,我已经创建了一个 GUI、一个背景和一个 sprite(用于宇宙飞船)。我还添加了箭头键检测以便能够移动对象,但问题是当我移动对象时它移动不流畅,你可以看到它有点“跳跃”。
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include "Spaceship.hpp"
#include <vector>
// Here is a small helper for you! Have a look.
#include "ResourcePath.hpp"
int main(int, char const**)
{
// Create the main window
sf::RenderWindow window(sf::VideoMode(800, 600), "SpaceShuttle");
window.setFramerateLimit(30);
// Call to non-static member function without an object argument
// Set the Icon
sf::Image icon;
if (!icon.loadFromFile(resourcePath() + "space-shuttle.png")) {
return EXIT_FAILURE;
}
window.setIcon(icon.getSize().x, icon.getSize().y, icon.getPixelsPtr());
// Load a sprite to display
sf::Texture texture;
if (!texture.loadFromFile(resourcePath() + "bg.png")) {
return EXIT_FAILURE;
}
sf::Sprite sprite(texture);
// Create a graphical text to display
sf::Font font;
if (!font.loadFromFile(resourcePath() + "sansation.ttf")) {
return EXIT_FAILURE;
}
sf::Text text("SpaceShuttle K1LLM33K", font, 50);
text.setFillColor(sf::Color::White);
text.setPosition(100.0, 130.0);
// Load a music to play
/* sf::Music music; if (!music.openFromFile(resourcePath() + "nice_music.ogg")) { return EXIT_FAILURE; }
// Play the music
music.play();
*/
Spaceship spaceship(window);
sf::Clock sf_clock;
// Start the game loop
while (window.isOpen()) {
// Process events
sf::Event event;
while (window.pollEvent(event)) {
// Close window: exit
if (event.type == sf::Event::Closed) {
window.close();
}
// Escape pressed: exit
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) {
window.close();
}
// Move Spaceship
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) { spaceship.moveship('l'); }
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) { spaceship.moveship('r'); }
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) { spaceship.moveship('u'); }
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) { spaceship.moveship('d'); }
}
// Clear screen
window.clear();
// Draw the sprite(s)
window.draw(sprite);
spaceship.drawsprite(window);
// Draw the string(s)
window.draw(text);
// Update the window
window.display();
}
return EXIT_SUCCESS;
}
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include "ResourcePath.hpp"
#include "Spaceship.hpp"
Spaceship::Spaceship(sf::RenderWindow& game_window){
auto surface = game_window.getSize();
ss_x = surface.x/2;
ss_y = surface.y/2;
ss_speed = 5;
ss_width = 128;
ss_height = 128;
ss_radius = ss_width/2;
}
void Spaceship::drawsprite(sf::RenderWindow& game_window){
sf::Texture ship;
if (!ship.loadFromFile(resourcePath() + "space-shuttle-64.png")) {
return EXIT_FAILURE;
}
sf::Sprite ss_sprite(ship);
ss_sprite.setPosition(ss_x - ss_sprite.getGlobalBounds().width/2, ss_y - ss_sprite.getGlobalBounds().height/2);
game_window.draw(ss_sprite);
}
void Spaceship::moveship(char move){
if(move == 'l'){ ss_x -= ss_speed; }
else if(move == 'r'){ ss_x += ss_speed; }
else if(move == 'u'){ ss_y -= ss_speed; }
else if(move == 'd'){ ss_y += ss_speed; }
}
Spaceship::~Spaceship(){}
#ifndef Spaceship_hpp
#define Spaceship_hpp
#include <iostream>
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include <stdio.h>
using namespace std;
class Spaceship {
public:
Spaceship();
Spaceship(sf::RenderWindow&);
~Spaceship();
void moveship(char);
void drawsprite(sf::RenderWindow&);
private:
signed int ss_x, ss_y;
unsigned int ss_speed;
int ss_width, ss_height, ss_radius;
};
#endif /* Spaceship_hpp */
最佳答案
正如评论中所建议的那样,这里的问题是您没有在计算中考虑两帧之间耗时。因此,发生的情况是您在任何帧添加了固定量的速度,而忽略了两个连续帧可能需要非常不同的时间才能完成这一事实。
还有另一个问题(这似乎是您问题的主要原因):您正在检查事件循环内部是否按下了键。这是不正确的,只有当你的键被按下并且在循环期间有其他事件时,这才是正确的。你需要在每一帧检查这个。
解决最后一个问题的另一种方法是在检测到 press
/< 时将 bool 标志设置为 true
/false
code>release 为您要测试的键。如果您查看 isKeyPressed
方法,您还会发现第二种方法比第一种方法更有效。
更改主循环以获取每一帧耗时的最简单方法,according to the docs是这样的:
sf::Clock sf_clock;
// Start the game loop
while (window.isOpen()) {
// Get time elapsed since last frame
float dt = clock.restart().asSeconds();
// Process events
sf::Event event;
while (window.pollEvent(event)) {
// Close window: exit
}
// Move Spaceship, this must be done outside of the pollEvent loop !
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) spaceship.moveship(dt, 'l');
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) spaceship.moveship(dt, 'r');
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) spaceship.moveship(dt, 'u');
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) spaceship.moveship(dt, 'd');
}
// Draw, etc..
}
然后你必须在 moveship
方法中考虑 dt
(我在 switch case< 中更改了你的
if/else if
/code>,我发现在这种情况下它更干净并且应该更有效率):
void Spaceship::moveship(float dt, char move) {
switch (move) {
case 'l': ss_x -= dt * ss_speed_x; break;
case 'r': ss_x += dt * ss_speed_x; break;
case 'u': ss_y -= dt * ss_speed_y; break;
case 'd': ss_y += dt * ss_speed_y; break;
}
}
按照 Jesper Juhl 的建议,我做了一些 integration在这里(你真的应该看看 the article )。
顺便说一句,我建议对您的代码进行一些修改:
// First of all, you should use floating-point values that you convert
// in screen space at render time for your coordinates
// You could also think about using vectors instead, I won't here
class Spaceship {
private:
float ss_x, ss_y;
float ss_speed_x, ss_speed_y;
// You should also store your sprite instead of creating it over
// and over again
sf::Sprite ss_sprite;
};
Spaceship::Spaceship(sf::RenderWindow& game_window) {
// You can then take those modifications into account
// in your constructor:
auto surface = game_window.getSize();
ss_x = ss_y = 0.5f;
ss_speed_x = 5.f / surface.x;
ss_speed_y = 5.f / surface.y;
ss_width = 128;
ss_height = 128;
ss_radius = ss_width/2;
sf::Texture ship;
if (!ship.loadFromFile(resourcePath() + "space-shuttle-64.png")) {
// This is really an awful way to handle an error, but I won't
// go into details here. A better way would be to have an Init()
// method that returns an error code on failure for example.
exit(EXIT_FAILURE);
}
ss_sprite = sf::Sprite(ship);
// http://www.sfml-dev.org/documentation/2.4.1/classsf_1_1Transformable.php#a56c67bd80aae8418d13fb96c034d25ec
ss_sprite.setOrigin(ss_width / 2, ss_height / 2);
}
// Finally, you reflect those modifications in your draw code
void Spaceship::drawsprite(sf::RenderWindow& game_window){
auto size = game_window.getSize();
ss_sprite.setPosition(ss_x * size.x, ss_y * size.y);
game_window.draw(ss_sprite);
}
关于c++ - SFML 2D 游戏——流畅的宇宙飞船运动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41779058/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!