loading texture in SFML with std::future - c++

Visual Studio Express 2012, CTP1 c++ compiler
The following code works. It loads an image and displays it on the window until you close it.
#include <memory>
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(800,600), "hello");
auto Load = []() -> std::unique_ptr<sf::Texture> {
std::unique_ptr<sf::Texture> tex_ptr(new sf::Texture);
tex_ptr->loadFromFile("hello.png");
return tex_ptr;
};
auto tex_ptr = Load();
sf::Sprite spr(*tex_ptr);
while (window.isOpen())
{
sf::Event ev;
while (window.pollEvent(ev))
{
if (ev.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(spr);
window.display();
}
}
In the following code, I'm trying to load the image asyncronously using std::async. It prints "load success", which indicates that the load succeeded in the lambda. Then, outside, after I've retrieved the texture from the future, I check other properties of the texture. The size prints out correctly. However, no image shows up. I just get a black window, which closes on command.
#include <future>
#include <memory>
#include <iostream>
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(800,600), "hello");
auto Load = []() -> std::unique_ptr<sf::Texture> {
std::unique_ptr<sf::Texture> tex_ptr(new sf::Texture);
if (tex_ptr->loadFromFile("hello.png"))
std::cout << "load success\n";
else
std::cout << "load failure\n";
return tex_ptr;
};
auto tex_ptr_future = std::async(std::launch::async, Load);
auto tex_ptr = tex_ptr_future.get();
sf::Sprite spr(*tex_ptr);
// Oddly, this prints out exactly what I expect
auto size = tex_ptr->getSize();
std::cout << size.x << 'x' << size.y << '\n';
while (window.isOpen())
{
sf::Event ev;
while (window.pollEvent(ev))
{
if (ev.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(spr); // nothin'
window.display();
}
}
Does anybody see anything I'm doing wrong?

Related

Game does not launch from Menu

I am new to Game Development. I managed to create a simple game (like Space Invaders) as well as a simple start Menu using C++ and SFML. However, upon pressing "Enter" on the main menu, the game is not being launched. How do I link it properly? I appreciate your help. This is not homework.
main.cpp codes
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>
#include "GameObjectManager.h"
#include "Menu.h"
using namespace std;
int main()
{
sf::Texture galaxyBackgroundTexture;
sf::Sprite galaxyBackground;
if (!galaxyBackgroundTexture.loadFromFile("Textures/galaxybackground.png")) {
cout << "Failed to load Image" << endl;
}
galaxyBackground.setTexture(galaxyBackgroundTexture);
sf::RenderWindow window(sf::VideoMode(1200, 800), "Space Invader Test");
Menu menu(window.getSize().x, window.getSize().y);
window.setFramerateLimit(144);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Key::Return)
{
menu.GetPressedItem();
cout << "Play button has been pressed." << endl;
GameObjectManager* gameObjectManagerManager = new GameObjectManager(&window);
gameObjectManager->update();
gameObjectManager->render(window);
}
else if (event.type == sf::Event::Closed)
{
window.close();
}
else if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape)
{
window.close();
}
}
window.clear();
window.draw(galaxyBackground);
menu.draw(window);
window.display();
}
return 0;
}
Menu.h
#pragma once
#include "SFML/Graphics.hpp"
#define MAX_NUMBER_OF_ITEMS 2
class Menu
{
public:
Menu(float width, float height);
~Menu();
void draw(sf::RenderWindow& window);
int GetPressedItem() { return selectedItemIndex; }
private:
int selectedItemIndex;
sf::Font font;
sf::Text menu[MAX_NUMBER_OF_ITEMS];
};
Menu.cpp
#include "Menu.h"
Menu::Menu(float width, float height)
{
if (!font.loadFromFile("arial.ttf"))
{
cout << "can't load font" << endl;
}
// initialise Menu items
menu[0].setFont(font);
menu[0].setColor(sf::Color::Red);
menu[0].setString("Play");
menu[0].setPosition(sf::Vector2f(width / 2, height / (MAX_NUMBER_OF_ITEMS + 1) * 1));
// EXIT
menu[1].setFont(font);
menu[1].setColor(sf::Color::White);
menu[1].setString("Exit");
menu[1].setPosition(sf::Vector2f(width / 2, height / (MAX_NUMBER_OF_ITEMS + 1) * 2));
}
selectedItemIndex = 0;
Menu::~Menu()
{
}
void Menu::draw(sf::RenderWindow &window)
{
for (int i = 0; i < MAX_NUMBER_OF_ITEMS; i++)
{
window.draw(menu[i]);
}
}
The console window would print:
"Play button has been pressed"
But it does not proceed to the game. Nothing else happens.
"window redefinition" error occurs because both your RenderWindow objects have the same identifiers (i.e. window). You might want to change the name of the second window or better yet use the same window.
The second error, sf::Text::setColor() is deprecated means that it is no longer "useable" or "is not suggested to be used". SFML has two new better functions for this:
sf::Text::setFillColor() : to set the fill of your text.
sf::Text::setOutlineColor() : to give your text an outline (you also need to do change the thickness using setOutlineThickness()).
Moreover, I'd suggest you to use a State Machine for different scenes instead of two separate windows. It really isn't that difficult and will help you learn a few more things. You're somewhat already achieving this with your gameObjectManager. You just need to abstract it and implement it for your menu class as well. And since you have only two scenes you can simply use an integer or boolean to switch between these two.
EDIT: an idea of what you need to do to your main.cpp file
int main()
{
sf::RenderWindow window(sf::VideoMode(1200, 800), "Space Invader Test");
GameObjectManager* gameObjectManagerManager = nullptr;
bool inGame = false; //true = game has started, false = menu screen
while (window.isOpen())//this is the main loop
{
sf::Event event;
while (window.pollEvent(event)) //this is the event loop
{
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Key::Return)
{
if(!inGame)
{
if(menu.GetPressedItem() == PlayButton) //assuming your function returns which button in the menu has been pressed
{
cout << "Play button has been pressed." << endl;
inGame = true;
gameObjectManagerManager = new GameObjectManager(&window);
}
else
{
window.close(); //since the other button is exit
}
}
}
if (event.type == sf::Event::Closed) window.close();
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Escape) window.close();
}
//this is the place where you call your updates
if(inGame) gameObjectManagerManager->update();
window.clear();
window.draw(galaxyBackground);
if(!inGame)menu.draw(window);
if(inGame) gameObjectManagerManager->render();
window.display();
}
return 0;
}

RenderWindow not working across multiple functions

I'm new to SFML, and have been watching a tutorial that puts everything in a single main function. When making my own program, I tried to split it into multiple functions, but it isn't working properly, can anyone explain why this works:
#include <SFML/Graphics.hpp>
#include <iostream>
int main()
{
sf::RenderWindow window(sf::VideoMode(512, 512), "window", sf::Style::Resize | sf::Style::Close);
while (window.isOpen())
{
sf::Event evnt;
while (window.pollEvent(evnt))
{
if (evnt.type == evnt.Closed)
{
window.close();
}
}
window.clear();
window.display();
}
return 0;
}
and this doesn't:
#include <SFML/Graphics.hpp>
#include <iostream>
sf::RenderWindow window;
void setup()
{
sf::RenderWindow window(sf::VideoMode(512, 512), "window", sf::Style::Resize | sf::Style::Close);
}
int main()
{
setup();
while (window.isOpen())
{
sf::Event evnt;
while (window.pollEvent(evnt))
{
if (evnt.type == evnt.Closed)
{
window.close();
}
}
window.clear();
window.display();
}
return 0;
}
They will both compile and run, but in the former, the window will stay open, and in the latter, it won't.
The window variable that you've declared inside setup() is shadowing the global window. object. Try the following:
void setup()
{
window.create(sf::VideoMode(512, 512), "window", sf::Style::Resize | sf::Style::Close);
}

Window not responding while using sockets SFML

I am doing some simple SFML game, and I want to have network communication using udp Sockets. But the problem is that window is blocked and not responding if I try to update position of circle using coordinates that socket receives. Here is the code below. Does anyone know what the problem is?
#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>
#include <iostream>
#include <string>
#include <iostream>
int posX=100,posY=220,x=5;
sf::UdpSocket receiver;
sf::SocketSelector selector;
void changePosition ();
void defineWindow(sf::RenderWindow &window);
void drawCircle(sf::CircleShape &circle, sf::RenderWindow &window);
int main ()
{
receiver.bind(15000);
selector.add(receiver);
sf::RenderWindow window (sf::VideoMode(800,600), "Krugovi");
defineWindow (window);
return 0;
}
void changePosition ()
{
if (x>0 && posX+x>685) {
posX=685;
x=-x;
}
else if (x<0 && posX+x<15) {
posX=15;
x=-x;
}
else
posX=posX+x;
}
void defineWindow(sf::RenderWindow &window)
{
sf::CircleShape circle(50);
sf::Event event;
sf::Clock clock;
while (window.isOpen()) {
while(window.pollEvent(event)) {
if (event.type == sf::Event::KeyPressed) {
if (event.key.code == sf::Keyboard::Escape)
window.close();
}
if (event.type==sf::Event::Closed)
window.close();
}
window.clear(sf::Color::White);
char msg[5];
size_t received;
sf::IpAddress ip;
unsigned short port;
std::string string;
if (selector.wait()) {
if(receiver.receive(msg,sizeof(msg),received,ip,port)==sf::UdpSocket::Done) {
posX=atoi(msg);
}
}
drawCircle(circle,window);
window.display();
}
}
void drawCircle(sf::CircleShape &circle, sf::RenderWindow &window)
{
circle.setFillColor(sf::Color::Yellow);
circle.setOutlineThickness(15);
circle.setOutlineColor(sf::Color::Red);
circle.setPosition(posX,posY);
window.draw(circle);
}
sf::SocketSelector::wait() without any parameters will wait forever until something is received on one of it's sockets, so you won't be responding to events in your window.
If you pass it a time to wait, for example sf::milliseconds(5) then you can continue to poll for events
Relevent docs here

Sfml pollEvent, every new image deletes the previous one

My problem is that the function don't do what I want.
This "CreateWindow" function has the main loop. In the main loop I want a fixed background and, every time I press the H button, I want to draw a Card (sprite) on the background.
What's the problem here? My function draw the cards but when I press H the previous card is deleted and the next card is drawn.
This is something about the event I think, because every time an event happens (I move the mouse, I press an other key etc) the previous card is deleted...
I'm using sfml 2.0
Here is my implementation of the Graphic class
#include "Graphic.h"
#include "SFML/Graphics.hpp"
#include <iostream>
#include <string>
#include "Card.h"
#include <string>
#include <sstream>
Graphic::Graphic(int offset)
{
this->offset = offset;
}
Graphic::~Graphic()
{
//dtor
}
int Graphic::CreateWindow(sf::RenderWindow& window, Deck &deck0)
{
sf::Vector2i screenDimensions(800, 600);
//Dimensioni della window
window.create(sf::VideoMode(screenDimensions.x, screenDimensions.y), "BlackJack", sf::Style::Titlebar | sf::Style::Close);
int index = 0;
window.setKeyRepeatEnabled(false);
//settare il background
sf::Texture bTexture;
sf::Sprite bImage;
if(!bTexture.loadFromFile("Background.png"))
std::cout << "Error" << std::endl;
bImage.setTexture(bTexture);
bImage.setScale(1.0, (float)screenDimensions.y / bTexture.getSize().y);
//MAIN LOOP----------------------
while(window.isOpen())
{
sf::Event Event;
while(window.pollEvent(Event))
{
window.clear();
window.draw(bImage); // this is the function which draw the background
if (Event.type == sf::Event::Closed)
{
window.close();
}
if(Event.key.code == sf::Keyboard::H)
{
Card * y = deck0.dealFirst();
drawCard(window,y->graphNumber,y->getSeed(),offset);
offset = offset + 50;
}
window.display();
}
}
}
int Graphic::drawCard(sf::RenderWindow &window, int graphNumber, string seed, int offset)
{
std::ostringstream oss;
oss << graphNumber << seed << ".png";
std::string var = oss.str();
sf::Texture QHTexture;
sf::Sprite QHImage;
if(!QHTexture.loadFromFile(var))
std::cout<< "Error" <<std::endl;
QHImage.setTexture(QHTexture);
QHImage.setScale(0.5, 0.5);
QHImage.setPosition(offset + 100, 400);
window.draw(QHImage); //this is the function which draw the card's sprite
return 0;
}
Alright you shouldn't be drawing inside of your while(window.pollEvent()) loop, you should be drawing something like this:
while(window.isOpen())
{
sf::Event Event;
while(window.pollEvent(Event))
{
if (Event.type == sf::Event::Closed)
{
window.close();
}
if(Event.key.code == sf::Keyboard::H)
{
Card * y = deck0.dealFirst();
drawCard(window,y->graphNumber,y->getSeed(),offset);
offset = offset + 50;
}
}
window.clear();
window.draw(bImage); // this is the function which draw the background
window.display();
}
The way you were drawing your draw call will only happen if there is an SFML event, and will only ever clear if there is an sfml event(Which is ok if you dont want it to constantly render every frame... and aren't planning any kind of animations...).
So when you hit H an sfml event was being triggers that called your draw card function, however since your card is a local variable to the function you wrote, at the end of the function it is cleared out. You need to store your cards somewhere, such as a vector or list of sf::Sprite. So an example would be:
#include "Graphic.h"
#include "SFML/Graphics.hpp"
#include <iostream>
#include <string>
#include "Card.h"
#include <string>
#include <sstream>
Graphic::Graphic(int offset)
{
this->offset = offset;
}
Graphic::~Graphic()
{
//dtor
}
int Graphic::CreateWindow(sf::RenderWindow& window, Deck &deck0)
{
sf::Vector2i screenDimensions(800, 600);
//Dimensioni della window
window.create(sf::VideoMode(screenDimensions.x, screenDimensions.y), "BlackJack", sf::Style::Titlebar | sf::Style::Close);
int index = 0;
window.setKeyRepeatEnabled(false);
//settare il background
sf::Texture bTexture;
sf::Sprite bImage;
if(!bTexture.loadFromFile("Background.png"))
std::cout << "Error" << std::endl;
bImage.setTexture(bTexture);
bImage.setScale(1.0, (float)screenDimensions.y / bTexture.getSize().y);
//MAIN LOOP----------------------
while(window.isOpen())
{
sf::Event Event;
while(window.pollEvent(Event))
{
if (Event.type == sf::Event::Closed)
{
window.close();
}
if(Event.key.code == sf::Keyboard::H)
{
Card * y = deck0.dealFirst();
drawCard(window,y->graphNumber,y->getSeed(),offset);
offset = offset + 50;
}
}
window.clear();
window.draw(bImage); // this is the function which draw the background
for(int i = 0; i < cardList.size(); ++i)
{
window.draw(cardList[i]);
}
window.display();
}
}
int Graphic::drawCard(sf::RenderWindow &window, int graphNumber, string seed, int offset)
{
std::ostringstream oss;
oss << graphNumber << seed << ".png";
std::string var = oss.str();
sf::Texture QHTexture;
sf::Sprite QHImage;
if(!QHTexture.loadFromFile(var))
std::cout<< "Error" <<std::endl;
QHImage.setTexture(QHTexture);
QHImage.setScale(0.5, 0.5);
QHImage.setPosition(offset + 100, 400);
cardList.push_back(QHImage); //this adds the sprite to our list
return 0;
}

Why does SFML Shader cause segmentation fault?

Why does sf::Shader cause segmentation fault.I am going to show the code and i am telling to those that look the code that i use an engine and it works perfectly.So it doesn't cause the crash except with sf::Shader.And the code stops when i load the shader.
main.cpp
#include <iostream>
#include "CoreEngine.h"
#include "maingame.h"
int main()
{
//CoreEngine e(new MainGame(new Vector2i(800, 600), "Mama"));
//e.start();
Window::createWindow(800, 600, "Mama");
Window::clearColor(124, 32, 125);
bool running = true;
while(running){
if(Window::isWindowClosed())
running = false;
sf::RectangleShape shape(sf::Vector2f(20, 20));
shape.setPosition(10, 10);
sf::Shader shader;
if(!shader.loadFromFile("fragment.fs", sf::Shader::Fragment))
std::cout << "dfsfsdf";
Window::clear();
Window::getDrawer()->draw(shape, &shader);
Window::render();
}
}
Here is a compiled version of the code.
#include <iostream>
#include <SFML/Graphics.hpp>
int main()
{
//CoreEngine e(new MainGame(new Vector2i(800, 600), "Mama"));
//e.start();
sf::RenderWindow window(sf::VideoMode(800, 600), "Msadama");
sf::Shader shader;
if(!shader.loadFromFile("fragment.fs", sf::Shader::Fragment)){
std::cerr << "Shader failed to load" << std::endl;
return 0;
}
sf::RectangleShape shape(sf::Vector2f(20, 20));
shape.setPosition(10, 10);
while(window.isOpen()){
sf::Event event;
while(window.pollEvent(event)){
if(event.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(shape);
window.display();
}
}
Your call to sf::Shader::loadFromFile is failing, which triggers your if statement because you are checking for the wrong condition. What you really want is:
sf::Shader shader;
if(!shader.loadFromFile("fragment.fs", sf::Shader::Fragment))
std::cerr << "Shader failed to load" << std::endl;
return 0;
}
std::cout << "dfsfsdf";
Window::clear();
Window::getDrawer()->draw(shape, &shader);
Window::render();
Regardless, you shouldn't be loading your shader from a file every frame. Do it once, check the error, then enter the main loop. Something like this (untested):
int main()
{
Window::createWindow(800, 600, "Mama");
Window::clearColor(124, 32, 125);
sf::Shader shader;
if(!shader.loadFromFile("fragment.fs", sf::Shader::Fragment))
{
std::cerr << "Failed to load shader" << std::endl;
return 0;
}
bool running = true;
while(running){
if(Window::isWindowClosed())
running = false;
sf::RectangleShape shape(sf::Vector2f(20, 20));
shape.setPosition(10, 10);
Window::clear();
Window::getDrawer()->draw(shape, &shader);
Window::render();
}
}