Skip to content
mrmbernardi edited this page Jul 26, 2024 · 20 revisions

Note: All new C and C++ files and existing ones should adopt this style.

Coding style can be based on the following example source code. /// comments are just for the purpose of this coding style page.

  • Indent: spaces
  • Indent width: 4ch
  • Max line width: 128ch

Source files

Example.cpp:

/// Start with a description of the contents of this source file.
/**
 * Functions related to guest creation and guest animation logic.
 */

/// Alphabetically ordered standard headers
#include <stdlib.h>
#include <string.h>
/// Alphabetically ordered library headers
#include <SDL/SDL.h>
/// Alphabetically ordered application headers
#include "addresses.h"
#include "example.h"
#include "park.h"
#include "window.h"

/// Global (extern) variables are prefixed with 'g', followed by title case.
int32_t gNumGuests = 0;

/// Local (static) variables are prefixed with '_', followed by lower camel case.
static int32_t _nextGuestIndex;

/// Local function declarations
static Peep* GetLastGuest();

/// All functions should be Upper CamelCase (PascalCase)
/// Only local functions need documentation (javadoc style)
/// Global functions should have their documentation in the header file.

static Peep* CreateGuest(const int32_t spawnIndex);
{
    /// Arguments and local variables use camelCase
    Entity* peepSprite = CreateEntity(spawnIndex);
}

/**
 * Gets the last guest in the linked list of guests.
 * @return A reference to the last peep.
 */
static Peep* GetLastGuest()
{
    /// all braces must be on their own lines.
    if (gNumGuests == 0)
    {
        return nullptr;
    }

    /// Flag checking and integers representing booleans do not need
    /// to use boolean comparison operators.
    if (!(gParkFlags & PARK_FLAG_OPEN))
    {
        return nullptr;
    }

    /// Do not place comments on the same line as code
    if (gNumGuests == 1)
    {
        return gSprites[_nextGuestIndex];
    }
    else
    {
        /// Block comments use // not /* */
        // The following will iterate through the linked list
        // until the last peep is found.
        /// Pointer asterisks are placed next to the variable name.
        /// E.g. int32_t a, *ptrA, *ptrB
        Peep* peep = gSprites[_nextGuestIndex];
        /// Always be explicit with NULL checks
        while (peep->next != nullptr)
        {
            peep = peep->next;
        }

        /// Always use the explicit auto* over auto
        auto* peep2 = peep;

        /// Avoid comments that describe what the code says, e.g.
        // Returns the peep
        return peep;
    }
}

/// Use regions to allow text editors to collapse large blocks of code
#pragma region Animation Tables

/// Public structure members are camelCase.
/**
 * Represents a currently running animation.
 */
struct PeepAnimation
{
    int32_t animationIndex;
    int32_t animationLength;
};

class PeepAction
{
private:
    /// Private or Protected variables start with an underscore
    int32_t _actionType;
}

/// Local constants do not require underscore prefix. They are title case.
static const int32_t WalkingAnimation[] =
{
    0, 0, 0, 1, 1, 1, 2, 2, 3, 2, 3, 2, 1, 0,
    3, 0, 0, 1, 1, 1, 2, 2, 3, 2, 2, 2, 1, 0
};

static const int32_t JumpingAnimation[] =
{
    8, 7, 9, 5, 5
};

#pragma endregion

/// Feel free to sign parts of the code with your name / user name

// ~IntelOrca: This should be moved into Animation.cpp in the future.
PeepAnimation CreateAnimation(const int32_t startFrameIndex, const int32_t length)
{
    PeepAnimation result;
    result.AnimationIndex = startFrameIndex;
    result.AnimationLength = length;
    return result;
}

/// If a function definition runs over the line length limit, the arguments
/// should be broken up as follows:
void ShowAnimation(int32_t columns,
                   int32_t rows,
                   int32_t isResizable)
{
    /// Function calls with many arguments can be broken up like the following.
    /// The closing parenthesis should appear at the end of the last argument.
    CreateWindow(
        gDefaultWindowX,
        gDefaultWindowY,
        columns * 200,
        rows * 300,
        isResizable ? WF_RESIZABLE : 0);
}

/// Template parameters should be prefixed with `T`, e.g. `TFoo`
template<typename TGenerator, typename TSizeType = size_t>
void take(TGenerator g, TSizeType num)
{
}

Header files

Example.h:

/// Use the following header guard style to prevent multiple inclusions.
#pragma once

/// Keep includes to a minimum in header files. Usually just the header files necessary
/// for the rest of the header file.
#include "common.h"

/// Constants use constexpr (not #define) and use title case with a "k" prefix.
constexpr uint8_t kMapBaseZ = 7;

/// Actual macros (that are not expressible as constexpr) use SHOUTING_SNAKE_CASE.
#define SOME_MACRO(foo, bar) .foo = bar

/// Global (extern) variables are prefixed with g and then title case.
extern int32_t gNumGuests;

/// Documentation for global functions are kept in the header file and use javadoc style.
/**
 * Creates a new guest ready to enter the park.
 * @param spawnIndex The index of the spawn spot to create the guest at.
 * @return A new peep.
 */
Peep* CreateGuest(int32_t spawnIndex);

/// Enums should be enum classes with specified types.
enum class ClimateType : uint8_t
{
    coolAndWet,
    warm,
    hotAndDry,
};

clang-format and Git hooks

The .clang-format file in this repository reflects the code style described above. The program clang-format can be used to reformat code style 'issues'. This is also what the CI pipeline does when building PRs. The repository also features a Python script scripts/run-clang-format.py that wraps clang-format and provides a patch instead of modifying the files.

To make life a little easier, a Git hook can be installed. This hook will execute pre-commit and halt the commit when issues arise and supply a patch to fix the issues. Just use the following lines in the .git/hooks/pre-commit file.

#!/bin/bash
src=`git diff-index --cached --name-only HEAD -- 'src/*.cpp' 'src/*.hpp' 'src/*.h'`
if [ ! -z "$src" ]; then
    ./scripts/run-clang-format.py $src
fi

Another way to format your code in-place is to run git clang-format.

Clone this wiki locally