Monday, January 9, 2012

Shoot, collide and collect

First, happy new year everyone!

In order for the ship to collide with the environment, I have to setup collisions for the ship itself and for the objects of the environment (buildings for now).

In FreshEngine, you can use collision primitives (sphere, box, capsule...) for dynamic (moving) objetcs or static objects, and you can use arbritrary collision meshes (usually simplified geometry) for static objects only.

You can collide primitives with primitives, and primitives with meshes. You cannot collide meshes with meshes.

There's also the ability to ray cast against primitive or meshes, but I won't make use of ray casting for now.

So I will use collision meshes on the environment and collision primitives on the ship and bullets.

Let's start with the environment. Here you can see the collision meshes for my buildings:

Note that I've added a taller building since last time. This one is higher than the max altitude of the ship, making a barrier you cannot pass (or bullets can't pass).

Now I setup the ship's collision using primitives. I chose to use the capsule primitive for the ship as well as the bullet. I created also a mine with a sphere collision primitive because I've got some gameplay ideas that I want to test with a mine.

Notice how I have exagerated the length of the bullet collision primitive. That is to ensure it will collide with thin objects (like walls) even when moving fast.

Also for the screenshot here I moved the pieces apart but they are all centered at the origin for export.

I'm planning to limit the amount of available bullets in order to create some startegic gameplay. Also I want to start with a low firepower and have the ability to improve that over time. The first implementation will be the ability to increase the fire rate (or shortening the delay between bullets).

So there will be two items that will represent these improvements.One (blue) will be extra amunition, the other (red) will be increased fire rate. At maximum rate (minimum delay), one bullet will be shot each frame, so 60 bullets per second.

So I create simple colored boxes to represent the items, and add a sphere collision primitive to them:

Pretty simple. You can see in order to make the item easily pickable I made the collision sphere quite larger.

Now I need to place the items in the map. I will make use of the ability to place objects at arbitrary location in Tiled:

I put these objects in my tileset, but they are not used as tiles. You can see I've created three new layers on top of the tile layer (Ground). These layers are objecs layers.

Objects on these layers can be placed with pixel precision in the map. So for instance I can put several items onto the same tile. That is why I made smaller icons for items.

As you can see, I've also added an icon for fuel and motherShip as I've got some ideas of how these should work. I'll implement them later.

Theres also a respawn point, which is where your ship appears when you start the map. I might need several of those later, so I made a layer specifically for that information.

Now the format for objects in the map file is a bit different than the one for the tiles, so I had to update my xml parser a little.

Item collisions
There are several filters you can use in FreshEngine to tell what collides with what. And there are several collision callback functions that you can use depending on the behavior you want to capture.

For the ship/items collisions, I've used the trigger callback, so it is called only once when the collision occurs.

All the collision behavior has been implemented in lua as the overhead is manageable and collisions won't occur all at the same time.

Shooting bullets

This one made my head hurt a bit.

There are two approaches here:

The first one is to create on the fly a new bullet when needed (by cloning the one from the library), and destroy it when it collides. Altough quite simple, this approach made me nervous because I could feel that creating and destroying objects on the fly at high rate could potentially create some serious performance problems.

The second idea is to create a pool of bullets (corresponding to the max bullets that can be on flight at a given time) with all bullets hidden at the beginning. When you shoot a bullet, you make it visible and when it collides you make it invisible again at re-initialise its position at the ship position.

That sounded much better in term of performance, but for me sounded a lot more difficult to implement as I don't have much programming experience...yet :P

The first challenge is to identify which bullet is to be hidden when a collision appear. To implement that, I made use of the ability to attach a custom attribute to an object in FreshEngine. So I added an ID to each bullet that I can querry when a collision occurs.

Next you need to manage your pool of bullets in order to know which bullets are available. I made use of a table of available bullets with a pointer to the top. When a bullet dies it is put back on top of the stack and he pointer increases, when a bullet is shot, the new bullet goes in flight and the pointer to the available is decreased.

That is not as trivial as it may sound because you might shoot two bullets in sequence, but the second could well be dead before the first one if it encounters a obstacle first.

Only the bullets that are in flight are updated. So it's very fast.

I have to say this was my first serious C++ implementation challenge (besides setting up the project in Visual Studio).

Here's the result (I will make videos further down the line, but you'll have to do with the screenshots for now)

It's quite fun to shoot everywhere. I've also quickly added some sound effects to have a feeling of the shooting rate. It quite helps to get the feeling and to know at wich rate you're firing.

I've also added some sounds when the bullet hits a building, with some random sample selection of broken glass sounds.

My only question for now is, as you need to orient the ship to orient the fire (fires straight in front of the ship), will this be practical and precise enough when surrounded by ennemies?

As a first step, I did some tests with the mines. Currently mapped to a button, they stay where you put them. There's a little rotation animation playing to give some life to them. I'm planning to use them with ennemies to create some sort of mine walls or something.

As you can shoot the mines as well, it is useful to evaluate if it's easy to shoot at static objects. I must say it's quite easy, but we'll see how it goes with moving object!

Next: First Ennemies implementation

No comments:

Post a Comment