Goal Kick
Monday, 29 February 2016
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!
Some really nice goals (and indeed near misses) possible. Feels nice!
Friday, 26 February 2016
Conventions
Some coding conventions I prefer.
So this:
becomes:
But after getting used to it, it's really no more readable than:
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.
For example, none of the comments in this snippet are necessary, they should be removed!
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)
current_state->OnStep(_dt);
// helper to update the position
update_position(_dt);
// check for state change
if (current_state->StateOver()) {
current_state->ChangeToNextState();
}
}
becomes:
void Player::Update(double _dt){
// step the current state (states do all the work)
current_state->OnStep(_dt);
// helper to update the position
update_position(_dt);
// check for state change
if (current_state->StateOver()) {
current_state->ChangeToNextState();
}
}
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:
while(condition)
do_something();
do_something_else();
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!
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!
Comments
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.
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;
ResetVelocity();
}
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.Tactics
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:
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!
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) {
3:
4: // 1. get the reversed ball position
5: int x = grid.getReversed(j);
6:
7: // 2. get the players position for the new perspective
8: int p = player.positions.get(x);
9:
10: // 3. flip the player position
11: int r = grid.getReversed(p);
12:
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.
Tuesday, 23 February 2016
Sunday, 21 February 2016
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:
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!)
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!)
Subscribe to:
Posts (Atom)