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

Conventions

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)  
   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!

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.

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;  
   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:

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.


Sunday 21 February 2016

Throw-In

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!)