HGE Go work

I just realized I never actually posted about why I was doing a C binding of C++. Basically I bound most of Haaf’s Game Engine (HGE) from C++ to C. I ended up getting a bit stuck on the GUI elements and getting a nice way to let them do simple inheritance and polymorphism based on the current C++ classes. This actually wasn’t a problem for my end-game which was to take that C binding and make a Go version with cgo.

I had initially planned on this to be a pure cgo binding, but as I looked more closely at how the HGE helpers were written I quickly realized that a cgo/port hybrid might be more interesting. I’ll quickly describe HGE’s architecture so you can see how this ended up being a very natural fit.

First, HGE has a singleton class, HGE, that handles various things for the engine. Such as, providing a game loop, state management, drawing to the screen, audio output, resource loading, and a few other things. This is really the meat of the engine in which everything else is built upon. The engine also has various “helpers” which take this main singleton and add some specific higher-level functionality, like font loading, Sprite loading/rendering, GUI controls, particle effects, and a few others. As mentioned before, all functionality in the helpers are built using (and in some cases other helpers) the HGE class.

Since all the helpers were fairly straight forwardly written around the base HGE class, it was very easy to bind the HGE class to C and then to Go. After that, the helpers were pretty straight forward to port from C++ to Go.

Here’s an example from the Particle System:
void hgeParticleSystem::Render()
{
int i;
DWORD col;
hgeParticle *par=particles;

col=info.sprite->GetColor();

for(i=0; i < nParticlesAlive; i++) { info.sprite->SetColor(par->colColor.GetHWColor());
info.sprite->RenderEx(par->vecLocation.x+fTx, par->vecLocation.y+fTy, par->fSpin*par->fAge, par->fSize);
par++;
}

info.sprite->SetColor(col);
}

And this is the ported code to Go:
func (ps *ParticleSystem) Render() {
col := ps.Info.Sprite.Color()

for i := 0; i < ps.particlesAlive; i++ { par := ps.particles[i] ps.Info.Sprite.SetColor(par.color.HWColor()) ps.Info.Sprite.RenderEx(par.location.X+ps.tx, par.location.Y+ps.ty, par.spin*par.age, par.size) } ps.Info.Sprite.SetColor(col) }
As you can see, they do the exact same thing. The only real difference is the for loop in Go uses the array directly and the C++ code moves the par pointer in the loop.

As another example, the Sprite render function:
void hgeSprite::Render(float x, float y)
{
float tempx1, tempy1, tempx2, tempy2;

tempx1 = x-hotX;
tempy1 = y-hotY;
tempx2 = x+width-hotX;
tempy2 = y+height-hotY;

quad.v[0].x = tempx1; quad.v[0].y = tempy1;
quad.v[1].x = tempx2; quad.v[1].y = tempy1;
quad.v[2].x = tempx2; quad.v[2].y = tempy2;
quad.v[3].x = tempx1; quad.v[3].y = tempy2;

hge->Gfx_RenderQuad(&quad);
}

func (sprite *Sprite) Render(x, y float64) {
tempx1 := float32(x - sprite.HotX)
tempy1 := float32(y - sprite.HotY)
tempx2 := float32(x + sprite.W - sprite.HotX)
tempy2 := float32(y + sprite.H - sprite.HotY)

sprite.Quad.V[0].X, sprite.Quad.V[0].Y = tempx1, tempy1
sprite.Quad.V[1].X, sprite.Quad.V[1].Y = tempx2, tempy1
sprite.Quad.V[2].X, sprite.Quad.V[2].Y = tempx2, tempy2
sprite.Quad.V[3].X, sprite.Quad.V[3].Y = tempx1, tempy2

sprite.Quad.Render()
}

As you can see, this one is identical with the syntax ported to Go from C++. The biggest difference is that I tried to make the ported version as Go-like as possible. So you see sprite.Quad.Render() instead of something like sprite.hge.Gfx_Render(sprite.quad)

To be clear, the majority of the binding and helpers are written and work (mostly, as do all ported tutorial examples.) There is at least one spot that is still totally unimplemented, and that’s the hgeResourceManager port to Go. This is the class that does things like parses a resource script and can (does?) pre-caches resources.

Even with the few know issues left, I decided I wanted to port the rest of HGE to Go. I haven’t had nearly enough time to work on it, but even still some things are already working. It’s currently depending upon cgo for SDL and OpenGL. It’ll likely also use cgo for OpenAL. What currently works is some things like: input, timer, & rand are all complete, opening up a window and setting some states, and drawing lines and untextured quads (the texture code doesn’t seem to be working yet.) Overall though, I’m pleased with the progress so far, and think it’s going to end up working out very well.


Speak Your Mind

Your email address will not be published. Required fields are marked *

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>