Monday, 30 May 2011

New ideas..

Well Tank has only been on ice a few days and I'm already itching to learn new stuff. One of the major issues I faced when writing Tank was the choice between single player and multiplayer. As it happens, in that instance multiplayer won out.

Now I feel an overwhelming urge to learn about Artificial Intelligence (AI) and how it can be used in a single player game scenario. After researching for only an hour, I am coming to realise that this is a huge, complex subject, and even the simplest AI routines are going to take some serious thinking about.

Before I can even start playing with AI, I need to create a platform upon which to graphically display the results of the routines. Looking at a list of numbers never excited me like watching something moving around on screen. So I wrote a small program that displays a flat floor and a 3D object, and lets the user move the camera around by using the mouse. The camera remains pointing at the 3D object, and stays a set distance from it, but this distance can be altered by using the mouse scroll wheel, a kind of zoom in/out setup. It's pretty rudimentary, but eventually it will have variables that define mouse sensitivity, zoom speed, etc... It already has minimum and maximum zoom levels, and ceiling and floor limits.

A while back, I was talking to a friend about AI routines and single player game design in general, and it turns out that he studied game design as part of his university degree. Not so much the coding side, but the overall game design itself. So I brought the subject up again last night, and managed to blag some of his basic 3D models to play around with. I find that having "characters" to play with rather than just basic cubes gives a little more incentive and inspiration when working.

So I'm working with Tom "Cypher" Joyce at the moment on this project, with him providing models and ideas while I'm trying to implement that into code. Tom is using Maya to build the models then exporting them to Google Sketchup then sending me the file. I am then resizing and reorientating them to suit the game world and exporting from Sketchup into a DirectX format that can be imported directly into DBPro. Right now there is a "soldier" on the map who can't move, turn, die, can't do anything really. But I can use the mouse to move the camera around him.

He looks a bit dull and uninteresting sat there, but there is no lighting applied yet, and that makes all the difference. I have some ideas about the AI routines, but I am already approaching a massive challenge, and that is how to work out the position of the mouse pointer with relation to the world floor. That sounds ridiculous really but let me explain; if the world was going to be completely flat then there wouldn't be an issue at all. A simple call to "mousex" and "mousey" would return the position of the mouse pointer. But I don't intend to keep the floor flat for long, this isn't Tank. When the floor really is 3D and has raised and lowered areas then it is going to be a LOT harder to work out where the mouse is pointing, all because of that extra dimension. To put it another way, look at your mouse now. You can move it left and right (x axis) you can move it forwards and backwards (y axis), you can move it diagonally (combination of x and y axes) but imagine if you could lift the mouse up off the desk. I need to work out the position of it there (albeit virtually) and do it in real time.

So before I even start to think about AI routines, the next wall is already in front of me - how to use a 2D input device to provide accurate input to a 3D application?

The next few days could be interesting...

Thursday, 26 May 2011

Project on ice...

Well I knew this point would come, but I didn't think it would be so soon. Tank has evolved from a solid block simulation to a playable multiplayer game within a matter of months. It's my first pet project, and it will still be semi-active, but for now, I am putting Tank on ice.

I've decided to take a break from development of this particular game. I am itching to try new stuff. I want to learn about AI, bitmap-based text, new effects. There are so many elements involved in the creation process that I am starting to feel a little bogged down. The whole idea of me doing this was to get away from the feeling of stagnation, and up to this point I believe I've achieved that. From the joyous realisation of working out a routine, to the hair-pulling frustration of near punching the monitor, I've been through some extremes with this game. I think it's been a great project to get me back into coding, and I've learned a lot. Skills, I hope, which I can use in other, more original projects. I have plenty of ideas swimming around in my head.

I know it's bad practice to leave a thing like this unfinished, and I really do intend to come back to this at some point (unless someone wants to adopt it and continue development), but for now I have a real need to move on. Useful lessons have been learnt over the last couple of months, but so many corners remain unturned. I feel that now is the time to venture out and look around those corners.

I'll be blogging about it here again when I get something going, but for now I'll sign off with a few screenshots of Tank (Click the images for larger versions). The game made it to version 0.9a, nearly v1.0, but not quite. Fully playable, but in need of some bolt ons. I did what I set out to do. I created a game.

Hunting for enemies...

A near miss...


Game Over!!

Multiplayer home-made server..

To be continued....

Sunday, 22 May 2011

Who said explosions have to be Red and Yellow ?

Just a quick update this time, and I promise to keep it short.

I have been working on the shockwave/explosion routine of Tank in order to get rid of the side-effects presented when using Sprites for my explosions. I'm getting somewhere near now, so I thought I'd upload a short video of how it's currently looking. I do intend to make the shockwave a little less opaque, but it's still an early version of the routine.

The video shows a stationary enemy tank which already has depleted health - no one shot kills here. I fire at the tank but intentionally aim low, just to show the effect of the shockwave on that tank. If you look carefully, you will see my projectile falls far short of the enemy, yet the wave still takes him out. The shockwave is actually expanding while it exists, but due to the low frame rate of the video capturing software it's not that easy to notice.

As you can see, I decided to go for a "non-standard" colour for the explosion particles. I did this primarily for two reasons; Firstly, it stands out more when there is a distant battle occurring, and Secondly, I can do whatever the hell I like in the world of Tank :)

So that's it for now, other than a quick thank you to Nick Baumer for helping me see the light when coding the shockwave routine. I'm still not decided on an enemy locator function yet...

Monday, 16 May 2011

Network improvement! (mini-update)

Just a small update this time.

After testing the multiplayer feature over the internet, I am happy to report that it was a massive improvement over the previous version. I want to offer my thanks to Nick, Ragnar and Jonny for the testing session, which actually turned into a game (sort of).

That can only be good right?

So it turns out that there is a silver lining to last week's cloud of despair. Having wrestled long and hard against the pathetic TCP protocol, I found myself having to confront a completely different beast: the pathetic UDP protocol. Yes, both of these network communication methods are rubbish, complex and not very efficient, but it turns out that UDP is at least allowing my game to work. So the silver lining is that I have been "forced" to learn two methods of network communication. It could come in handy one day I guess.

So while testing the online gameplay, I noticed a number of other problems. Apart from the ridiculous amount of accuracy needed to hit an enemy (as described in the last blog post), it became blatantly obvious that using sprites for explosions isn't going to work. The main problem right now is that explosions always appear - even if they occur behind a building. I'll try to explain what I mean...

The "art" of aiming and firing a weapon involves many senses, and a person sub-consciously makes decisions about the trajectory and point of impact, based on multiple factors. One of these factors might be the results of a previously taken shot. The same applies to videogames. And there is a big flaw in Tank while using sprites for the explosions. If I was to shoot at an oncoming enemy player, and my projectile was to go straight over his head and hit the ground behind him, then the explosion would obviously occur at that point. But as sprites are rendered on a 2D plane (namely "in front" of the 3D plane) then the explosion would appear to be in front of the enemy tank. This would make my brain conclude that I need to aim higher (in order to shoot further), whereas in reality, I am already shooting too far.

So once again, I'm having to make a pretty major change to the game code, in order to rid the program of it's current explosion routines. Which, I might add, took me ages to get working. So I am working on a prototype routine which involves a primary shockwave at the point of impact, and then....well, I don't know what yet, it's still a prototype. But I am hoping to integrate the "splash damage" collision detection into this new routine. Also, it's going to be 3D based, so it's possible that shockwaves and explosions could be partially hidden by nearby buildings.

Here is a video of the very first attempt at this. Bear in mind that the sprite-based explosions are still present here, but you should notice that the shockwave on the further building appears "behind" the closer building. Note, when I make the first shot, the shockwave routine is disabled. I turn it on for the remaining shots.

The video is only running at 30fps, but it's just to demonstrate what I'm attempting to achieve.

So this is what I'm working on right now. Once I have it working properly in single player, I will create a multiplayer version. This is my primary task at the moment. 

I'm still thinking about solutions for the "where the hell is everybody?" problem, and thanks to suggestions from friends, they range from overhead icons, through a minimap to a full-on proximity warning system a la Aliens!

This was meant to be a mini-blog, but as usual I've found myself banging on and on. Let me sign off by saying the multiplayer system is totally useable now (even though I have an idea of how to optimise it further if needed), and I can press on with other important things, like blowing sh*t up!

Saturday, 14 May 2011

Splash Damage!

If you read my last blog entry, you'll know that I'd hit a brick wall with the Tank project. My TCP-based network code simply wasn't cutting it for multiplayer data transfer over the internet. If I'd have done more research before putting pen to paper (well, fingers to keyboard...) then I'd have known this before I started.

Lesson learned.

So after wrestling with the intricacies of UDP over the last week, I've finally made some headway and managed to rewrite the network communication routines based on this new protocol. I don't want to rave too much about it at this point, because the new build is currently untested over the internet, although it does work well over my home network. Then again, so did the TCP version. A note; if you are considering converting something from TCP to UDP, don't look at some TCP code and think "hmm, how would I make the UDP version of that?" because if you do, you are asking for trouble. The two methods of data transfer are completely and utterly different to each other and the conversion involves so much more than simply replacing TCP commands with UDP ones. Trust me on this. Anyway, I'm not going to write any more about it until I've tested it with the guys from DaGodz, other than to say that I'm glad I took a few steps away from the project for a while. You don't know how close it was to ending up in the trashcan.

So, new developments...

At last, tanks can shoot at each other! A bit of a plus for a multiplayer Tank game I think. To actually show enemy projectiles, I had two realistic choices.

  • Send the positional data of the active projectile to all players except the one who fired it (because they already know). The other clients could then render the projectile based on this data.
  - Plus points: Ridiculously accurate positioning of the projectile, relatively small routine to handle it.
  - Minus points : Massive increase of network data flow, dropped/bad data packets would cause mayhem.

  • Send a signal to say a player has fired, use the client to render the projectile and calculate its path and velocity based on known turret position and angle values.
 - Plus points : Nearly zero additional data to be transferred for each shot fired, client already knows where the projectile will land (even before it is fired!), dropped data packets wouldn't be an issue.
 - Minus point : Not quite so accurate, but damned close (2 or 3 pixels maybe), quite a complex routine to handle the ballistic path.

In addition to this, players who are seeing a projectile being shot (but haven't fired it themselves) would need to generate the explosion at the point of impact, as well as all associated sounds. Bearing in mind these sounds need to be positional, otherwise an explosion at 500 metres would have the same volume as one hitting at 5 metres etc... (Same goes for size of explosion). So much to think about.

So I decided it's best to go for option 2. The "firing" player tells the server it has fired. The server tells all the other players this has happened. All the other players render a projectile and handle its trajectory, point of impact, collision damage and everything else. Here is a picture of my base routine for doing this. (Note this is an early version, and some comments probably won't make any sense. They don't to me, so why should they to you?! My comments are in Green by the way, in case you're a muggle.)

You can click on the image for a larger version if you're interested.

Whilst writing this routine, I noticed a few other areas that could do with tweaking, so I tweaked them. Bad mistake. When the program crashes with some error or other, I don't know whether it's my new routine, or the tweaks I did to the existing ones.

Lesson learned.

One huge problem I have found, which I never expected to be an issue at all, is that enemy tanks are seriously hard to hit! If they are moving, it's nigh on impossible. I'm imagining this will be somewhat of a problem. The grid doesn't look that big when you are driving around in a tank, but when you see how small an enemy tank appears, you get a completely different sense of scale. You only truly see how big the map is once you are dead, and you are presented with an overhead view of the "action". The active tanks are simply minute. To give you an idea of scale, each tank is designed to be 6x4x2 units in size. The game grid is 1000x1000 units.

To counter this unexpected problem, I am planning to introduce two "features". The first one is to have an icon floating over each player, which alerts enemy players to their position. This icon will be highly visible even from a distance (though not through buildings to begin with). I had originally intended to use this as one of the "perks" that a player could achieve during game play, but I think it needs it as standard, otherwise it's possible to drive around for ages without seeing anyone else.

Secondly, and I have no idea at all about how I'm going to implement this, is that the projectiles will have a "Splash Damage" effect on impact. This means that an area around the impact point will also generate damage. Less damage than a direct hit, but still damage. This way it will be possible to cause damage to an enemy tank even if you don't score a direct hit. I could even make this splash damage radius variable depending on power-ups.... (Getting ahead of myself yet again.See? I do that all the time...)

So still plenty to do with the project. I really hope the UDP netcode has sorted out the lag issues, because frankly if it hasn't, this will probably be a LAN-only game. I'm itching to get on to something more original now I have cut my teeth with Tank, and I really don't fancy spending any more time messing with data packets and crap like that.

First few items of the ToDo list...

  • Work out some sort of "Splash Damage" function
  • Make some sort of "enemy is right here" indicator
  • Handle the event if a player disconnects mid-game
  • Improve the view a player gets if he/she is dead and are waiting for the others
  • Start thinking about a front end for all this...

Sunday, 8 May 2011

One step forward, and two steps back...

Well after the highs of yesterday comes the dawning realisation that things with the Tank project are not quite as rosy as they seem.

After more extensive testing of the networking model with Lisa, Chris and Nick, it has become apparent that the TCP networking protocol used by Tank for multiplayer data transfer simply isn't going to cut it. I haven't even implemented projectile tracking, ammo & health crates, or vehicle-vehicle collision yet, and already the latency is more than noticeable. It looks like I'm going to have to start over with the netcode, but base it on the UDP protocol this time. That's a lot of recoding. Right now I'm wishing I had gone down the single player/AI route.

It feels like I've learnt to speak Japanese and I should have been learning Chinese all along.

This is a major setback for me and I could easily hit the "Erase Project" button right now. But I'm not going to be too hasty, I'll take a break from it for a few days and let my emotions settle down.

I have to end this blog post on a positive note, and it's not all bad news. I did manage to achieve a few goals. 

  • The players now have dedicated spawn points. Previously they were randomly generated positions, which meant there was a chance that a player could spawn inside a tower. This would mean the player's health would steadily drop to zero causing death, without having been shot or anything. Pretty frustrating I'd imagine. The spawn points are in the corners of the game grid. The towers, while still being pseudo-randomly placed, are coded to stay away from these areas. I have also updated the floor graphics to reflect the new spawn areas.
  • There is now an audible alarm that sounds when the player health remains below 20%. This is a bit annoying at the moment (as there is currently no way to replenish health), but it's supposed to be annoying right? It's a warning! Once there are ambient sounds and vehicle movement noises added, the sound will fit in with the game a little better. I think.
  • There are now routines in place for when the Tank drives off the gaming grid. The Tank object disappears and is replaced with an explosion (still loads of work needed on this), then after a delay of a few seconds, the player is switched to an overhead view of the grid, so he/she can watch the battle continue between any remaining players. Again, this still needs a lot of work, but the basic functionality is there.
  • There is a routine in place for when the Tank collides with a tower and dies because of it. It works in a similar way to the "Tank off grid" routine.
  • My proudest achievement of this version is the way the towers are now generated based on a known seed. All players get the exact same map, based on a single integer passed to the client from the server. From this variable, I can instruct the client to generate any number of towers, with their x and z co-ordinates, their width, depth, height and texture all matching perfectly across the connected players, and all from a single transferred number. If it wasn't for this single achievement I think I would have given up on this by now.
So to sum up (because I'm banging on a bit now), the project at this moment is hanging in the balance between "Something I'm working on" and "Something I worked on". On one hand I'm wondering why I put myself through this, and on the other I'm considering it a learning experience, complete with its ups and downs.

One thing's for sure, you don't realise how much work goes into creating a videogame until you try to do it yourself.

Saturday, 7 May 2011

A place I thought I might never be...

Some great news this time!

Tank is now at the point where multiple players can connect to a game server and interact with each other! If I'm honest with myself, this is a place I thought I might never be. It's not over yet, not by a long chalk, but I feel good that I've managed to get this far. Of course I couldn't have done it without the guys from DaGodz. Suggestions, encouragement, but mainly help with testing the multiplayer code all add up to what I am considering to be a team project.

So I have decided, as this is my first multiplayer project (and I want to keep it real about what I am able to achieve) that Tank is initially going to be a 4 player game. The netcode over a LAN can handle 16 players in theory, and we've tested it to a point over the net with 10. But there is a lot more data I need to throw around, and for it to be viable over the internet using the TCP protocol, 4 players is a realistic starting point.

There are 101 things left to do. For example, currently the players can just drive around the grid, ramming each other! There is no code in place to allow them to shoot. If you drive off the grid, the game closes. If your Tank health reaches zero, the game closes. There is no facility to replenish health or ammo (other than using the "God mode" magical "A" button, which will obviously be removed for the v1.0 release. Also, I had removed the towers for the multiplayer test. The reason for this is because they are currently randomly generated in position and size. This means that each player would have a different layout of towers which is obviously wrong.

So here is a picture of a multiplayer game test. It shows the server running on the right, and each player in a small window. OK, it's not very exciting to look at I know, but it's an achievement. In this test, each player is on a seperate PC on my home network, but the test I did last night with Ragnar and Nick proved that it works just as well over the internet.

My next goals are to have dedicated spawn points for the players (they currently spawn at random locations), set up some kind of tower scheme where all players see the towers in the same places, and I need to lock the server when 4 players have joined, to stop people joining mid-game.

Of course the whole thing needs a front end, death sequences, ammo and health crates, slightly better collision detection on the tanks, more sound effects and of course, the ability to actually fire projectiles at each other...