Gun Bastard

Bit of an update

Been a while since I updated, so here's what's been going on at the Beercave lately.

First off, the Beercave has moved. Still getting settled in and unpacked in the new place but I'm back to a point where I can get some work done again.

Gun Bastard progress update

In s staggering break with tradition, I've been using my weekend to actually get some work done! No, I don't really believe it either...

I started the day off by knocking up a particle system. After hooking it up make the enemies explode when shot it looked a little something like this:

Basic particle explosions

As you might have noticed, it's a bit on the excessive side - I accidentally set the explosions to repeat every beat instead of only firing once. Looks like I'll be able to get plenty of stuff on screen at once though :)

Once I was satisfied I could chuck particles around without any problems, I thought I should see about making things a bit prettier. After fixing the particle size and colour to match the game sprites, I added a motion trail effect to my explosion particles and ended up with this:

Pretty particle explosions

Not quite up to OddBob's standards yet, but a definite improvement.

With that done, I spent a bit of time refactoring things to keep the codebase nice and tidy. One thing that was a bit ugly about Sheep Snaggers 2 was the huge chunks of boilerplate code I was using to spawn my game entities and attach the relevant behaviours to them. It works, but as the project gets bigger it's not really sustainable and I ended up with a whole bunch of near-identical 'Spawner' classes for the different entities.

So, to make my life easier in future, I've built myself a generic entity spawner system which takes a folder full of entity definitions (basically a list of behaviours to attach to the game object) and can then generate entities by name. So instead of having

enemy = GameObject(
  x = 0,
  y = 0,
  name="enemy"
)
SpriteBehaviour.Attach(enemy,
  texture="alien1",
  scale=2
)
PhysicsBehaviour.Attach(enemy)
EnemyBehaviour.Attach(enemy)
#etc.
The equivalent now looks like:
enemy = EntitySpawner.Spawn("enemy")
Much nicer! Should help me maintain my sanity once I get a whole bunch of different enemy types in there.

Brand new Bastard

With SS2 finally fixed up and shipped, I've been thinking about what to work on next. While I'm still pretty keen to make a crack at some of the ideas in there, I can't help but think I should really finish up Gun Bastard first.

With that in mind I took a quick look at the old codebase, went 'uurhg!', and promptly binned the lot and started again ('cos that's just how we roll in indie-land).

What I've got so far looks like this:

Doesn't look like much so far, but the new stuff is a lot easier to work with.

Inspired by this article I thought it might be cool to have the AI synced to an external timer, so I hacked up a basic events system that I could drive with my metronome class. Right now all it does is make the enemies change direction every beat but I'm planning on making it the core of the game AI and hopefully hooking it up to the audio system so that events happen in time with the soundtrack. If it works out, it should be awesome :D

Playing pool

I've noticed the frame rate on Gun Bastard has a tendency to plummet when things get a bit splodey, so I should probably start looking at optimising the code a little before I go any further.
Since the explosions are the most obvious source of slowdown, at least some of the problem is likely down to object creation overhead on the various particles I'm chucking about the screen.

In order to minimise the overhead, I thought I should investigate object pooling.

The bastards have landed

Spent a bit more time playing around with Gun Bastard this weekend, so here's a quick WIP build for you to play with.
Needs a lot of work on balancing and generally making things fun, but it's just about playable.

Download Gun Bastard v 0.1

Reasons to love Python

It let's you do twisted things like this:

waves = [[Clown, Clown, Clown],
	[Clown, Tank, Bunny, Clown],
	[Clown, Tank, Tank, Clown],
	[Clown, Tank, Tank, Bunny],
	[Tank, Tank, Tank, Clown],
	...
	]

where Clown, Tank and Bunny are the Types of the various enemies
and later...

for enemy in waves[wave]:
	enemy(xpos, ypos, 0, 0, self.target)

and it just figures it out and calls the constructor for the relevant type.

The bastard in motion

I knocked up a quick gameplay video of Gun Bastard - it's not looking too shabby.

Back to the bastard

With Sheep Snaggers finally out the door, and after recovering from a nasty toothache that turned into a whacking great abscess - leaving me spending the week on the couch cold a feverish with foul tasting poison dripping into my mouth - I finally got back to work on GUN BASTARD today.
After a bit of a slow start where I fumbled around with a couple of things that weren't working right* I've managed to get a bit more done.

Oh behave!

I spent the last couple of days reading over the Owyl docs, and I've managed to implement some basic AI in Gun Bastard.
I've got two different follow behaviours for the bad guys, a "shoot object x if you can see it", and I've farmed the player controls out to joystick move and fire behaviours rather than them being in the game loop.

New game - GUN BASTARD

With Sheep Snaggers pretty much finished, I've been thinking about how I could have improved the structure of the code. As it stands, it's a pretty horrendous spaghetti mess - I hacked features on pretty much at random, and it shows.
I've come up with a much better design, where the main game loop nice and simple

while running:
  think() #handles control input and AI
  update() # move things around
  render() # draws the end result

and the different game modules each have their own versions of the 3 functions. When I switch game modes, I swap out the function pointers for the relevant module and everything stays inside the one loop, which makes handling game events much cleaner.
In Sheep Snaggers, the attract mode and high score entry each have their own seperate copy of the game loop, which then has to throw events back to the main loop - hideous I know, but that's what happens when you don't plan ahead...
Anyway, to test the new structure out, I needed a nice simple game concept.

Enter GUN BASTARD.