I was unsatisfied with GLUT, and felt bogged down by SDL. I wanted a simple, lightweight library for writing cross-platform games. Furthermore, I wanted control. There is nothing more annoying than having to relinquish control over your main loop to some stupid library. I call the library, the library doesn't call me.
So I decided to write such a library myself. That was the genesis of PIG: The Portable Independent Game library. The final push to get me to actually write the thing was our final project requirement for Operating Systems - something useful and OS related. PIG was the perfect fit.
PIG runs on Windows and Mac OS X. It consists of the following components:
- The PIG GL Extension. Piggle is responsible for setting up an OpenGL graphics context, flushing the buffer, and switching resolutions. Setting up the screen is as simple as this:
pig::OpenGLView myView; myView.goFullscreen(1024,768); // or myView.goWindow(1024,768,25,40); drawMyCoolStuff(); myView.flush();
- For input, you subclass from the pig::MouseHandler or pig::KeyHandler classes and tell PIG to send input to your handlers. To actually get PIG to process the input, you call pig::handleInput(). If a key has an ascii representation, you can the lower-case version. Otherwise, you check against types defined in the pig::Key class like pig::Key::UP_ARROW or pig::Key::ESC. The mouse handler can be given sub-pixel delta information and scroll wheel input. All keys come with string representations, making it easy to write out and read in keyboard settings.
void MyKeyHandler::keyDown(Key k) {
if(k=='a') doSomething();
else if(k==pig::Key::SHIFT) startPlayerRunning();
else if(k==pig::Key::DOWN_ARROW) moveDown();
}
// on some platforms, dx and dy provide sub-pixel mouse delta information
void MyMouseHandler::updateMouse(float x, float y, float dx, float dy) {
player.lookX += p_dx;
player.lookY += p_dy;
}
MyKeyHandler keyboard;
keyboard.setAsGlobalHandler();
MyMouseHandler mouse;
mouse.setAsGlobalHandler();
while(true) {
pig::handleInput();
}
- PIG comes with a rich set of classes and functions for manipulating files. It has FileReader and FileWriter classes where you need merely specify the endian-ness of the file and it will handle all conversions. It has functions for creating files, moving files, renaming files, and much more. It can create open/save file dialogs. With PIG FileIO, reading and writing files is easy on any platform and endianness.
std::string filename = pig::openFileDialog();
if(filename.length()>0) {
pig::FileReader file(filename,pig::LITTLE_ENDIAN);
int myInt = file.readInt();
file.readData(myBuffer, 1024);
}
- Every game needs high-resolution timing. PIG guarantees <5 ms accuracy.
pig::Timer myTimer; myTimer.update(); double timeDiff = myTimer.getTime(); player.pos += direction*speed*timeDiff;
- PIG provides bare-bones support for threads. You can create threads, wait on threads and create locks.
pig::ThreadRef myThread = pig::createThread(myFunc, myArgs); pig:: AutoLock myLock; pig:: waitOnThread(myThread);
- The idea of having the monster AI code separate from the main program is very appealing. PIG has support for dynamic libraries. You compile a PPC and x86 versions and let PIG decide which to use.
pig::DynamicLibrary ai("monsterAI",true);
monsterThink = (monsterThinkType)ai.func("monsterThink");
- If you're writing a cross-platform game, you don't want to have to wrestle with Mac OS X .nib files or provide a WinMain function. If you include StartUpApp.cpp, PIG will initialize everything and call a function you define called 'enterGame'. You're in control from that point on. On Mac OS X, you can go ahead and delete your .nib file, none is needed. PIG truly allows you to use the exact same code on both platforms, no preprocessor switches necessary!
In order to show off the PIG library, I was working on a simple DOOM clone called 'Witches in a Castle'(named with Snakes on a Plane style directness). It was to be a silly little project, with random levels and lots of gore. I used nearest-neighbor filtering on everything to give it that old-school software look. Unfortunately, with the pressures of the semester and math classes taking up most of my time, I had to drop the project. It was looking pretty cool too! Maybe someday I'll finish it up. My friend Dan Bruington did the sprites.
I will put up PIG for download soon.
HOG: The Handy OpenGL GUI Toolkit was a project for my Software Engineering class. We were to create a small 'peanut project' over the semester, with full documentation. HOG wound up being a pretty huge undertaking, but I've been reaping the benefits since. If you want to write a cross-platform GUI, the choices out there right now are pretty unappetizing. They uncustomizable, slow, or released under a restrictive license. GLUI, the closest available library to HOG, is extremely ugly and takes advantage of ancient OpenGL features not even implemented on non-PC drivers. I wanted a GUI whose look could be tailored to whatever game or editor it was being used in.
HOG is a cross-platform C++ library for displaying and receiving input from user-interface widgets like scroll-bars, sliders, text fields, and more in an OpenGL window. It supports Mac OS X and Windows. Developers can write their user interface(the locations of widgets, what functions are called when widgets are manipulated, etc.) by changing a simple text file interpreted by HOG when the application starts. Every graphics call that HOG makes to display the widgets is abstracted to a GUI renderer class for easy customizability of the appearance of the GUI. HOG comes with complete documentation and sample source code demonstrating its capabilities.
HOG has a pretty impressive suite of widgets, with everything from HSB color choosers to text fields. Implementing a text field with support for non-monospace fonts, scrolling, mouse selection, and copy and paste was no small feat, and is something I have promised myself I will NEVER DO AGAIN. I think creating the text field widget dampened my spirit for implementation considerably. This is the sort of thing you want to outsource.
You can either create your widgets in your source, or load them from a text file. HOG can parse special widget text files:
@Window myWindow {
title "My Window"
size 0.5 0.5
position 0.5 0.5
@ScrollableTextField myScrollableTextField {
size 0.3 0.3
position 0.1 0.1
text "Initial text goes here..."
editable 1 # is text editable?
}
@Button myButton {
title "Do it!"
position 0.4 0.1
function "DoIt" # function to be called when button is clicked
}
}
To create a complete GUI using this file using the default HOG theme, LineLooks, all you have to do is something like this:
#include "hog/GUI.h"
#include "hog/Controls.h"
...
void MyDoItFunc( hog::Widget *widget ) {
printf("Button was clicked!\n");
}
hog::LineLooks myGUITheme;
hog::GUIManager myGUIManager(&myGUITheme);
myGUIManager.registerFunction("DoIt",MyDoItFunc);
myGUIManager.load("widgets.txt");
myGUIManager.think(timer.getTime());
myGUIManager.draw();
I recently put HOG to good use in writing the editor for my Prayer game engine.
I am eager to put HOG up on the web, but it still needs more polish. For more information, documentation, and development drama, take a look at the final HOG report I turned in for class.