Football Simulation
Engine - Node Module
As previously mentioned in my blog HERE, I had been looking to design and build a
football manager game, with the main purpose being to improve my JavaScript
(JS) and node (Node JS) skills. I soon found there were no existing node
package modules (npm) that could provide a simulated match result.
I posted on a few sites to
try and see if anyone had done this before - there’s no point repeating work is
there? After finding nothing specific that matched my purpose I went on ahead
and built my prototypes which consisted of two random numbers and a little use
of player skill to create results (see previous blog), but it didn’t really fit
the bill for a football manager games back end as it didn’t take other factors
into consideration.
So, I went ahead and built my own, and as of today it
is now available on the npm website HERE or run
npm install footballsimulationengine
How does it work?
Great
question, glad you asked. Basically, you provide it with two JSON strings, each
its own team and requiring a specific set of JSON objects. This includes team
name, players, player positions, skills and each players starting position.
Example:
{
"name": "Team1",
"players": [{
"name": "Player",
"position": "GK",
"rating": "99",
"skill": {
"passing": "99",
"shooting": "99",
"tackling": "99",
"saving": "99",
"agility": "99",
"strength": "99",
"penalty_taking":
"99",
"jumping": "300"
},
"startPOS": [60,0],
"injured": false
}...],
"manager": "Aiden"
}
Key things to
remember:
· Each team MUST have 11 players
· The code currently does not check
these parameters, so the skills SHOULD be between 1 and 100.
· Except for “jumping” which is intended to be
the maximum jump height of the player in centimetres.
· Start Position should between you
pitch Sizes Width and half of the pitch length. The code deals with switching
their start position side. E.g if my pitch size is [120, 600], “startPOS”
SHOULD BE [0-120, 0 - 300].
The other
thing we will need to start a game/match is pitch size, which is shown in
[width, height] where the pitch is intended to be taller than it is wide, like
below.
PIC
Example Pitch JSON:
{
"pitchWidth": 120,
"pitchHeight": 600
}
We feed these
three JSONs into the initiate function like so:
Example:
initiateGame(team1,
team2, pitch).then(function(matchDetails){
console.log(matchDetails);
}).catch(function(error){
console.error("Error: ", error);
})
what we get
back is a super larger JSON with both teams, their originPOS (so we can get
them back to their original position), relativePOS (so we know where they’re
heading towards), and a whole bunch of match details such as the score, number
of shots and importantly, where the ball is, ball direction.
The main idea
is that the game runs in iterations
this allows the client using the simulation engine to change players throughout
the game, set up the game in certain positions.
Playing
iterations is then as simple as running that big old outputted JSON back into a
play iteration function which in turn, gives an updated big old output JSON.
Example:
playIteration(matchDetails).then(function
(matchDetails) {
console.log(matchDetails);
}).catch(function(error){
console.error("Error: ", error);
}
Example Output:
{
kickOffTeam:
{ name: 'Team1',
players:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object] ],
manager: 'Aiden'
intent: 'defend' },
secondTeam:
{ name: 'Team2',
players:
[ [Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object],
[Object] ],
manager: 'Joe',
intent: 'attack' },
pitchSize: [ 120, 600 ],
ball:
{ position: [ 76, 314 ],
withPlayer: true,
Player: 'Joe Bloggs',
withTeam: 'Team2',
direction: 'south' },
half: 1,
kickOffTeamStatistics:
{ goals: 0,
shots: 0,
corners: 0,
freekicks: 0,
penalties: 0,
fouls: 0 },
secondTeamStatistics:
{ goals: 0,
shots: 0,
corners: 0,
freekicks: 0,
penalties: 0,
fouls: 0 },
iterationLog:
[ 'Closest Player to ball: Aiden Gallagher',
'Closest Player to ball: Joe Bloggs' ] }
An important
feature here is the “iterationLog” which gives an overview of what has happened
during that iteration. i.e. someone has passed the ball, someone has taken a
shot, scored, freekick awarded, penalty taken, a throwin given and taken.
Finally, the
last function that can be played is switch sides of the teams that are playing,
i.e. after half time or if running into extra time.
Example:
startSecondHalf(matchDetails).then(function
(matchDetails) {
console.log(matchDetails);
}).catch(function(error){
console.error("Error: ", error);
}
TL;DR / Overview:
· Three function; initiateGame - needs
two team JSONs and a Pitch Details JSON, playIteration - takes the output from
initiate game and updates one movement of each player, startSecondHalf -
switches the sides the players are on.
· All three functions are return
promises
· JSON isn’t checked so make sure you’ve
got it right
· Recommended match length is 10,000
iterations.
If you’d like
help setting up, have some general questions please feel free to comment below
and I’ll get back to you ASAP.
Improvements:
This code is
setup on a public Github which you can find HERE and I’m hoping people who use the
module (if anyone) will help me improve it! You can raise issues HERE but
otherwise please get in touch by email: aiden.g@live.co.uk
Visual Example:
For those who
want to see, here is a youtube video of the game being used in an example I have set up. Feel free to get in touch and I can send you the "manager" setup and some instructions.
No comments:
Post a Comment