Hey all,
The deal is to create sort of roguelike game engine using SFML. the first step is of course loading the bitmap font and printing stuff into screen. The actual printing and showing works fine but the performance is a real issue here.
Would any of you have any idea what's actually the problem in my code? Can it be improved somehow?
There's the link to whole thing, its not big, four files in total
http://www.cs.uta.fi/~a231769/source.zipAny suggestions are appreciated. I find SFML quite nice compared to SDL and I would love using it on my project.
If people rather look at code in the post, I don't mind putting it up but for now I left it out 'cos even tho there isn't _that_ much stuff there, it still takes some space..
(EDIT)
It seems even drawing rectangle using sf::Shape::Rectangle drops fps from 1000 to 10
anyways: here are parts of the code:
Mainloop:
int main()
{
// Create main window
rl::System::init( 1024, 768 );
rl::System::window = new sf::RenderWindow( sf::VideoMode( 1024, 768 ), "SFML Graphics" );
rl::System::showFps( true );
rl::Surface::root->setFont( "data/fonts/arial8x8.png", 8, 8 );
//rl::System::window->SetFramerateLimit( 60 );
// Start game loop
while (rl::System::window->IsOpened())
{
// Process events
sf::Event Event;
while (rl::System::window->GetEvent(Event))
{
// Close window : exit
if (Event.Type == sf::Event::Closed)
rl::System::window->Close();
}
// Clear screen
rl::System::window->Clear();
// Print stuff ito surface
for( int y = 0; y < 96; y++ )
for( int x = 0; x < 128; x++ ) {
rl::Surface::root->setChar( x, y, 'M' );
rl::Surface::root->setBack( x, y, sf::Color( 0 + x, 120, 0 + x) );
}
// Finally, display the rendered frame on screen
rl::System::flush();
}
return EXIT_SUCCESS;
}
Rendering function:
System.cpp
void rl::System::flush() {
for( int y = 0; y < rl::Surface::root->sHeight; y++ )
for( int x = 0; x < rl::Surface::root->sWidth; x++ ) {
rl::SurfaceData * dat = rl::Surface::root->content[ x + y * rl::Surface::root->sWidth ];
int X1 = x * rl::Surface::root->cWidth;
int Y1 = y * rl::Surface::root->cHeight;
window->Draw( sf::Shape::Rectangle( X1, Y1, X1 + rl::Surface::root->cWidth, Y1 + rl::Surface::root->cHeight, dat->back ) );
if( dat->c != ' ' ) {
int srcx = (dat->c % 16 )*rl::Surface::root->cWidth;
int srcy = (dat->c / 16 )*rl::Surface::root->cHeight;
dat->sprite.SetSubRect( sf::IntRect( srcx, srcy, srcx + rl::Surface::root->cWidth, srcy + rl::Surface::root->cHeight ) );
dat->sprite.SetX( x * rl::Surface::root->cWidth + 0.5f );
dat->sprite.SetY( y * rl::Surface::root->cHeight + 0.5f );
window->Draw( dat->sprite );
}
}
if( show_fps ) {
static char buf[128];
memset(buf, 0, 128);
sprintf(buf, "FPS: %3.1f", game_fps );
text_fps.SetText( buf );
window->Draw( text_fps );
}
window->Display();
game_fps = 1.f / window->GetFrameTime();
}
Surface code, which holds the information of the font and stuff to draw on the screen
Surface.h
#ifndef _RL_SURFACE_H_
#define _RL_SURFACE_H_
#include <SFML/Graphics.hpp>
#include <iostream>
#include <vector>
#include "System.h"
namespace rl {
class System;
class SurfaceData {
public:
SurfaceData() {
this->back = sf::Color( 0, 0, 0 );
this->fore = sf::Color( 255, 255, 255 );
this->c = ' ';
}
sf::Color back;
sf::Color fore;
sf::Sprite sprite;
int c;
};
class Surface {
public:
Surface();
Surface( int width, int height );
void setFont( std::string file, int cWidth, int cHeight );
void setChar( int x, int y, int ascii );
void setBack( int x, int y, sf::Color color );
static Surface * root;
friend class rl::System;
private:
std::vector< SurfaceData*> content;
sf::Image tileset;
sf::Image glyphs[128];
int cWidth;
int cHeight;
int sWidth;
int sHeight;
};
};
#endif
Surface.cpp
#include "Surface.h"
#include <iostream>
#include <string>
rl::Surface * rl::Surface::root;
rl::Surface::Surface() {
}
rl::Surface::Surface( int width, int height ) {
this->sWidth = width;
this->sHeight = height;
for( int i = 0; i < width * height; i++ )
this->content.push_back( new SurfaceData() );
}
void rl::Surface::setFont( std::string file, int cWidth, int cHeight ) {
this->cWidth = cWidth;
this->cHeight = cHeight;
if( !this->tileset.LoadFromFile( file.c_str() ) ) {
std::cerr << "Error loading font";
exit( -1 );
}
this->tileset.CreateMaskFromColor( sf::Color( 0, 0, 0 ) );
for( int i = 0; i < this->sWidth * this->sHeight; i++ ) {
this->content[ i ]->sprite.SetImage( this->tileset );
}
}
void rl::Surface::setChar( int x, int y, int ascii ) {
this->content[ x + y * this->sWidth ]->c = ascii;
}
void rl::Surface::setBack( int x, int y, sf::Color color ) {
this->content[ x + y * this->sWidth ]->back = color;
}
[/code]