/Dunjun

A project documenting and demonstrating the process of developing a game from scratch.

Primary LanguageC++OtherNOASSERTION

Dunjun

Update

This project has been halted and most likely will not continue.

I have had to stop the project for a few reasons:

  • Lack of time
  • Not fun to create anymore
  • I didn't program the way I wanted to program from the start (C/C-styled C++)

Description

This project will be documenting and demonstrating the development of making a game from scratch1! Every step of the game development process and every line of code will be explained thoroughly.

The game will be a 3D based game. More will be revealed about the game as the project persists.

YouTube Channel: GingerGames

GitHub: Dunjun GitHub

1With minimal libraries such as GLEW, GLFW (Pre Day 73), SDL2 (Post Day 73), and the STB libraries.

YouTube Playlists

Episode List

Introduction

Lighting and Deferred Rendering

GLFW3 to SDL2 Migration

Scene/World Architecture

Data-Oriented Design and Custom Allocators

  • 084 - Remove get/set methods (Prefer Data)
  • 085 - Public Member Variables
  • 086 - POD Math Types1
  • 087 - Data Oriented Design
  • 088 - Custom Allocators
  • 089 - Allocator Types and Array
  • 090 - Queue
  • 091 - Start Implementing HashMap
  • 092 - Finish HashMap & MutliHashMap funcs
  • 093 - Murmur Hash Function
  • 094 - TempAllocator
  • 095 - Implementing an Entity Component System
  • 096 - Data-Oriented Scene Graph
  • 097 - Finish SceneGraph
  • 098 - Data-Oriented RenderSystem
  • 099 - Fix Entity Creation & RenderSystem

Contact

FAQ

Will this be a simple game, for teaching purposes?

No! In fact, the game design has been made to require complex concepts which exist in more than most game designs.

Are the accompanying videos just recordings of someone programming?

No! 99%1 of the programming for the game is recorded in the videos; every step of the game development process and every line of code will be explained thoroughly.

1Some of the code will not programmed in the videos but this will mostly be bug fixes or minor changes to the code that can be explained quickly.

What platforms will this game support?

This game will support Windows1, Mac OS X2, and Linux34.

1XP and Above 2OS X 10.8+. Maybe higher 3Including Steam OS. 4Most likely Debian based systems only.

I have a problem with X...

Please feel free to contact with any problem:

Prerequisites

Before we can begin, you need to make sure you have all the things you will need.

  • A reasonable amount of experience with C++
    • C++11 experience will help
  • Graphics card compatible with OpenGL 2.1
    • DirectX 9 Equivalent Cards
  • Text Editor and C++11 Compiler, or IDE (MSVC 12 compiler capabilities at least)
  • The initial libraries:
    • GLFW - For creating the context, window, and handling input (Pre Day 73)
    • GLEW - To use new OpenGL functions
    • SDL2 - For creating the context, window, and handling input (Post Day 73)

Building

At the moment, only Windows is supported through the Visual Studio solution. Mac OS X and Linux will implemented later when needed/wanted.

Most of the code should compile on Mac OS X and Linux with probably only a few minor changes.

Supported Platforms

Graphics APIs:

  • OpenGL 2.1 (through GLEW)

Platforms:

  • Windows (Through MSVC 12)
  • OS X (To be added)
  • Linux (To be added)

Dependencies

Tools

  • C++ compiler with decent C++11 support
    • If Visual Studio, please use at least MSVC 12.
    • Clang is preferred to GCC on other platforms but not necessary.

Libraries

  • OpenGL 2.1 (Rendering)
  • GLFW 3.1 (Window, Input and, Context Handling) (Pre Day 73)
  • SDL 2 (Window, Input and, Context Handling) (Post Day 73)
  • GLEW (OpenGL Extension Wrangler Library)
  • STB Libraries (Image and Font Loading)

Conventions

  • See .clang-format for formatting style
  • Allman Indenting
  • CamelCase
  • Tabs for indentation
  • Spaces for alignment
  • More below!

Classes

PascalCase (Upper CamelCase) (e.g. ShaderProgram)

Functions, Methods, and Variables

camelCase (e.g. loadFromFile)

Namespaces

PascalCase (e.g. Dunjun::)

The end of a namespace must appended by namespace then its name.

Example:

namespace Dunjun
{
namespace Inner
{
...
} // namespace Inner
} // namespace Dunjun

Using and Typedef

In C++11, using is a superset of typedef. using is preferred in this style guide.

// Using
using FooBar = std::pair<Foo, Bar>;
// Typedef
typedef std::pair<Foo, Bar> FooBar;

Comments

C++ style comments // are preferred but C-style comments /**/ can be used. The reasoning is that C-style comments cannot be nested and most IDEs/Editors can comments whole blocks in the C++ style which can allow for uncommenting a single line easily.

Arrays and Vectors

When an collection of data is needed, use a std::vector unless it is fixed at runtime. If it is a fixed array, use a classic C array or std::array.

The vector's elements are guaranteed to be contiguous, so you can pass &v[0] to any function expecting a pointer to an array; e.g., C library routines, OpenGL. Also, std::vector<char> buffer(2048); is a brilliant way to allocate a local buffer.

Prefer std::vector unless the profiler says that there is a problem and the array is tiny.

Pointers

Raw pointers (e.g. Bar*) can be used, but if a smart pointer can be used, please do so.

Shorthand for smart pointers (std::unique_ptr, std::shared_ptr, std::weak_ptr) of classes can be declared with using.

  • UPtr -> unique_ptr
  • SPtr -> shared_ptr
  • WPtr -> weak_ptr

Do not use std::auto_ptr, use std::unique_ptr as it is much better and std::auto_ptr is depreciated. std::shared_ptrs and std::weak_ptrs are to be use sparingly.

Example:

class Bar
{
public:
	using UPtr = std::unique_ptr<Bar>;
	using SPtr = std::shared_ptr<Bar>;
	using WPtr = std::weak_ptr<Bar>;

	...
};

If a class/etc. does not need a certain smart pointer, do not give a shorthand.

Variables

camelCase (e.g. temp, m_world, s_time)

Variable Prefixes

  • m_ for protected/private member variables
  • s_ for static/local persist variables
  • g_ for global variables (should never be used! (except on a few rare occasions but if done so, place them within a namespace, at least!))

Example:

GLOBAL f32 g_globalVar;
extern int g_externVar;

class Foo
{
	void func()
	{
		LOCAL_PERSIST u64 s_localVar;

		...
	}

private:
	char m_memberVar;
};

Enums

All enum items should use PascalCase (e.g. CursorMode).

If a strong enum is preferred, please use one (e.g. enum class).

Example:

enum class CursorMode
{
	Normal,
	Hidden,
	Disabled,
};

If a weak enum is needed, please prefix the item with the name of the enum then an underscore.

Example (made up):

enum Flag : u32
{
	Flag_1 = 1,
	Flag_2 = 2,
	Flag_3 = 4,
	Flag_4 = 8,
	Flag_5 = 16,
	Flag_6 = 32,
	Flag_7 = 64,
	Flag_8 = 128,

	Flag_A = Flag_1,
	Flag_B = Flag_2,
	Flag_C = Flag_3,
};

Static Defines

In Dunjun/Common.hpp, there are some defines for static:

#define GLOBAL static
#define INTERNAL static
#define LOCAL_PERSIST static

Please using these rather than the keyword static to indicate which type of static is being used.

Example:

GLOBAL int g_thingy;

INTERNAL void doSomething()
{
	LOCAL_PERSIST char s_buffer[10];

	...
}

Annotations

  • TODO - todo
  • NOTE - note to reader (can be used in conjunction with TODO)
  • IMPORTANT - important (can be used in conjunction with TODO or NOTE)
  • FIXME - fix as soon as possible (does not work as intended/not at all)
  • HACK - don't use in production (similar to FIXME but still works)

Example:

// TODO(fred) IMPORTANT(fred): This is some example text for a todo that is
// important. It also spans multiple lines. This annotation was written by
// `fred` as indicated next to the annotation.