This document describe the conventions adopted for the development of games named Seven Keys.
Você pode ler isso em português em [Folha de Estilo](Folha de Estilo.md)
All file .cpp must have un .hpp corresponding, with send name. Both must have the name of classe which they implement.
Class Names:
class Guard : public Object
Files Names:
guard.cpp
guard.hpp
-First the header of source file
-after the library engine
-after the library specific of the game
-after the library standards the c/c++
#include "boss.hpp"
#include "core/level.hpp"
#include "core/environment.hpp"
#include "core/keyboardevent.hpp"
#include "core/animation.hpp"
#include <iostream>
Namespaces should be used whenever possible Namespaces should always be named
using namespace std;
Declare the variables the most locally possible. The variables should be declared the most closer to their use All the variables shoud be initialised.
for(int id = 1; id < quantidade_salas; id++)
{
Room * aux = room_list.at(rand() % id);
CreateRoom(aux, &id, aux->pos_x, aux->pos_y, quantidade_salas, stage_id);
aux ++;
}
Variables statics should be used only when its necessary due their scratchs of variations and bad over the code, when it don't be utilized as constant(const).
static Font_Manager *instance;
The nomeclature must follow the standard "CamelCase" for Classes and Enums. Names of classes must be composed for nouns.
class Guard : public Object
For class members the standard adopted is the "lowerCamelCase"
static ActionID removeGuardID;
For methods, functions, variables and namespaces the standard used must be the "snake_case" Methods and functions must contain at least a verb and a noun.
void update_vision();
For constants and macros should be used the "SCREAMING_SNAKE_CASE", except in parameters which shoud be adocted the style "snake_case".
#define SPEED 150.5
In parameters:
void Player::get_weapon(string weapon_id)
In structs it will be used "snake_case", the same shoud be accompained of one typedef
typedef struct _Area
{
double left, right;
double top, bottom;
} Area;
For typedef the standard to be followed is the standard "CamelCase" in types compounds as a struct and enum.
typedef struct _Area
{
...
} Area;
For simples styles as int and double shoud be used the standard snake_case.
typedef unsigned int natural_numbers;
In declarations the pointers shoud be use the asterisk near to name of the variable, and shoud follow the model "snake_case" as the example.
Environment *env = Environment::get_instance();
Class must have methods and class members consistents with what hes name especifies.
The declarations make um in orther of the more open (public) for the most closed (private) in context of encapsulation. public before the protected, protected before the private.
The first declarations shoud be the constructors and destructors, soon after the class members, followed by methods.
class Font_Manager
{
public:
static Font_Manager* Instance();
static void init() throw (Exception);
void load_font(string path, unsigned int font_size) throw (Exception);
void close_font();
SDL_Texture* message()const;
void make_message(SDL_Renderer * renderer, string message, Color color) throw (Exception);
protected:
Font_Manager();
~Font_Manager();
private:
static Font_Manager* instance;
SDL_Texture* m_message;
TTF_Font* m_font;
};
Constructor shoud always be defined in each class.
.hpp
Animation(const string& image, double x, double y, double w, double h,
int frames, unsigned long speed_in_ms, bool loop = false);
~Animation();
.cpp
Animation::Animation(const string& texture, double x, double y, double w,
double h, int frames, unsigned long speed_in_ms, bool loop)
: m_impl(new Animation::Impl(texture, x, y, w, h, frames, speed_in_ms, loop)) {
}
Only virtuals destructs allowed, when necessary.
The method shoud have the funcionality features of his nomeclatures. They shoud be separeted of the other declarations of the classe for blank lines before and after, forming paragraphs.
...
void show_health()
{
Environment* env = Environment::get_instance();
Rect healthbar {(double)env->canvas->w()/15, (double)env->canvas->h()/24, m_player->health() * 2, 12};
env->canvas->fill(healthbar, Color::RED);
Rect borda {(double)env->canvas->w()/15, (double)env->canvas->h()/24, 100*2, 12};
env->canvas->draw(borda, Color::RED);
}
...
The type of return should be declared always before the mane of the function in the same line.
...
void show_health()
{
...
}
...
For indenting should used the standard of tab of four spaces.
Not do much thing on the same line. To this does not happen, you should prevent exceeding the limit of 80 characters per line. For breaks of line, in cases of expressions very large, should use the following principles:
- Break after comma;
Impl(Button* button, const string& idle_image_id,
const string& active_image_id)
: m_button(button), m_text(nullptr), m_idle(Color::GREEN),
m_active(Color::BLUE), m_border(Color::BLACK), m_thickness(1),
m_state(IDLE)
- Break before the operators;
Item* pill = new Item(m_player, "icon_pill", path, (double)env->canvas->w()
* 1/35 + 2, (double)env->canvas->h() * 25/30 + 2, 9999, true);
m_player->add_child(pill);
- Align the new line with the same level the start of expression the previous line.
For operators shoud give a space before and one after.
m_player->set_stamina(m_player->stamina() + 0.05);
Braces should be used whenever possible, even in situations where language allows not be used. The braces shoud be open one line below the end of the expression or declaration and shoud be closed one line below the block instructions:
if(x + m_player->w() > env->canvas->w())
{
x = env->canvas->w() - m_player->w();
}
Always use 'else' in kind 'if' control structures. In type 'switch' structures, 'cases' that represent the main flow must come before the cases that represent alternative flow or error messages. The standard to be following is without spaces between the control structute and the parentheses of condition, and between the operations of condition. It's better using command operations as 'and', 'or', 'not', natives of c++.
Bad code:
if(id != Button::clickedID)
{
return false;
}
Good code:
if(id not Button::clickedID)
{
return false;
}
else
{
//nothing to do.
}
The standard to be following is without spaces between the repetition of structures and parentheses, and in conditions of repetition spaces before the , and between the signals of relation and operarion space before and after.
for(int id = 1; id < quantidade_salas; id++)
{
Room * aux = room_list.at(rand() % id);
CreateRoom(aux, &id, aux->pos_x, aux->pos_y, quantidade_salas, stage_id);
aux ++;
}
The variables and class members shoud be used in standard snake_case, the variables shoud be for standard declared with the type following for a space the name of variable and the same must be initialized. {space}{space} = {space};
double w = env->canvas->w();
The functions and methods shoud following format: ({space}{comma}{space}...);
Animation(const string& image, double x, double y, double w, double h,
int frames, unsigned long speed_in_ms, bool loop = false);
Structs shoud have only primary data and can not be implemented any funcionality type or related.
typedef struct _ ItemInfo { string name; string type; int variations; int weight; bool walkable; bool unique; double mass; int x, y; } ItemInfo;
The declaration of enum shoud be used with on typedef following for his parameters between braces.
<typedef>{space}<enum>{space}<{PARAMETRO1, PARAMETRO2}>{espaço}<NomeType>;
```c++
typedef enum { NONE, BLEND } BlendMode;
For comments the only one line shoud be utilized double bar.
// Room Criation
For comments the two or more lines must be utilized the bar with an asterisk.
/*
string *str;
str = (string*)(&id);
*str = "stage1";
*/
The documentation on style "JavaDoc" shoud be used for comments of class and method. Is advisable only the use of @param, @return, @throws and in some cases @deprecated. For any commentary to style JavaDoc for comments of class and methods, shoud be used comments of @param, @return, @throws and @deprecated if is necessary. The standard adopted was as follows:
/**
* [Weapon::Weapon Receives the object parent (weapon), your identifier and
* all your attributes(resistance, damage and attack speed)]
* @param id [identifier of object]
* @param resistance [Resistance of the Weapon, may change depending the weapon]
* @param damage [Damage of the Weapon, may change depending the weapon]
* @param attack_speed [Attack speed of the Weapon, may change depending the weapon]
*/
Assertives must be used whenever one unexpected behavior, conditions impossible and corrupted data which can not be treated. His parameters must contain at least one condition and an error message or with the state and/or expected value.
assert(percent >= 0 && "Must be >= 0")
Exceptions shoud be treated in context most appropriate using catch, if the context is not appropriate an exception must be spread using throw.
Bad code:
...
try
{
srand(time(NULL));
SevenKeys keys;
keys.init("7 Keys", 1280, 720, 1, true);
keys.run();
} catch (Exception ex)
{
cerr << ex.message() << endl;
return -1;
}
...
try
{
audio_manager = new AudioManagerWrapper();
if (not audio_manager)
{
throw AudioManagerSfxAllocationException("Out of memory for a new AudioManagerSfx");
}
audio_manager->init();
} catch (AudioManagerMusicAllocationException audio_manager_music_allocation_exception)
{
// Do something significant
...
}
...
The excetion "AudioManagerSfxAllocationException" there is not one catch for treat it and is spread to the caller method.
should avoid the cast forced as follows:
m_player->x() + (moviment.first * delta)/1000.0;
A maneira correta de se fazer é usando o cast da propria linguagem: The right way to make is using the cast own language.
m_player->x() + (moviment.first * delta) / (double)1000;