12/18/09

I'm a lumberjack and I'm ok!

I had another busy night of game development last night. The new feature of the night was to add a logger to my engine.  I had 3 requirements for my logger:
  1. I need to be able to create multiple instances of the logger so I can create log files for each area of my engine.
  2. I need to be able to differentiate between normal debug messages and error messages when I'm reviewing the log.
  3. I need to be able to disable logging across the system at compile time.
With these requirements in mind, I created a pretty simple logging class that is easy to use and gets the job done.
class Logger
{
    //Fields
    FILE* file;  //File the log is saved to

    //Methods
    void CloseFile(); //Closes the logging file
public:
    //Constructor/Destructors
    Logger(){file = NULL;}
    ~Logger();

    //Methods
    bool OpenLog(char* filename);     //Opens the log with the given filename
    void Write(char* msg, ...);       //Writes a normal message to the log
    void WriteError(char* msg, ...);  //Writes the message to the log and flags it as error
};
Nothing too earth shattering here.  To use the logger, create an instance then call OpenLog with the filename of the log file you want created.  One note you need to make here is that if you are creating files in another directory make sure that directory exists.  C++ won't create the directory for you if it doesn't.

I'm rather proud of the write methods.  As you can see they use variable arguments which is something I've never done before.  This will allow me to use formatting in the messages I send to the log, instead of either having to create the formatted message before I send it to the logger or adding a write method for every combo of parameters I need.  Here are the guts of  Write:

void Logger::Write(char *msg, ...)
{
#ifdef LOGGING_ON
    //Get the variable arguments
    va_list listPointer;
    va_start( listPointer, msg );

    //Get the current time
    boost::posix_time::ptime t(boost::posix_time::second_clock::local_time());
    std::string time = boost::posix_time::to_simple_string(t);

    //Write time

    fprintf(file,"[%s] ",time.c_str());

    //Write the msg
    vfprintf(file,msg,listPointer);

    //End the line
    fprintf(file,"\n");

    //flush the file
    fflush(file);
#endif
}
WriteError is almost exactly the same except it adds "Error!!!!!!" to the message so you can differentiate error messages in the log from normal messages.  The key to the whole operation is vfprintf.  This method allows me to just pass the va_list right in without caring what's actually in it.  Also you can see that I'm checking for the definintion of LOGGING_ON.  Commenting out that defininition which lives in Logger.h will turn off logging system wide at compile time.

The one area where this logger fails is that it is not thread safe.  If I ever did plan on adding multiple threads that wrote to the same log file, this wouldn't work very well because there exists the possibility that the two threads would be writing to the log at the same time causing some jumbled log messages.  Right now I don't plan on adding multi-threading to my engine, but if I do, I'll need to revisit this.

Now that I have logging in place, my next step is to come up with a consitent and elegent way of handling exceptions.  This probably isn't going to be a new class that I write, but instead a standard for how I write all code.  I've got a little research to do, but as always, I'll let you know how it goes.

References
Here are some thinks to sites that helped me develop the logger:

12/14/09

Boosted spirits

I added boost to my solution this evening and surprisingly it went rather smoothly. No major hiccups to speak of tonight. It appears that my C++ solution skills are becoming ninja like! Well maybe not quite to that level, but I certainly am more versed in it than I was just a couple weeks ago.

As part of my inclusion of boost, I modified the ResourceManager so that it uses shared pointers instead of actual pointers. This is going to solve the major flaw I had that really prevented me from handing out the same resource twice without fear of one of the copies being destroyed. Now the smart pointer will handle all the freeing of resources.

The next task I have in mind is to handle logging and exception handling. I don't want to get too far into development without these two in place. I haven't read to much into best practices as far as logging and exception handling in games goes, so I've got some research to do. I'll post links to whatever I find on the subject in my next post which should hopefully cover how I implemented the system.

Resource Manager

I've created my first major piece of functionality for my game engine. I added a very simple resource manager which will be responsible for loading all games assests into memory and then distributing them upon request. As I wrote in my previous post, I originally wanted to create a resource cache, but I realized that was going to add a lot of overhead for something that in the end I probably wasn't going to need since the games I'll be making with this engine are probably not going to be very rich in assets. That being said, I don't think it would be terribly difficult to convert into a resource cache if I ever wanted to go that route.

So lets get into the meat of it. My resource manager consists of two classes, Resource and ResourceManager. The names pretty much give away their purposes. Resource represents a single asset that has been loaded into memory. It holds the asstet's raw data along with a filename and the size of the asset.

ResourceManager does most of the heavy lifting. It takes in a zip file or a single file and creates Resources from them. The pointers to the Resources are stored in two std lib containers, a map and a list. Each container has its dedicated purpose. The map is used for random access of the Resources using the Resource's filename as the key. The list is used for looping through the resources. Right now the list is only being used in the destructor of the ResourceManager when it releases all of the resources. If I ever wanted to convert this to a ResourceCache, the list would play a much greater role by becoming a sorted list of assets ordered by last use.


The major flaw I have in my design right now is I store and handout regular pointers to a resource. This becomes a problem when I hand out the same resource more than once and one of the recipients releases the resource. All other pointers to that resource become garbage because the memory that the resource pointer pointed to has been released. This leads me to my next task, adding boost to my solution.

In Game Coding Complete they use boost's shared pointers extensively to solve this exact issue. The shared pointers will allow me to hand out multiple copies of the same resource without worrying about resources being released prematurely because the shared pointer keeps track of references to itself and won't release memory until all resources have been released. I've read a little on using boost and I've heard that it isn't the easiest thing to add to a solution, so wish me luck.

12/4/09

It's me again

Long time, no blog. I got a new job as a work at home web developer and that's been taking much of my precious game development time. I'm finally starting to get back into the groove of things now that I've pretty much figured out how my work schedule is going to go.

I'm back working on the TetrisClone project. I haven't made many strides since my last post, but I have a game plan that I'm hoping will lead me to the completion of this project. The first step of my plan is to get a solid base in place. Something that I can possibly use on other games. Some may even call want I'm creating an engine!

I've started work on the resource manager which will handle all the loading and passing out of game assets that must be loaded off of disk. I'm drawing a lot of inspiration for my engine from the book Game Coding Complete 3, and the resource manager is no different. I had originally planned on creating a ResourceCache like they have in the book's source code, but in favor of time, I've decided just to create a ResourceManager that will hold all the game assets needed in memory for as long as they're needed. I figure the games I'm going to be creating will be small enough to allow me to do this and it will save me from having to debug a cache.

I've started off by adding the zip file importer from Game Coding Complete, slightly modified, but mostly intact, to my project. Again, I had aspirations to write my own zip file importer, but for the sake of time, I decided to borrow (giving the proper credit in the source of course).

Just copying the code from the GCC source to mine wasn't enough though. Again, as I delv into the depths of c++, I ran into some issues that I wasn't anticipating. The zip reader from GCC uses zlib(http://www.zlib.net/) to do the heavy lifting. It uses a 3rd party .lib file which I've never used in c++ before. It wan't too hard this time to figure out what I needed to do though.

First I created a new Libs folder to hold this library file and future ones if needed. I then went into the properties of my executable project and added the new directory to "Addition Library Directories" under Configuration Properties>Linker>General. Then I added zlib.lib to Additional Dependencies under Linker>Input.

It seems like I'm having much more trouble with setting up projects properly than I am getting the code to work. I guess I'll learn as I go on that front. I haven't seen too many books or articles describing how to set up vs in depth.

Now that I can read in zip files, it's time to move on to the meat of the operations, the resource manager. Hopefully I'll have this done and have all the details of my adventures soon.