Showing posts with label c#. Show all posts
Showing posts with label c#. Show all posts

Sunday, September 30, 2018

Battlescape

Back in 2014 I started work on a real-time strategy game called Zyrtuul. I knew that it was too much work for a single person, but often I just want to work on what I love rather than focusing on what is feasible, so I went ahead anyway.

I made a lot of progress over the year, but eventually (and inevitably) I ran out of steam. RTS games are complex and a lot of work, so I chose to rather change course and focus on games with smaller scope that I could actually release.




Since then I have released a few games on iOS. But although I had fun with them (despite the torture of the iOS deployment process) the problem with games that are small in scope is that, put simply, I'm not really passionate about them. Often I ask myself, would I play this myself? And usually the answer is no. I'm into games with more complexity and depth, and those are the kinds of projects I'd like to work on. Those are the kinds of projects that challenge and excite me.





With the games market so over-saturated the chances of getting your game recognized are pretty low anyway, so I thought "well fuck it, I'm going to work on whatever the hell I please, it's just a hobby in my spare time anyway."

And so I resurrected Zyrtuul. Except this time I decided that I'd go all out and make it multiplayer.





Back in 2014 when I first started work on Zyrtuul I was still fairly new to Unity and C#, and the idea of RTS networking admittedly scared me off a bit. Fast forward to 2018 and I have a fair bit of experience with Unity and C#, and my way of doing things has shifted significantly (coding conventions, design patterns that work well with Unity's world-view etc).

And so... I decided to start 'from scratch' (create a new project) and just drag in / re-factor the useful bits of code. I also decided to expand the scope and go all out. I wanted to challenge myself -- multiplayer and the full shebang.

The new project's work-in-progress name is Battlescape. It's a squad-based multiplayer game focusing on co-operative gameplay. I've always loved games like Starcraft and Warhammer: 40k, and back in the day LAN battles of Starcraft were inspirational for me. However, they've become very niche and overly competitive over the years (for example, the only way to be competitive in Starcraft 2 is practically devote your life to the game). I miss RTS games. I feel that they have become a niche genre; almost abandoned.




So I'm thinking, why should they be? I love them. Other people used to love them. I honestly feel that the mutliplayer RTS genre does not need to be inaccessible or intimidating to average players.

My idea with Battlescape was to focus on the co-operative aspect of it. It's multiplayer RTS, but you're all on the same team working together to overcome increasingly difficult challenges. Team-work, camaraderie, low pressure and a focus on allowing you to easily choose to play with your friends as if it was an old-school LAN.





I've made some really good progress so far. I'm quite proud of my squad formation logic. You can change formations on the fly and the units handle it intelligently (I was tipsy when I wrote the code and had to do some fair bit of math-wangling with a fuzzy brain). The core logic of the game is in place. However, as with most pet projects of large scope, I ended up burning myself out a bit.




I'm still in love with this project, but I've decided to take a break and come back to it later with fresh eyes. Also, I have unfinished older projects which (as with this one) I've abandoned due to burn-out. They need to be re-visited. Check out my posts on Araxxis Squadron and Lyntheria for more info.




Wednesday, February 19, 2014

Loading Terrain Heightmap Data Via C# Script in Unity

For my real-time strategy game Zyrtuul I need to be able to load different landscapes at run-time. A fundamental part of this is loading terrain heightmap data from script. I implemented this last night. I noticed that many people have been asking how to do this online, but I did not see any complete solutions presented. It turned out to be significantly easier than anticipated. This implementation allows you to save your heightmap using any image format (I assume it is saved in Assets/Resources/Heightmaps). Simply attach this script to your terrain object and it will load up the specified heightmap automatically.



Thursday, November 7, 2013

Implementing Path-Finding in Zyrtuul

In this post I discuss my implementation of path-finding in the real-time strategy game I'm currently building (the working title for the game is Zyrtuul, though I might end up changing that).

A commonly used path-finding algorithm in game development is the A* algorithm (pronounced 'A star') which is an extension of the older well-known graph traversal algorithm called Dijkstra's Algorithm. I coded up a C++ implementation of various path-finding algorithms back in 2005 (as part of one of the demonstration applications that accompanied my CompSci master's degree), so I chose to re-use my old implementation of A* rather than re-inventing the wheel.

I started off coding the game as well as the game engine in C++ because, at the time, my main interest was in developing the underlying technology. But as it progressed I started wanting to focus on the actual game rather than the technology. Coding the engine and game simultaneously was simply taking too long (and I wasn't really learning anything new, having done so much engine work over the years already). So I decided to switch to the Unity engine for the game.


Unity doesn't support C++, instead you write scripts in C# or Javascript (edit: apparently Boo and their own language called UnityScript are also supported). I am therefore now coding in C# (simply because I have more experience using C# than the others).

Converting the code from C++ to C# was initially pretty straight-forward until I realized that C# does not provide a priority queue (a fundamental component of the path-finding algorithm) as part of its library. With my initial C++ implementation I was using the STL priority queue, but I now realized that I would have to find an implementation online or else write my own.

A priority queue is a data structure that keeps its elements sorted based on some user-specified criterion, in our case based on the path node cost / distance when conducting a path-finding query. In short, a priority queue is the most efficient way of performing path queries because of the fact that it automatically keeps itself sorted when you add or remove items.

It seems that the Microsoft C# team decided that a priority queue was too niche to be included in the .NET foundation library, so I was out of luck. Fortunately others had encountered this problem as well and so I was able to find a priority queue C# implementation online that, with some minor modification, suited my needs. Once the priority queue was done the rest of the graph traversal / path-finding code came together nicely. So I ended up getting a task that would ordinarily take a significant amount of time and effort done in about a day due to code re-use.



Path-finding solved the macro-navigation problem (navigation on a large scale), but micro-navigation was still a problem due to the fact that the pathing grid has limited resolution and also due to the fact that the grid is not static -- moving entities can invalidate previously valid routes. A vehicle could easily determine that to get from one side of the map to the other it needed to move around a lake or large obstacle that was blocking its way, but it still had issues on a smaller scale. For example, if vehicle A was told to find a path to some point and then vehicle B was instructed to move to a location that blocks this path, vehicle A would eventually encounter vehicle B and need to determine how to deal with it.

For this game I could get away with very simple collision detection and collision response based on bounding spheres and having vehicles 'pushed away' from one another when they are colliding. This partially solved the problem of vehicles coming into contact with one another (they would simply push one another out of the way), but was far from perfect as it could lead to 'jostling'. Also, it just made them look downright impolite. If two vehicles were headed directly toward one another, they would simply push head to head with neither able to get past. Alternatively, if you told many vehicles to move to a single location they would all mass together, jostling and pushing one another in an attempt to settle at that location.



One attempted solution was a "frustration factor"... when a vehicle was too close to another vehicle it had a frustration factor value that represented how 'frustrated' the vehicle was, with the idea being that it would eventually decide to simply find a new path to its destination it it became annoyed enough. This was simply a floating point value that increased over time when the vehicle was too close to another vehicle, and decreased over time when it wasn't. If a vehicle's frustration factor rose beyond a certain threshold it would request a new route to its current destination. Unfortunately I spent far too much time trying to get this to give the desired results and I found it to be too unpredictable. Eventually I decided that the moment a vehicle encounters another vehicle, one of the two vehicles must immediately find a new path. I arbitrarily decided that in the case of path blocking conditions the unit that was created first gets to keep its current path and the more recently created unit has to find a new path.

Quite a few other rules are also in place to handle various conditions and edge cases, but I think I've already written too much and so won't go discuss these here. The navigation behaviour of the individual units is fairly solid at this point, but not quite perfect (it's close though, better than some commercial RTS games I've seen). However, it will suffice for now -- I can hone it further later on, when polishing the game up.