Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
sfml2d游戏&x2013;太空船平稳运行 我试图用XCODE作为编译程序,用SFML作为库,在C++中做一个简单的游戏。到目前为止,我已经为宇宙飞船创建了一个GUI、一个背景和一个精灵。我还添加了箭头键检测,以便能够移动对象,但问题是,当我移动对象时,它移动不平稳,你可以看到它有点“跳跃” main.cpp #包括 #包括 #包括“Spaceship.hpp” #包括 //这里有一个小帮手给你!看一看。 #包括“ResourcePath.hpp” int main(int,字符常量**) { //创建主窗口 sf::渲染窗口(sf::视频模式(800600),“航天飞机”); 设置帧率限制(30); //不带对象参数调用非静态成员函数 //设置图标 sf::图像图标; 如果(!icon.loadFromFile(resourcePath()+“space sputter.png”)){ 返回退出失败; } setIcon(icon.getSize().x,icon.getSize().y,icon.getPixelsPtr()); //加载要显示的精灵 sf::纹理; 如果(!texture.loadFromFile(resourcePath()+“bg.png”)){ 返回退出失败; } 雪碧雪碧(纹理); //创建要显示的图形文本 sf::字体; 如果(!font.loadFromFile(resourcePath()+“sansation.ttf”)){ 返回退出失败; } sf::文本文本(“航天飞机K1LLM33K”,字体,50); text.setFillColor(sf::Color::White); text.setPosition(100.0130.0); //加载要播放的音乐 /*sf::Music Music;if(!Music.openFromFile(resourcePath()+“nice_Music.ogg”){return EXIT_FAILURE;} //演奏音乐 音乐。播放(); */ 太空船太空船(窗口); sf::时钟sf_时钟; //开始游戏循环 while(window.isOpen()){ //处理事件 sf::事件; while(window.pollEvent(事件)){ //关闭窗口:退出 如果(event.type==sf::event::Closed){ window.close(); } //按下退出按钮:退出 if(event.type==sf::event::KeyPressed&&event.key.code==sf::Keyboard::Escape){ window.close(); } //移动宇宙飞船 如果(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){spaceship.moveship('l');} 如果(sf::Keyboard::iskeypress(sf::Keyboard::Right)){spaceship.moveship('r');} 如果(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){spaceship.moveship('u');} 如果(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)){spaceship.moveship('d');} } //清屏 window.clear(); //画精灵 窗口。绘制(精灵); 太空船。drawsprite(窗口); //画线 窗口。绘制(文本); //更新窗口 window.display(); } 返回退出成功; } 太空船 #包括 #包括 #包括“ResourcePath.hpp” #包括“Spaceship.hpp” 太空船::太空船(sf::渲染窗口和游戏窗口){ auto surface=game_window.getSize(); ss_x=表面x/2; ss_y=表面y/2; ss_速度=5; ss_宽度=128; ss_高度=128; ss_半径=ss_宽度/2; } 虚空宇宙飞船::drawsprite(sf::渲染窗口和游戏窗口){ sf::纹理船; 如果(!ship.loadFromFile(resourcePath()+“space-shutter-64.png”)){ 返回退出失败; } sf::雪碧ss_雪碧(船); ss_sprite.setPosition(ss_x-ss_sprite.getGlobalBounds().width/2,ss_y-ss_sprite.getGlobalBounds().height/2); 游戏窗口绘制(ss_sprite); } void Spaceship::moveship(字符移动){ 如果(move='l'){ss_x-=ss_speed;} 如果(move='r'){ss_x+=ss_speed;} else if(move='u'){ss_y-=ss_speed;} 如果(move='d'){ss_y+=ss_speed;} } 太空船::~Spaceship(){} 太空船 #ifndef飞船(水电站) #定义太空船 #包括 #包括 #包括 #包括 使用名称空间std; 二级宇宙飞船{ 公众: 宇宙飞船(); 宇宙飞船(sf::RenderWindow&); ~宇宙飞船(); 无效船舶(char); 虚空drawsprite(sf::RenderWindow&); 私人: 署名int ss_x,ss_y; 无符号整数速度; int ss_宽度、ss_高度、ss_半径; }; #endif/*宇宙飞船水电站*/_C++_User Interface_Sfml - Fatal编程技术网

sfml2d游戏&x2013;太空船平稳运行 我试图用XCODE作为编译程序,用SFML作为库,在C++中做一个简单的游戏。到目前为止,我已经为宇宙飞船创建了一个GUI、一个背景和一个精灵。我还添加了箭头键检测,以便能够移动对象,但问题是,当我移动对象时,它移动不平稳,你可以看到它有点“跳跃” main.cpp #包括 #包括 #包括“Spaceship.hpp” #包括 //这里有一个小帮手给你!看一看。 #包括“ResourcePath.hpp” int main(int,字符常量**) { //创建主窗口 sf::渲染窗口(sf::视频模式(800600),“航天飞机”); 设置帧率限制(30); //不带对象参数调用非静态成员函数 //设置图标 sf::图像图标; 如果(!icon.loadFromFile(resourcePath()+“space sputter.png”)){ 返回退出失败; } setIcon(icon.getSize().x,icon.getSize().y,icon.getPixelsPtr()); //加载要显示的精灵 sf::纹理; 如果(!texture.loadFromFile(resourcePath()+“bg.png”)){ 返回退出失败; } 雪碧雪碧(纹理); //创建要显示的图形文本 sf::字体; 如果(!font.loadFromFile(resourcePath()+“sansation.ttf”)){ 返回退出失败; } sf::文本文本(“航天飞机K1LLM33K”,字体,50); text.setFillColor(sf::Color::White); text.setPosition(100.0130.0); //加载要播放的音乐 /*sf::Music Music;if(!Music.openFromFile(resourcePath()+“nice_Music.ogg”){return EXIT_FAILURE;} //演奏音乐 音乐。播放(); */ 太空船太空船(窗口); sf::时钟sf_时钟; //开始游戏循环 while(window.isOpen()){ //处理事件 sf::事件; while(window.pollEvent(事件)){ //关闭窗口:退出 如果(event.type==sf::event::Closed){ window.close(); } //按下退出按钮:退出 if(event.type==sf::event::KeyPressed&&event.key.code==sf::Keyboard::Escape){ window.close(); } //移动宇宙飞船 如果(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){spaceship.moveship('l');} 如果(sf::Keyboard::iskeypress(sf::Keyboard::Right)){spaceship.moveship('r');} 如果(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){spaceship.moveship('u');} 如果(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)){spaceship.moveship('d');} } //清屏 window.clear(); //画精灵 窗口。绘制(精灵); 太空船。drawsprite(窗口); //画线 窗口。绘制(文本); //更新窗口 window.display(); } 返回退出成功; } 太空船 #包括 #包括 #包括“ResourcePath.hpp” #包括“Spaceship.hpp” 太空船::太空船(sf::渲染窗口和游戏窗口){ auto surface=game_window.getSize(); ss_x=表面x/2; ss_y=表面y/2; ss_速度=5; ss_宽度=128; ss_高度=128; ss_半径=ss_宽度/2; } 虚空宇宙飞船::drawsprite(sf::渲染窗口和游戏窗口){ sf::纹理船; 如果(!ship.loadFromFile(resourcePath()+“space-shutter-64.png”)){ 返回退出失败; } sf::雪碧ss_雪碧(船); ss_sprite.setPosition(ss_x-ss_sprite.getGlobalBounds().width/2,ss_y-ss_sprite.getGlobalBounds().height/2); 游戏窗口绘制(ss_sprite); } void Spaceship::moveship(字符移动){ 如果(move='l'){ss_x-=ss_speed;} 如果(move='r'){ss_x+=ss_speed;} else if(move='u'){ss_y-=ss_speed;} 如果(move='d'){ss_y+=ss_speed;} } 太空船::~Spaceship(){} 太空船 #ifndef飞船(水电站) #定义太空船 #包括 #包括 #包括 #包括 使用名称空间std; 二级宇宙飞船{ 公众: 宇宙飞船(); 宇宙飞船(sf::RenderWindow&); ~宇宙飞船(); 无效船舶(char); 虚空drawsprite(sf::RenderWindow&); 私人: 署名int ss_x,ss_y; 无符号整数速度; int ss_宽度、ss_高度、ss_半径; }; #endif/*宇宙飞船水电站*/

sfml2d游戏&x2013;太空船平稳运行 我试图用XCODE作为编译程序,用SFML作为库,在C++中做一个简单的游戏。到目前为止,我已经为宇宙飞船创建了一个GUI、一个背景和一个精灵。我还添加了箭头键检测,以便能够移动对象,但问题是,当我移动对象时,它移动不平稳,你可以看到它有点“跳跃” main.cpp #包括 #包括 #包括“Spaceship.hpp” #包括 //这里有一个小帮手给你!看一看。 #包括“ResourcePath.hpp” int main(int,字符常量**) { //创建主窗口 sf::渲染窗口(sf::视频模式(800600),“航天飞机”); 设置帧率限制(30); //不带对象参数调用非静态成员函数 //设置图标 sf::图像图标; 如果(!icon.loadFromFile(resourcePath()+“space sputter.png”)){ 返回退出失败; } setIcon(icon.getSize().x,icon.getSize().y,icon.getPixelsPtr()); //加载要显示的精灵 sf::纹理; 如果(!texture.loadFromFile(resourcePath()+“bg.png”)){ 返回退出失败; } 雪碧雪碧(纹理); //创建要显示的图形文本 sf::字体; 如果(!font.loadFromFile(resourcePath()+“sansation.ttf”)){ 返回退出失败; } sf::文本文本(“航天飞机K1LLM33K”,字体,50); text.setFillColor(sf::Color::White); text.setPosition(100.0130.0); //加载要播放的音乐 /*sf::Music Music;if(!Music.openFromFile(resourcePath()+“nice_Music.ogg”){return EXIT_FAILURE;} //演奏音乐 音乐。播放(); */ 太空船太空船(窗口); sf::时钟sf_时钟; //开始游戏循环 while(window.isOpen()){ //处理事件 sf::事件; while(window.pollEvent(事件)){ //关闭窗口:退出 如果(event.type==sf::event::Closed){ window.close(); } //按下退出按钮:退出 if(event.type==sf::event::KeyPressed&&event.key.code==sf::Keyboard::Escape){ window.close(); } //移动宇宙飞船 如果(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){spaceship.moveship('l');} 如果(sf::Keyboard::iskeypress(sf::Keyboard::Right)){spaceship.moveship('r');} 如果(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){spaceship.moveship('u');} 如果(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)){spaceship.moveship('d');} } //清屏 window.clear(); //画精灵 窗口。绘制(精灵); 太空船。drawsprite(窗口); //画线 窗口。绘制(文本); //更新窗口 window.display(); } 返回退出成功; } 太空船 #包括 #包括 #包括“ResourcePath.hpp” #包括“Spaceship.hpp” 太空船::太空船(sf::渲染窗口和游戏窗口){ auto surface=game_window.getSize(); ss_x=表面x/2; ss_y=表面y/2; ss_速度=5; ss_宽度=128; ss_高度=128; ss_半径=ss_宽度/2; } 虚空宇宙飞船::drawsprite(sf::渲染窗口和游戏窗口){ sf::纹理船; 如果(!ship.loadFromFile(resourcePath()+“space-shutter-64.png”)){ 返回退出失败; } sf::雪碧ss_雪碧(船); ss_sprite.setPosition(ss_x-ss_sprite.getGlobalBounds().width/2,ss_y-ss_sprite.getGlobalBounds().height/2); 游戏窗口绘制(ss_sprite); } void Spaceship::moveship(字符移动){ 如果(move='l'){ss_x-=ss_speed;} 如果(move='r'){ss_x+=ss_speed;} else if(move='u'){ss_y-=ss_speed;} 如果(move='d'){ss_y+=ss_speed;} } 太空船::~Spaceship(){} 太空船 #ifndef飞船(水电站) #定义太空船 #包括 #包括 #包括 #包括 使用名称空间std; 二级宇宙飞船{ 公众: 宇宙飞船(); 宇宙飞船(sf::RenderWindow&); ~宇宙飞船(); 无效船舶(char); 虚空drawsprite(sf::RenderWindow&); 私人: 署名int ss_x,ss_y; 无符号整数速度; int ss_宽度、ss_高度、ss_半径; }; #endif/*宇宙飞船水电站*/,c++,user-interface,sfml,C++,User Interface,Sfml,正如评论中所建议的,这里的问题是,在计算中没有考虑两帧之间经过的时间。因此,所发生的情况是,您在任何帧上添加了固定数量的速度,忽略了两个连续帧可能需要非常不同的完成时间这一事实 还有一个问题(这似乎是问题的主要来源):您正在检查事件循环中是否按下了键。这是不正确的,只有当按下您的键并且在循环过程中发生其他事件时,这才是正确的。你需要在每一帧检查这个 解决最后一个问题的另一种方法是,当检测到要测试的按键按下时,将布尔标志设置为true/false。如果您查看一下isKeyPressed方法,您还会

正如评论中所建议的,这里的问题是,在计算中没有考虑两帧之间经过的时间。因此,所发生的情况是,您在任何帧上添加了固定数量的速度,忽略了两个连续帧可能需要非常不同的完成时间这一事实

还有一个问题(这似乎是问题的主要来源):您正在检查事件循环中是否按下了键。这是不正确的,只有当按下您的键并且在循环过程中发生其他事件时,这才是正确的。你需要在每一帧检查这个

解决最后一个问题的另一种方法是,当检测到要测试的按键按下时,将布尔标志设置为
true
/
false
。如果您查看一下
isKeyPressed
方法,您还会发现第二种方法比第一种方法更有效

更改主循环以获取每帧经过的时间的最简单方法如下:

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
(我在
切换案例中更改了
if/else if
,我发现这种情况下更干净,应该更有效):

正如Jesper Juhl所建议的,我在这里做了一些(你真的应该看看)

顺便说一句,我建议您对代码进行一些修改:

// 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);
}

尝试使用VSync而不是每秒30帧。我可以推荐阅读-这与你的问题相关,也是一本好的阅读。另请参见。@LogicStuff VSync用于修复纹理撕裂问题,而不是用于固定帧速率或解决问题
#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 */
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..
}
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;
    }
}
// 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);
}