Control RenderWindow from another function - c++

this may sound as a really simple question, but I have SFML 1.6 and I want to control my RenderWindow from another function... I'm not very good at C++ or SFML... :)
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <iostream>
using namespace std;
int main()
{
// Create the main window
sf::RenderWindow App(sf::VideoMode(800, 600, 32), "Guessing Game");
App.SetFramerateLimit(60); //Set FPS limit to 60 FPS
//Variables
bool atmainmenu = true;
//End Variables
// Start main loop
while (App.IsOpened())
{
printmessage(atmainmenu);
// Process events
sf::Event Event;
while (App.GetEvent(Event))
{
// Close window : exit
if (Event.Type == sf::Event::Closed)
App.Close();
// Escape key : exit
if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape))
App.Close();
if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::M)){
}
if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::F)){
}
}
// Display window on screen
App.Display();
}
return EXIT_SUCCESS;
}
void printmessage(bool atmainmenu)
{
if(atmainmenu){
//$$$$$$$################# HERE <----
}
}
That is my code, but I want to control 'App' from atmainmenu. Is there anything I have to do? thanks
waco001

Pass your renderwindow as a parameter to the function like so:
void printmessage(bool thing, sf::RenderWindow& app)
{
app.doSomething();
}
Dont forget to the window as a reference&
Then call the function in main
printmessage(atmainmenu,app);

Related

Sfml lostFocus / gainedFocus cpu usage

Why when I run this simple code and just doing nothing CPU usage by this app is around 0.4%
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 800), "hi", sf::Style::Close | sf::Style::Titlebar);
window.setFramerateLimit(60);
sf::Event event;
bool lostFocus = false;
while (window.isOpen())
{
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
else if (event.type == sf::Event::LostFocus)
lostFocus = true;
else if (event.type == sf::Event::GainedFocus)
lostFocus = false;
}
if (!lostFocus)
{
window.clear(sf::Color::White);
window.display();
}
}
}
But when I click on other app, CPU usage by this app increases to 12%.
Does GainedFocus actually eat so much cpu power or what?
(I just wanted to make a simple pause of game and saw this cpu usage)
As already mentioned, when your window doesn't have focus and you're not updating the window, the loop goes into a hot spin where it's continuously checking for events. When you've lost focus, you instead want to block and wait for a GainedFocus event to occur. As a very simple example, you could do something like
void block_until_gained_focus(sf::Window& window) {
sf::Event event;
while (true) {
if (window.waitEvent(event) && event.type == sf::Event::GainedFocus) {
return;
}
}
}
Then your main game loop could look something like
while (window.isOpen())
{
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
else if (event.type == sf::Event::LostFocus)
wait_until_gained_focus(window);
}
window.clear(sf::Color::White);
window.display();
}
Now if you wanted to do additional work while focus is lost you'll need a different implementation, but the key here is to use waitEvent instead of pollEvent.

(Boolean/SFML) How do I create a boolean that checks collision?

So I recently got into SFML programming, and I need help creating a bool that checks if two rectangles are colliding or overlapping each other.
This is the code so far:
bool collision(sf::Rect rect, sf::Rect rect2){
return rect.getGlobalBounds().intersects(rect2.getGlobalBounds());
}
I'm receiving these errors:
missing template arguments before 'rect'
missing template arguments before 'rect2'
expected primary-expression before ')' token
I am making a platformer and cannot find an efficient way to test collision between the player and the world.
This is the kind of code I want to write for this simple program:
if(collision(rectangle1,rectangle2)){
std::cout << "collision" << std::endl;
}
Any help is appreciated! :)
Here is my code:
#include <SFML/Graphics.hpp>
#include <SFML/Window/Keyboard.hpp>
#include <SFML/Graphics/Rect.hpp>
int main(){
sf::RenderWindow window(sf::VideoMode(800,600),"INSERT_WINDOW_TITLE", sf::Style::Titlebar | sf::Style::Close);
sf::RectangleShape rect1(sf::Vector2f(20.f,20.f));
rect1.setFillColor(sf::Color::Blue);
sf::RectangleShape rect2(sf::Vector2f(20.f,20.f));
rect2.setFillColor(sf::Color::Green);
bool collision(sf::FloatRect r1, sf::FloatRect r2)
{
return r1.intersects(r2, sf::FloatRect());
}
while(window.isOpen()){
sf::Event event;
while(window.pollEvent(event)){
if (event.type == sf::Event::Closed)
window.close();
}
if(sf::Keyboard::isKeyPressed(sf::KeyBoard::W) && collision(rect1,rect2) == false) rect1.move(0.f,-1.f);
if(sf::Keyboard::isKeyPressed(sf::KeyBoard::S) && collision(rect1,rect2) == false) rect1.move(0.f,1.f);
if(sf::Keyboard::isKeyPressed(sf::KeyBoard::A) && collision(rect1,rect2) == false) rect1.move(-1.f,0.f);
if(sf::Keyboard::isKeyPressed(sf::KeyBoard::D) && collision(rect1,rect2) == false) rect1.move(1.f,0.f);
window.draw(rect1);
window.draw(rect2);
window.display();
}
}
Rect is a class template, not an actual class. There are predefined typedefs called IntRect and FloatRect for Rect<int> and Rect<float> respectively. You want to use one of those:
bool collision(sf::FloatRect r1, sf::FloatRect r2)
{
sf::FloatRect intersection;
return r1.intersects(r2, intersection);
}
UPDATE:
Here's a "fixed" version of your code. I added an overload that takes Shapes and forwards to the Rect collision-checking function. I also repositioned your rect2 rectangle; otherwise you cannot move as you already have a collision.
#include <SFML/Graphics.hpp>
#include <SFML/Window/Keyboard.hpp>
bool collision(sf::FloatRect r1, sf::FloatRect r2)
{
sf::FloatRect intersection;
return r1.intersects(r2, intersection);
}
bool collision(sf::Shape const & r1, sf::Shape const & r2)
{
return collision(r1.getGlobalBounds(), r2.getGlobalBounds());
}
int main(){
sf::RenderWindow window(sf::VideoMode(800,600),"INSERT_WINDOW_TITLE", sf::Style::Titlebar | sf::Style::Close);
sf::RectangleShape rect1(sf::Vector2f(20.f,20.f));
rect1.setFillColor(sf::Color::Blue);
sf::RectangleShape rect2(sf::Vector2f(20.f,20.f));
rect2.setFillColor(sf::Color::Green);
rect2.setPosition(100.f, 100.f);
while(window.isOpen()){
sf::Event event;
while(window.pollEvent(event)){
if (event.type == sf::Event::Closed)
window.close();
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::W) && collision(rect1,rect2) == false) rect1.move(0.f,-1.f);
if(sf::Keyboard::isKeyPressed(sf::Keyboard::S) && collision(rect1,rect2) == false) rect1.move(0.f,1.f);
if(sf::Keyboard::isKeyPressed(sf::Keyboard::A) && collision(rect1,rect2) == false) rect1.move(-1.f,0.f);
if(sf::Keyboard::isKeyPressed(sf::Keyboard::D) && collision(rect1,rect2) == false) rect1.move(1.f,0.f);
window.clear();
window.draw(rect1);
window.draw(rect2);
window.display();
}
}
Note that there are other issues here as well; e.g. your game loop runs as fast as possible right now, which is probably not what you want. This code does run, though.

How to draw an object onto sfml window when a function is called?

I have a character sprite moving across the screen and when I press 'a' I want the program to draw the sword sprite onto the screen and make the sword go away when I am not pressing 'a'. Currently I have an attack function that sets a showweapon boolean as true, and a if statement that is supposed to draw the weapon onto the screen but nothing happens. Is there a better way to do this?
main.cpp
#include <iostream>
#include <SFML/Graphics.hpp>
#include "Character.h"
#include "Projectile.h"
#include "Weapon.h"
using namespace std;
bool scroll = false;
Character player("/Users/danielrailic/Desktop/Xcode /NewGame/ExternalLibs/Player.png");
Weapon woodsword("/Users/danielrailic/Desktop/Xcode /NewGame/ExternalLibs/WoodSword.png");
bool showweapon;
int main() {
// insert code here...
int windowWidth = 5000;
int windowHeight = 5000;
sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight ), "Awesome Game" );
sf::Texture dungeon;
dungeon.loadFromFile("/Users/danielrailic/Desktop/Xcode /NewGame/ExternalLibs/DungeonBack.png");
sf::Sprite backround;
backround.setTexture(dungeon);
while (window.isOpen()){
// check all the window's events that were triggered since the last iteration of the loop
sf::Event event;
while (window.pollEvent(event)){
// "close requested" event: we close the window
if (event.type == sf::Event::Closed)
window.close();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
player.left();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
player.right();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){
player.forward();
}
if (sf:: Keyboard::isKeyPressed(sf::Keyboard::Down)){
player.backward();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LShift))
{
player.Highspeed();
}
else{
player.Lowspeed();
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A)){
woodsword.attack();
}
window.clear(sf::Color(255, 255, 255));
window.draw(backround);
if(showweapon == true){
window.draw(woodsword.getSprite());
window.display();
cout << "Hello";
}
window.draw(player.getSprite());
window.display();
window.setFramerateLimit(70);
}
}
I am also not receiving the "hello" message
weapon.h
class Weapon : Character{
bool showweapon;
public:
sf::Texture texture;
//Constructor
Weapon(string wep)
: Character(wep){
texture.loadFromFile(wep);
showweapon = false;
}
sf::Sprite getSprite() {
sf::Sprite sprite;
sprite.setTexture(texture);
sprite.setTextureRect(sf::IntRect(0, 0, 100, 100));
sprite.setPosition(x_pos, y_pos);
return sprite;
}
//Methods
void attack();
};
void Weapon::attack(){
showweapon = true;
}
If you need to see anything else let me know. Thanks for any help!
I changed the if statement to : if (woodsword.showweapon == true) and I also made a sheath method in the weapon class that sets showweapon false so the sword goes away when I don't press 'a'. Thanks for everyones help.

SFML - pollEvent double run mouseclick

I have main like this :
#include <SFML/Graphics.hpp>
#include <iostream>
#include "okno.h"
using namespace sf;
int main()
{
// Create the main window
RenderWindow app(VideoMode::getDesktopMode(), "Okno" ,Style::Fullscreen);
app.setKeyRepeatEnabled(false);
okno aplikacja(app);
// Start the game loop
while (app.isOpen())
{
// Process events
Event event;
event.type=Event::JoystickButtonPressed;
event.mouseButton.button = Mouse::Right;
while (app.pollEvent(event))
{
// Close window : exit
if (event.type == Event::Closed)
app.close();
if( event.type == Event::KeyPressed && event.key.code == Keyboard::Escape )
app.close();
}
aplikacja.click_przyciski(event);
aplikacja.obsluga_przyciskow();
event.type=Event::JoystickButtonPressed;
event.mouseButton.button = Mouse::Right;
aplikacja.rysuj();
aplikacja.menu=true;
event.type=Event::JoystickButtonPressed;
event.mouseButton.button = Mouse::Right;
//sleep(seconds(5));
// Update the window
//app.display();
}
return EXIT_SUCCESS;
}
And class okno.cpp like this :
#include "okno.h"
#include <iostream>
using namespace std;
int wyswietlanie =0;
okno::okno(RenderWindow &app): window(app)
{
textures[0].loadFromFile("grafika/tlo.png");
textures[1].loadFromFile("grafika/logo.png");
textures[2].loadFromFile("grafika/siatka.png");
textures[3].loadFromFile("grafika/button_start.png");
textures[4].loadFromFile("grafika/button_informacje.png");
textures[5].loadFromFile("grafika/button_wyjscie.png");
textures[6].loadFromFile("grafika/button_cofnij.png");
czcionka.loadFromFile("czcionki/czcionka_1.ttf");
for (int j=0;j<i;j++)
sprites[j].setTexture(textures[j]);
float x,y;
x=window.getView().getSize().x;
y=window.getView().getSize().y;
tekst.setString("Projekt wykonal : \n Wojciech Sorota.");
tekst.setCharacterSize(30);
tekst.setPosition(x/10,y/10);
tekst.setColor(sf::Color::Red);
tekst.setFont(czcionka);
sprites[0].setScale(x/sprites[0].getTextureRect().width,y/sprites[0].getTextureRect().height);
sprites[1].setPosition(x/2 - sprites[1].getTextureRect().width/2,y/2 - sprites[1].getTextureRect().height/2);
sprites[3].setPosition(x/10,y/10);
sprites[2].setScale(x/2/sprites[2].getTextureRect().width,y/2/sprites[2].getTextureRect().height);
sprites[2].setPosition(x/8,y/4);
sprites[4].setPosition( x/10+ sprites[3].getPosition().x + x/ 15,y/10 );
sprites[5].setPosition( x/10 +sprites[4].getPosition().x +x/15,y/10);
sprites[6].setPosition(x/10 + tekst.getPosition().x + tekst.getGlobalBounds().width,y/10);
menu=true;
}
okno::~okno()
{}
void okno::rysuj()
{
this->rysuj_intro();
this->rysuj_menu();
}
void okno::start_gra()
{
}
void okno::click_przyciski(Event &event)
{
if(event.type == Event::MouseButtonReleased && event.mouseButton.button == Mouse::Left)
{
if(click_sprite(sprites[3]))
start_gra();
else if(click_sprite(sprites[5]))
window.close();
else if( click_sprite(sprites[4]))
wyswietl_info(event);
}
}
void okno::wyswietl_info(Event &event)
{
{
while(1)
{
if(sf::Mouse::isButtonPressed(sf::Mouse::Left) && click_sprite(sprites[6]))
{
event.type=Event::JoystickButtonPressed;
event.mouseButton.button = Mouse::Right;
return;
}
window.clear();
window.draw(sprites[0]);
window.draw(sprites[2]);
window.draw(sprites[6]);
window.draw(tekst);
obsluga_przyciskow();
window.display();
}
}}
bool okno::click_sprite(Sprite a)
{
// transform the mouse position from window coordinates to world coordinates
sf::Vector2f mouse = window.mapPixelToCoords(sf::Mouse::getPosition(window));
// retrieve the bounding box of the sprite
sf::FloatRect bounds = a.getGlobalBounds();
// hit test
if (bounds.contains(mouse))
{
return true;
}
return false;
}
void okno::obluga_cofnij()
{
}
void okno::obsluga_przyciskow()
{
if(mysz_nad_sprite(sprites[3]))
sprites[3].setColor(sf::Color(100,100,100));
else
sprites[3].setColor(sf::Color(255,255,255));
if(mysz_nad_sprite(sprites[4]))
sprites[4].setColor(sf::Color(100,100,100));
else
sprites[4].setColor(sf::Color(255,255,255));
if(mysz_nad_sprite(sprites[5]))
sprites[5].setColor(sf::Color(100,100,100));
else
sprites[5].setColor(sf::Color(255,255,255));
if(mysz_nad_sprite(sprites[6]))
sprites[6].setColor(sf::Color(100,100,100));
else
sprites[6].setColor(sf::Color(255,255,255));
}
bool okno::mysz_nad_sprite(Sprite a)
{
sf::Vector2f mouse = window.mapPixelToCoords(sf::Mouse::getPosition(window));
if (a.getGlobalBounds().contains(mouse))
return true;
return false;
}
void okno::rysuj_intro()
{
if (wyswietlanie == 0)
{
for ( int n=0;n<=254;n++)
{
window.clear();
sprites[0].setColor(sf::Color(255, 255, 255, n));
sprites[1].setColor(sf::Color(255,255,255,n));
sleep(milliseconds(n/15));
window.draw(sprites[0]);
window.draw(sprites[1]);
window.display();
}
for (int n=254;n>=0;n--)
{
window.clear();
sprites[1].setColor(sf::Color(255, 255, 255, n));
sleep(milliseconds(n/15));
window.draw(sprites[0]);
window.draw(sprites[1]);
window.display();
}
wyswietlanie++;
}
}
void okno::rysuj_menu()
{
window.clear();
if (wyswietlanie==1)
for ( int n=0;n<=254;n++)
{
window.clear();
sprites[2].setColor(sf::Color(255,255,255,n));
window.draw(sprites[0]);
window.draw(sprites[2]);
window.draw(sprites[3]);
window.draw(sprites[4]);
window.draw(sprites[5]);
window.display();
if (n==254)
wyswietlanie++;
window.clear();
}
window.draw(sprites[0]);
window.draw(sprites[2]);
window.draw(sprites[3]);
window.draw(sprites[4]);
window.draw(sprites[5]);
window.display();
}
My question is why after i click on sprites[6] then i go back to loop [ pollEvent ] and then pollEvent return last event , but last event is mouseclick soo then it run script on mouseclick how to protect my function for this ?
SFML Event handling
Events should be handled something like this:
sf::Event event;
while (app.pollEvent(event))
{
// handle each event you want
switch (event.type)
{
case sf::Event::Closed:
closed(event);
Exit();
break;
case sf::Event::KeyPressed:
keyPressed(event);
break;
case sf::Event::KeyReleased:
keyReleased(event);
break;
case sf::Event::MouseButtonPressed:
mouseButtonPressed(event);
break;
case sf::Event::MouseButtonReleased:
mouseButtonReleased(event);
break;
case sf::Event::MouseMoved:
mouseMoved(event);
break;
/* ...many more events exist */
default:
cerr << "unhandle event of type: " << event.type << endl;
break;
}
}
And then, have a function for each event you want to handle.
void mouseMoved(const sf::Event& event)
{
// do something with the mouse event
mRelMousePos.x = event.mouseMove.x - mMousePos.x;
mRelMousePos.y = event.mouseMove.y - mMousePos.y;
mMousePos.x = event.mouseMove.x;
mMousePos.y = event.mouseMove.y;
}
As mentionned by #Hiura, you can't assign an event type to an sf::event and then reuse it in the pollEvent method, to be more precise, it's more the event.mouseButton.button = Mouse::Right; part that is problematic here. This is partly because the sf::Event class stores its event parameters (mouseButton, key, etc.) inside a union and partly because that's not the use intended for the sf::Event class.
Your code
Please code in english, always, you never know when you'll need to share a piece of code. And I'm not saying this because I'm a self-centered english speaking individual, in fact, I'm a french canadian.
Now, let's take a look specifically at the code you provided.
// Process events
Event event;
// these are problematic, you shouldn't do that.
//event.type=Event::JoystickButtonPressed;
//event.mouseButton.button = Mouse::Right;
while (app.pollEvent(event))
{
// using a switch or else if here would lower code repetition
// and useless check.
// Since both cases do the same thing, you could have just merge them.
// Close window : exit
if ((event.type == Event::Closed)
|| (event.type == Event::KeyPressed
&& event.key.code == Keyboard::Escape ))
{
app.close();
}
else if (event.type == Event::MouseButtonReleased
&& event.mouseButton.button == Mouse::Left)
{
// this should really go here
aplikacja.click_button(event); // thanks Google Translation
}
}
// Why? Why do you send the last event from your event loop to that?
//aplikacja.click_przyciski(event);
Some unnecessary tweaks here just for fun:
bool okno::click_sprite(Sprite sprite) // remember, meaningful names
{
// transform the mouse position from window coordinates to world coordinates
sf::Vector2f mouse = window.mapPixelToCoords(sf::Mouse::getPosition(window));
// see how it's clearer and I just removed 7-8 LOC and the comments
// are now unnecessary here. The if clause was redundant since the contains
// method already returns a bool value.
return sprite.getGlobalBounds().contains(mouse);
}
I'm not going to go through the entire code, but you are close to a working app with SFML. There is some nice tutorials and the SFML source code is quite clear, see the SFML Github repo and the SFML game dev book for more info on how to use each part of SFML.

SFML Crash using Clear function

I'm new to SFML and am currently reading through the documentation. For some reason, however, my "program" crashes whenever I call the Clear() function. My program code is as follows:
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <cstdlib>
#include <iostream>
void HandleEvents(sf::RenderWindow &App)
{
sf::Event Event;
while (App.GetEvent(Event)) {
if (Event.Type == sf::Event::Closed) {
App.Close();
exit(0);
}
if ((Event.Type == sf::Event::KeyPressed) && (Event.Key.Code == sf::Key::Escape)) {
App.Close();
exit(0);
}
}
}
int main()
{
sf::RenderWindow App(sf::VideoMode(800, 640, 32), "SFML Graphics");
App.SetFramerateLimit(60); // cap the framerate at 60 FPS
while (App.IsOpened()) {
HandleEvents(App); // handle events... duh
App.Clear(); // When I remove this line, the program doesn't crash....
App.Display();
}
return EXIT_SUCCESS;
}
So do any SFML gurus have advice for me? I've tried researching this problem but the only other person I've seen who tried to ask this had a broken link (because of the new SFML forums).
Thanks.