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
Related
I want to display my player in the window but my player sprite is not showing in the window. I am new to c++. I want to learn classes, inheritence, composition, etc in this way.I have 3 files Player.cpp, Game.cpp and main.cpp. I am using main.cpp to call Game.cpp using a fuction called Run().
Got nothing to try.
Player.cpp
#include "Player.hpp"
#include "string.h"
#include <iostream>
void Player::initPlayer()
{
const char* playerTexturePath = "/Users/don/Desktop/sfmlgames/game1/img/MCmid.png";
if(!mPlayerTexture.loadFromFile(playerTexturePath))
{
std::cout << "mPlayerTexturePath not found!!" << std::endl;
}
mPlayerSprite.setTexture(mPlayerTexture);
mPlayerSprite.setPosition(100.f, 100.f);
mPlayerSprite.setScale(1.f, 1.f);
}
void Player::draw_player(sf::RenderWindow &win)
{
win.draw(mPlayerSprite);
}
Game.cpp
#include "Game.hpp"
#include <iostream>
Player player1;
//Constructor: Create a window and Player
Game::Game() : mWindow(sf::VideoMode(640, 480), "Game")
{
//Frame rate 60
mWindow.setFramerateLimit(60);
player1.initPlayer();
}
//Game loop
void Game::Run()
{
while(mWindow.isOpen())
{
render();
events();
update();
}
}
void Game::events()
{
sf::Event event;
while (mWindow.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
mWindow.close();
}
}
}
void Game::update()
{
}
void Game::render()
{
mWindow.clear(sf::Color::Red);
player1.draw_player(mWindow);
mWindow.display();
}
main.cpp
#include "Game.hpp"
int main()
{
Game game;
game.Run();
}
I don't think I will need to give code to hpp files.
The problem was with image I dont know why. I used another image and it worked fine.
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;
}
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);
}
I have recently started to learn SFML and I wanted to make a Pong clone because it should be easy but I got into this problem while coding:
The bat movement is very laggy and when I press A or D it moves a bit then stops then moves again and continues.
#include <SFML/Graphics.hpp>
#include "bat.h"
int main()
{
int windowWidth=1024;
int windowHeight=728;
sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight), "SFML window");
bat Bat(windowWidth/2,windowHeight-20);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if(sf::Keyboard::isKeyPressed(sf::Keyboard::A))
Bat.batMoveLeft();
else if(sf::Keyboard::isKeyPressed(sf::Keyboard::D))
Bat.batMoveRight();
else if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
Bat.batUpdate();
window.draw(Bat.getShape());
window.display();
}
return 0;
}
bat.h
#ifndef BAT_H
#define BAT_H
#include <SFML/Graphics.hpp>
class bat
{
private:
sf::Vector2f position;
float batSpeed = .3f;
sf::RectangleShape batShape;
public:
bat(float startX, float startY);
sf::FloatRect getPosition();
sf::RectangleShape getShape();
void batMoveLeft();
void batMoveRight();
void batUpdate();
};
#endif // BAT_H
bat.cpp
#include "bat.h"
using namespace sf;
bat::bat(float startX,float startY)
{
position.x=startX;
position.y=startY;
batShape.setSize(sf::Vector2f(50,5));
batShape.setPosition(position);
}
FloatRect bat::getPosition()
{
return batShape.getGlobalBounds();
}
RectangleShape bat::getShape()
{
return batShape;
}
void bat::batMoveLeft()
{
position.x -= batSpeed;
}
void bat::batMoveRight()
{
position.x += batSpeed;
}
void bat::batUpdate()
{
batShape.setPosition(position);
}
Your problem is you're input handling strategies (polling events vs. checking current state).
In addition, the way you've implemented this right now, means that if there are – just assumption – 5 events in the queue, you'll move the bat 5 times between drawing. If there is only one event (e.g. "key down"), you'll move the bat once.
What you'll typically want to do is check the events while iterating over them:
while (window.pollEvent(event)) {
switch (event.type) {
case sf::Event::Closed:
window.close();
break;
case sf::Event::KeyDown:
switch (event.key.code) {
case sf::Key::Left:
bat.moveLeft();
break;
// other cases here
}
break;
}
}
(Note this is from memory, so untested and might include typos.)
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?