Working on my 2D Game Engine

Posts 115 of 17 · Page 1 of 2
Working on my 2D Game Engine
Hello guys, I am here to show you progress of my 2d game engine. I'm trying to make it VERY object oriented, and yeah. Here's the Source too.

So far it supports Playing, pausing, resuming and stopping Music and sound effects, Displays images, and a work in progress textbox class which will create a semi transparent textbox with the loaded font and message and stuff. The textbox class is nowhere near complete though

Keep in mind this is like .1% complete, and of course I'm going to add color keying, animations etc. Whatever is in a game this engine should support.

This took me about 4 hours so far. I'm restarting what I stopped last summer, which would be pretty badass if I still had it and didn't delete the source when I formatted



 
main.cpp
Code:
#include "SDL.h"
#include "gfx.h"
#include "class.h"
#include "textbox.h"
const char* debugLog = "C:\\sdl\\log.txt";
int main(int argc, char* args[])
{
	SDL_Surface* Image = LoadIMG("C:\\sdl\\test.png");
	SDL_Surface* Screen = NULL; 
	SDL_Event event;
	bool quit = false;

	Program Engine;	//create an instance of Program, defined in class.h
	Video Window;		//create an instance of Video, for using the screen

	Window.Width = 640;
	Window.Height = 480;
	Window.BPP = 32;
	Window.Flags = SDL_SWSURFACE;

	Music TestSong;
	Textbox Box;
	//Start SDL and init everything needed right now
	if( Engine.Init(SDL_INIT_EVERYTHING) == false)//init SDL
	{
		Engine.LogToFile(debugLog, Engine.Error);
	}
	if( Engine.MixInit(DEFAULT_FREQ, MIX_DEFAULT_FORMAT, 2, DEFAULT_CHUNK_SIZE) == false)//Init Music
	{
		Engine.LogToFile(debugLog,Engine.Error);
	}
	if( Engine.FontInit() == false)	//Init TTF fonts
	{
		Engine.LogToFile(debugLog,Engine.Error);
	}
	if( TestSong.Load("C:\\sdl\\SONG.wav") == false)	//load song
	{
		Engine.LogToFile(debugLog,TestSong.Error);
	}
	if( Box.LoadFont( "C:\\sdl\\CALIBRI.ttf",52) == false)	//load font
	{
		Engine.LogToFile(debugLog,Box.Error);
	}
	Bo*****tFontColor(255,255,255); //make it white

	Screen = Window.SetVideo(Window.Width , Window.Height , Window.BPP , Window.Flags);
	Engine.WindowName("Engine 0.02a",NULL);

	//draw image
	ApplySurface(0,0,Image,Screen);
	//draw box ontop of image
	Bo*****tRGBA(Screen->format,47,107,140, 210);
	Box.DefineRect(15 , 350 , Window.Width - 30, Window.Height - 365);

	if ( Box.DrawBox(Screen , Box.RGBA , Box.Rectangle, NULL, "This is a test!") == false)
	{
		Engine.LogToFile(debugLog, Box.Error);
	}
	SDL_Flip(Screen);
	while(quit == false)
	{
		while(SDL_PollEvent(&event))
		{
			if(event.key.keysym.sym == SDLK_1)
			{
				if(TestSong.Play(INFINATE) == false)
				{
					Engine.LogToFile(debugLog, TestSong.Error);
				}
			}
			else if(event.key.keysym.sym == SDLK_ESCAPE)
			{
				quit = true;
			}
			else if(event.key.keysym.sym == SDLK_2)
			{
				TestSong.PauseResume();
			}
			else if(event.key.keysym.sym == SDLK_3)
			{
				TestSong.Stop();
			}
		}
	}
	//free all memory
	TestSong.Free();
	Window.Free(Image);
	Engine.MixClose();
	Engine.Close();
	return 0;
}


 
gfx.h
Code:
#include "sdl_image.h"

SDL_Surface* LoadIMG(char* file)
{
	SDL_Surface* image = IMG_Load(file);
	return image; //return it for use
}
void ApplySurface(int x, int y, SDL_Surface* src, SDL_Surface* dst)	//applies something to a surface
{
	SDL_Rect temp;		//temp rect use for coords
	temp.x = x;
	temp.y = y;
	SDL_BlitSurface(src,NULL,dst,&temp);		//apply it
}


 
class.h
Code:
#include "SDL.h"
#include "SDL_mixer.h"
#include "SDL_ttf.h"
#include <stdarg.h>
#include <stdio.h>
/*=================================================================================================================
==================================================PROGRAM CLASS==================================================
===================================================================================================================*/
class Program
{
public:
	void LogToFile(const char* path,char* text);
	void Close(); 
	void MixClose();
	void FontClose();
	void WindowName(const char* name,const char* icon); 
	char* Error;
	bool Init(Uint32 flags);
	bool MixInit(int Freq, Uint16 format, int channel, int chunksize); //sound freq(set to 22050), audio format,channel,sample size(4096)
	bool FontInit();
private:
};
bool Program::FontInit()
{
	if( TTF_Init() == -1)
	{
		Error = TTF_GetError();
		return false;
	}
	else
	{
		return true;
	}
}
void Program::FontClose()
{
	TTF_Quit();
}

bool Program::Init(Uint32 flags)
{
	if( SDL_Init(flags) == -1)
	{
		Error = SDL_GetError();
		return false;
	}
	else
	{
		return true;
	}
}
void Program::Close()
{
	SDL_Quit();
}
void Program::MixClose()
{
	Mix_CloseAudio();
}
void Program::LogToFile(const char* path, char* text)	//writes error to file
{
	FILE* file;
	file = fopen(path,"a+");		//add text to a file or create if it does not exist
	fprintf(file,"%s \n",text);	//write to the text file
	fclose(file);		//close file after writing
}
void Program::WindowName(const char *name, const char* icon)
{
	SDL_WM_SetCaption(name,icon);
}
bool Program::MixInit(int Freq, Uint16 format, int channel, int chunksize)
{	
	if( Mix_OpenAudio(Freq, format, channel, chunksize) == -1)
	{
		Error = Mix_GetError();
		return false;
	}
	else
	{
		return true;
	}
}


/*=================================================================================================================
==================================================GRAPHICS CLASS==================================================
===================================================================================================================*/
class Video
{
public:
	SDL_Surface* SetVideo(int w, int h, int bpp, Uint32 flags);
	void Free(SDL_Surface* surface);
	int Width;
	int Height;
	int BPP;
	Uint32 Flags;
private:
};
void Video::Free(SDL_Surface* surface)
{
	SDL_FreeSurface(surface);
}
SDL_Surface* Video::SetVideo(int w, int h, int bpp, Uint32 flags)
{
	SDL_Surface* Screen = SDL_SetVideoMode(w,h,bpp,flags);
	return Screen;
}

/*=================================================================================================================
==================================================AUDIO CLASSES====================================================
===================================================================================================================*/
#define INFINATE -1 
#define DEFAULT_FREQ 22050
#define DEFAULT_CHUNK_SIZE 4096
class Music
{
public:
	Mix_Music* Song;
	bool Load(const char* path);
	void Free();		//will free the memory taken by the song
	bool Play(int timesToPlay);	//-1 plays forever
	void Stop();
	void PauseResume();
	
	char* Error;	//used for tracking errors, char* = SDL_GetError()
	int Frequency;
	Uint16 Format;
	int Channel;
	int Chunksize;	//sampling rate
private:
};
void Music::Stop()
{
	Mix_HaltMusic();
}
void Music::PauseResume()
{
	if (Mix_PausedMusic() == 1)
	{
		Mix_ResumeMusic();
	}
	else
	{
		Mix_PauseMusic();
	}
}
bool Music::Load(const char *path)
{
	Song = Mix_LoadMUS(path);
	if(Song == NULL)
	{
		Error = Mix_GetError();
		return false;
	}
	else
	{
		return true;
	}
}
void Music::Free()
{
	Mix_FreeMusic(Song);
}


bool Music::Play(int timesToPlay)
{
	if( Mix_PlayMusic( Song, timesToPlay) == -1)
	{
		Error = Mix_GetError();
		return false;
	}
	else
	{
		return true;
	}
}
/*==================================================================================================================
=====================================================SOUND EFFECTS================================================*/
class SoundEffect
{
public:
	Mix_Chunk* SFX;
	bool Load(const char* path);
	void Free();
	bool Play(int channel, Mix_Chunk* sfx, int timesToPlay); //timesToPlay is 0, then plays once

	char* Error;
	int Frequency;
	Uint16 Format;
	int Channel;
	int Chunksize;	//sampling rate
private:
	const char* file;
};
bool SoundEffect::Play(int channel, Mix_Chunk* sfx, int timesToPlay)
{
	if( Mix_PlayChannel(channel, sfx, timesToPlay) == -1)
	{
		Error = Mix_GetError();
		return false;
	}
	else
	{
		return true;
	}
}
bool SoundEffect::Load(const char *path)
{
	SFX = Mix_LoadWAV(path);
	if(SFX == NULL)
	{
		Error = Mix_GetError();
		return false;
	}
	else
	{
		return true;
	}
}
void SoundEffect::Free()
{
	Mix_FreeChunk(SFX);
}


 
textbox.h
Code:
#include <stdarg.h>
#include <stdio.h>
#include "sdl_image.h"
#include "SDL.h"
#include "SDL_ttf.h"

class Textbox
{
public:
	bool DrawBox(SDL_Surface *dst, Uint32 Color, SDL_Rect rect, char* title, char* text);
	void SetRGBA(SDL_PixelFormat* fmt, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
	void DefineRect(Sint16 x, Sint16 y, Uint16 w, Uint16 h);
	void SetFontColor(Uint8 r, Uint8 g, Uint8 b);
	bool LoadFont(char* path, int size);
	
	TTF_Font* Font;
	SDL_Color FontColor;
	Uint32 RGBA;		//stores all RGBA values
	SDL_Rect Rectangle;
	Uint8 Red;		//individual RGBA values if needed
	Uint8 Blue;
	Uint8 Green;
	Uint8 Alpha;
	char* Error;
private:

};

void Textbox::SetFontColor(Uint8 r, Uint8 g, Uint8 b)
{
	FontColor.r = r;
	FontColor.g = g;
	FontColor.b = b;
}
bool Textbox::LoadFont(char* path, int size)
{
	Font = TTF_OpenFont(path, size);
	if( Font == NULL)
	{
		return false;
	}
	else
	{
		return true;
	}
}

void Textbox::SetRGBA(SDL_PixelFormat* fmt, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
	RGBA = SDL_MapRGBA(fmt,r,g,b,a);
	Red = r;
	Blue = b;
	Green = g;
	Alpha = a;
}
void Textbox::DefineRect(Sint16 x, Sint16 y, Uint16 w, Uint16 h)
{
	Rectangle.x  = x;
	Rectangle.y = y;
	Rectangle.w = w;
	Rectangle.h = h;
}
bool Textbox::DrawBox(SDL_Surface *dst, Uint32 Color, SDL_Rect rect, char* title, char* text)
{
	SDL_Surface* temp = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_ANYFORMAT, Rectangle.w, Rectangle.h, 32, 0,0,0,0);		//temp surface used to draw box
	SDL_Surface* message = TTF_RenderText_Solid(Font, text, FontColor);
	if ( SDL_FillRect(temp, NULL, RGBA) == -1)
	{
		Error = SDL_GetError();
		return false;
	}
	if( SDL_SetAlpha(temp,SDL_SRCALPHA,Alpha) == -1)
	{
		Error = SDL_GetError();
		return false;
	}
	if( SDL_BlitSurface(message,NULL,temp,NULL) == -1)	//write  message to temp
	{
		Error = SDL_GetError();
		return false;
	}
	if ( SDL_BlitSurface(temp,NULL,dst,&rect) == -1)	//write temp to screen
	{
		Error = SDL_GetError();
		return false;
	}
	SDL_FreeSurface(temp);		//always free memory
	SDL_FreeSurface(message);
	return true;
}
Keep us up to date!
I don't mean to discourage you but making a game engine takes a LOTTT of work. You say you are 0.1% done and have worked 4 hours on it. So doing the math....you are going to need to spend 4000 hours on it. Obviously it's not going to take you that long but it will still require a ton of hours. Making a game engine will let you learn a ton of stuff on the way but in the end it's not worth it. If the end result to make your own game in your engine, then you should probably use another game engine (I recommend looking into DarkGDK). But if you really want to learn, then I think making your game instead of making a game engine will be more rewarding. However, if you really want to just make a game engine, you should find some other people or friends that can work with you on it. Anyways, good luck!
Quote Originally Posted by zhaoyun333 View Post
I don't mean to discourage you but making a game engine takes a LOTTT of work. You say you are 0.1% done and have worked 4 hours on it. So doing the math....you are going to need to spend 4000 hours on it. Obviously it's not going to take you that long but it will still require a ton of hours. Making a game engine will let you learn a ton of stuff on the way but in the end it's not worth it. If the end result to make your own game in your engine, then you should probably use another game engine (I recommend looking into DarkGDK). But if you really want to learn, then I think making your game instead of making a game engine will be more rewarding. However, if you really want to just make a game engine, you should find some other people or friends that can work with you on it. Anyways, good luck!
Lol I am not for using public engines, I think it takes away most of the fun for me. Yeah I know what I'm getting into but i have experience so it's all kay.
Quote Originally Posted by Auxilium View Post


Lol I am not for using public engines, I think it takes away most of the fun for me. Yeah I know what I'm getting into but i have experience so it's all kay.
I think exactly the same! Fun part is programming the core stuff. For me, it is more rewarding to know that lots of people will use your work to make other games than creating a game with the tools provided by others.

I'm not saying that using APIs sucks, but for me, the fun part is creating them.
Engine version 0.03a
Update: Added Colorkeying and animation support. No movement yet, but next on list. (can't see animation on a printscreen though, but it's there!!) (Tails is making some phat beats and such with his turntables)
Made text nice and smooth costing only a little more memory

Lol, I literally have to go in 4 minutes, so this is quick advice.

Looks good, just some suggestions:
You have a textbox class, which has things like focus, text, background and a border. This is all in-common with a form, panel, text-field, or a button. My point being, you should use a more OOP implementation.

UIControl
- Has background color maybe. Interface functions like setFocus(const bool isFocused) or other interface functions like mouseOver or mouseOut or mouseDown or keyDown or keyUp or keyPressed.

Then have UIPanel inherit UIControl and implement things like child controls etc...

Then have UIForm inherit UIControl

Then have UILabel inherit UIControl

Then have UIButton inherit UILabel

Then have UITextField inherit UILabel

and UITextBox inherits UITextField

just stuff like that. You could also put it inside of a namespace GameUI or something to contain the UI subsystem. Trust me, it will make your life a lot easier. It sounds like a lot of work now, but it will save you a lot of time. (I've gone through writing my first engine before without it and it turned from very simple to very complicated quickly because I did not use an OOP design very well.)

Also, I would suggest you have a (not a singleton but a global variable) to handle the UI subsystem. Like adding forms and managing their location etc... (I can elaborate more when I get back from school lol I really go to go.)

Anyway, good luck and post the progress.
I'm also looking forward to that elaboration : )
Thanks for the input Jetamay.

update: I am rewriting what i made so far. I realized I never really planned out how everything should go in place, and coded it one piece at a time. This time I actually made a plan, using a lot of OOP and inheritance (I hope)
Ew @ all class defs in a single .h :3

Looks pretty good in the 10 seconds I glanced at it before leaving work, but there are some lapses in the OO nature of the design.
Quote Originally Posted by Broderick View Post
Ew @ all class defs in a single .h :3

Looks pretty good in the 10 seconds I glanced at it before leaving work, but there are some lapses in the OO nature of the design.
Yes I agree about the ew. Which Is why I'm rewriting it to be more organized and oop
use UML notation for all of your code, it is very useful and its a way of planning your project.
Quote Originally Posted by unspeakable View Post
use UML notation for all of your code, it is very useful and its a way of planning your project.
Do all 71 of your posts contain "USE UML HURR DURR"?
Quote Originally Posted by unspeakable View Post
use UML notation for all of your code, it is very useful and its a way of planning your project.
I think i'd rather pass.
Posts 115 of 17 · Page 1 of 2

Post a Reply

Similar Threads

Tags for this Thread

None

Need help?