Thursday, 3 November 2016

Short Passing

Tweaked user controlled short passing now feels nice and crisp. Compare with short-passing-demo to see the improvements in passes connecting with the receiver. A receive state helps the AI connect with the pass, and the input switching is tweaked so the receiver doesn't grab input too soon and run away in the opposite direction.

Some A.I. controlled dribbling and short passing.

Wednesday, 2 November 2016

Player Search

Added functionality to search for players based on name, nationality, playing skills etc.

Saturday, 24 September 2016

Dribbling Speed

Player's running speed slows down when they are dribbling with the ball. Tap to knock the ball forward and gain a little speed to get away from pursuing defenders, but lose a little ball control!

Tuesday, 30 August 2016

Short Passing Demo

Assisted pass by tapping fire. Indicator turns green when there is a possible pass recipient.

and without the debug indicator:

Sunday, 8 May 2016

Sunday, 1 May 2016

Detecting Danger

With hit detection, triangle turns red when dribbling player detects an obstacle to avoid.

Saturday, 30 April 2016

Some Vector Math

The problem is to allow the player to work out if if there is a dangerous obstacle (an opposing player) in his path whilst dribbling. This is similar to a "field of view" but just re-sized to what the player considers "too close for comfort." So when an opposing player enters the danger area, the dribbler will try to change direction or get rid of the ball.

Here's the vid:

Teaching myself vector math from the beginning again, there is probably a more elegant way to do this. Anyway, here's what my brain came up with.

Given the position of the player p, his normalized velocity v, an angle specifying how wide the field of view should be and a length specifying the size, we can calculate a triangular field of vision (three points, p1, p2, p3) like this:

p1 = p
p2 = v.rotate(angle/2)  x length
p3 = v.rotate(-angle/2) x length

With different parameters, this can also be used to select possible pass receivers etc.

Example in code:

// calculate the angled vectors
Vector3 side1 = position + velocity.rotated(-25, 0, 0).normalised() * 200;
Vector3 side2 = position + velocity.rotated( 25, 0, 0).normalised() * 200;

// p1 is just the position of the player
p1.x = position.x;
p1.y = position.y;

// p2 is end point of the first side
p2.x = side1.x;
p2.y = side1.y;

// p3 is the end point of the second side
p3.x = side2.x;
p3.y = side2.y;

For the uber curious, here's the rotated() function:

// ----------------------------------------------------
//  rotated
// ----------------------------------------------------
Vector3 Vector3::rotated(double a, double x_origin, double y_origin) {

a = RADIANS(a);

Vector3 rotated = *this;

rotated.x -= x_origin;
rotated.y -= y_origin;

double nx = cos(a) * rotated.x - sin(a) * rotated.y;
double ny = sin(a) * rotated.x + cos(a) * rotated.y;

rotated.x = nx;
rotated.y = ny;

rotated.x += x_origin;
rotated.y += y_origin;

return rotated;

Wednesday, 27 April 2016

An Idea

Not very realistic, but fun. Player transfers to be done with an in-game browser on an Ebay type site.

Monday, 25 April 2016


Check out the goal at 1:26 (change youtube speed setting to 2x for actual speed)

Tuesday, 12 April 2016

Handy New Feature

Holding Player 1 Start + Left on the stick brings up the IP address for a few seconds.

Saturday, 2 April 2016

Another Pressing Example

Of course, if the dribbler manages to change direction, then pressing players would recalculate their interception paths, so it might appear in the static screenshot that a simple turn by the dribbler would easily evade the pressers, but as soon as he does so, the pressing targets would also change to intercept his new run.

We can also tweak the values for how far ahead of the dribbler the pressers will project. Again, the static screenshot may make it seem like they are planning a path way too advanced of the ball, but in reality the dribbler is moving quite fast and will converge with the nearest interception circle in only a second or so.

[click to enlarge]

What we might want to do for less aggressive pressing players, is to extend a path from the initial calculated intercept point to the middle of the goal, and set the new target a percentage along this new line.  this would result in a kind of pressing that favors pushing the dribbler into the flanks whilst protecting the goal area.

Pressing Diagram

Just an explanation of what's going on.

More Pressing

Here is an example (with slow moving players for clarity) to show how a team with high pressing might work. This case shows a team that tries to press with three players at all times (the pressing is not initiated until a blue team player starts dribbling).

Pressing players are highlighted with a blue spot, their "intelligent" interception target is shown by a red circle.

The intercept algorithm has the nice side effect that different pressing players seem to work together and don't all just head for the ball - they head for where they think the ball will be when they get there - therefore you can see the red target circles kind of "covering" for each other.

For testing, the attacking player has been given perfect dribbling, and the pressing players don't tackle.

Monday, 28 March 2016

Intercept with Diagnostics

Just easier to see - the white circle indicates the calculated interception destination for the pressing player.

The interception point depends on the distance from the presser to the ball, and the direction and speed of the ball.

Sunday, 27 March 2016


When defending, if a player transitioned to the "press" state, he would initialize his "seek" behavior which directed him to run to the ball.

The problem with this was, since the ball is continuously moving, the pressing player invariable ended up arriving a fraction too late to have any impact, and ended up chasing the ball from behind until he was relieved of his pressing duties.

The solution is to introduce a new A.I. behavior - "intercept" - which makes a guess at where the ball is going to be, and heads the player there instead.

Here you can see the defenders "connecting" with their intercept target nearly every time.

Friday, 25 March 2016

Close Control

Just a look under the hood.

When the ball flashes red, that means the player can change direction and successfully keep the ball. Two skills will determine the behavior - dribbling and close-control.

A player can do close control (change direction) when the ball is close enough to him. Better dribblers keep the ball closer, so can change direction easier. This dribbling aspect is shown in the vids, first an average dribbler, then an expert dribbler. You can see how timing comes into it to change direction at the right moment.

The close-control skill is not demonstrated, close control is 100% sure fire for now. That means, if the ball is in control range, the close control will always be successful. In future the success rate will depend on the close-control skill rating.

An average Dribbler:

A great Dribbler:

Wednesday, 23 March 2016

Retro Consoles

Megadrive/Mega CD/32X, Super Nintendo, Saturn, Dreamcast, Nintendo 64, Gamecube and Amiga in one. No emulators!

Monday, 21 March 2016

Gimp My Ride

Here's some amateur gimping of a section for a Mortal Kombat Bezel. Using only the smudge tool, you get a pretty nice result!

Monday, 14 March 2016

Mario (Super Nintendo) and SWOS (Amiga)!

LED's temporarily switched off until we can isolate the bezel from the screen to eliminate glare.

Of course, only when we own the originals... :D

The Arcade Rig

Amiga 600 Setup

Boot Sequence

Here's the new boot sequence for anyone who's interested. Much faster since the update to 64bit Mint 17.3! Next we'll remove the diagnostic output.

Saturday, 12 March 2016

Friday, 11 March 2016

Multi Platform Launcher

So the arcade machine needed a little maintenance. Whilst doing that, I got the bug for making it a multi platform launcher.

Emulators for other platforms are integrated seamlessly with the launcher. Notice the change in background to signify platform. Backgrounds can be customized for each platform.

Tuesday, 8 March 2016

Tackling, a Rethink

On reflection, one of the things that made sensi so simple and fluid was the tackling. Not the slide tackle, but tackling without sliding.

Basically, you ran into the attacker who had the ball and just changed direction when you thought you were close enough. Hopefully you'd come out with the ball. No real concept of a "tackle" mechanic.

As an insight to how the "clash" worked, you could see the cpu "cheat" if you dibbled straight and let him catch you from behind. He'd know the precise time to reverse his direction and come away with the ball.

But, in another twist of fate for sensi play-ability, the user controlled player could also take advantage of this "cheat." Due to the controller a.i. which took into account the direction you are pushing the joystick, you could clock the non-controlled player in your team who is going after the man with the ball, then hold the joystick in the opposite direction. This meant:

a) you wouldn't be switched to control the perusing player until:
b) he reached the appropriate point where he could steal the ball, and since you were already holding the joystick in the opposite direction (preferably away from your goal!), your player would come away with the ball.

We will do something similar, though not identical, in Senseless.

Since we have a hybrid dribbling system (Kick Off + Sensi), the rules for tackling are as follows:

1. When attacking player and tackler are running in a straight line, the core game mechanics will run uninhibited. So in this hypothetical, if the tackler is running faster, he will take over control of the ball by dribbling (knocking it forward) as normal. This could result, for example, in putting the attacker off his timing in changing direction at the right moment to keep control.

2. As long as the attacking player isn't doing some close control (changing direction with the ball under control), then the close control of the tackler (he times it right to change direction when the ball is close enough) will win out.

3. If the attacking player changes direction with the ball under control (close control) in anticipation of a tackle, and the tackler also times his change of direction correctly, then the winner of the clash will be determined by the match engine through comparing the two players dribbling and tackling attributes.

You can see it here. You have to look closely, because the defending players don't have any attacking a.i. programmed, so after the tackle, they are pretty lost. But you can see them pressing the ball and attempting the tackle, sometimes successfully, sometimes not.

Sunday, 6 March 2016

Fix, Kinda

Not perfect, but now it's the closest goal-side player who presses...

The Futile Chase

If you watch some old Sensible Soccer vids, you'll notice that a defending player who is not goal side will chase the attacking player around in vain, never catching up with him.

Now I know why...

Game Design - Tackling

So, in implementing the defending team tactics, we encounter the player tackle state. But what is a tackle?

I mean, we know abstractly what a tackle in football is, but the action must have a consequential mechanical reality in the game engine.

There are two kinds of tackle: the slide tackle and the standing tackle.

The mechanical reality of the slide tackle is pretty straight forward. The player launches towards the ball, and if his feet touch it, he knocks it forward in the same direction, thus dispossessing the attacking player. Players with a better rating for tackling will have a longer and more accurate "lunge."

But what about the standing tackle? What does it mean in the game to "tackle" in this way?

The existing game mechanics of dribbling/controlling have the defending player take over ownership of the ball when it is within his control range. So in practice, the defending player just has to run into the ball to do a "tackle." Simple.

The additional layer is the player attributes. For example, a player good at tackling vs a player bad at dribbling will result in the defending player winning the "struggle for control of the ball" almost every time.

One final quirk not seen in Sensi, is that we will implement deflections. So if an attacking player simply dribbles into the path of an opposition player, he can not run straight through him - it will result in the ball deflecting off the defending player. This also applies to the ball in open play - if it is traveling too fast to control it will deflect off players in its path.

The above considerations are designed to make your tactical instruction actually matter in the game engine.

So, the upshot of all that for the state machine system is -

The default defend state remains the same: Cover. In this state the player merely tries to get to the sector dictated by the tactic.

Depending on the team tactical instructions, the player may transition from the cover state to the press state. It is only within the press state that the player has the possibility to transition to a tackle state.

Saturday, 5 March 2016

Zen-like Thought For the Day

Kick Off was a game for gaming fans who quite like football. Sensible was a game for football fans who quite like gaming.

Defending : Cover

Pretty happy with this. The existing architecture was able to handle the new A.I. requirements quite nicely.

We only need to modify the "Cover" behavior to accept the positioning "attitude" as a parameter. Then, when calculating the target position, we simply use the grid tool to shift the sector up or down rows in proportion to the attitude value.

So here's an example of the defending teams "covering" positions with two different attitudes. One to sit back more and one to press higher up.

Here the defensive line drops off and sits deep, closer to their own goal.

Here the defensive line press higher up the pitch.

Tactics: Defending

[read this first]

Defending Tactics

A team is deemed to be "defending" simply when one of its players is not in possession of the ball, and until one of its players gains possession.

The configurable defending tactics are:


This refers to the moment the ball changes hands. I.E. the team was attacking, but has just lost the ball. The degrees are:

N0: Ultra defensive, whole team immediately turn the other way and get behind the ball.
N1: Defensive. Everybody except forwards tries to get behind the ball.
N2: Normal. This is a neutral attitude, just go to positions as normal.
N3: Risky. Linger in forward positions in anticipation of the next ball turnover.
N4: Kevin Keegan. Just stay up-field without regard for chasing back.


As described in the example above, repeated here for completeness:

N0: Stand off the player in possession and focus on covering your own position on the pitch. Only attempt to retrieve the ball if you are your teams closest player to the ball, AND the ball is in your zone.
N1:  Stick to your zone, but always press the ball if you are the closest to the ball.
N2: Press the ball if it is in your half, and you are one of the three nearest players to the ball.
N3: Press all over the pitch, if you are one of the three nearest players.
N4: Always press if the ball is anywhere near to your zone.


N0: Light. Stand off. Never dive in. Avoid tackling almost always.
N1: Almost never employ the slide tackle.
N2: Balance between normal tackling (stealing the ball) and slide tackling.
N3: Favor the slide tackle whenever available.
N4: Slide with no fear of yellow or red cards!


N0: Paranoid. Stay a few sectors deeper than the standard positioning config.
N1: Deep. Stay one or 2 sectors deeper than usual.
N2: Normal. Stay in configured sectors.
N3: High. Push up one or 2 sectors
N4: Adventurous: Push up as high as possible.


This indicates the attitudes when the team regains possession.

N0: Just clear the ball.
N1: Clear the ball if under any pressure at all.
N2: Balance between safety and counter attack.
N3: Try to keep the ball whenever possible.
N4: Hold on to the ball at all costs, risking losing it in dangerous positions.

A.I. Design

General Overview

Degrees of precision in creating tactics will be limited to five discrete options on a sliding scale:

Low, Medium-Low, Medium, Medium-High, High.

Think of a slider bar widget the user can drag from low to high. Different descriptors will be used for different tactical aspects, but the meaning remains the same. For example:


Low: Stand off the player in possession and focus on covering your own position on the pitch. Only attempt to retrieve the ball if you are your teams closest player to the ball, AND the ball is in your zone.

Medium-Low:  Stick to your zone, but always press the ball if you are the closest to the ball.

Medium: Press the ball if it is in your half, and you are one of the three nearest players to the ball.

Medium-High: Press all over the pitch, if you are one of the three nearest players.

High: Always press if the ball is anywhere near to your zone.


Low: Do not release the ball until a suitable short pass candidate is found. Do not clear the ball, even when under pressure.

Medium-Low:  Release the ball only as a last result if no short pass candidate appears. Clear the ball if under pressure.

Medium: Release the ball to the best candidate, short or long. Clear the ball if under pressure.

Medium-High: Look for long pass whenever possible. Pass short only as a last resort.

High: Get rid!! (just hoof it up the pitch at first opportunity)

For the sake of brevity, these five notches will be referred to as N0 - N4.

Tactical aspects are only configurable at the team level. For individual player instructions, the concept of a "role" will be used. At most, the team instructions may be configurable separately for defenders, midfielders and attackers. For example:

Sweeper: This tactical role will cause the player to remain very deep, always the last defender for his team. He will never press the ball unless an attacker is bearing down on him and he is the last man. When he gets the ball, his actions will depend on the team instructions.

Poacher: Will never stray far from his zone. will stay as close to the opponents 6 yard box as possible. Will shoot at every opportunity. Will not chase back to defend.

Friday, 4 March 2016


So the match engine runs continuously without having to manually reset the ball position. All breaks in play are handled and match starts again without interference.

Going forward, and taking my cue from an awesome presentation given at the GDC, I've decided to give Dino Dini's approach a go and concentrate on getting the game working *without* the user controls.

So the A.I.  should be able to play a good game of football on its own, then we add the user to the mix.

Credit Where It's Due

If you already know what a kernel is, move right along, nothing to see here :)


If you call yourself a "Linux user," what do you mean when you say that you "use Linux?"

What is Linux anyway?

You probably already know that it has nothing to do with the apps you are running to get things done. Like Firefox, Chrome, Gimp or whatever. They are available on other "operating systems" too, right? Right.

So what about the more basic stuff like your desktop, the menu you use to start apps, the task bar and all those windows you bring up to configure your settings, network, display and such? Nope, still nothing to do with Linux.

Maybe you are a l33t h4x0r and do stuff in the terminal (you know simple stuff like changing directory and listing the files), but you are still not actually "using Linux" directly. These are all programs (read "apps") written by Richard Stallman and his friends at the GNU project. They are part of GNU, not Linux.

Yup, when you type "ls" to simply list the files, this is not some magical functionality of Linux. It is a genuine "app" written by the folks at GNU and just given the name "ls."  No different from your fancy "app" to browse the net or read e-mail. Really, it even has a main() and everything... :p

All of these apps, PLUS the Linux app, make up the "GNU" operating system that you are using.

So what is Linux, what does it actually do, and when are you actually using it? As simply as I know how to describe it, Linux is the "app" that lets other apps do stuff. Basically, it cares about the hardware so other apps don't have to. For example, what is a "file" and how do you open one? You might have your stuff stored on a CD (optical technology) for example, which is completely different from a hard disk (magnetic technology). Yet you can still open "files" on each of them. This is what Linux does.

From a programmers point of view, Linux provides a function to "open" a file and deliver it to us in a specific format. It is Linux which does all the hard work of getting the data off the actual hardware; we don't care if it is an optical device or a magnetic device, or if the data is stored sequentially or whatever. Linux handles all that for us.

It even handles interactions with your processor, deciding which apps will get access to the next "cycle" of instructions and allocating them intelligently to give you the illusion of running several programs simultaneously.

Anyway, Linux (written by Linus Torvalds) is just one component (granted, a very important one) out of thousands that make up the system you are running on your computer when you claim to be a "Linux user." For most of the others we have to thank Richard Stallman and GNU.

On a side note, the GNU project does indeed have their own kernel in development. It's called "The Hurd" and for several technical reasons isn't considered a viable alternative to Linux for every day use yet.

As an example to illustrate the point, the Apple Mac runs the Mac OS operating system, which uses the XNU kernel. This is directly analogous with saying that you run the GNU operating system which uses the Linux kernel.

But nobody says they are running XNU, or they are an "XNU user."

This is why I think we should endeavor to respect Stallman's wishes and try to remember to refer to it as "GNU/Linux". And if you have never heard of Stallman or GNU, please take a look, and learn about who they are, where they came from and what they are doing:

Wednesday, 2 March 2016

Camera Tweak

And here is is softened up a bit.

Camera Tricks

Instead of just centering on the ball, the camera favors the attacking team so that the goal comes into view quicker. Needs to be softened out but not bad for a first try.

Tuesday, 1 March 2016


Just some physical interactions with the new goal graphic. Code-wise, the physics system is such a basic approximation, I only had to change one number to make it look OK with the new graphic; the depth of the goal.

Sunday, 28 February 2016

User Controlled

Here's the first hash up of the user controlled throw in state. It's not perfect, but it keeps the match moving along.

Saturday, 27 February 2016

Post Physics

Just playing around, I'm really happy with the quick and dirty approximations for net and, especially, post physics.

Some really nice goals (and indeed near misses) possible. Feels nice!

Friday, 26 February 2016


Some coding conventions I prefer.

White Space

Let indentation improve readability whenever possible. Only use blank lines between two lines of equal indentation. This gets more lines on the screen at once to improve overview of current code segment.

So this:
 void Player::Update(double _dt){  
   // step the current state (states do all the work)  
   // helper to update the position  
   // check for state change  
   if (current_state->StateOver()) {  

 void Player::Update(double _dt){  
   // step the current state (states do all the work)  
   // helper to update the position  
   // check for state change  
   if (current_state->StateOver()) {  

Bracket Style

I used to always prefer this style for readability:
 void Class::Method()  
   // do stuff  

But after getting used to it, it's really no more readable than:
 void Class::Method(){  
   // do stuff  

Prefer this style for the same reason as above - more lines fit in the same vertical space, giving a better overview of the current code segment.

Also, always use brackets, even when optional! For example, don't do this:

It just makes it a pain when the code develops and you want to change the loop to contain more than one line. It is especially annoying in nested blocks.

Parameter Names

This is the only time I ever use an underscore prefix. It helps not only to avoid member variable name clashes, but makes it clearer within the method when you are working with a passed in parameter, and when you are working with a member.

Method Names

For public methods, use camel case.

For private functions, use all lower case with underscore between words.

I think this differentiates nicely between the actual interface of the class, and private functional/procedural-style helpers to encapsulate private functionality.

It's kind of like, when you talk in public you try to speak well with proper grammar (camel case for the public interface: it kind of looks official and formal) but when you're chatting in private, it's less formal (lower case, underscore style). That's how my brain sees it, at least!


Although useless comments can help make the code look prettier, they just add unnecessary vertical bulk. High level languages document themselves with good class and method names. Let the code speak for itself wherever possible.

For example, none of the comments in this snippet are necessary, they should be removed!
 void Player::SetPosition(int _x, int _y){  
   // set the players x position  
   position.x = _x;  
   // set the player y position  
   position.y = _y;  
   // update the sprite position  
   sprite->SetPosition(position.x - sprite->GetWidth() / 2, position.y - sprite->GetHeight());  

Method Documentation

Use Doxygen documentation in header files. In source files I like the following comment block, I think it helps segregate functions and makes files with lots of methods easier on the eye. In this case, I think it's worth the sacrifice of vertical space. Though, as with all of these conventions, I'm open to persuasion!
 // --------------------------------------------------  
 // SetPosition  
 // --------------------------------------------------  
 void Player::SetPosition(int _x, int _y){  
   position.x = _x;  
   position.y = _y;  
   sprite->SetPosition(position.x - sprite->getWidth() / 2, position.y - sprite->getHeight());  
 // --------------------------------------------------  
 // AttachInput  
 // --------------------------------------------------  
 void Player::AttachInput(GameLib::Input::InputDevice* _input){  
   input = _input;  
 // --------------------------------------------------  
 // DetatchInput  
 // --------------------------------------------------  
 void Player::DetatchInput(void){  
   input = NULL;  

Tabs vs Spaces 

Prompted by a reply on google plus, my view on this controversial one is that you should use tabs for indentation. That's what a tab is for, after all. Plus, it allows people to customize thier indentation size when reading your code, without modifying the file.


Sometimes making things easy makes things harder.

Since we just have a single basic coordinate system for the whole game, and a grid system to tell the player where to go on the pitch, the game doesn't have any local/world transformations built in.

This means, if we don't want to manually configure each position twice (once for facing north and once for facing south), and we don't want to calculate a rotated point in game, each frame for each player (we don't!), then the tactics creator needs some fancy goings on to export the target sectors for both orientations.

It's more of a brainphuck than it first seems!

Anyway, after pulling my hair out for a few hours trying to come up with an elegant mathematical solution for rotating target sectors (there isn't one dammit!), I came up with this little snippet, which I think is rather nifty:

1:  // for all ball positions  
2:  for (int j = 0; j < PositionList.SECTORS; ++j) {  
4:    // 1. get the reversed ball position  
5:    int x = grid.getReversed(j);  
7:    // 2. get the players position for the new perspective  
8:    int p = player.positions.get(x);  
10:   // 3. flip the player position  
11:   int r = grid.getReversed(p);  
13:   // save flipped position to list  
14:   player.positions_flipped.set(j, r);  
15:  }  

Basically, when creating the grid to begin with, we save a list of the sector id's in reverse order. Then when calculating the sector for a player facing south, we take the original sector (configured in tactics editor) and do the following steps:

1. Find what the ball sector number would be if the grid was reversed. This is like saying "if I was playing down the pitch, which sector would the ball be in from my perspective?"

2. Get the players configured target sector for this new ball sector.

3. Like step 1, find what this target sector would look like from the perspective of a player facing south.

4. Voila.

The clever, "powerful" bit is that the list of reversed indices magically tells you how any sector will look from the perspective of a player facing the other way. This will be obvious to some, but took me a bit of working out!

Thursday, 25 February 2016

Invasion of the Sensi Giants

Just because it's funny. And I've just finished a long night of programming under the hood with no visible progress whatsoever.

Sunday, 21 February 2016


After a lot of refactoring, the first extra match state is working: Throw-ins.

Saturday, 20 February 2016

Camera Height

In the sensi tradition, gameplay over graphics. The pulled out camera makes the sprites smaller, but easier to see team mates and build passing moves without having to look at a radar.

Doing Lines

Made the pitch markings a bit smoother. They are rendered on the fly to allow for custom size pitches.

Just for fun, a checked pitch texture:

Sunday, 7 February 2016

Back at It

So after a bit of a break for the xmas hols and an extra-busy month in work, development is back underway for Senseless! Yay!

To ease use back in, we're doing a bit of refactoring. Right now the player states are controlled in a top-down hierarchy, so the team state sends a message to the players to tell them what to do.

This is a bit (very) messy because it really makes the state machine too complicated to manage. Instead of each individual state strictly controlling it's behavior, it can be randomly "messaged" to change from outside. We don't like this.

Much better is a bottom-up mechanism. So the player "surveys" his environment and decides for himself what to do.

For example, in a throw-in match state, the team will not look up it's throw in taker and then send a message to that player to take the throw in. Instead, the player will recognize his team is in the throw-in state, and he will check to see if he is the designated throw in taker, then trigger the state change to take the throw-in. Much nicer me thinks.

Instead of continuously checking the match state, later we might want to turn this into an "observer" pattern. Normally I don't like to overload on patterns but here I think it makes a lot of sense. The player "observes" the state of the match. Seems pretty intuitive.

Just a reminder, the state of the game: (the flickering is only in the video cap. Honest!)

Monday, 18 January 2016

Roast My Game

Great idea for Indie Devs. Look out for Senseless Soccer Beta 0.00.1!!!