由于某种原因创建sfml窗口时,会调用sf :: Event :: Closed,然后关闭该窗口吗?
还请注意,有时在更改sfml函数以及第一次重新编译并运行时,仅在第二次运行后才发生此问题,依此类推
这是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我必须使用其动态库来调用它,并使游戏逻辑和图形库彼此分开
答案 0 :(得分:1)
在调用某些函数的顺序上存在问题。当您这样做时:
movesnake(this->SFML->OnEvent());
OnEvent
将首先被调用,然后是movesnake
。但是,由于您从未进行过轮询,并且OnEvent
正在使用您的event
变量,因此任何事情都可能发生。实际上,event
永远不会正确地用window.pollEvent
填充,因此您具有不确定的行为。
最后,OnEvent
返回Keys::quit
,因为UB,因此movesnake
这样处理。将轮询移到movesnake
之外(可能在处理事件之前,可以移到OnEvent
中)可以解决问题。