Gaming Your Way

May contain nuts.

Lessons learned the hard way, part 100

Right now I have next to no time for working on MTR, as it's December - which means that about a million client projects should be finished by the end of the month.

Getting my ass up and continue coding after doing it for 12 hours is, let's be candid here, not easy and most of the time I just want to drop myself onto the couch and play for an hour. Right now I'm playing Assasin's Creed 4 (Black Flag) on the XBox One, which is reasonable fun, if you overlook the fact that the novelty has worn off a bit after 30 games with the "same" theme. But the open world and the the lush caribbean environments make up a lot. I event spent some time just sailing between the small island and hunt down the "hidden" items scattered around the map.

Back to the title of the post, which isn't as unrelated to the post as usually.

In the post about the new HUD I mentioned that I want the thing to be dynamic and showing the order of the cars while they progress through the race. With this idea I coded a little sort function that creates orders the cars according to their position on the track. The idea is simple enough: every time a car hits a waypoint, I store it away and use it to sort, higher waypoint id means better position. As the ids start with 0 after a round I just add 1000 for each lap and that problem is solved, too.

There might be the chance that two cars share the same waypoint and this is taken care of by comparing the time when the cars hit the waypoint making the one with the lowest time first.

The first version of this updated the position of the HUD each time a waypoint was his and espeacially in the early stages of the race this could change quite frequently, causing an ever moving HUD (which was quite distracting, tbh). The second thing that didn't work out like planned (quite logical now, but I didn't see this when I thought of it) is the way the time is displayed. I only wanted to show the current time on the first car and show only the difference to the first on the other cars. Yet again, during the start of the race there is nearly no difference, resulting in changing 1/100 secs, which didn't help at all. I'm going to test if I may stop the time for 2nd, 3rd and 4th car, showing a fixed difference (instead of a running time) to the first car and update it only every odd waypoint. Either that or I drop that and just show the race time ...

No image this time (it would just show the track, 4 cars and the HUD anyway), maybe next week ...

-- Oliver/nGFX

Spoiler ahead

Ok, here's the deal, I post a few pictures now and I don't want to start a system war about what kind of system is the better one for playing games. 

...

...

...

...

I got my Xbox One the other day (and a day one edition at that), but due to the odd family commitment I haven't touched the box until a few minutes ago.


Yes, indeed a day one box.


Seems to be a Xbox One - guess why I know it?


Don't play with plastic bags ...


All mine! ALL MINE! Muhahaaaahahaaaa ....

Well it seems that I have to find room for another brick ...


The new Kinect sensor is larger than the old one and it doesn't have an USB connector anymore Also the cable is a lot thicker.


Finally. This one is also bigger as my old 360 (the black one).

Let's get this thing connected ...

... back, 30 minutes later. Update installed (500mb), Kinect set up, logged in to xbl - all seems to work. The new dashboard is a bit different so it took a minute to find my way around, but voice control is working flawless so far.

The new controller isn't as heavy as the 360 one, but then I use the chatpad which adds a few gram to the equation. Still, it feels like it was made for my hands, the sticks are a bit easier to move it seems, but that's not a bad thing. I just hope the bring the chatpad back because I very much liked it.

Oh, the the thing is silent, nearly impossible to hear from the couch - you couldn't say that about the first xbox 360 (the white one). I'm going to have a look at AC4 now ...

... Oliver / nGFX

Some boring numbers

Lost Outpost went gold the other day ( I should really have mentioned that here shouldn't I ? ) and it's currently waiting for sign off with the sponsor, so I thought let's go through some numbers just to try and show why it's taken forever to finish.

For the 10 levels ( Plus 5 Swarm levels ) we use 396 tiles, or 1,653,371 bytes worth. When compiled all the levels come in at 2,232,249 bytes.

99% of the images have been converted to png8 to save file size ( All done by hand ) which come in as 1510 images, or 17,942,059 bytes ( This includes the tiles ).

We have 272 sound effects ( Including 7 pieces of music ), when published as a swc that's 5,547,127 bytes. To give it a bit of perspective, Outpost:Haven was our most sound heavy game before this, with 158 sounds. There are 10 different shell casing sounds, an additional one just for shot gun shells, 3 different samples for a crate being shot and 12 vocals for the automated announcement system on Haven.
I went a little bit crazy with the sound I think.

 

 

In regards the source, this is more vague. Not so much the numbers themselves, I'm not just making them up, but the meaning of them. When someone says they've coded something and it's taken 2000 lines, it doesn't really mean shit as everyone codes differently. Personally I'm murder for lots of white space and for using a Class for everything ( I've been told I'd break one line out into it's own class if I could, which aside from making me laugh is very close to the truth ).
So yeah take the following with a pinch of salt, it's quite meaningless, hence me comparing the code in Lost Outpost to Outpost:Haven's as a kind of benchmark ( I can only compare my own code to my own code as my style if fairly consistent  ).

Outpost:Haven had 266 Classes, taking up 2,304,945 bytes. This includes 27 Classes that weren't mine, general utility stuff.

Lost Outpost uses an unbelievable 425 Classes, 4,317,541 bytes. That's fucking insane. Oh hang on it's not too bad, the same 27 Classes that weren't mine in Haven are included in that figure too. So less than 400, that's nothing...

30 unique physics objects ( Crates, desks etc. ), 133 "Non-Baddie" items. These are items which the baddie handler routine controls, but aren't strictly baddies, so it goes from the spinning fan shadow to music triggers to flushable toilets to the medi-packs you collect etc. 6 Classes are for the hidden game ( With it's assets coming in at a mere 255k ) and a majestic 37 Classes for all the particle effects, with 9 of those being various smoke effects. The overkill for the particles was for performance reasons rather than me over engineering for the sake of it.

The in-game terminals were a mere 3 Classes, although they came in at more than 4000 lines of code ( I guess if you deleted all the white space and comments, that would be about 40. I'm joking, but not by much ).

PDA, which is the inventory, maps and the log screen, was a mere 14 Classes but had more code than all the particle effects combined.

And I've started to bore myself, so it's time to stop. Just to recap, Lost Outpost is a huge fucking game which should equate to over an hours worth of total story play time.

Squize.

How the MTR car AI works ...

... or should, once I find the time to finish that slog. 

I must admit it was one of my worst ideas to take a stab at a racing game (and sell it to a client). The only luck so far is that it's a "when it's done" deal, so there's no deadline on this except my own wish to get it done and collect some cash for the client version.

The basic idea to do a "quick" little racing game wasn't that bad, but I really, really underestimated the amount of work I had (or rather still have) to poor into it. One of the most time eating tasks still is writing the car AI, which completely didn't appear on my radar until it was way to late.
I've written my share of AI code so far, so I thought this one wouldn't be much different. I think I was wrong with that.

The main big different with what I have written so far is that character can move freely, if something blocks the way, turn left or right and continue moving until you can resume the old path (or just run the a* again to find a new way to the player). For cars this doesn't quite work this way (now that's a surprise).

So cars need to use throttle to speed up and breaks to slow down you need to use steering angles to change direction and you must obey the limits (otherwise it'll looks like cheating). Moving the car along the track is quite easy if you have a fixed track, just draw a spline and let the car move along it. Too bad MTR has a built in track editor, so we need to construct the path for every track. (I covered this in an earlier post).


Waypoints for the AI.

Trouble enters the equation when we add other cars to the track and we cannot follow the waypoints anymore if some other car blocks the path. I calculate the throttle / steering values in steps, blending the values in the end (and then blend the desired values with the current ones).

First step is looking at the waypoints ahead and decide which lane is the shortest (using floating waypoints), then the desired throttle is calculated based on the distance between the last waypoint we've passed and the next. The shorter the distance the slower the car should go, I use 100% for the max distance and 75% for the smallest distance). 

Next step is deciding what angle we turn the wheels in order to head towards the next waypoint and if the angle is greater than the allowed one, we reduce speed further.

After this I have a basic throttle value (say 90%) and a steering value (say 20%, of the max steering angle).

 


Damn obstacles.

Now it gets a bit more complicated, we need to look for obstacles that might block the path we've just selected. The image above shows the problem, the red line shows the desired next spot we want to reach, the yellow line shows the current throttle, with the dark blue line showing the max throttle (but that's only for debugging). Important is the cyan line that is shown at the back of the green car, as it shows where we would hit the green car if we would follow the current path.

Right now, if this happens I offset the waypoint until we can pass the green car (adjusting steering to -20%), but only if there is enough room (there are also checks to see if we can pass on the left or right side of the obstacle), if we cannot pass we need to reduce speed to stay behind it.

Now just blend the values and pass them to the car and repeat this every time we hit a waypoint or another car is close enough to overtake.

If I ever get that video grabber to run I'll post a video next week.

They're nearly here

So Lost Outpost has been sold, to maxgames.com, and we're just fixing the last few bugs and adding the branding. We can't give a launch date yet, but it should be next week sometime. 

We're so nearly there, and we can't wait.

Squize.

"TV and the Internet are good ...

... because they keep stupid people from spending too much time out in public."
― Douglas CouplandJPod

I wonder what spambots will make out of that.

Anyway, it's Sunday again and time for the weekly post. Problem is, there's nothing even remotely game-related to write about. I spent most of the time coding a client project and let me tell you: writing an e-mail verification system is oh-so-shit boring. Plus keep in mind: never underestimate the user to do something really bone-headed when presented with a simple form.

What's not to understand with "username, 8 to 16 characters, allowed are letters A-Z, numbers, minus or underscore, do NOT use ä,ö,ü,ß"? You know it when you've got the first one on the phone telling you "I can't enter my username - it's 'Hans Müller' " ...

Ok, to make this post just a tiny bit useful: what about using a cloud based sync and Unity projects?

I for instance gave up on the idea to store a Unity project directly in the Skydrive folder (but it's the same for Dropbox, google drive, ... whatever). The problem is that unity creates a shitload of temp files whenever you change code and it recompiles it. For me it worked for some time, but then it choked and resulted in missing files.

But I wanted to sync my current Unity project between 3 computers without using an USB Drive, the obvious and quite simple idea was: use 7zip and a batch file (two actually). I use 7z as it has a nice command line version and it creates a slightly better compression than zip and I can't stand rar.

So when starting to work I hit the "unzip.bat", which deletes the local project  and then unzips the project from the cloud (and starts Unity afterwards). When done for the day it's "zip.bat", which zips the local project and moves it to the skydrive folder. It really is a no brainer, but it saves a good deal of traffic and time - 26mb (7zip) instead of 157mb (uncompressed, ~4500 files) or 38mp (zip) ...

I'm going back to code some game related stuff tonight so at least I have something for next week.

-- Oliver (nGFX)

And then they said that burning the secret documents ...

... only made things worse.

See, all the good intentions are gone by now - that is having the weekly post done before Sunday, well at least it's not 23:52h.

Although I have a good reason as I haven't worked at all for two days straight, trying to get my laptop back to work. In theory it would have been a case of just restoring the last weekly backup, but alas ...

I'm using a Dell, you know, running win 8.1 pro (64bit) with Intel Rapid Storage (magically using a SSD and a HDD mixed up for speed), Intel onboard gfx and an additional ATI Radeon card for 3d / games. I mention this because this combination is the the reason for the two wasted days (although, it's partly my fault).

The whole mess starts with me noticing that the Catalyst Control Center wasn't running (so no choice which card to use), as I had that earlier (when running still running win 8) so I knew that I just needed to install the latest ATI drivers again. That done and a reboot later the only thing I got was a black screen and a flickering cursor. What followed was a lot of cursing, because after I used a "recover to last working version" I ended up with a clean win 8 install and just a few of my settings and none of my programs left.

Ha! No problem, I have a backup that is just one day old.

To cut this short, in order to get the OS partition restored I needed the following: change boot mode to legacy (UEFI by default, to run the linux based frontend of the backup software), turn off the Rapid Storage/RAID settings in BIOS in order to access the HDD and write back the partition. With this in the recovery only took about 30 minutes, great that there's nothing to be found about this on the interwebs ... and you only come to this after 2 days of "can't this", "error that".

Oh and I had to install the ATI drivers provided by Dell in order to make things work with win 8.1 ...

... now lets's start with this week's post.


Yes, I used that image before.

I mentioned that the HUD in MTR is far from ideal or even "pretty", too much information, too small and not helpful. One of the tasks on my list therefore read "redesign HUD" and this post will go through some of the iterations that the HUD went through.

The information I wanted to show was: car, position ( the badge icon), lap time/total time and boost (the battery). Once the race is running, having 4 pairs of changing numbers is quite a bit much distraction from the track.


Iterations of the new HUD.

As you can see the icons changed quite a bit and all of the icons that were used as labels are gone now, too. 

The final HUD comes in two flavours: horizontal (for smaller screens) and vertical (for larger screens):


Default view for larger screens ...


... and for smaller ones.

The latest version adds a hint of color to the backgrounds of the badges (using the car's main color). The position is now shown by the order of the badges, the local player is marked by the orange line (color may change). It also brings back the battery icon, well sometimes, but that's for another post ...

More next week,

-- Oliver / nGFX

You can't make an omelette without breaking an egg

(from: Some Like It Hot)

Even though the title is a quote from a movie, it also is very true for development. As mentioned last post I was about to rewrite (again) parts of the game to make it easier to maintain and debug.

One of the bigger changes is that I moved states from code to a visual finite state machine (FSM). Honestly it was one of the better ideas I had since I started with a game I have virtually no "knowledge" of (because I really don't like racing games). As a result I killed about 2/3 of the code in my "RaceController", reducing it to (currently) ~300 lines of code.


Early version of the RaceController FSM.

The final version is a bit more complex, though. To be true this doesn't count in the code needed for the FSM, but *my.* code is a lot shorter now.

For the AI code however it is something different and I found it a fine line between using the FSM and handle things through code. I had to decide whether to make "Reached waypoint, what now?" a simple method call or a state. The AI is done in code now as most events coming in just alter target values that are dealt with in the main loop of the AI.

In any case this makes the AI a tad more robust when dealing with corners, speed and lanes. For example there is a value that keeps track of the lane the car is on (0 being the inner lane, 1 the outer and 0.5 the middle of the road). When the AI decides it wants to change the lane from 0 to 1 (because in corners the inner lane is faster) it sets the fTargetLane to 1 instead of fLane (the variable that holds the current lane we're on). Before easing the lane value the AI can now check if there is room to change the lane (another car blocking the way) and delay easing. Same goes for speed and steering.

Easing between current and target value also allows to add some "personality" to the AI, but that's stuff for a later post.

"All right, driver, once around the park, slowly, and keep your eyes on the road."
(again, Some Like It Hot)

-- Oliver / nGFX