Recommends having the constructor/deconstructor do nothing so we can explicitly set the order of initialization via init functions
gMemoryManager.startUp();
gFileSystemManager.startUp();
gVideoManager.startUp();
...
This is assuming most of the inizializations are for singletons such as managers like TextureManager, RenderManager, etc.
Keep heap allocations to a minimum, and never allocate from the heap within a tight loop.
// Shift the given address upwards if/as necessary to
// ensure it is aligned to the given number of bytes.
inline uintptr_t AlignAddress(uintptr_t addr, size_t align)
{
const size_t mask = align - 1;
assert((align & mask) == 0); // pwr of 2
return (addr + mask) & ~mask;
}
shifted_amount = aligned_addr[-1]
Its a good idea to override the increment/decrement operator for custom containers like a home-written binary tree; the complexity of iterating through the structure in usage is simplified to a ++/--
At Naughty Dog, we permit runtime hashing of strings, but we also use C++11’s user-defined literals feature to transform the syntax "any_string"_sid directly into a hashed integer value at compile time
At Naughty Dog, we started out using a variant of the CRC-32 algorithm to hash our strings, and we encountered only a handful of collisions during many years of development on Uncharted and The Last of Us. And when a collision did occur, fixing it was a simple matter of slightly altering one of the strings (e.g., append a “2” or a “b” to one of the strings, or use a totally different but synonymous string). That being said, Naughty Dog has moved to a 64-bit hashing function for The Last of Us Part II and all of our future game titles; this should essentially eliminate the possibility of hash collisions
The postincrement operator increments the contents of the variable after it has been used. This means that writing ++p introduces a data dependency into your code—the CPU must wait for the increment operation to be completed before its value can be used in the expression. On a deeply pipelined CPU, this introduces a stall. On the other hand, with p++ there is no data dependency. The value of the variable can be used immediately, and the increment operation can happen later or in parallel with its use. Either way, no stall is introduced into the pipeline. ... This shouldnt matter in loops anyways due to compiler optimization
Dynamic arrays are probably best used during development, when you are as yet unsure of the buffer sizes you’ll require. They can always be converted into fixed size arrays once suitable memory budgets have been established.
a PS3 development kit has 256 MiB of retail memory, plus an additional 256 MiB of “debug” memory that is not available on a retail unit. If we store our strings in debug memory, we needn’t worry about their impact on the memory footprint of the final shipping game. (We just need to be careful never to write production code that depends on the strings being available!)
http://www.joelonsoftware.com/articles/Unicode.html
You will need to manage a database of all human-readable strings in your game, so that they can all be reliably translated. The software must display the proper language given the user’s installation settings. The formatting of the strings may be to- tally different in different languages—for example, Chinese is sometimes writ- ten vertically, and Hebrew reads right-to-left. The lengths of the strings will vary greatly from language to language
At Naughty Dog, we use a localization database that we developed in-house. The localization tool’s back end consists of a MySQL database located on a server that is accessible both to the developers within Naughty Dog and also to the various external companies with which we work to translate our text and speech audio clips into the various languages our games support
cvar_t
(configration variable) data type
which are accessible via the in-game console and can be saved to diskNaughty Dog Uncharted & Last of Us uses C++ code generated from scheme programming language data definitions:
;; Define a new data type called simple-animation
(deftype simple-animation()
(
(name string)
(speed float :default 1.0)
(fade-in-seconds float :default 0.25)
)
)
results in the generated C++:
struct SimpleAnimation
{
const char* m_name;
float m_speed;
float m_fadeInSeconds;
};