I ported the "Manage different screens in a game" from SFML 1.6 to 2.0 but have a problem I can't figure out. Am running VC++ Express 2010. The link to the 1.6 code on the web is:
https://github.com/SFML/SFML/wiki/TutorialScreensscreen_0:
When the project is run via debug, screen_0.hpp runs fine and the "presentation.png" image is displayed fine. Everything works as expected. If I highlight "Exit" and press ENTER, it exits. I highlight "Play" and execution progresses to screen_1.
screen_1:
When screen_1 is displayed, I see the "presentation.png" image with "Play" and "Exit" on it. A lot of horizontal black lines are cycling through out the display really fast at random. No sprite rectangle is displayed. Pressing any arrow key does nothing.
Pressing the ESC key takes me back to screen_0 as it should. The "presentation.png" image is displayed and the "Continue" and "Exit" text are displayed properly. Everything works in screen_0. Highlighting "Continue" takes me back to screen_1 and the same problem for screen_1 is repeated.
In the code for screen_1, I set a breakpoint on the "App.display();" line. Pressing the F5 key to continue VC++ debug, I see that the screen alternates between the ("presentation.png" image with the "Play" and "Exit" text on it) and a (black screen with no sprite rectangle on it). When I step through the execution for screen_1, it steps from "while(Running)" to "App.display();" in a loop as it should.
So why is the screen_1 alternating between ("presentation.png" with Play and Exit on it) and a (black screen with no sprite rectangle on it)?
PS: I didn't know how to convert the "App.SetBackgroundColor(sf::Color(0, 0, 0, 0));" from SFML 1.6 to 2.0 so I commented those lines out and replaced them with "App.clear();".
All of my converted SFML 2.0 code follows:
// SFML 2.0 - Manage Different Screens In A Game *** Main.cpp ***
//
#include "stdafx.h"
#include <fstream>
#include <iostream>
#include <sfml/Graphics.hpp>
#include "screens.hpp"
int _tmain(int argc, _TCHAR* argv[])
{
//Applications variables
std::vector<cScreen*> Screens;
int screen = 0;
//Window creation
sf::RenderWindow App(sf::VideoMode(640, 480, 32), "SFML Demo 3");
App.setPosition(sf::Vector2i(10, 10)); //Set topleft corner of window to 10, 10.
//Mouse cursor no more visible
App.setMouseCursorVisible(false);
//Screens preparations
screen_0 s0;
Screens.push_back (&s0);
screen_1 s1;
Screens.push_back (&s1);
//Main loop
while (screen >= 0)
{
screen = Screens[screen]->Run(App);
}
return EXIT_SUCCESS;
}
// SFML 2.0 - Manage Different Screens In A Game *** Screen.hpp ***
/* When speaking about screens, I mean Menu screen, Config screen, Game screen,
etc... Those screens you find in every games. The problem here is that each
screen can be compared to a small SFML application : Each screen will have
its own events and will use some variables useless for other screens.
So, we need to separate each screen in order to avoid conflicts. With SFML,
it's very simple to do that! You just have to create a cScreen class which
will represent each screen. This is an virtual object and it's containing
only one method:
*/
#pragma once; // Must have this statement or get compile errors.
class cScreen
{
public :
virtual int Run (sf::RenderWindow &App) = 0;
};
// SFML 2.0 - Manage Different Screens In A Game *** Screens.hpp ***
/* screens.hpp contains the cScreen include, plus the hpp of each screens of the
game. Here, screen_0 is a menu, and screen_1 is the game. Each screen
inherits from cScreen :
*/
#ifndef SCREENS_HPP_INCLUDED
#define SCREENS_HPP_INCLUDED
//Basic Screen Class
#include "screen.hpp"
//Including each screen of application
#include "screen_0.hpp"
#include "screen_1.hpp"
#endif // SCREENS_HPP_INCLUDED
// SFML 2.0 - Manage Different Screens In A Game *** Screen_0.hpp ***
/* screen_0.hpp contains the object definition and its code. "Run" is like the
main loop you can have in a simple SFML application. The constructor defines
the first value of private members which are finally more like static
variables in our case. This permits to have a fade presentation at first
loading, since the menu will appear directly. Once background is shown, we
use two string to make a menu in which you can navigate with direction's key.
Choosing "Play" will go to the game, "Exit" will exit the application by
returning -1 to the main function :
*/
#pragma once;
#include <iostream>
#include "screen.hpp"
class screen_0 : public cScreen
{
private:
int alpha_max;
int alpha_div;
bool playing;
public:
screen_0 (void);
virtual int Run (sf::RenderWindow &App);
};
screen_0::screen_0 (void)
{
alpha_max = 3*255;
alpha_div = 3;
playing = false;
}
int screen_0::Run (sf::RenderWindow &App)
{
sf::Event Event;
bool Running = true;
sf::Texture Image;
sf::Sprite Sprite;
int alpha = 0;
sf::Font Font;
sf::Text Menu1;
sf::Text Menu2;
sf::Text Menu3;
int menu = 0;
if (!Image.loadFromFile("presentation.png"))
{
std::cerr<<"Error loading presentation.png"<<std::endl;
return (-1);
}
Sprite.setTexture(Image);
Sprite.setColor(sf::Color(255, 255, 255, alpha));
if (!Font.loadFromFile("verdanab.ttf"))
{
std::cerr<<"Error loading verdanab.ttf"<<std::endl;
return (-1);
}
Menu1.setFont(Font);
Menu1.setCharacterSize(20);
Menu1.setString ("Play");
Menu1.setPosition(280.0, 160.0);
Menu2.setFont(Font);
Menu2.setCharacterSize(20);
Menu2.setString("Exit");
Menu2.setPosition(280.0, 220.0);
Menu3.setFont(Font);
Menu3.setCharacterSize(20);
Menu3.setString("Continue");
Menu3.setPosition(280.0, 160.0);
//Clearing screen
App.clear();
if (playing)
{
alpha = alpha_max;
}
while (Running)
{
//Verifying events
while (App.pollEvent(Event))
{
// Window closed
if (Event.type == sf::Event::Closed)
{
return (-1);
}
//Key pressed
if (Event.type == sf::Event::KeyPressed)
{
switch (Event.key.code)
{
case sf::Keyboard::Up:
menu = 0;
break;
case sf::Keyboard::Down:
menu = 1;
break;
case sf::Keyboard::Return:
if (menu==0)
{
//Let's get play !
playing = true;
return (1);
}
else
{
//Let's get work...
return (-1);
}
break;
default :
break;
}
}
}
//When getting at alpha_max, we stop modifying the sprite
if (alpha<alpha_max)
{
alpha++;
}
Sprite.setColor(sf::Color(255, 255, 255, alpha/alpha_div));
if (menu==0)
{
Menu1.setColor(sf::Color(255, 0, 0, 255));
Menu2.setColor(sf::Color(255, 255, 255, 255));
Menu3.setColor(sf::Color(255, 0, 0, 255));
}
else
{
Menu1.setColor(sf::Color(255, 255, 255, 255));
Menu2.setColor(sf::Color(255, 0, 0, 255));
Menu3.setColor(sf::Color(255, 255, 255, 255));
}
//Drawing
App.draw(Sprite);
if (alpha==alpha_max)
{
if (playing)
{
App.draw(Menu3);
}
else
{
App.draw(Menu1);
}
App.draw(Menu2);
}
App.display();
}
//Never reaching this point normally, but just in case, exit the application
return (-1);
}
// SFML 2.0 - Manage Different Screens In A Game *** Screen_1.hpp ***
/* screen_1.hpp contains the game itself. We can't exit from the game directly.
If you push Escape, you'll go on the Main Menu. If you move the "player" and
go to the menu, you can go back to the game and your position will stay the
same. Because your object screen_1 has not been destroyed
*/
#pragma once;
#include <iostream>
#include "screen.hpp"
class screen_1 : public cScreen
{
private:
int movement_step;
int posx;
int posy;
sf::Sprite Sprite;
public:
screen_1 (void);
virtual int Run (sf::RenderWindow &App);
};
screen_1::screen_1 (void)
{
movement_step = 5;
posx = 320;
posy = 240;
//Setting sprite
Sprite.setColor(sf::Color(255, 255, 255, 150));
Sprite.setTextureRect(sf::IntRect(0, 0, 10, 10));
}
int screen_1::Run (sf::RenderWindow &App)
{
sf::Event Event;
bool Running = true;
//Clearing screen
App.clear();
while (Running)
{
//Verifying events
while (App.pollEvent(Event))
{
// Window closed
if (Event.type == sf::Event::Closed)
{
return (-1);
}
//Key pressed
if (Event.type == sf::Event::KeyPressed)
{
switch (Event.key.code)
{
case sf::Keyboard::Escape:
return (0);
break;
case sf::Keyboard::Up:
posy -= movement_step;
break;
case sf::Keyboard::Down:
posy += movement_step;
break;
case sf::Keyboard::Left:
posx -= movement_step;
break;
case sf::Keyboard::Right:
posx += movement_step;
break;
default:
break;
}
}
}
//Updating
if (posx>630)
posx = 630;
if (posx<0)
posx = 0;
if (posy>470)
posy = 470;
if (posy<0)
posy = 0;
Sprite.setPosition(posx, posy);
//Drawing
App.draw(Sprite);
App.display();
}
//Never reaching this point normally, but just in case, exit the application
return -1;
}
Thanks for any help,
Raptor