Sign in to follow this  
dudedbz1

SDL engine up and running

Recommended Posts

Hi all! I managed to get my engine to work. It handles all the SDL stuff.
//Example

#include <SDL.h>

#include "SDL_EngineMain.h"

int main(int, char**)
{
	//100%	
    SDL_Engine myEngine;
	
	//100%
	myEngine.Init(SDL_INIT_VIDEO);
	
	//100%
	myEngine.InitWindow(300, 200, SDL_ANYFORMAT);
	
	//100%
	myEngine.AddImage("bob.bmp");
	
	//100%
	myEngine.GetImage(0)->Setx(50);
	
	SDL_Event event;
	
	while (true)
	{
		if (SDL_PollEvent(&event))
		{
			if (event.type == SDL_QUIT)
                break;
		}
		
		//100%
		myEngine.DrawImage(0);
		
		//100%
		myEngine.Flip();
	}
	
	//100%
	myEngine.DeInit();
}

You can try it out too if you want.

Share this post


Link to post
Share on other sites
Oh yeah. Anyways, I'll post the engine source when its ready, right now it handles SDL initialization, deinitialization, and Image(s). Image is a class used by SDL_Engine, but you can use it directly also. Once I get to making it handle music and ttf_text(<---ttf first) I will release it.

Share this post


Link to post
Share on other sites
Yup. Actually, I dont know. It handles the specific SDL stuff instead of you doing it manually in functions. If you consider that a wrapper, yes it is.

P.S. I dont know really how to let you test it. Making it a .a only gives linker errors, so I included it into my project directly. Any ideas?

P.P.S. Though I wouldnt actually consider it a wrapper. I am aiming at making it handle all the image and text image stuff. And maybe music. Stuff that you normally initialize and use, not like keyboard input.

//Edit: I wrote 'P.S.S.' instead of 'P.P.S.'.
//Edit: Whats '@OP'?

Share this post


Link to post
Share on other sites
@OP means 'To the original/originating poster'

If I said:
@evolutional: You are a staff member

That would mean that I am talking to Oli(evolutional) directly. It's just a shorthand notation to directing comments. OP is the 'original poster', which is always shorter than typing. or copy/pasting the person's name that started the thread. (O and P being right next to each other on the keyboard [wink])

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
Quote:
Original post by evolutional
Is it a C++ wrapper for SDL?


sounds like it.

@OP you don't have a link?


Oh now I know what OP is. Well, no, I dont have a link. Even if I did, how would I upload the engine? I have it directly in my project(separate files though), because when I tried making it into a library it game me linker errors. Any ideas on it?

Share this post


Link to post
Share on other sites
This is very structurally based using surface indexes instead of object oriented design. The thing about programming is that there is no right way to do it. My personal thoughts on the matter is that I find object orientation much more natural and easy to use then the non-object oriented approach. If you were to try and create a pong clone using this, you might not have much difficulty, but I would find it easier if you had your own Surface class that handled the loading and destruction of SDL surfaces, a sprite class used at a more advanced level managing multiple surface images, and a base engine class putting it all together.

Go ahead and try putting the system you've made to use in a pong clone and see how far you get before deciding object orientation is more managable [wink].

Share this post


Link to post
Share on other sites
i have a similar thing, but with important differences.

i have an SDL class, which when instatanciated calls SDL_Init(0)

when all refernces to it go out of scope; it calls SDL_Quit()

i then have a Rendering class, which has a refernece to an SDL. it inits the video subsystem and de-inits it on destruction

i have a Network class, that has a reference to SDL_Net( which has a reference to a SDL instance...)

and so on. basically i'm trying to wrap anything that requires a init function and a de-init function into a class with constructor/destructor. i havent sorted out all the details ( specifically having one SDL_Surface shared between multiple Image objects in an intelligent manner )

Share this post


Link to post
Share on other sites
Quote:
Original post by Rob Loach
This is very structurally based using surface indexes instead of object oriented design. The thing about programming is that there is no right way to do it. My personal thoughts on the matter is that I find object orientation much more natural and easy to use then the non-object oriented approach. If you were to try and create a pong clone using this, you might not have much difficulty, but I would find it easier if you had your own Surface class that handled the loading and destruction of SDL surfaces, a sprite class used at a more advanced level managing multiple surface images, and a base engine class putting it all together.

Go ahead and try putting the system you've made to use in a pong clone and see how far you get before deciding object orientation is more managable [wink].


Well, to tell you the truth my pong clone got messy so I decided on OOP. Anyways, I have just that, not anything else.

I have an 'Image' class that you can use all alone. It handles all other the 'SDL_Surface*' stuff, including loading and freeing it. However, my engine uses that same class, so instead of having a bunch of 'Image's floating around they get pushed in the engine, which stores them in a 'vector'.

Now I think I am going to do the same thing in the engine, but with a 'Text' class that you can use all alone, but the engine using it to draw the text.

So all in all, I am actually doing what you just said.

Share this post


Link to post
Share on other sites
Quote:
Original post by Rob Loach
You could take the .NET approach and implement a ImageCollection class that manages all images within a linked list/vector.


My engine does just that. It doesnt show you the vector, it retrieves the 'Image' from the vector and returns it all in one function.

//Edit: Anyways, I'm not working with visual studio, I'm using code::blocks with the mingW compiler.

Share this post


Link to post
Share on other sites
Ok, I ran into a problem. Look:

...
if (EnableText)
{
if (TTF_Init() == -1)
return 1;

m_TextInitialized = true;
}
else
m_TextInitialized = false;
...

This code runs fine and everything is great. Except for the error handling. Normally, in main() i should have this:

...
if (myEngine.Init(SDL_INIT_VIDEO | SDL_INIT_TIMER, true) != 0)
// Handle error!
...

But - what should I do to handle the error? A message box would work, but will mess up if it was in fullscreen. I've seen stuff like this:

fprintf(stderr, "Error: Could not initialize SDL!");

Will that work? I mean, will it print that message to the stderr.txt file that is created when the program is run? Or do I have to manually open stderr.txt and print to it?

Share this post


Link to post
Share on other sites
Quote:
Original post by dudedbz1
Ok, I ran into a problem. Look:

...
if (EnableText)
{
if (TTF_Init() == -1)
return 1;

m_TextInitialized = true;
}
else
m_TextInitialized = false;
...

This code runs fine and everything is great. Except for the error handling. Normally, in main() i should have this:

...
if (myEngine.Init(SDL_INIT_VIDEO | SDL_INIT_TIMER, true) != 0)
// Handle error!
...

But - what should I do to handle the error? A message box would work, but will mess up if it was in fullscreen. I've seen stuff like this:

fprintf(stderr, "Error: Could not initialize SDL!");

Will that work? I mean, will it print that message to the stderr.txt file that is created when the program is run? Or do I have to manually open stderr.txt and print to it?



it will work.

however, a message box is not a bad way to go for that particular error - you cant have switched to fullscreen if you haven't initialised SDL.

however, implementing your own logging system if also good.

if you cant initialise SDL or the SDL graphics subsystem, you can use a O.S. defined message box. afterwards you can make your own message box that is a SDL_Surface* and is inside your app window. that way fullscreen wouldnt affect it...

Share this post


Link to post
Share on other sites
Quote:
Original post by Rob Loach
...My personal thoughts on the matter is that I find object orientation much more natural and easy to use then the non-object oriented approach. If you were to try and create a pong clone using this, you might not have much difficulty, but I would find it easier if you had your own Surface class that handled the loading and destruction of SDL surfaces, a sprite class used at a more advanced level managing multiple surface images, and a base engine class putting it all together...


In my experience it's quite difficult to make a good OOD when you are at a beginning level of programming, where I am. When I did my tetris clone I attempted a nice OO approach and everything went sort of really well. Except that when almost finished, some flaws in the design started to 'exponentially' cause difficulties. I spent most time at the end correcting my mistakes.

@OP: It would be nice to see your code, and / or discuss the issues with OO design at an beginner's level

Share this post


Link to post
Share on other sites
Quote:
@OP: It would be nice to see your code, and / or discuss the issues with OO design at an beginner's level


I may not be an expert, but please dont call me a beginner.

Fine, lets discuss the code instead.

SDL_EngineMain.h:

#include <SDL.h>

#include <SDL_Image.h>

#include <vector>

#include "Image.h"

#ifndef SDL_ENGINEMAIN_H
#define SDL_ENGINEMAIN_H

using std::vector;

class SDL_Engine
{
public:
SDL_Engine(): m_Screen(NULL), m_TextInitialized(false)
{
}
~SDL_Engine();

int Init(unsigned int SDL_Flags, bool EnableText = false);
int DeInit();

int InitWindow(unsigned int Height, unsigned int Width, unsigned int SDL_Flags);

void AddImage(const char *FileName);
Image *GetImage(int i);

int DrawImage(int ImageToDraw);

void Flip();

void PrintError(const char *Error);

private:
SDL_Surface *m_Screen;

bool m_TextInitialized;

vector<Image*> m_Images;
};

#endif /*SDL_ENGINEMAIN_H*/



SDL_EngineMain.cpp

#include <SDL.h>

#include <SDL_image.h>

#include <SDL_ttf.h>

#include <vector>

#include <cstdio>

#include "Image.h"

#include "SDL_EngineMain.h"

using std::vector;

SDL_Engine::~SDL_Engine()
{
for (int i = 0; i < m_Images.size(); i++)
delete m_Images[i];
}

int SDL_Engine::Init(unsigned int SDL_Flags, bool EnableText)
{
if (SDL_Init(SDL_Flags) == -1)
return 1;

if (EnableText)
{
if (TTF_Init() == -1)
return 1;

m_TextInitialized = true;
}
else
m_TextInitialized = false;

return 0;
}

int SDL_Engine::DeInit()
{
if (m_TextInitialized)
TTF_Quit();

SDL_Quit();
}

int SDL_Engine::InitWindow(unsigned int Height, unsigned int Width, unsigned int SDL_Flags)
{
m_Screen = SDL_SetVideoMode(Height, Width, 0, SDL_Flags);

if (m_Screen == NULL)
return 1;

return 0;
}

void SDL_Engine::AddImage(const char *FileName)
{
Image *Temp = new Image;

Temp->SetSprite(FileName);

m_Images.push_back(Temp);
}

Image *SDL_Engine::GetImage(int i)
{
if (i < m_Images.size())
return m_Images[i];

return NULL;
}

int SDL_Engine::DrawImage(int ImageToDraw)
{
if (ImageToDraw < m_Images.size())
{
SDL_Rect Source;
SDL_Rect Dest;

Source.x = 0;
Source.y = 0;
Source.w = m_Images[ImageToDraw]->Getw();
Source.h = m_Images[ImageToDraw]->Geth();

Dest.x = m_Images[ImageToDraw]->Getx();
Dest.y = m_Images[ImageToDraw]->Gety();
Dest.w = Source.w;
Dest.h = Source.h;

SDL_BlitSurface(m_Images[ImageToDraw]->GetSprite(), &Source, m_Screen, &Dest);

return 0;
}

return 1;
}

void SDL_Engine::Flip()
{
SDL_Flip(m_Screen);
}

void PrintError(const char *Error)
{
fprintf(stderr, Error);
}



Image.h:

#include <SDL.h>

#include <SDL_image.h>

#ifndef IMAGE_H
#define IMAGE_H

class Image
{
public:
Image(int x = 0, int y = 0): m_x(x), m_y(y)
{
}
~Image()
{
SDL_FreeSurface(m_Sprite);
}

int Getx() {return m_x;}
void Setx(int x) {m_x = x;}

int Gety() {return m_y;}
void Sety(int y) {m_y = y;}

int Getw() {return m_Sprite->w;}
int Geth() {return m_Sprite->h;}

void SetSprite(const char *FileName)
{
m_Sprite = IMG_Load(FileName);
}
SDL_Surface *GetSprite() {return m_Sprite;}

private:
int m_x;
int m_y;

SDL_Surface *m_Sprite;
};

#endif /*IMAGE_H*/



To tell you the truth, I think its going great.

Share this post


Link to post
Share on other sites
some random advice.

in your header files, you can try this


// these first
#ifndef FILENAME_H
#define FILENAME_H

// then these
#include <lots_Of_STL>
# ...
# ...

class FILENAME{};

#endif



that way you avoid #include'ing the #include's( the STL headers ) multiple times

also you need some checks in your draw code for NULL surfaces( or somewhere, just to tell the application that this surface is invalid )

a personal favouite is for the draw routine to check if the surface is NULL; and if it is then set the pointer to some default image created in-code, like
in half-life2 if they cant find a texture it makes it a pink and black checkerboard. its obvious that somethings wrong and your program doesn't have to crash/shutdown
[/source]

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
some random advice.

in your header files, you can try this

*** Source Snippet Removed ***

that way you avoid #include'ing the #include's( the STL headers ) multiple times

also you need some checks in your draw code for NULL surfaces( or somewhere, just to tell the application that this surface is invalid )

a personal favouite is for the draw routine to check if the surface is NULL; and if it is then set the pointer to some default image created in-code, like
in half-life2 if they cant find a texture it makes it a pink and black checkerboard. its obvious that somethings wrong and your program doesn't have to crash/shutdown
[/source]


Good idea, I shall do that. However, how would I make the NULL surface a color? Not specifically a pattern, just some color?

Share this post


Link to post
Share on other sites
like so

link to function thats used here


SDL_Surface *notFound = SDL_CreateRGBSurface(

SDL_SWSURFACE,
/*width*/100,
/*height*/100,
SDL_GetVideoSurface()->BitsPerPixel,
SDL_GetVideoSurface()->format->Rmask,
SDL_GetVideoSurface()->format->Gmask,
SDL_GetVideoSurface()->format->Bmask,
SDL_GetVideoSurface()->format->Amask

);

for( int i = 0 ; i < notFound->w ; ++i ){
for( int j = 0 ; j < notFound->h ; ++j ){
putpixel(notFound,i,j,SDL_MapRGB( R,G,B ) );
}
}


Share this post


Link to post
Share on other sites
Ok, but I think I'm not going to make it a color or anything. I'll just quit the program and say what happened in stderr.txt. Because if something went wrong, most likely you wont like playing the game that way anyways.

Anyways, any other comments?

Share this post


Link to post
Share on other sites
Quote:
Original post by dudedbz1
Quote:
@OP: It would be nice to see your code, and / or discuss the issues with OO design at an beginner's level


I may not be an expert, but please dont call me a beginner.

Hey man, I'm sorry. I meant myself, I consider myself a beginnner.

Anyways, just some thoughts I have:

About your Image class:
// Constructor:
Image(int x = 0, int y = 0)
: m_x(x), m_y(y), m_Sprite(NULL) //Initialize m_Sprite with a NULL pointer
{
}

// Destructor:
~Image()
{
if (m_Sprite != NULL)
SDL_FreeSurface(m_Sprite);
else
fprintf(stderr, "Error: m_Sprite is NULL.\n"); //assuming m_Sprite should never be NULL on destruction
}

// This will result in faster blitting,
// you will need SDL_DisplayFormatAlpha for surfaces with alpha blending or colorkey:
void SetSprite(const char *FileName)
{
m_Sprite = SDL_DiplayFormat(IMG_Load(FileName));
}
It may (or may not, I'm sure there are better ways) be useful to store the const char* FileName within the Image object. That way you can also keep track of which image went wrong in case of bugs, by printing it to stderr.


Not really important and / or related, but it's nice to have some functions like these that make your code shorter, for example:

bool operator == (SDL_Color a, SDL_Color b)
{
return (a.r == b.r && a.g == b.g && a.b == b.b);
}
bool operator != (SDL_Color a, SDL_Color b);
{
return (a.r != b.r || a.g != b.g || a.b != b.b);
}
void SetRect(SDL_Rect& Rect, int x, int y, int w, int h)
{
rect.x = x;
rect.y = y;
rect.w = w;
rect.h = h;
}


@rip-off: Wouldn't it be easier to use SDL_FillRect to fill a surface with a color?
int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);

That's it for now.

Share this post


Link to post
Share on other sites
Quote:
Original post by DeadXorAlive
Quote:
Original post by dudedbz1
Quote:
@OP: It would be nice to see your code, and / or discuss the issues with OO design at an beginner's level


I may not be an expert, but please dont call me a beginner.

Hey man, I'm sorry. I meant myself, I consider myself a beginnner.

Anyways, just some thoughts I have:

About your Image class:
*** Source Snippet Removed *** It may (or may not, I'm sure there are better ways) be useful to store the const char* FileName within the Image object. That way you can also keep track of which image went wrong in case of bugs, by printing it to stderr.


Not really important and / or related, but it's nice to have some functions like these that make your code shorter, for example:
*** Source Snippet Removed ***

@rip-off: Wouldn't it be easier to use SDL_FillRect to fill a surface with a color?
int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);

That's it for now.


I will check for NULL, as I had it in mind, but for the later changes. Anyways, now the engine supports text, I just have to test it.

//Edit: Yay the text also works. And I made it so you can always use the class by itself, or use it through the engine. All you do is this:

//through the engine!

myEngine.AddText();

myEngine.GetText(0)->SetTextColor(0, 255, 0);

myEngine.GetText(0)->SetSize(15);

myEngine.GetText(0)->SetFont("arial.ttf");

myEngine.GetText(0)->SetText("Cool, it works!");

myEngine.DrawText(0);

//not through the engine!

Text *theText = new Text;

theText->SetSize(15);
theText->SetFont("arial.ttf");
theText->SettextColor(0, 255, 0);
theText->SetText("Cool, it works!");

delete theText;



It works! Sooo cool. Anyways, the only problem with using the class alone is that you have to make your own drawing function, sorry.

//Edit(2): I use '0' because it is the first 'Image'/'Text' stored in the engine. Most likely I will use an enum when I start storing more images.

[Edited by - dudedbz1 on October 23, 2005 2:58:10 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this