It's been a while since I coded anything outside of my day job. To be honest I got a little worn out towards the end of November with trying to do too many things at once and only recently have found the energy to code anything on nights/weekends.
Tonight, just for fun, I started working on a very small block puzzle game I had an idea for about a week ago. It's not done yet (and won't really work anything like the screenshot above) but I started working on the little engine for it tonight.
I'll probably finish it tomorrow or at some point in the next week and just put it up somewhere for people to play. It's a very simple/small idea so it shouldn't take me long to finish it.
Just a quick update to say that I've been working with Ashton Morris who has been making some really fun music for the car game lately.
Otherwise I've been working on improving the controls/physics more and more and also messing around with improving the gameplay camera system. It leads ahead of you now while you're moving so you can see where you're going more easily (up until now you were always dead-center on the screen and it was sometimes tricky).
I've been pretty frustrated with the way the physics are working in the game lately and have been thinking a lot about going back to the drawing board with the whole way that they work. It would be a pretty big job but I think the 'feel' of the game is the most important thing to get right and really want to nail the movement/controls before moving onto other parts of the game. I guess I'm being a bit obsessive but it's still not feeling the way I'd like it to.
Mostly worked on fixing bugs tonight (UI stuff, some weird controls glitches, race position issues when cars were destroyed) but also finally added UI for health bars over cars. Makes it a lost easier to figure out who to take down now.
I also rearranged some of the way health works on cars to simplify it and centralized some of the car data so it's easier to access it from other scripts and other boring things like that. Good progress tonight but not very exciting screen shot material.
I should be getting sound effects and music pretty soon from people helping me with that and I'm excited to get those in.
Going to work a bit on making some cool rocket effects next I think!
I started experimenting with what a world map/track selection menu for the game might look like tonight. I'm still trying to work out how to organize all the different locations/events/racer villains and thought a cute little 3D map might be cool.
One of my goals in the game is to have themed racing teams. Surfers, lumberjacks, scientists, etc. Basically a bunch of AI racers that all have similar uniforms and come from specific parts of the world and show up in races in those places. Eventually you will face off with a local champion in each place before unlocking the next (think Pokemon gym leaders).
This world map would basically just be a fancy menu though (no walking around on it or exploring or anything). You'd be able to spin it around but then you'd just select an unlocked location and it would show you all available events in that place.
I have mostly been working on data stuff and UI improvements lately which are not terribly exciting to screenshot or write about but I wanted to make a small update to say the game is still coming along!
I've been talking to people about sound effects and music lately too which is very exciting. Looking forward to getting all that in since sound will make a HUGE difference to how the combat feels.
Tonight I only had a couple of hours to work on this but I got it so you can switch your weapons around in the inventory and it shows all the stats on each one.
I think next I'll be working more on the in-game UI. I want to show health on cars and add portraits to all the AI racers (right now they only show up on players).
Also want to show lap times/total race times and stuff like that soon too.
Got home pretty late tonight but really wanted to make SOME kind of progress on the game so quickly I added health/damage to cars and a little particle effect explosion when they are destroyed.
I created ObjectHealth and DamageInfo classes that send/receive damage to objects that can be destroyed (I could easily blow up trees right now if I threw the scripts onto them for example). DamageInfo has the amount, type and source of damage being dealt. When a desctructable reached 0 health it triggers a UnityEvent that I can assign to whatever I want to happen when something is destroyed. For cars it triggers a function in another script that instantiates an explosion and removes the car from the race. For trees I could just trigger a 'tree explosion' (wood bits flying everywhere) or whatever I want.
Nothing fancy but it works great and it's fun blowing up cars now!
I started modelling some more weapons and thinking more about how I want them to work in the game tonight. I had originally thought of creating a randomization system that combines 3 different weapon parts to make different random weapons and stats but after some experimenting I think it ends up making them all just kind of look/feel the same since I have to design all the parts to fit properly with each other and can't really do crazy/interesting things with them. So I'd rather design a pool of hand-made unique weapons and randomize smaller details, colours and stats. This would be more like Diablo where you have bits of armor or swords/axes etc that can look the same but have different stats instead of what I had originally thought of, which was closer to the guns in Borderlands.
Weapons right now have these base stats:
- Rate of Fire
- Reload Speed
- Magazine Size
- Max Ammo
- Projectile (Rockets, bullets, lasers, whatever)
- Linked/Alternating shots (All guns come in pairs on the car right now and either fire at the same time or alternate back and forth).
All of this is working and driven by ScriptableObjects in Unity right now. So it's really easy for me to create a new weapon, give it some stats, assign a 3d model and projectile to it and have it work in the game.
Eventually I will also have more interesting traits like abilities, damage type or special stat boosts (some larger guns might slow your car down for example) but for now this is a starting point.
I still need to have cars actually take damage and explode next, so I'll hopefully be doing that tomorrow night now that I have some more weapons to play around with and test the feel of.
I've been working on the weapons over the last few days. They are still very rough/early/basic but I wanted to at least let you choose a weapon from the character UI and have it actually equip (showing up with graphics) and work on the car. Right now it's just basic yellow bullets but I'll be adding rockets and some kind of shotgun-like blast next.
I also added some names/portraits that appear over player's cars. I'm still experimenting with position and whatever (and all the UI graphics are still filler/temp). I'm going to be adding healthbars to AI racers and players soon too.
It's been a couple of weeks since I updated anything here. I wish I could say it's because I've been busy working on the car game but the truth is between starting 2-3 new projects for work and a bunch of Big Life Stuff that got in the way the last couple of weeks I haven't had a lot of time/energy/motivation for working on my own projects. BUT THAT ENDS NOW.
I'm finally back on the game and tonight I managed to play around a bit with some dynamic lighting ideas and much more importantly, I finished the main game loop, so you can have 1-4 players join/drop into the game and play races and it loops back to the menus where you can select different vehicles and then play more rounds.
It's very far from being finished still but the basic framework is now in place and I feel like I can at least hand people some controllers and let them play around with the game a bit to have some fun races.
Right now there are 1-4 human players and then the rest of the slots fill up with AI so there are always 8 cars on the track.
Next I'm going to finish up some little polish things I still have to do with the race results screen and then start working (FINALLY) on adding the weapons! I'm pretty excited to be getting back to gameplay stuff after a lot of work on data structures and backend stuff for the game.
I've been working on a lot of backend stuff that isn't very exciting to talk about this week. Data structures, UI systems, etc.
I spent most of today changing the physics/controls around quite a bit to make the cars feel like they have a bit more weight and slide around a little less. I think it feels pretty good right now but it's something I'll be tweaking forever I imagine.
You can now have an inventory of cars (which I will eventually let you buy) in your player profile. You can select which one you want to use before a race starts. Right now I have 3 different little cars to choose from (the small car, the pickup truck and a little coupe).
I worked a bit on improving the AI today as well (to adjust to the new physics/controls).
I'm really hoping to get the race win/results screen stuff done next and then move on to adding weapons!
I was thinking about the car/weapons/racing teams gameplay design tonight and writing down a lot of things in preparation for beginning work on this stuff in the car game this coming week. While thinking about the cars and weapons I started trying to come up with fake manufacturers/companies for the game. I didn't really come up with any real names that I like but I decided to just design some little logos for fun anyway to unwind at the end of the evening. I probably won't actually use any of these in the final game but I'll use them while working on the prototype.
I've been working on a very rough/early version of the co-op UI. What you see above is for creating a new player profile while playing 4 player co-op. Each player has this UI in a corner of the screen and can select a portrait and enter in a name using a game controller (so no need to fight over a keyboard or get up if you're comfortable in a chair). I designed the keyboard to be super reusable so that later on you can enter in item names or other things with it as well. Of course I'll also just let people use keyboards to enter in names and stuff too on PC.
The portraits seen here were provided by Zac Gorman who kindly offered draw some to help me with my prototyping. All the actual UI graphics I made quickly myself and are just temp art to get functionality and layout working (which is why they are flat and not very pretty/interesting right now).
I've been heavily inspired by the Destiny UI in terms of having a controller-driven cursor system. With mouse-overs it helps keep things tidy on the screen by letting you hide some information that isn't needed until you move the cursor over it. I'll be using it for item/car info boxes and stuff eventually later on.
Probably my last car for the day. This one started out being modelled after a Gremlin but it was hard to make a chubby-looking Gremlin when it's defining feature is how long and flat it is... so I just sort of gave up after a while and here we are.
I've been really struggling in Blender today trying to get the right chubby/toy-like look of the vehicles. I'm quite happy with this little dump truck! It took me quite a while to get it right though. I'm having a lot of fun making these. Can't wait to get more of them into the game.
Working on some new vehicles today to take a break from website stuff and coding!
I was posting some screenshots on Twitter a while back about my work on the random track generation in the untitled car game and a few people asked me how I was doing it. It's nothing super fancy but I thought I'd finally write about what I did!
The car game has completely randomized tracks. Every time you load a race it creates a whole new layout based on some basic inputs.
My basic goals for the track generation were:
- Different maps every time
- Tracks must be a full loop (starting point and end point are the same)
- Intersections where the track crosses itself.
- Size control. I wanted to be able to say 'make a big map' or 'make a small map' etc.
- Adding new track parts to the generation should be easy
With all of this in mind I tried to come up with the simplest thing possible to accomplish this. My first idea (seen right) was to just make a bunch of randomly-shaped squares that connect at the corners... but I didn't like having each 'loop' be a boring box shape.
I went through a few other ideas that I ended up ditching before coming up with something that I was happy with and that fit all my criteria. It ended up being much simpler than some of my more complicated initial ideas.
The tracks right now are all built with a set of these basic shapes on the left. I have 4 corner pieces, 2 straight pieces, 4 starting lines (1 for each direction) and two intersections. I chose to keep each rotation of the same shape of tile separate so I could have more control over the placement of objects onto them that might block the camera if they are positioned oddly. By keeping them separated I can place tall buildings or trees on the far side of the track and not worry about them rotating in front of the camera. The game uses a fixed isometric/orthographic camera so this would have been an issue.
Every tile is a prefab in Unity and I use a tweaked tagging system I initially created for Moon Hunters to tag all of the pieces. The tags tell the generator what they are (tile), what shape they are (straight, curve, intersection), and what directions they connect to other tiles (up, down, left or right).
The way the taging system works, at runtime, when I need a specific piece I can grab a list of matching tiles by simply calling TagTool.GrabObjects("tile straight left right speedway") and it will return to me any tiles where those tags match. Then I just select a random one from the list and place it on the grid. (Note: The 'speedway' tag is there to say that it's for the speedway level. On a swamp level I would use 'swamp' instead to get different prefabs that match them levels theme).
That's great but how do you know where to put them?
So yeah, after ditching a few different generation ideas I ended up using something pretty simple. Using all the stuff above, what my generator basically does is builds a list of spots on a grid and lays down track as it goes.
I build a grid that has the width and height given and just choose a random spot on the map to start the track (Spot 1 on the left here). Then I begin a loop of the following steps:
- Find another random spot.
- Use A* pathfinding to make sure we can make it there.
- Temporarily add the new section of the track but store it in-case we need to remove it later.
- Make sure there is a legal pathfinding path from this new spot back to the starting position. I never add a new point unless it's possible to complete the track from this new point.
- If everything checks out, go back at step #1 until we've created the number of nodes we want. If anything has gone wrong, back up a step and then go directly back to the starting line.
Once we've created X number of nodes (given at the start) we find a route back to the starting position and finish the track.
As it builds the paths it also stores the type of tile it's using. So it tells the path that it's a straight, or a curve and gives which directions each piece has a connecting neighbour (up, down, left or right) so that later on it knows how to choose the correct tile prefab for each position.
The above method works great but the A* I wrote at first would never choose a path that looped back over itself (because it would mark parts of the track as 'unpassable') so I had to find a solution for intersections.
What I ended up doing was changing the A* so that it would cross over straight parts of the track (which I had already tagged as 'straight' for my prefab/tag system) as long as they were perpendicular to the direction of the new path and there was an empty space somewhere on the other side (it can cross several straight paths in a row if it's a legal path).
So then I ended up with nice looping paths with interesting shapes!
If ever the system tries to draw any path to the next node and it fails for any reason, it instead backs up one node and draws a path back to the starting line. So I always end up with a full loop and never a dead-end in a corner of the grid.
Once the whole track is built I have to find a good spot for the starting line. Since it's possible for Spot #1 to be a curve, all I do it move along the path I made until I find a straight, and then add the tag 'startingline' to it and also give it the direction the track is going so it knows which direction to face the cars. When the tiles are generated it grabs a starting line instead of the normal straight piece automatically.
So hopefully this was all clear enough to understand. At the basic level it's just drawing a line within a given area and making sure it always has a path back to the start to form a full loop. It stores a bunch of information in the form of some tags for each tile as it goes along and when it's ready, it uses the tags to grab random parts that match the tags.
This means I can make 'straight' pieces that have jumps, or have obstacles or any other variation I want and all I have to do is tag them properly and they will be added to the track generation automatically.
I had a lot of work left to do adding variations and themes and obstacles now! But the basics are all in and working quite well now.
If anyone actually got this far and has any questions feel free to tweet at me or leave a comment.