Fill out your e-mail address and click submit to join the positech games newsletter!

On Holiday

Filed under: Uncategorized cliffski 12:22 pm October 29, 2011

I’m on holiday for a week. Don’t bother trying to burgle my house, it’s protected by an ex-commando, and my two cats.

SEE YOU SOON

 

Range Modifiers

Filed under: game design,gratuitous tank battles cliffski 10:09 pm October 27, 2011

This is something I really like, and comes in reply to feedback about how people hate having to guess what the underlying numbers are in tower defense games. I got it implemented today *still needs optimising…*. It’s a way to show easily the effects of a range boost augmentation for a unit. The units in GTB are built from GSB-style modules but some are ‘augmentations’ that apply to any module, such as ‘boost range by 10%’. I thought it might be cool, if such an aug is fitted, to show it as a distinct band on the range indicator when you select a unit. It’s the slightly separated strip around the edge of the range indicator for the selected riflemen.

The brighter triangle represents the firing field-of-view for that soldier. Some units have 360, like mechs, but infantry can’t swivel their hips like that :D

Thoughts?

Knowing what your code does

Filed under: programming cliffski 4:40 pm October 26, 2011

Do you know how your game works? I bet you *think* you do. And if you do, there are never surprises when you suddenly take a look at a frame of it being rendered. Invariably, mistakes mean stuff works differently to how you intended it to.

I use AQTime, which is pricey as hell, but fantastic, as a profiler. You can control it from code too, so I can pause my game mid-battle, hit ‘F’ to go one frame-advance, and that frame is profiled by aqtime. It then will dump tons of stats, telling we call times and counts for every function (or even line)  and let me see this:

This chart immediately tells me that some lightmapbuffer sprite code was being run. It should be skipped in daylight levels, so clearly I have a bug. And that’s before I even begin to look at performance optimisations in this frame.

If you write big complex stuff and don’t have a professional quality profiler, you need one. They are absolutely fantastic.

Fixing my heap crash bug

Filed under: gratuitous tank battles,programming cliffski 5:19 pm October 25, 2011

Well I did it. I am 99.9% sure I finally crushed my random crash bug. Here are the gory details.

It crashed in debug (or release) and seemingly somewhere random. Possibly much later than the actual cause, as is the way with these things. By using Microsoft’s handy CheckHeap functions, I was able to progressively narrow it down to a certain bit of code. (Essentially you check the integrity of the whole heap at two points, then when one of them triggers, you know whether it was inside or outside the enclosed code.

So what I narrowed it down to was some code that command bunkers, hospitals and repair shops run, where they go through their list of ‘supported’ units (the ones they are affecting) and updates them. Essentially this means telling all the units in the list that they now are not supported, then rebuilding a new up-to-date list. For speed reasons this is only done every X frames.

Now the obvious case for a crash is that some unit that was in the list when we added it, has been deleted, and thus when we go to tell them they are no longer being supported, we write to gibberish and cause mayhem. BUT! I know that this is never the case because no units are deleted mid-battle, ever.

Except that it turns out I’m wrong about that :D . They ARE deleted if… I drop a 25 man squad of infantry into a 12-man trench or bunker. At that point 13 of them get deleted. If I dithered when placing them long enough for a nearby command bunker to ‘claim’ them, then when I release them, I set off a time bomb, and after X frames, the command bunker will write to freed memory and hilarity ensues.

All fixed now, obviously. The easy fix would be to not support units until they are placed, but that isn’t nice for the GUI, and also I needed to rewrite the code to use a different system anyway so that multiple bunkers could overlap (they don’t stack though).

2 days. probably 20+ hours of debugging. What a pain. Insert comment about needing to get my act together regarding smart pointers here.

Bah.

Random heap corruption.

Filed under: gratuitous tank battles,programming cliffski 5:52 pm October 24, 2011

My heap is corrupt. No I’m not talking about my car, or my house, but it’s a boring programming thing. Essentially, it means somewhere, I’ve been silly and have written code that writes to memory that it shouldn’t be. This is something that is very very hard to track down.

The trouble with C++, is it lets you do silly things. Not just write to memory that isn’t yours, you could do crazy stuff like define + as meaning subtract, and vice versa. C++ is the programming practical jokers language of choice. There are even competitions to see who can write the most unintelligble crap with it.*

Of course, I try to write the most sensible, intelligible code that I can. After all, I’m the poor schmuck who has to support it, and fend off bug reports from angry customers. The BIG problem with C++ is that when you write some code that does crazy stuff, even when it goes wrong, you might not know about it until much later, maybe seconds or even minutes later, which means hundreds of thousands, if not millions of lines of code have been processed since the actual error.

In other words, you can’t look at a call stack and see where you screwed up, which you can do, in 99% of bugs. Even multithreaded bugs can be at least reasonably interrogated with the call stack and watch window.

With a heap screwup like mine, you are back to pre-debugger, stone age thinking such as.
“When did this start happening”

“What had I done before it crashed? and what had I *not* done?”

The last one is especially helpful because it rules out certain causes. My crash is NOT a result of the level editor, the unit design screen, units exiting the map, nightvision, nighttime, order-giving or path-assigning. It happens in debug, and its only been happening the last week, maximum.

So that means I’ve probabyl screwed up the new pathfinding code or the new AI code. These are two recent areas of much rewriting. I’m combing through them right now. I’ve tried various tools and debug flags to help, but sadly they either don’t run, or slow the game to unplayable speeds, where the bug will likely never trigger.

Fun fun fun!

*C++ is FAST, which is why I use it. If you think 2D games don’t need speed, try cloning GSB or GTB to run at 1920 1200 res and run smoothly on a 4 year old video card. You NEED a lot of speed for all this stuff.

 

Amazingly cheap computing

Filed under: Uncategorized cliffski 10:09 pm October 17, 2011

I guess the younger you are, the less this post may resonate.

Computers and computing gadgets and software is staggeringly cheap. Yes, games, but practially everything. I recently bought Sony Vegas HD 11 video editing software. It does EVERYTHING, and it cost under £100, as I recall. I’ve spent more than that on getting my boiler serviced. This is software that I could use to run an entire video editing business. It’s mad.

I also bought an external 1 terrabyte back up drive yesterday for £45.

FOURTY FIVE POUNDS for a TERRABYTE.

I need not remind you that a terrabyte is over 1,000,000 megabytes, which is a million zipped copies of war and peace. And I got a device that can store all that for less than the price of a tank of petrol. This is staggering.

Meanwhile, to compensate, the rest of the world gets stupidlty expensive. I just bought a 990mm by 395mm piece of 2mm thick polycarbonate (plastic) and it cost me £27 including tax and delivery. Madness. Getting a drain unblocked cost me over £100.

We live in strange times indeed. Everything is so expensive its a wonder people can afford to live, and yet anything encoded digitally is so cheap as to be laughable, and the technology that would have been dismissed a decade ago as a pipe-dream is now practically disposable. As an IT engineer I worked on 30MB hard drives you could practically crush a car with. You now wouldn’t bother buying a hard drive below a terrabyte, and you could put that in a large pocket.

If only all this crazy advances in computing tech co0uld be applied to making this stuff cheaper. Insulation FTW.

Gratuitous Tank Battles video and screenshots

Filed under: gratuitous tank battles cliffski 11:36 am October 15, 2011

In case you missed my minor PR splurge, there is a new video, and new screenshots of the game. The screenshots are clickable on the slightly redesigned site here:

http://www.gratuitoustankbattles.com

There is also a moddb page now here:

http://www.moddb.com/games/gratuitous-tank-battles

And mroe excitingly than all that is the new video. You can watch it in 720 res HD if you like :D . PLEASE upvote it, tweet it blah blah, if you think you can help spread the word. Mentioning the game on forums is especially helpful. The more hype and eventual players the more maps everyone will have :D

Opinions on how it looks are most welcome:

Also note that Democracy 2 is on sale at direct2drive:

http://www.direct2drive.co.uk/481/7494/product/Buy-Democracy-2-Download

And hopefully the parasites DLC for GSB will be on sale through steam on monday.

That’s a full day surely?

Programming AI in a tower defense game

Filed under: game design,gratuitous tank battles,programming cliffski 4:58 pm October 12, 2011

This is not an easy task. It is for most Tower Defense games, because they are simply scripted. The level has a set number of enemies of certain types and times, and they appear as attackers. And of course, most TD games don’t let you play as the attacker, so programming the defense AI is not needed. I need both of these to be non-scripted for Gratuitous Tank Battles.

I need attacking AI that ideally adapts mid battle to your decisions, and this is harder than it sounds. The first approach I took was to have a system with 3 types of placement timing mode (steady placement, or hoard points for a big attack or spam the current unit) and two types of unit selection (random, and select the one that has been most effective so far…with some variation).

The AI would switch randomly between these combinations and it looked pretty convincing. Sudden waves of identical units followed up by who-knows what. The problem was, it obviously did so with little care as to what it was up against.The ‘most effective unit’ code was good, because it meant totally useless designs which charged into a hail of bullets would not see much repeat business, but something major was lacking. That was the anticipating of future events.

If the defender has placed 6 machine-gun turrets (rubbish, but devastating to infantry) you shouldn’t place down infantry, regardless how well they did earlier in the battle. If they have lots of laser turrets, place down shielded units to get past them…etc.

So today, at the end of a long day of video rendering and editing, and tweaking, and bug fixing, I’m starting work on a more generic system for opponent army composition analysis, that can take snapshots of the enemy forces and realise that its 63.2% anti-shield units, and thus we should de-prioritise shielded unit selection etc.

This is annoying, fiddly, long winded code that nobody will ever see, as such, but will make Gratuitous Tank Battles a convincing challenge, which is well worth spending time on.

Working on tweaking the mechanics

Filed under: game design,gratuitous tank battles cliffski 5:01 pm October 8, 2011

It’s easy to get caught up with features, graphics, optimising and going through a checklist of items to do when you work on a game, and not set aside time to keep fiddling with the mechanics. There are an absolute ton of variations to the mechanics of any game. The only real way you know if the mechanics are right, is by trial and error.

If you wonder what the hell I’m on about with ‘game mechanics’, it’s basically the rules and systems by which the game is played. For example, in chess, the pieces all move in different ways. Some can only move forwards, some can only move 1 square at a time… None of the chess mechanics are obvious. Imagine designing it from scratch. We take for granted the idea of a knight moving over other units, or castleing, or units like bishops having infinite ‘range’, but none of them is ‘obvious’.

Right now, my bugbear is support units. GTB has repair trucks and ambulances for attackers, hospitals and repair yards for defenders. My current mechanic is this:

The support units pulse out ‘waves’ of effect at a certain interval and radius. Any damaged vehicle (repair) or soldier (hospital) within that radius at the time gets X of their health replaced.


Look! Neither side is bothering with hospitals or repair units…

This seems ineffective, and there is little real incentive to use these units. I might have just set the costs for them too high or the effect too small, but in fact i think it’s more fundamental. By the time people are losing health, they are a lost cause, and the interval between lost health and death is too slow to enable a health pulse to really do much good.

Possible solutions:

  • Ultra-rapid health pulses to ensure timing not an issue,
  • Reduce armor and shields and increase health of all units
  • Make support units dirt cheap so they are worth it anyway
  • Allow recently destroyed / killed units to be revived by the pulses.
  • Change the mechanic entirely so that the units don’t use pulses, but act as damage modifiers to protect everyone within their radius, effectively making them mobile buffs.

I’m planning on trying out the last option. It involves a lot of fiddly code, but what doesn’t eh?

BTW, stuff like this takes AGES, and it’s why I REALLY hate clones of games, where some talentless drone comes along and just copies an existing game design but slaps on some new textures. Yes, it really is easy to copy the mechanics of a popcap game, but coming up with those mechanics took a ton of work. This stuff is never obvious, and I personally don’t think it can be reliably learned from books. I think you have to just keep trying stuff.

Debug Tools and defensive AI.

Filed under: game design,gratuitous tank battles,programming cliffski 6:10 pm October 4, 2011

Life is so much simpler when you bunch up all your hotkeys and toggles for debugging the game into a single menu. I feel like I have a rough idea what’s going on now. I also feel more confident about coding decent defensive AI when you play as the attacker:

The code for defending basically needs to manage three things. The play style (Is it spamming units, hoarding points, or steadily placing), The choice of units (Does the enemy have units weak Vs lasers? Are there lots of infantry needing flamethrowerising?) And the choice of unit placement. I’ve been concentrating on the unit placement debug UI today, so I can see what the AI is thinking when it chooses to place a turret at X rather than Y. More work to do, but currently it evaluates proximity to enemies, their size, victory-point value, closeness to the exit and proximity to the placement, plus it also has bonuses for being able to cover multiple paths from a single location.

It all needs lots of tweaking and balancing obviously, but it’s getting there. Attacking AI is much simpler.

After getting this stuff done, I’m thinking of experimenting with a unit ‘cooldown timer’ beyond a certain level to prevent spamming the same unit everywhere. Essentially there are supply delays if you plonk down 4 heavy tanks all very quickly, as new ones need to be dispatched from your offscreen HQ. I think it might be a good mechanic that encourages variety.

Next Page »