Hi,
i got a weird problem with my gamemenu class. when the game starts, the menu is loaded and displayed and as long, as the user doesn't press an arrow key, nothing happens.
when he presses an arrow key, another menuitem gets selected and the menu gets redrawn.
my problem now is, that when i start the game in fullscreen and when i press an arrow key the _FIRST_ time, i get a black screen for less than a second before the menu gets redrawn. in windowmode i haven't this problem or maybe it's just to fast to recognize it.
i don't see any problems with the code so maybe it's an sfml internal mechanic that i am using wrong or sthg.
here is the main function, but i think the problem isn't there:
#include <time.h>
#include <iostream>
#include "iqchallenge.h"
#include "title.h"
#include "game.h"
#include "information.h"
#include "KeySelection.h"
#include <fstream>
sf::RenderWindow* APPLICATION = NULL;
void FatalError( const char* text )
{
printf( "%s\n", text );
std::cin.ignore();
exit( EXIT_FAILURE );
} // end FatalError
// initializes the random generator and sfml
void Init()
{
// initialize random generator
srand((unsigned int)(time(NULL)));
// read config.txt
// it contains the videmode settings
sf::VideoMode VMode = sf::VideoMode( 640, 480, 32 );
std::ifstream File( "media/config.txt" );
if( !File.is_open() )
FatalError( "Couldn't load file \"config.txt\"" );
std::map<std::string,std::string> values;
while( File && !File.eof() )
{
std::string line;
getline( File, line );
if( line.length() > 1 )
{
int index = line.find( '=' );
if( index != std::string::npos )
{
std::string key( line, 0, index );
std::string v( line, index+1, line.length() );
values.insert( std::make_pair( key, v ) );
}
}
}
File.close();
// init sfml
VMode.Width = atoi( values["width"].c_str() );
VMode.Height = atoi( values["height"].c_str() );
VMode.BitsPerPixel = atoi( values["color"].c_str() );
if( !VMode.IsValid() )
FatalError( "Couldn't initialize VideoMode" );
if( atoi( values["fullscreen"].c_str() ) == 0 )
APPLICATION = new sf::RenderWindow( VMode, "IQ Challenge" );
else
APPLICATION = new sf::RenderWindow( VMode, "IQ Challenge", sf::Style::Fullscreen );
APPLICATION->SetFramerateLimit( 60 );
APPLICATION->UseVerticalSync( atoi( values["vsync"].c_str() ) == 1 );
APPLICATION->ShowMouseCursor( false );
} // end Init
// shuts down the application by releasing the resources
// allocated in Init()
void CleanUp()
{
delete APPLICATION;
APPLICATION = NULL;
} // end CleanUp
void Clear()
{
APPLICATION->Clear();
}
void Show()
{
APPLICATION->Display();
} // end Clear and Show
// entry point of the application
int main()
{
Init();
while( APPLICATION->IsOpened() )
{
// handle "close application" events
sf::Event Event;
while( APPLICATION->GetEvent( Event ) )
{
if( Event.Type == sf::Event::Closed ||
(Event.KeyPressed && Event.Key.Code == sf::Key::Escape) )
{
APPLICATION->Close();
}
}
switch( Title() )
{
case( 0 ): Game(); break;
case( 1 ): KeySelection(); break;
case( 2 ): Information(); break;
case( -1 ):
case( 3 ): APPLICATION->Close(); break;
}
}
CleanUp();
return EXIT_SUCCESS;
} // end main
and here is the menuclass:
#include "SimpleMenu.h"
#include "iqchallenge.h"
SimpleMenu::SimpleMenu() : BackGround( NULL )
{
FontSelected = NULL;
FontNormal = NULL;
for( int i=0; i<COUNT_MODES; ++i )
Color[i].r = Color[i].g = Color[i].b = 255;
} // end Konstructor
// this method automatically scales the background image to the boundaries
// given by the RunMenu Method and finally draws it
void SimpleMenu::DrawBackground( const sf::Rect<int>& Boundary )
{
if( BackGround )
{
sf::Sprite Sprite( *BackGround );
Sprite.SetScale( (float)Boundary.GetWidth() / Sprite.GetSubRect().GetWidth(), (float)Boundary.GetHeight() / Sprite.GetSubRect().GetHeight() );
Sprite.SetPosition( (float)Boundary.Left, (float)Boundary.Top );
APPLICATION->Draw( Sprite );
}
} // end DrawBackground
// sets a background image for the menu
void SimpleMenu::SetBackground( sf::Image& Image )
{
BackGround = &Image;
} // end SetBackground
// sets the fontcolor that will be used for a given mode
void SimpleMenu::SetColor( int mode, sf::Color& color )
{
if( mode >= 0 && mode <= COUNT_MODES )
Color[mode] = color;
} // end SetColor
// sets the font for a normal and selected item
void SimpleMenu::SetFonts( sf::Font& Normal, sf::Font& Selected )
{
FontNormal = &Normal;
FontSelected = &Selected;
} // end SetFonts
// draws an item at the middle of the boundary's width
// boundary is the boundary for the menu given by the runmenu method
// text is the text of the item
// x and y is the calculated offset for the item, that was calculated in the runmeenu method
// w is the width of the boundary
// h is the heightoffset between two items
// mode is the mode of the item (enabled,disabeld,selected)
void SimpleMenu::DrawItem( const sf::Rect<int>& Boundary, const std::string& Text, int x, int y, int w, int h, int mode )
{
sf::Font Font;
if( mode != SELECTED )
Font = ( FontNormal != NULL ? *FontNormal : sf::Font::GetDefaultFont() );
else
Font = ( FontSelected != NULL ? *FontSelected : sf::Font::GetDefaultFont() );
std::string Temp;
if( mode == SELECTED && ItemEyeCandy != 0 )
{
Temp = ItemEyeCandy;
Temp += " ";
Temp += Text;
Temp += " ";
Temp += ItemEyeCandy;
}
else
Temp = Text;
const int fontsize = Font.GetCharacterSize();
sf::String String;
String.SetText( Temp );
String.SetFont( Font );
String.SetColor( Color[mode] );
String.SetSize( (float)fontsize );
String.SetPosition( (Boundary.Left+Boundary.Right)/2.0f - String.GetRect().GetWidth()/2.0f + ItemOffsetX, Boundary.Top+y + ItemOffsetY - fontsize/2.0f );
APPLICATION->Draw( String );
} // end DrawItem
// this method controls the input of the user and draws all items
// the boundary parameter tells us the boundaryrect of the menu
// the menu is controlled via the arrow keys of the keyboard
// escape or window closed events return -1
int SimpleMenu::RunMenu( const sf::Rect<int>& Boundary )
{
bool IsDone = false;
int last = -1;
int y = 0;
int curY = 0;
// delta is the offset between two items
unsigned int delta = 0;
delta = ( FontNormal ? FontNormal->GetCharacterSize() : sf::Font::GetDefaultFont().GetCharacterSize() );
delta = std::max( delta, FontSelected ? FontSelected->GetCharacterSize() : sf::Font::GetDefaultFont().GetCharacterSize() );
y = (int)(( Boundary.GetHeight() - ( delta * Entries.size() ) ) / 2);
while( !IsDone )
{
// handle all events
sf::Event Event;
while( APPLICATION->GetEvent( Event ) )
{
switch( Event.Type )
{
case( sf::Event::Closed ): return -1;
case( sf::Event::KeyPressed ):
{
if( Event.Key.Code == sf::Key::Escape )
return -1;
else if( APPLICATION->GetInput().IsKeyDown( sf::Key::Up ) )
SelectedIndex = MoveSelection( -1 );
else if( APPLICATION->GetInput().IsKeyDown( sf::Key::Down ) )
SelectedIndex = MoveSelection( 1 );
else if( APPLICATION->GetInput().IsKeyDown( sf::Key::Return ) )
IsDone = true;
} break;
}
}
// check if the user pressed an arrow key
if( SelectedIndex != last )
{
// if so -> redraw the menu and set the new selected item
Clear();
last = SelectedIndex;
DrawBackground( Boundary );
curY = y;
for( unsigned int i=0; i<Entries.size(); ++i )
{
int mode = DISABLED;
if( IsEnabled( i ) )
{
if( i == SelectedIndex )
mode = SELECTED;
else
mode = ENABLED;
}
DrawItem( Boundary, *Entries[i], 0, curY, (int)Boundary.GetWidth(), delta, mode );
curY += delta;
}
Show();
}
}
return SelectedIndex;
} // end RunMenu
in the last method (runmenu) inside the if( selectedindex != last ) is the important code. i am confused why i only get this black screen the first time a press an arrow key in fullscreen mode. i then can't reconstruct this problem no matter how fast i press the keys.
hoping for help
edit:
is there a better tag for code? only green without highlighting is hard to read imo.