When creating the sfml window for some reason the sf::Event::Closed is called and then closes the window is there anyway to fix this?
Also note that sometimes when changing the sfml functions and recompiling and running for the first time this issue doesn't occur only after the second run and so on
here is snakepart header
struct snakepart{
int x, y;
snakepart(int col, int row);
snakepart();
};
here is the main function
#include "Snake.cpp"
int main() {
SnakeClass s;
s.start();
return 0;
}
here is the main header file with most file declarations
#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
here is the header file for the SFML functions
#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
here is the header for the snake functions
#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
Below is the code used to call the SFML functions.
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);
}
below is the SFML graphics functions *Note i am returning enums for the above function
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 I am having to call it using its dynamic library and keep the game logic and the graphic libraries separate from each other
You have an issue on the order that some of your functions are being called. When you do:
movesnake(this->SFML->OnEvent());
OnEvent
will be called first, followed by movesnake
. However, since you've never polled before hand and OnEvent
is using your event
variable, anything can happen. Indeed, event
is never properly filled by window.pollEvent
, therefor you have undefined behavior.
In the end, OnEvent
returns the Keys::quit
because UB, and so movesnake
handle it as such. Move the polling outside of movesnake
(possibly in OnEvent
, just before handling the events) can solve the problem.