Oversteer Racing: Dev blog #34 – The one where we tie up a few loose ends

It's been a fairly busy month but I have managed to work on Oversteer Racing, so that's a significant step forward from previous months ;-)

As it's been a while since I could put a reasonable amount of time in on the game I've been getting back up to speed by fixing a few minor bugs and tying up some loose ends. Most of this work has still been focused on the end of the race and making sure the data is correct. I've made sure that the race summary uses the correct driver and team names (as set by the player) and also made sure that the code correctly determines the time gaps between the cars.

I've also fixed a few minor bugs where data was being misrecorded (incorrect pit stop numbers, DNFs etc) and also fixed a bug that meant that smoke wasn't being shown when an engine failure occurred. I've also been working my way through all the settings scenes and making sure those settings are reflected in the game (i.e. if you switch on advanced handling then that is toggled on in the game).

Next month...

I hope to finish off all the work on the code to handle the end of the race and correctly record the results and update player stats etc.

Oversteer Racing: Dev blog #33 – The one where we get the move done and fix things

As mentioned last month I had to spend some time moving my website over to a new host this month. As I was moving the site I took the opportunity to try and simplify things a bit. The old site used WordPress and that's great but it requires some effort to maintain (software updates, database backups etc). As I needed to move the website anyway I chose to stop using WordPress and use Jekyll (a static site builder instead). This should pay back in terms of time but offer similar functionality.

I have managed to do some work on Oversteer Racing over the last few weeks too. I'm still working on the code to handle the end of the race. I've made good progress and the code is handling most of the scenarios I'd previously outlined for the end of the race. It still needs a lot more polish but it's been good to make some progress again.

Next month...

Further work on the end-game code and I also want to make sure that, if users change the names of drivers and teams, these are reflected in the end-game scenes.

Oversteer Racing: Dev blog #32 – The one where we plan a move

It's been a difficult month and I'm really struggling to think of any tasks I've completed on Oversteer Racing. I've been away which dramatically reduced the amount of time I could spend on the game and I've also had some other tasks that have demanded my attention.

One of the issues is that the web host I use for this site (and a number of others I run) has been bought out by GoDaddy. For a variety of reasons I'm not keen to be a customer of GoDaddy (feel free to check out their page on Wikipedia as that covers a number of the issues). As a result I've had to start looking for a new host. That process has also resulted in me reviewing a number of the things that demand my attention to see if I can reduce my time commitment by changing how I do things. The idea is that by reducing some of the complexity of the sites I support I could get a 'pay back' in terms of time. Quite a few of the websites I run rely on a database (or many) and some other software such as WordPress (for example). This has a knock on in terms of finding good web hosts and supporting the sites as I need to make sure the sites are up-to-date (in terms of software updates) and also to take automated backups etc.

In an attempt to reduce the amount of time I spend looking after websites I've decided to convert some of my sites to using Jekyll (which is a static site builder). I've decided to use this site as a test site as it's small. The idea being that I can build the site in a Vagrant VM and check in the site files to Git and then just deploy them to a simple, static site (something that's offered by many hosts).

So, sorry for the lack of progress or a conventional dev blog but it's one of those times where other tasks take priority.

Next month...

Hopefully I'll have moved this site, will be well on the way to moving the others and will then have more time to work on Oversteer Racing.

Oversteer Racing: Dev blog #31 – The one where it's never ending

Unfortunately it's been a really busy month for a variety of reasons. I've found it very difficult to find regular blocks of time to work on Oversteer Racing and so progress has been very slow.

When I have been able to work on the game I've been looking at the end of the race and producing the race summary. I have code to track the race finishers and retirements. The main issue is dealing with cars that are yet to finish the race and, even more tricky, predicting the race result if the player retires before the end.

I did also find time to fix a slightly annoying issue that's been present for some time. When the player car turns, the front wheels of the car rotate to reflect the turning of the steering wheel, this was not the case for the rival cars. If you look closely in any of the game play videos to date you can see that the rival cars steer straight ahead even when turning. I have now fixed this so that the wheels on the rival car rotate correctly too.

Next month...

I'll continue working on the code to handle the end of a race.

Oversteer Racing: Dev blog #30 – The one where we look at the end of the race

February has been another busy month because I've needed to work on my fantasy F1 competition and haven't been able to spend much time on Oversteer Racing. In the time I have managed to find I've been working on the end of the race. On the face of it this might seem a pretty simple task, show the positions of the cars and add up championship points, but it's actually a lot more tricky than it might first seem.

The main complication around the end of the race is determining the positions of the cars. There are two scenarios to consider:

  1. The player completes the race normally - In this situation the finishing position of the player is known, as is the position of all the cars that finished before the player did. However, although we allow the race to run for a few seconds after the player crosses the line we cannot be sure all the cars have finished (unless the player is last). As not all cars will have finished then we need to look at the cars that are still running whilst also accounting for others that might've retired and determine the complete finishing order. In the simplest case we could just assume that the remaining cars finish in the same order as they are currently running but should the result always be predictable in that case?
  2. The player retires or crashes - In this situation determining the final race order is much more tricky. It may be that some cars have crashed out but there will always be some cars that are still running. If none of the cars have pitted or all of the running cars have completed their final pit stops then determining the order is relatively easy (it's a similar task as the first scenario). That said, if the race is still in its early stages then we should include some degree of unpredictability as the finishing order is unlikely to remain the same as the current running order. If the race is part way through and some cars have pitted but others have not then the current running order when the player retired is not representative of what the running order should be once all the strategies have played out. This is a more complicated scenario to model as we must also take into account cars on different strategies. In order to do this we need to work out what cars are out of position, determine if that is due to a scheduled stop or due to a stop for a replacement wing etc and then work out the expected running order once all of the cars have pitted. We then need to predict the final result and this may also have an unpredictable element to it (i.e. just because a car will be leading after the pit stops doesn't mean it will always win the race).

So, in summary, not only is there the practical task of storing race data there is also a task to model/predict the result of the race in some cases. At the moment I'm just focusing on the simplest case since even that includes some element of result modelling and, once that's done, I'll look at the more complicated situation.

Next month...

I'll continue working on the code to handle the end of a race.

Oversteer Racing: Dev blog #29 – The one where this time every year we do something else

It's always the same this time of year as I need to spend time on some other projects/tasks. For example, I need to get boring stuff done like tax returns and company accounts etc but I also need to work on my fantasy F1 competition. Given that the F1 season starts in March I need to make sure the competition launches at the beginning of March at the latest. As a result I tend to have to spend a lot of January and February working on other things and not working on Oversteer Racing I'm afraid.

Next month...

Probably another month with only a limited amount of time to work on Oversteer Racing.

Oversteer Racing: Dev blog #28 – The one where we review the last season (year)

I thought it might be helpful to list out some of the tasks that I've completed this year as a way of reflecting on how the game has developed. There have been a lot of little changes but the main pieces of work have been:-

  • Race order - keeping track of the order of the cars. This is a pretty fundamental thing for a racing game
  • Bug fixing - I've uncovered and fixed quite a lot of bugs and little issues throughout the year
  • AI car pit stops - the AI cars can now decide when to make a pit stop, enter the pits, drive to their 'box', stop for the correct amount of time and then exit the pits. Adding this to the game is a significant piece of work and it now brings a strategic aspect to the racing.
  • Car avoidance - I spent a lot (it feels like months and months) working on code to get the AI cars to avoid other cars. This is now working reasonably well. It may, like a lot of the game, need a bit more tweaking as I add more features and play test the game but it's functional for now.
  • Defensive driving - the last task completed this year was to add code allowing AI drivers to make a decision to take a defensive line when being followed by another car.

Why is it taking so long?

There's a simple answer to this… Oversteer Racing is a hobby project for my spare time. A lot of things affect the amount of spare time I have and, on top of that, a lot of things affect how much energy I have in my spare time to work on the game. I'll be the first to admit that I haven't been able to put in as much time as I'd hoped this year... and I really can't promise that the situation will change for 2019. I'll do my best but hobby projects have to fit around other things.

One game dev blog I regularly read is the blog by Jake Birkett from Grey Alien Games. Early in 2018 Jake wrote a blog post called "You are spending too long making your game" - it's a great read (like all of Jake's blog posts) but it hit home a bit. I've been making Oversteer Racing for some time now and still have a long way to go... but it's taking too long. Obviously I'm not a full time game dev and that brings a whole host of challenges and, as should be clear, I'm not able to work on it full time or expect a return that matches the time put in. With that in mind I plan to start 2019 with a review of my plans for the game and to see what things I can cut from the initial release. There are definitely some nice to haves but I can always add these later so that I can get the game out as soon as I can given the constraints I have.

Oversteer Racing: Dev blog #27 – The one where we go on the defensive

It's been a relatively quiet month in terms of Oversteer Racing. I've managed to do a few things but not as much as I'd hoped and, due to Christmas etc, I expect next month to be less productive than November.

Going defensive

One thing I did look at this month was getting the rival cars to start following a defensive line. I've already added slipstreaming/tows to the cars but I also want the rival cars to react to the player and each other and defend a position. There's a fine balance here as racing cars that are always on the the defensive probably won't be fun. Conversely, racing against a car that seems ambivalent to your presence won't be fun either.

For some time I've been able to create alternative routes on the race track and allow cars to switch between them. This is also how I get AI cars to enter the pit lane etc. Up until recently switching between routes on the main race track has been a random choice by the AI. I've now set up the AI cars to be more likely to take the more defensive line if the car behind them has been within range of a tow during the previous lap.

I plan to also change the likelihood of a driver defending their position to be linked to the "aggressiveness" value of the driver in the car. Aggressive drivers will be more likely to defend than more passive drivers. On a related issue, cars being lapped should not defend the position.

Next month...

Next month will be very busy so it's unlikely I'll get much done on Oversteer Racing unfortunately.

Oversteer Racing: Dev blog #26 – The one where we toe in rather than toe out

It's been another busy month and once again I've been focussing my efforts on obstacle avoidance... it's been some time now since I've looked at anything else!

However, I'm starting to make progress and, although there are still a few collisions, the AI behaviour is getting to the point where some accidents are avoided and the cars are more challenging to race against. The key to the improvement was some time spent tweaking the values that control when an AI car will choose to avoid another car and how the AI cars detect other cars. On this last point I'd primarily been using three raycasts at the front of the car. These can be seen in this screenshot (from last month's devblog):-

Non-player cars failing to avoid each other

I was using a central raycast with another on either side angled out from the car. The result was inconsistent as, initially, AI cars would turn to avoid another car but but often wouldn't turn enough and, as a result, would clip the edge of another car.

By setting up scenarios where cars needed to take avoiding action and stepping through the action I could see the issue. Initially the cars would detect an obstacle and turn to avoid it. This change of direction meant the obstacle would not be directly in front of the car. At this point the left or right angled raycast would detect the obstacle. The car would then turn some more to avoid the obstacle. However, as the car got closer to the obstacle then the angle of the side raycasts meant that the obstacle wouldn't be detected when close to the car. This meant that the cars would move to avoid the obstacle but stop detecting it when it was close and therefore not move enough.

The solution was to "toe-in" the raycasts rather than have them "toe-out" as was the case originally. This means that the AI cars are more 'concerned' with objects that are directly in front of them at long range but less concerned about objects that are in front but off to one side. As the AI car approaches the obstacle then the side raycasts are increasingly likely to detect a side obstacle as well as one in front. The result is a more consistent move to avoid an obstacle.

Screenshot showing raycasts on an NPC car

The AI cars won't always avoid an obstacle but their behaviour is more consistent and they are generally "doing the right thing" now. One other benefit has been that AI car behaviour when racing wheel-to-wheel is also more challenging now - as can be seen by this clip of the red AI car racing against the player (blue and white car).

Animated gif showing AI racing behaviour

Oversteer Racing: Dev blog #25 – The one where it's hit and miss, although mainly hit

Recently I've been working on AI behaviour for the rival cars. The main focus has been convincing the non-player cars to avoid other cars rather than slamming into the back of them. As Oversteer Racing has a more realistic damage model than some top-down racers collisions tend to be more serious than in other games.

One downside of the non-player cars following a series of potential routes around the track means that they have no knowledge of where the edge of the track is. This makes things difficult when it comes to avoiding objects because it's hard to work out which way to turn to avoid the object. For example, if a car has stopped on track then can the non-player cars pass to the left or to the right without leaving the track?

The work I've been doing uses a number of ray-casts from the cars to detect obstacles. Once an obstacle has been detected I use the route markers to determine which side of the track has more space. The car then steers towards that space.

This is still a work in progress as the cars are not consistently avoiding obstacles. To some degree I'm happy if the cars don't always get this right because that seems more realistic but, at present, the non-player cars get this more wrong than right...

Non-player cars failing to avoid each other

Non-player cars failing to avoid each other