Jump to content
Site Stability Read more... ×
  • Advertisement
Sign in to follow this  
  • entries
  • comments
  • views

About this blog

Incomprehendable ramblings of the most unproductive programmer to set foot in these forums in ages.

Entries in this blog


SDL_net chat server

Ok. I am going to try to get this right this time.

I am a big fan of text based MUDs. I got my start playing ROM based MUDs when I was about 17 (over 12 years ago!). There have been many improvements made to IDE's and compilers along with their free availability which helped decreased the need to have a remote host that had all of the build tools. The broadband boom has made it cheap and convenient to develop and test MUDs on a home computer through either a cable or DSL connection where traditionally they were hosted on college servers and low cost commercial servers because broadband in the home was pretty expensive.

I wanted to see how difficult/easy it would be to re-write one of these monsters from the ground up. Most of the popular hack n' slash style MUDs I have played are based on the Diku->Merc->ROM family which are written in C. Most have had so many different programmers that they have become a mass of spaghetti code that requires an in depth knowledge of the code in order to add or modify some of the simplest things. I hope to change that.

Starting off last night because of a post in the beginners forum regarding a simple chat server I began writing some code.

Here is what I wrote down as some needs:
1. cross platform code to be run on the major platforms of Windows, Mac and *nix.

2. C++ standard library containers and strings need to be utilized instead of the traditional home brew versions. Save on some time and bugs.

3. An embeded database system instead of flat files. Not everyone has access to or wants to set up and maintain MS SQL Server or MySQL and flat files turn out to be very cumbersome when adding fields to objects.

With that in mind I came up with these solutions:
1. SDL and the SDL_net library. SDL and it's add-on libraries are proven to be cross platform and pretty solid and best of all the S in SDL stands for "Simple". Why look any further.

2. Nothing here to explain. This is the reason STL became a standard in the first place.

3. SQLite3 is actively being developed and I have had some success converting older ROM based MUD flat files to this embeded database system in the past. A giant side bonus to this is that newer versions of PHP have a built in interface to the SQLite3 library to easily integrate game information into your web pages. A thin wrapper around this will need to be developed.

So... last night I wrote a simple multi-user chat server using SDL_net. The code is linked here.

Next is to add some more functionality like loging in and password recognition.





The goal of this whole project is to make a simple framework for me to work with in creating NES & SNES style 2d tile based games. I don't want to have to worry about creating base sprite classes, tile classes, fonts and simple HUDs. So basicly I am writing a (S)imple (G)aming (L)ayer. Using SDL underneath will help porting to different platforms if people wish to do so (in other words, not me).

The use of OpenGL as the graphics API has allowed me to introduce alpha blending, rotation and scaling on a hardware level that basic SDL can only offer in software emulation.

Some things I have come to enjoy so far:

- SGL_Sprite is a basic 2d image or part of an image that can be drawn, stretched, blended, and/or rotated anywhere on the screen. SGL_Sprite's need outside information to tell them where and how to be drawn.

- SGL_Entity is more of a physical entity in your game world. It contains a pointer to an SGL_Sprite to act as it's visual representation. An SGL_Entity object contains all of the information it needs to represent itself on the screen as well as check if it has collided with another entity.

- SGL_SurfaceManager is available to help manage loading and unloading SGL_Surface objects and makes sure you do not load the same surface twice.

- SGL_SpriteManager is available to help manage and act as a container of SGL_Sprite objects.

- SGL_EntityManager is available to help manage and act as a container of SGL_Entity objects.

Soon to come: Demo or something




Project SGL

I started my SDL+OpenGL framework today. I am going to get something finished if it kills me this time. This is mainly spawned from wanting to use SDL but SDL not having the *oomf* I want or may want in the future.

I find myself re-writing a ton of the same code all the time, re-writing it slightly different each time. This time I am making a library I can edit and re-use all the time.

Here's a breakdown of how it will work in theory:
(Things with a * next to them have a working implementation already although not optimized)

SGL_XXX will be the naming convention used for classes and function calls specific to the library.

SGL relies on the STL quite a bit but only internally. In the instance of std:string it is pretty well hidden behind the class interfaces which all ask for const char * pointers and return the same. This was a decision I made to make my life with file i/o much simpler and will be the case throughout since it is quite easy to use the std::string.c_str() method to get a character array.

*SGL_Surface is a class I am working on that has most of the functionality of an SDL_Surface along with built in pixel manipulation. the BlitSurfaceEx member function supports scaling, rotation, and alpha blending while the BlitSurface functions support scaling and blending. It also supports multiple color keys where you can specify the level of alpha for different colors.

*SGL_Point is a class that acts as a 2D point in space and has integer and floating point interfaces.

*SGL_Vertex is a class that acts as an OpenGL vertex with x,y,z coordinates and a color. This class is mainly used behind the scenes as the SGL library is meant to be used for 2D applications.

*SGL_Rect is a class that contains an SDL_Rect but has the added functionality of being able to internally convert to texture coordinates while keeping the original integer level of a SDL_Rect intact for usefulness. Can also be rendered as a filled or empty polygon. Features interfaces for collision detection between other SGL_Rectangle and SGL_Point objects.

**(In the works)SGL_Circle:
**(In the works)SGL_Polygon:
**(In the works)SGL_Line:

*SGL_Sprite is a simple sprite class that has almost no internal data except for a source surface and source rectangle. It is meant to be a base class for more complex graphical objects. Using the DrawSpriteEx member function, you can scale, rotate, and/or blend a sprite. Think of an SGL_Sprite as a textured quad that can be stretched and/or rotated.

*SGL_File is a simple file i/o class that wraps C style file I/O. I love the ease of working with text files but hate writing specialized code every time to read/write my files. Most notably it has interfaces for reading single or quoted words as one token and reading multiple line strings by specifying an end_of_string character. There are also integer and floating point reading interfaces.

(**somewhat working)SGL_Font/SGL_Glyph is a simple bitmap font library for using bitmap fonts generated with "Bitmap Font Builder" (I will refer to it as BFB). It generates a stand alone font file from the bitmap and widths file from BFB so you don't have to keep the bulky bitmaps. This is just a simple library and is meant to be expanded as needed. Writing strings in printf style is supported but word wrapping is not.

Some notes on rotation and scaling:
Scaling is done by changing the size of the destination rectangle in the BlitSurface and DrawXXX functions. Rotation is available through specifying a SDL_Point of origin to rotate around and an angle of rotation from 0.0f to 1.0f.

I will start posting a link to the working code in a tarball in my next post.




Finally some light at the end of the tunnel

First off let me say how much of an idiot I am. Next, lets restate the obvious... *IDIOT*.

Past week or so I have been having problems adding simple un-filled primitives to my SDL/OpenGL library. The colors were getting skewed and since I am not at all familiar with 3d graphics concepts I did what anyone would do before posting my problems in the forums. I read. I read some more. I googled, I yahoo'd, I even asked jeeves. Unfortunately none of these things got it through my thick skull what was going wrong.

Here is the lowdown:
Drawing primitives by themselves works fine as long as I didn't load any textures. However, Load a texture and for some reason the primitives colors get all whacked out. Thinking it was the blending or alpha test I spent many days reading and pulling out hair from many trials and even more errors. My texture loading code worked fine. The blending/alpha test worked fine. But I could not color the primitives.

Here was the solution:
Being the GL newbie I am, I didn't realize what enabling or disabling all of these states do. I had blending, alpha testing, point, line smoothing, and depth testing enabled and disabled at button presses to see if these were the problem. I learned a lot but still no dice. Here is the kicker. When drawing textured geometry, GLTEXTURE_2D is required to be enabled. However, when not drawing textured geometry, it totally screws up everything else if it is still enabled. So, by disabling GL_TEXTURE_2D before drawing primitives, this solved my problem.


Anyway, not sure if this is the proper solution to my problem but it worked for me.

Currently in my GL2D library I have C style functions to:
-Load bitmaps to textures
-Set color keys on textures (fake it baby)
-SDL style blits (destination surface is ignored and sent to screen)
-Alpha blending/transparency
-Primitives: lines, rectangles, polygons, circles (filled or empty)

Some other conclusions:
There will never be a perfect 2D wrapper for OpenGL. Mainly because in order to wrap the functionality of OpenGL in 2D and hide the underlying 3D API from the user, you must trade off efficiency for ignorance. For example, batching textured quads by texture to cut down the number of glBindTexture, glBegin and glEnd calls will significantly improve your applications performance. However, in order to hide this pain in the arse from the end user, one must use glBindTexture, glBegin and glEnd calls inside the wrapped 2d blit function so the end user does not need to worry about doing these things at the cost of inefficiency. While the performance increase from using a 3D API as opposed to a 2D one is worth it even with these inefficiencies, one will eventually end up writing their own game specific rendering code.

Onward and sally forth!




Setting a colorkey in OpenGL

I found this to be truly annoying for most of the day today. By following most of the tutorials etc. I thought I had transparency down using the alpha channel etc. etc. Only to fnid that when scaling an image the border looked like it was overlapping and the color with the supposed alpha value of 0 was showing up on the edges of stuff.

Now at 1:45am and a 2 liter of coke along with some candy bars later, I have found my solution. Ok, so maybe I am not the sharpest tool in the shed but still, the amount of info for doing 2d in OpenGL that is pure crap is amazing. Hopefully the following will help some people out.

This is the code I use to set up my OpenGL window.

GLint GL2D_SetVideoMode( GLuint width, GLuint height, GLuint bpp, GLboolean fullscreen )
SDL_Surface *screen;

// set SDL_GL attributes
// always 32 bit and double buffered
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 32 );

// initialize the display window
if( (screen = SDL_SetVideoMode(width,height,bpp,(fullscreen)?SDL_OPENGL|SDL_FULLSCREEN:SDL_OPENGL)) == NULL )
return GL2D_ERROR;

// the ever important glortho call :)

// make sure everything is ok
if(glGetError() != GL_NO_ERROR)
return GL2D_ERROR;

// enable 2d textures

// set the blending mode

// disable depth testing

// tell the world we live!
printf( "GL2D initialized: %d x %d x %dbpp\n\r",
screen->w, screen->h, screen->format->BitsPerPixel );

return 0;

That may look wierd depending on your experience with SDL+OpenGL but it is working for me. The main things to look at are the glOrtho call and the glBlendFunc call.

The glOrtho call sets up the screen so that it works just like a 2d SDL screen with top left being 0,0 and bottom right being width,height. This was simple enough to do with the material available on glOrtho as long as you don't look for a tutorial. Just read from an OpenGL reference page about what the arguments do and it should be self explainatory.

The glBlendFunc call helps us with how our transparency works. I am not completely sure exactly what it does as opposed to the other settings, I have just found this to work for me and noticed that trying to set a colorkey without these values hasn't worked for me.

Ok, now that that is done... I have made myself a wrapper for an OpenGL texture so that it hides a few things from me that I shouldn't need to care about. Here is the GL2D_SURFACE structure I have made along with my bitmap loader:

GLuint texture_id; // the texture id of the surface
SDL_Surface *surface; // an SDL surface
GL2D_COLOR *colorkey; // the surface colorkey


GL2D_SURFACE *GL2D_LoadBMP( char *bitmap )
SDL_Surface *temp = SDL_LoadBMP( bitmap );
// I need an alpha channel to have a color key
SDL_Surface *image = SDL_DisplayFormatAlpha( temp );
SDL_FreeSurface( temp );
GL2D_SURFACE *surface = new GL2D_SURFACE;

surface->surface = image;
surface->colorkey = NULL;

// this gives us a unique texture id to bind to
// I may be using this wrong since this gets
// called for each surface I create but I have
// loaded a few textures at once and not had any
// problems.
glGenTextures( 1, &surface->texture_id );

// still not sure why i need this here but I do
glBindTexture(GL_TEXTURE_2D, surface->texture_id);

// this actually uploads the pixeldata from system
// to video memory
// notice the BytesPerPixel and the GL_BGRA
// for some reason on my windows machine the blue
// and red components on bitmaps are switched so this
// works for me. You might need to switch to GL_RGBA
// if they are switched on yours.
glTexImage2D(GL_TEXTURE_2D, 0, surface->surface->format->BytesPerPixel, surface->surface->w, surface->surface->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, surface->surface->pixels);

// using GL_NEAREST vs GL_LINEAR we don't anti alis edges on rotation or scaling
// using GL_CLAMP vs GL_WRAP so that we don't get artifacts on the edges when scaling

return surface;

The glTexParameteri function lets me set up the way textures work. This is what was giving me grief all day and I didn't even know it. All of the tutorials I found were saying use GL_LINEAR for the MIN and MAG_FILTER settings and i think one mentioned the WRAP_S and WRAP_G things with wrap. This caused me so much grief with the colorkey thing. Moving on to which, here is how I set a colorkey on a surface now:

void GL2D_SetColorKey( GL2D_SURFACE *surface, GL2D_COLOR *colorkey )
GL2D_COLOR pixel;
GLint x,y;

SDL_LockSurface( surface->surface );
for ( y = 0; y surface->h; y++ )
for ( x = 0; x surface->w; x++ )
GL2D_GetPixel( surface, x, y, &pixel );
// reset the old colorkey back to opaque
if ( surface->colorkey &&
pixel.red == surface->colorkey->red &&
pixel.green == surface->colorkey->green &&
pixel.blue == surface->colorkey->blue &&
pixel.alpha == 0 )
pixel.alpha = surface->colorkey->alpha;
GL2D_PutPixel( surface, x, y, &pixel );

// set the new color key
if ( colorkey &&
pixel.red == colorkey->red &&
pixel.green == colorkey->green &&
pixel.blue == colorkey->blue &&
pixel.alpha == colorkey->alpha )
pixel.alpha = 0;
GL2D_PutPixel( surface, x, y, &pixel );
SDL_UnlockSurface( surface->surface );

if ( colorkey )
if ( !surface->colorkey )
surface->colorkey = new GL2D_COLOR;

memcpy( surface->colorkey, colorkey, sizeof(surface->colorkey) );
if ( surface->colorkey )
delete surface->colorkey;
surface->colorkey = NULL;

glBindTexture(GL_TEXTURE_2D, surface->texture_id);

// using GL_NEAREST vs GL_LINEAR we don't anti alis edges on rotation or scaling
// using GL_CLAMP vs GL_WRAP so that we don't get artifacts on the edges when scaling

glTexImage2D(GL_TEXTURE_2D, 0, surface->surface->format->BytesPerPixel, surface->surface->w, surface->surface->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, surface->surface->pixels);

Pretty ugly but this was the most portable way I could figure out how to do it. Since bitmaps cannot hold an alpha channel I could just modify the bitmap loading code to set a colorkey at load time before the SDL_DisplayFormatAlpha call using SDL_SetColorkey and then the DisplayFormatAlpha call automatically does this for me. This is all well and good but what if I want to change or turn off the colorkey? I found modifying the pixels by brute force and then re-loading the pixeldata to the texture worked best for me. Also, in the future, this can be modified pretty easily to allow for multiple colorkeys which I never could get working on directdraw.

I did not add in the SDL_Image library but I am sure you could always just replace SDL_LoadBMP with SDL_LoadImage and everything should work ok but I will have to wait and see.

Ok, I am tired and need to go to bed, but I will be working more on this tomorrow.

I really need to thank PnP Bios again for his work on the hxRender library and some posts by Dave Perman and Kylotan a while back which have some informative stuff in them. I will have to go through my stuff to get the links but just needed to get a shout out. Oh, and Graveyardfilla has asked and answered some good questions regarding OpenGL and 2d on the forums as well. Hopefully when I am done this stuff will help someone so they don't have to go through what I did :)




Starting my new project

Well, a few days ago I started looking into moving into OpenGL for 2d stuff again. I took about a whole day of fiddling around with stuff and I got a good start thanks to using the hxRender library by PnP Bios. Now I want to move on and make an SDL like library for my own knowledge as well as hopefully give something back to the community as well. The main thing i am looking for now is how to render to a specific texture instead of the screen and how to switch back and forth. Otherwise the SDL like functions of specifying a destination to blit to won't quite feel right. I suppose that is my own opinion but ow well...

Here is a quick look at the header for the library. I haven't written any actual code yet since most of my time has been spent researching how to do most of these tasks. I still don't know how to change a colorkey value for a texture or if it is even possible and the rotation thing is kind of giving me a headache with the pushing and popping matrix thing which I don't even know if it is necessary yet.

Well, here it is so far.

* GL2D_defs.h *
* *
* GL2D #define macros *
* type defines for using the GL2D library *
* prototypes for library functions *
* *

// for the most part functions with a return value that isn't a pointer
// return 0 for success and -1 if a failure occured
// use these macros as -1 will be true and 0 will be false on most machines
#define GL2D_ERROR -1
#define GL2D_SUCCESS 0

// an easy way to check if functions failed or not
#define GL2D_OK(val) ( (val)==GL2D_SUCCESS ? TRUE : FALSE )

// GL2D's version of a color
// almost the same as SDL :)
typedef struct GL2D_COLOR
unsigned char red;
unsigned char green;
unsigned char blue;
unsigned char alpha;

// GL2D's version of a rectangle with integer
// will be used in some API blit functions
// to resemble SDL_Blit*
typedef struct GL2D_RECTI
GLint x;
GLint y;
GLuint w;
GLuint h;

// GL2D's version of a rectangle with floating point values
// for better translation by opengl.
// will be used in some API blit functions
// to resemble SDL_Blit*
typedef struct GL2D_RECTF
float x;
float y;
float w;
float h;

// GL2D version of a vertex
typedef struct GL2D_VERTEX
float x;
float y;

// if it helps to name it differently:

// GL2D structure to hold 4 verticies making up a quad
typedef struct GL2D_QUAD

// GL2D's version of an SDL surface.
// Since surfaces have some large differences
// from OpenGL textures I am sure this will
// operate differently than most people are used to but
// the purpose of this library is to hide the 3d bs from
// the user so I won't go into too much detail.
typedef struct GL2D_SURFACE
GLuint texture_id; // the texture id of the surface
GLuint width; // the width in pixels of the surface
GLuint height; // the height in pixels of the surface
GLuint bpp; // the bits per pixel of the surface
GLuint pitch; // the pitch of the surface (the actual width of a scanline in memory)
GLuint colors; // number of colors in the palette ( 0 if bpp > 8 )
void *palette; // pointer to the palette colors ( NULL if bpp > 8 )
void *pixeldata; // pointer to raw pixel data of the surface

// lirary startup/quit functions
GLint GL2D_Init(); // init GL2D - not sure if this will be necessary
GLint GL2D_Quit(); // exit GL2D - or if they will wrap regular SDL_Init and Quit

// init the video surface
// the return value isn't very useful since rendering functions in OpenGL
// do not require a destination surface/texture to render. The screen is the
// default render target.
GL2D_SURFACE *GL2D_SetVideoMode( GLuint width, GLuint height GLuint bpp, GLboolean fullscreen );

// Surface creation
GL2D_SURFACE *GL2D_CreateRGBSurface( GLuint width, GLuint height, GLuint bpp );
GL2D_SURFACE *GL2D_CreateRGBSurfaceFrom( void *pixeldata, GLuint width, GLuint height, GLuint bpp );
GL2D_SURFACE *GL2D_LoadBMP( char *bitmap );

// free a GL2D_SURFACE from memory
void GL2D_FreeSurface( GL2D_SURFACE *surface );

// pixel and primitives drawing functions
// pixel functions
GLint GL2D_GetPixel( GL2D_SURFACE *surface, GLuint x, GLuint y, GL2D_COLOR *pixel );
GLint GL2D_SetPixel( GL2D_SURFACE *surface, GLuint x, GLuint y, GL2D_COLOR *pixel );
// line function
GLint GL2D_DrawLine( GL2D_SURFACE *surface, GL2D_VERTEX *start, GL2D_VERTEX *end, GL2D_COLOR *color );
GLint GL2D_DrawLine( GL2D_SURFACE *surface, GLuint x1, GLuint y1, GLuint x2, GLuint y2, GL2D_COLOR *color );
GLint GL2D_DrawLine( GL2D_SURFACE *surface, float x1, float y1, float x2, float y2, GL2D_COLOR *color );
// rectangle functions
GLint GL2D_DrawRect( GL2D_SURFACE *surface, GL2D_RECTI *rect, GL2D_COLOR *color );
GLint GL2D_FillRect( GL2D_SURFACE *surface, GL2D_RECTI *rect, GL2D_COLOR *color );
// circle functions
// no idea how to do this in a good way other than points or as a polygon
GLint GL2D_DrawCircle( GL2D_SURFACE *surface, float origin_x, float origin_y, float radius, GL2D_COLOR *color );
GLint GL2D_FillCircle( GL2D_SURFACE *surface, float origin_x, float origin_y, float radius, GL2D_COLOR *color );
// polygon functions
GLint GL2D_DrawPolygon( GL2D_SURFACE *surface, GL2D_VERTEX *verts, GLuint num_verts, GL2D_COLOR *color );
GLint GL2D_FillPolygon( GL2D_SURFACE *surface, GL2D_VERTEX *verts, GLuint num_verts, GL2D_COLOR *color );

// Blitting functions
// If the destination quad differs in size from the source quad then scaling is done.
// If the alpha value is less than 1.0 then alpha blending is applied.
// Returns 0 on success and -1 if failure.
GLint GL2D_BlitSurface( GL2D_SURFACE *source_surface, GL2D_QUAD *source_quad, GL2D_SURFACE *destination_surface, GL2D_QUAD *destination_quad, float alpha );
GLint GL2D_BlitSurface( GL2D_SURFACE *source_surface, GL2D_RECTI *source_rect, GL2D_SURFACE *destination_surface, GL2D_RECTI *destination_rect, float alpha );
GLint GL2D_BlitSurface( GL2D_SURFACE *source_surface, GL2D_RECTF *source_rect, GL2D_SURFACE *destination_surface, GL2D_RECTF *destination_rect, float alpha );

// Conversion functions

I will keep posting stuff here as I continue to work on it. I am planning on keeping the C style functions since both OpenGL and SDL use them but I imagine this stuff should be easy to wrap up into a class or classes of some sort.




work sucks!!!

Ok, this is just getting frustrating. When you begin work at 7:30am you should be able to leave after 10 hours. Hopefully this week will get better and I can get back to work on my stuff without my brain feeling like a fried egg.




Just signed up for this gdnet+ thing

Just signed up for the gdnet+ thing today and am feeling pretty good to be contributing to a site that has helped me out a bunch over the past few years. Hopefully I can make use of the space and resources they are giving me access to. For now I will use it to host backups of my source just in case my hard drive goes down. Who knows, maybe someone will be able to use it :)



Sign in to follow this  
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!