Several months ago I attended a job interview where I was told that I didn’t have a great understanding of how to get stuff done in code and that I was relying to heavily on the software I was using. Since that time I’ve spent my disposable energy learning about everything I’d missed in Computer Science and everything I’d not fully appreciated at the time.
This revision reminded me of what I love about coding, and that’s the fact that it isn’t really coding, it’s problem solving in which you also learn Greek. For those who maybe don’t understand this or like myself aren’t fully aware of the process, any form of coding should go as such
- Write down the logical steps of what needs to happen
- Highlight what sections are too high-level
- Write a more detailed break down of the step until it isn’t high-level anymore
This very crude layout gives you the wonders of an algorithm in the way of psuedocode (high level language, not a programming language). From here each step is translated into the actual code to make the program you’re coding.
I’d like to use this process to help break down something I’ve only recently appreciated with my new found understanding of ADTs (Abstract Data Types) and OOD (Object Oriented Design). I’m going to be tackling in this article the idea of a combo system for a game I’m making. Let’s first start by breaking down the options for a player to take which then dictates their actions.
A player can perform the following combos: Swing the Hammer Throw the Hammer Swing, then Throw the Hammer Swing, then Swing the Hammer Swing, Swing, then Slam the Hammer
This is pretty good, quite simple interaction for a combo system. It effectively breaks down into X, Y, XY, XX, XXX as the options for key presses. So the user can perform two different 1-key actions, two different 2-key actions, and only one 3-key actions The issue is the fact that the user has options in this combo system, if it was the same action then we could just count how many times a button was pressed to a maximum count of 3 until the animation of the player had finished. This would be quite elegant for us to code simply put:
If the user presses attack and they're not at max attack combo add one to the combo
or in code terms
if(Input.KeyUp(KeyCode(E) && comboCount != MAXCOMBO) comboCount++
So this states if E is pressed and they’re not as the max number of key presses that the combo system allows for (in our case 3), then add one onto the combo count. Then it’s simply a matter of running through the animation states providing the condition of comboCount is high enough.
This will not do for our version! We need to be able to know what type of attack was made and what type of attack is going to occur next, in other words we need to store these. There are always plenty of ways around a situation, but given my appreciation for ADTs we’re going to use what’s called a “Queue” in our solution. This just stores data and we look at it in the order that it was added. So right now we have a pretty good idea of what we need to do.
Is the first press a Swing or a Throw? If Throw then end the combo system here If Swing, then create a small Queue to store following attacks If this animation hasn't ended & another attack is entered, queue it Check front of queue and play animation corresponding with attack value 'dequeue' front of queue
This works quite well and isn’t a million miles from a final solution that would work, we’d simply want to check that if it’s a throw to then dequeue all following items as that’s the end of a combo chain, and the same for if it’s the slam animation.
This might seem quite excessive if all we’re going to do is simply queue an animation attack or two, we could just have a value and set it to be 0, 1 or 2; 0 would signify no extra attack and to enter an idle state, 1 would be a normal swing which means we’re either waiting on a slam or to go idle, and 2 would be a throw which would end a combo anyway. We could more than likely get this to work, after all there’s never any one answer for one problem, however should we want to alter or branch out this combo system then it’s at least robust enough to survive that expansion.
As a for-instance, we could include heavy and light attacks, we could allow for fist fighting when the hammer has been thrown, we could allow for charged attacked mid-combo. There’s no real end to what you could do providing it makes sense, players are able to remember the options available to them, and that there’s a meaningful distinction between said options.
N.B. After writing this and going away to actually code the functionality, some of the code did end up changing as my perception of the problem wasn't fully understood - this will ultimately happen at some point, there's no getting around it or avoiding it. What's useful though is that the core flow of the program was recorded in this article and I've been able to just tweak the outside problems that were being caused. For those who find this challenge an interesting one, I'd neglected to think about how to reset the animation state within Unity (my tool of choice). This means an animation will either continue to loop or if you try to reset within something like an Update() function then you won't give your players time to build a combo queue. There are several things that may help to look at if you're in a similar position to me - Blend Trees & Time.deltatime.