window 启动时调用 sfml event::close
sfml event::close called when window starts
当由于某种原因创建 sfml window 时,调用 sf::Event::Closed 然后关闭 window 是否有办法解决这个问题?
另请注意,有时在第一次更改 sfml 函数并重新编译和 运行ning 时,此问题不会仅在第二次 运行 之后出现,依此类推
- 注意我还在学习sfml和c++
这里是 snakepart header
struct snakepart{
int x, y;
snakepart(int col, int row);
snakepart();
};
这里是主要功能
#include "Snake.cpp"
int main() {
SnakeClass s;
s.start();
return 0;
}
这是包含大多数文件声明的主要 header 文件
#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 函数的 header 文件
#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
这里是蛇函数header
#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 我不得不使用它的动态库来调用它并保持游戏逻辑和图形库彼此分离
您对某些函数的调用顺序有疑问。当你这样做时:
movesnake(this->SFML->OnEvent());
OnEvent
将首先被调用,然后是 movesnake
。但是,由于您之前从未进行过轮询并且 OnEvent
正在使用您的 event
变量,因此任何事情都有可能发生。事实上,event
永远不会被 window.pollEvent
正确填充,因此你有未定义的行为。
最后,OnEvent
returns Keys::quit
因为UB,所以movesnake
这样处理。将轮询移到 movesnake
之外(可能在 OnEvent
中,就在处理事件之前)可以解决问题。
当由于某种原因创建 sfml window 时,调用 sf::Event::Closed 然后关闭 window 是否有办法解决这个问题?
另请注意,有时在第一次更改 sfml 函数并重新编译和 运行ning 时,此问题不会仅在第二次 运行 之后出现,依此类推
- 注意我还在学习sfml和c++
这里是 snakepart header
struct snakepart{
int x, y;
snakepart(int col, int row);
snakepart();
};
这里是主要功能
#include "Snake.cpp"
int main() {
SnakeClass s;
s.start();
return 0;
}
这是包含大多数文件声明的主要 header 文件
#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 函数的 header 文件
#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
这里是蛇函数header
#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 我不得不使用它的动态库来调用它并保持游戏逻辑和图形库彼此分离
您对某些函数的调用顺序有疑问。当你这样做时:
movesnake(this->SFML->OnEvent());
OnEvent
将首先被调用,然后是 movesnake
。但是,由于您之前从未进行过轮询并且 OnEvent
正在使用您的 event
变量,因此任何事情都有可能发生。事实上,event
永远不会被 window.pollEvent
正确填充,因此你有未定义的行为。
最后,OnEvent
returns Keys::quit
因为UB,所以movesnake
这样处理。将轮询移到 movesnake
之外(可能在 OnEvent
中,就在处理事件之前)可以解决问题。