sfml event :: close在窗口启动时调用

时间:2018-07-23 11:25:02

标签: c++ sfml

由于某种原因创建sfml窗口时,会调用sf :: Event :: Closed,然后关闭该窗口吗?

还请注意,有时在更改sfml函数以及第一次重新编译并运行时,仅在第二次运行后才发生此问题,依此类推

  • 请注意,我仍在学习sfml和c ++

这是snakepart标头

struct  snakepart{

    int x, y;
    snakepart(int col, int row);
    snakepart();
};

这是主要功能

#include "Snake.cpp"

int main() {
        SnakeClass s;
        s.start();
        return 0;
    }

这是带有大多数文件声明的主头文件

#include "SnakePart.hpp"
#include <vector>
enum class Keys {
    key_up,
    key_down,
    key_left,
    key_right,
    quit,
    nothing,
    };
class IsdlClass {

public:
    virtual bool    OnInit() = 0;
    virtual Keys    OnEvent() = 0;
    virtual void    OnCleanup() = 0;
    virtual bool    pollEvent() = 0;
};

#endif

这是SFML函数的头文件

#include "../libsfmld/include/SFML/Window.hpp"
#include "../libsfmld/include/SFML/Graphics.hpp"
#include "../../includes/IFunctions.hpp"

class SFML :public IsdlClass {

public:
    SFML();
    virtual ~SFML();
    virtual bool    OnInit();
    virtual Keys    OnEvent();
    virtual void    OnCleanup();
    virtual bool    pollEvent();
    sf::RenderWindow window;

private: 

    sf::ContextSettings settings;
    sf::Event event;

};

extern "C"   {
    SFML    *start(void);
    void        deletesdl(SFML *sfml);
}

#endif

这是蛇函数的头文件

#include <iostream>
#include <vector>
#include <unistd.h>

#include "IFunctions.hpp"

class SnakeClass{

public:
    SnakeClass();
    ~SnakeClass();
    int    start();
    int     points, delay, maxW, maxH;
    char    direction, body, border, foodItem;
    bool    get;
    snakepart food;
    std::vector<snakepart> snake;
    void    dlerror_wrapper();

private:
    void    putfood();
    bool    collision();
    void    movesnake(Keys key);
    IsdlClass   *SFML;
    void    *dl_handle;
    bool    Running;
};

#endif

下面是用于调用SFML函数的代码。

  snakepart::snakepart(int col, int row) {

        x = col;
        y = row;
    }

    snakepart::snakepart() {

        x = 0;
        y = 0;
    }  


bool    SnakeClass::collision() {

        if (snake[0].x == 0 || snake[0].x == maxW / 10 - 1 || snake[0].y == 0 || snake[0].y == maxH / 10 - 3)
            return true;
        for (size_t i = 2; i < snake.size(); i++)
            if (snake[0].x == snake[i].x && snake[i].y == snake[0].y)
                return true;
        if (snake[0].x == food.x && snake[0].y == food.y) {

            get = true;
            // points += 10;
            // char c[5];
            // sprintf(c, "%d", points);
            if ((points%50) == 0 && delay > 0)
                delay -= 10;
        }else 
            get = false;
        return false;
    }

    void    SnakeClass::movesnake(Keys key) {

            while(this->SFML->pollEvent()) {
                std::cout << "after poll event\n";
                    switch(key)
                    {
                        case Keys::key_left:
                                if(direction!='r')
                                        direction='l';
                                break;
                        case Keys::key_up:
                                if(direction !='d')
                                        direction='u';
                                break;
                        case Keys::key_down:
                                if(direction!='u')
                                        direction='d';
                                break;
                        case Keys::key_right:
                                if(direction!='l')
                                        direction='r';
                                break;
                        case Keys::quit: //this is called when window is opened
                                direction = 'q';
                                break;
                        default:
                               break;
                    }
                if (key == Keys::nothing)
                    continue;
            }
        }

        void    SnakeClass::dlerror_wrapper(void) {
            std::cerr << "Error: " << dlerror() << std::endl;
            exit(EXIT_FAILURE);
        }

        int    SnakeClass::start() {
            dl_handle = dlopen("sfml/libsfml.dylib", RTLD_LAZY);
            IsdlClass * (*func)(void);
            func = (IsdlClass * (*)(void)) dlsym(dl_handle, "start");
            if (!func)
                dlerror_wrapper();
            this->SFML = NULL;
            this->SFML = func();
            if (this->SFML == NULL)
                std::cout << "error\n";
            maxH = 480;
            maxW = 640;
            if (this->SFML->OnInit() == false)
               Running = false;
            for (int i = 0; i < 5; i++)
                snake.push_back(snakepart(40 + i, 10));
            points = 0;
            delay = 110;
            get = false;
            direction = 'l'; //snake moves to the left
            srand(time(NULL));
                while(Running)
                {

                    if(collision())
                    {
                        std::cout << "game over" << std::endl;
                        break;
                    }
                    // while(this->SFML->pollEvent()) {
                        // std::cout << " events\n";
                        movesnake(this->SFML->OnEvent());
                    // }
                    // 
                    if(direction=='q')
                            break;
                }
            void    (*del)(IsdlClass *);
            del = (void (*)(IsdlClass *)) dlsym(dl_handle, "deletesdl");
            dlclose(dl_handle);
           return (0);
        }

下面是SFML图形功能 *请注意,我正在返回上述函数的枚举

    bool    SFML::pollEvent() {
        return (window.pollEvent(event));
}

bool    SFML::OnInit() {
    settings.antialiasingLevel = 8;
    window.create(sf::VideoMode(640, 480), "My window", sf::Style::Default, settings);
    window.setVerticalSyncEnabled(true);
    return true;
}

Keys    SFML::OnEvent() {

    window.setKeyRepeatEnabled(false);
    switch(event.type) {
            case sf::Event::Closed:
            std::cout << "Event close\n"; //this is called and returns the enum quit
                return (Keys::quit);
                break;
            case sf::Event::KeyPressed:
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
                {
                    std::cout <<"a\n";
                    return (Keys::key_left);
                }
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
                {
                    std::cout <<"d\n";
                    return (Keys::key_right);
                }
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
                {
                    std::cout <<"s\n";
                    return (Keys::key_down);
                }
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
                {
                    std::cout <<"w\n";
                    return (Keys::key_up);
                }
                else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
                {
                    return (Keys::quit);
                }
                break;
            default:
                break;
        }
}



SFML    *start() {
    std::cout << "create\n";
    return new SFML();
}

void    deletesdl(SFML *sfml) {
    delete sfml;
}

P.S我必须使用其动态库来调用它,并使游戏逻辑和图形库彼此分开

1 个答案:

答案 0 :(得分:1)

在调用某些函数的顺序上存在问题。当您这样做时:

movesnake(this->SFML->OnEvent());

OnEvent将首先被调用,然后是movesnake。但是,由于您从未进行过轮询,并且OnEvent正在使用您的event变量,因此任何事情都可能发生。实际上,event永远不会正确地用window.pollEvent填充,因此您具有不确定的行为。

最后,OnEvent返回Keys::quit,因为UB,因此movesnake这样处理。将轮询移到movesnake之外(可能在处理事件之前,可以移到OnEvent中)可以解决问题。