Skip to content

Instantly share code, notes, and snippets.

@grofit
Last active June 13, 2022 08:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grofit/7347adc22a4319a7c3873cd6d8bb97cf to your computer and use it in GitHub Desktop.
Save grofit/7347adc22a4319a7c3873cd6d8bb97cf to your computer and use it in GitHub Desktop.
Indie Gaming Advice Thread Backup

This is a backup of a post made MANY years ago over at Indie Gamer Forum at request of others I have put it here for others to read.

If you have any questions related to this I dont really check that forum so head on over to my open source projects discord and ping me there Discord, with that out of the way everything else here is a lift from the forum post, enjoy.

FREE tools to assist in getting indie projects started

I was looking through but could not find much listed on this topic so wanted to condense some lessons learnt over the years and some good (and free) tools that can be used for an individual or a team to get the best start on a project and to help keep everything moving along smoothly.

So you have come up with a great indie game idea and you have done more than the 99% and have decided to go from the "thinking" phase to the "doing" phase, now rather than rushing in to some implementation based on some torrent of ideas from your mind, lets have a look at some of the areas that make up the indie game and how you can be best equipped to start an indie game project.

Managing the Design, Scope and Progress

It is great having a head full of ideas, but without quantifying them and how they all fit together it will be VERY tough for you to make real progress, and this is even more important if you are working with a team of people.

Generally a good idea for managing the project is to have some sort of central ideas hub, and its important to not just have ideas but information around those ideas, like how long you think it will take, who is working on it, what dependencies that has on other tasks etc. There are plenty of free (or paid) Agile (Agile is just a term for a specific type of project management) tools which help solve this problem, such as Trello, Asana, Teamcity, Jira. (I will just focus on Trello here as its a free hosted solution).

So imagine that you have started on your prototype and you have done some animation bits you have some basic AI and you are needing someone to come in and implement some sort of inventory system. How do you tell this person what you want? do you just give them a verbal description? write it all down in a word document for them? just tell them high level ideas and hope they get it right?

If you use a project board like the ones above it is very easy to just create a some small encapsulated tasks which explain to anyone on your project what you expect from it, and is also helps everyone know how far along a project is and if someone comes up with an idea everyone else can comment on it in one place and track it's progress.

Look at this picture:

image

How easy is it for everyone to know what's going on in the project? even if you are just a single developer you can at least plan out your project ahead of time, and then if you get stuck on something, go work on another task. It also helps you easily change your focus from the minor details (which you will become absorbed with when you are implementing) and look at the bigger picture.

This sort of approach has helped me on so many projects know what else needs to be done, how far along I am, prioritise functionality etc, and its benefits become exponentially better the more people who are involved as everyone knows what everyone else is doing and can see that if the guy doing pathfinding is being too slow it will delay the guy doing the defensive AI task etc. You will also pre-empt some major obstacles because you will have to think out roughly how you will solve each problem so rather than hitting roadblocks in an ad-hoc manner you can ask the questions early on so you have the answers ready for when you get to those bits.

Also it is worth noting some of the tools above (Teamcity, Jira) can hook into your source control so as you compete issues/tasks they will update the board automatically and tie in your commits.

Quantifying your tasks

So we have gotten over the first hurdle of actually creating the notion of tasks so our team can work in parallel, however one area which is often overlooked is the quantifying of tasks. As it is all well and good having a task called "Create Inventory System", but what does that inventory system need to do?

So here is where quantifying your tasks comes in handy, and will also force you to make hard decisions about your project without even having to waste time implementing it, which sounds harsh, but how many times have you or someone you know had a great idea, ploughed weeks/months into something with just a rough idea of what they want, without sitting down and thinking what will this game actually consist of?

So for me personally whenever I start a task I want to know:

  • What is it I am doing?
  • Why am I doing it?
  • How will I know if it's done?

So the "What is it?" can be simple or complex, if it ends up being complex it will show you that your task is probably too big and needs to become multiple smaller tasks. The "Why am I doing it?" should be pretty straight forward, what does this achieve? in the inventory system example it allows your player to hold items which is pretty important in most games. Then finally the "How will I know if it's done", which is what most people struggle with. As you will always have more ideas the more you work on something, but sooner or later you have to say its finished and move on to something else, so how do you measure that completion of the task, how will you know when you have done everything that is required?...

I am sure a lot of you will be thinking that I am over-thinking this problem, and that this is all a big waste of time, which may be correct if you are some game design/developer/audio/modelling savant however I will let you decide for yourself after you have read the rest of this waffle.

So here is an example of something which I have seen before as a task, which is poor-average:

Inventory System

Need to create an inventory GUI for the player to be able to equip items and trade their stuff.

Here are some concepts I knocked up showing some examples of how it should look.

<insert some bad pictures and screenshots of other games here>

Now that tells us at the bare minimum that we will need to have a GUI display of some kind, and the player needs to be able to equip items and trade items, but it doesn't really quantify the HOW part of our questions above, and only just about covers the WHY section.

So lets look at another example of how to lay this task out in a far better way using a well known pattern for requirements gathering known as BDD (Behavioural/Business Driven Development/Design gotta love the permutations of these acronyms).

Inventory System

As a player
I want to be able to store my items
So that I can trade them
And I can equip them

Given I have an equip-able helmet in my inventory
When I drag and drop the item into the head slot
Then I should no longer have the helmet in my inventory
And should have the helmet equipped

Now the above example is pretty succinct, we use a common set of patterns here known as "As a... I want... So that" which cover the what and why, then we use another pattern known as "Given, When, Then" to describe how we will measure success. Now in the example shown the 2 ways, I have had to make some up front decisions now because I am being FORCED to measure completion. So I have had to specify that I will be using drag and drop functionality to move items around, and that when an item is equipped it is no longer in the inventory. I have not even covered the trading aspect, nor have I described how items make their way into the inventory, how a user drops items, if they can be stacked, if they are icons or 3d models, and there is no information there discussed about the design of them.

This kinda shows that we often think about tasks as big blocks of unknown, we associate some keywords to it, like Inventory, Trade, Equipment, Use, Drop etc but we rarely think through how we want this to function. One other major point to touch upon here is that this "Inventory System" is probably not just a 1 man/skill job. The logical implementation of the handling of items and equipping of items would probably be a programming job, but how the GUI for the inventory looks and feels is more of a UI designers job. So if you have trouble working out what your Inventory should do and look like, maybe you don't have as clear an idea of what you want and may need to ask people of that discipline to help you out, as there is no harm splitting this into many smaller tasks like:

  • Create logic for picking up items
  • Create logic for dropping items
  • Create logic for trading an item
  • Create logic for equipping an item
  • Create design for inventory view
  • Create design for item style in inventory
  • Create design for trading window
  • Create design for equipment window

There are an awful lot of things which go into this one feature, and each one of those tasks would require quantifying so you know when you run your game each one of those use-cases will be working. Which may seem quite daunting at first, but would you rather spend months of your time churning out code with no clear guide on what you want and just going by gut feel (which also makes it difficult to collaborate) or would you rather spend a week or so making all the difficult decisions up front so you know before you start how much work there is to do, who can do what and when it will all be finished by?

Collaborating / Source Control

Now there are lots of ways for people to collaborate on a project, from as simple as just emailing files around, or sharing on a network. However most people these days tend to use source control systems. Now there are lots of different types of source control systems (GIT, Mecurial, SVN, CVS, Perforce etc etc) however unless you are setting up your own server for this it is usually easier to use online source control systems so you can access your code anywhere.

Now the main one which most people will have heard of is Github, which is great for collaboration, however a free account means that your repositories are public, so anyone can see or fork your source code. So you would have to pay to have a private repository. Now Bitbucket is another alternative which is fairly well known, and provides free git repositories but you can have private repositories for free, providing your project team is less than 5 people. You can also get the normal issue tracking/wiki etc which helps with project collaboration.

There is also a good app which uses bitbucket issues to display in an agile way, as described in the first post here (http://www.bitbucketcards.com/).

So assuming you are using source control already you are half way there, now you need to make best use of your VCS.

Here is a BY THE BOOK example of how to use GIT with projects: image

Whole article at: http://nvie.com/posts/a-successful-git-branching-model/

It is worth noting as well that this above model still applies for larger projects but a lot of people now do GitHubFlow which is a more succinct path to live but requires much more automated testing/deployment, but worth looking into.

Now thats great and I tend to adhere to it for large projects, but for smaller ones or one man projects it is recommended to at least follow the dev and feature branch strategy. This allows you to keep each feature isolated and if someone breaks their build, it wont effect you. This is easy with GIT as you can just make these branches locally so the server does not need to be aware of them, just merge back into the development branch once your task/feature is complete and everyone will always be up to date.

GIT is not that great with binary files (see git NFS), you need tools like perforce to make best use of versioning binary files, but unless you are a VERY large project, and hosting is free this isn't a major concent.

Where do you fit in the team?

So you have had your idea of what indie game you want to make and you are sure your is gonna be great.

So now you need a team (you can go it alone but sooner or later you will need some other people), and you need to think where you will sit in this team and where everyone else will sit.

So generally your skill set will fall into:

  • Programming
  • Audio
  • 2d Art
  • 3d Art
  • Game Designer

If your skill set does not fall into any of those parts then chances are you are what we like to call an "Ideas Guy". You can do 2 things at this junction, you can either go and attempt to pick up at least 1 of the skills on the list so you can actually bring something to the project (and I don't see Project Management as a required skill, it helps but it is not specifically needed), or you just accept you are an ideas guy and see if anyone will join your vague project in the hopes of some profit share at the end. Long story short just don't bother starting a project if you can not contribute to one of the above, as you will have people asking you what you wan't and if you are not ready to get involved in the meat and potato of the project it will fail and you will waste everyone's time.

Now assuming you are not an Ideas Guy and you have a skill, then its time to start trying to make some sort of starting point for your project before you get a team together. Do not fall into the trap of doing 0 precursory work and just hoping you can get a group together AND THEN start putting it together. Here are some ideas of what you can do depending on your skill set.

Programming

If you are a programmer then start by making a super simple prototype, so for example if you are wanting to make a space game, make a simple prototype showing how your combat works and how the gameplay feels. It may take you a couple of weeks but at this point you will realise if this is still something you want to work on, if so then show off your prototype with your boxes flying around shooting other boxes and see who wants in.

Audio

As someone related to audio it is not as easy to represent your game with music alone, however if you were to make some music setting the scene and provide a few small bits of gameplay information to go with it and you should be good. This way people will know what sort of theme your game has and can see you have already spent some time thinking about it and putting some pieces together.

2d Art

This is a very good position to be in, as you can create a lot concept art which will portray the sort of art style, the themes and the sort of world the players would be experiencing. Ideally put a few blurbs down to go with it, but generally this will put you in a good position to start recruiting a team as you have something to inspire the rest of the team.

3d Art

You can make some 3d models for your game and show off some animations of the characters, again put a bit of a blurb down to go with them and you are good to go.

Game Designer

A great position to have when starting a project, just do as you would normally do, create a set of documents detailing the functionality, the overall aspects of the game for each member so everyone will know what they will need to do and what the end sort of project will look like. As a game designer you may not be able to create any of the actual content, but you can at least document how it all fits together, and if you can't then maybe the project wont work.

Ultimately you can see the theme here is use your skill to make something to turn your project from just an idea to an implementation, if you are relying upon everyone else to take your idea and run with it, then you are not needed, ideas are easy to have. It is the implementation which is the tough part so keep that in mind when you have your next idea, and ask yourself if YOU are ready to take the projects first steps into implementation.

TESTING YOUR STUFF!

Now this is often overlooked by most people, as testing is something seen as being sooooo far down the road that people wont think about it until the last moment. Now I will pretty much be speaking to the devs from this point on as we discuss AUTOMATED TESTS!!?! (BY GOSH!) and what they can do for you!

So lets take a scenario, you are making a space game, and you have lots of different guns with lots of different effects, some plasma some physical, laser, ion etc etc, and each of these gun types needs to react differently to different types of armour, such as physical, shields, reflective coatings, lead paint etc etc. So you have started doing your code and you have come to the point where you are flying around shooting things and you notice that your ion cannon is doing 0 damage to a ship... so you go to you re-start, faff around setting up your debugger to run, equip your ship with the same items and fly off to find the closest other ship to shoot. You hit it and it does 0 damage so you trace through the stack working out at which point the calculation went wrong, then you realise you made a typo and instead of doing 0.5f you did 0.

Not the end of the world, but this sort of thing could be caught earlier on in your development cycle, before you even run your game. Also writing your code in a way which lets it be tested makes your code better, you instantly write more separated and easier to maintain code and you can also then benefit from dependency injection techniques if you write your objects in such a way that they can be mocked. (If you don't use Dependency Injection you should look into it, IoC is best, ServiceLocator is bare minimum)

So how do we go about doing this? As depending on your engine you may approach this problem different ways, so in Unity you may have written this bullet firing logic as a script and attached it to a weapon so it is a MonoBehaviour (this makes it almost impossible to unit test properly and we will get on to that later), or if you have your own engine it may be some fancy pants private method put into your ship object or something, or you may have gone for something all together different.

However if we look at the bare bones of what we are trying to achieve here, we have a Weapon which has an ammo type, a damage amount then we have some armour which has a defence type and an armour amount (being very simple here). So rather than making these parts of another class lets model these as they should be done in code (I will use C# to demo).

public class Weapon
{
	byte DamageType { get; set; }
	float Damage {get; set;}
}

public class Armour
{
	byte DefenseType { get; set; }
	float Armour { get; set; }
}

So those seem legit, they do the bare minimum and have no knowledge of a ship, space or have any logic applied... now some of you will rush in and add a method to weapon or armour to handle the interaction between the 2, but really it should be another entity entirely that handles the damage between the 2, as these are just models of the LOGICAL REPRESENTATION OF A GAME ENTITY. Those letters are in caps because they are very important. If you are going to write good code you should split the LOGICAL representation of your entities from their PHYSICAL/RENDERED representations, this way you do not even need to render things to test your game, and if you dont need to render things you dont really need to run your game either... you could do it all from a console app OR A UNIT TEST RUNNER!

So this is NUnit's GUI test runner, it has a console test runner (or if you are super cool you will own Resharper for Visual Studio or Rider which is far better). image

So with this you can write some isolated tests, to prove that what you THINK happens in the logic, will actually happen, and you can run these tests every time you re-build your code, you check in your source control, or if you are super swanky you may have a build server and pipeline which you can plug it into.

Anyway so lets get on with a very simple implementation of a component to handle the interaction between weapon and armour so we can do a dummy test:

public class DamageCalculator : IDamageCalculator // You may have different implementations
{
	float CalculateDamage(Weapon weapon, Armour armour)
	{ return weapon.Damage - armour.Armour; }
}

Now that doesn't take into account the type of armour or damage, but if you imagine your implementation would have that stuff in. You can clearly see here that if we ignore the rendered stuff at the heart of the interaction where one entity attacks another, there will be resulting damage which can be applied to the victim, or could be passed over to some other entity to handle to check for shield reduction and stuff. However the key is that this is isolated logic, it is not tied to some mono behaviour, it is not tied to some inheritance chain, it is something very simple that encapsulates a single responsibility.

So how do we test this?

[TestFixture]
public class DamageCalculatorTests
{
	[Test]
	public void should_correctly_calculate_basic_weapon_damage()
	{
		var weapon = new Weapon { Damage = 10 };
		var armour = new Armour { Armour = 5 };
		var damageCalculator = new DamageCalculator();
		
		var expectedResult = 5;
		var result = damageCalculator.CalculateDamage(weapon, armour);
		Assert.That(result, Is.EqualTo(expectedResult));
		// This will pass
	}
	
	[Test]
	public void should_correctly_calculate_ion_damage_vs_shield_defense()
	{
		var weapon = new Weapon { DamageType = 2, Damage = 5.5f };
		var armour = new Armour { ArmourType = 3, Armour = 2 };
		var damageCalculator = new DamageCalculator();
		
		var expectedResult = 1.5f; // Lets pretend our game design document said that shields are x2 defense against ion damage (5.5f - (2*2))
		var result = damageCalculator.CalculateDamage(weapon, armour);
		// This will fail as the actual result with our current implementation is gonna be 3.5f
	}
}

So this above test fixture (what NUnit calls a class of testable methods) contains 2 tests, one which passes and one which fails. If you run this through the test runner (go google how) then you would be able to see without even running your game that this logic is not 100% right, and whats better you can then refactor your logic to make it pass the second test. This can be run as often as you like, so if you get some new guy on the team who decides to go re-write the weapon logic, does it still adhere to the game design requirements, and this is where those requirements mentioned earlier on really come into play, as if you have requirements like:

Implement Ion Damage Logic

As a designer
I want to have ion type weapons
So that I am stronger against physical armour
And weaker against shield armour

Given I have a weapon which does 5.5 ion damage
And the opponent has shield type armour of 2
When I attack
Then I should do 1.5 damage

Ok maybe you dont need to be explicit with the numbers and I am not sure if Ion is meant to have the above properties... but if you were to write a task like the above you can easily see if the developer has succeeded in doing what you wanted. So that new guy who has re-written all your logic may have buggered up your Plasma type damage but without a suite of unit tests to prove that this stuff works you wont know until you manually play the game and find it out. So this can REALLY SAVE TIME in the long run.

This doesn't mean you don't need testers, you still need them but they would do more exploratory testing to make sure the game functions and feels right, not having to go off shooting every type of weapon against every kind of ship every time a new release is made (regression testing).

So save yourself time and resources, and design your code well from the get go and separate your LOGIC from your PHYSICAL entities, I wont go over mocking here as I would need to make a contrived example with a player, but this is enough to get you started down that road. If you were to do this in unity you can have all your logic in another project and just put your logic dlls into your unity project and add the logical representations to your physical representations at runtime, so your monobehaviour now contains a Weapon class as a property, not as a hardcoded method within itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment