Transcript Document

GAME 1024: Advanced
Game Programming
Lesson 7: Super Magnificent Hyper Game Features
Hardcore Extreme Black Turbo!
By Kain Shin
Quiz
1.
2.
3.
4.
5.
6.
7.
8.
Write your name either…
1.
In binary ASCII format or …
2.
Spelled backwards
When does a static variable’s constructor get called when declared inside a
function?
Give one reason for game localization
What is one thing you can do to make a tester’s job easier?
What is one thing you can do to make an artist’s job easier?
Give one reason to add profiling to your game
Name a favorite game of yours. Give an example of a user statistic that might be
collected in that game
What is the difference between input spoofing and event spoofing when
recording and playing back a user play session.
Bonus Topic: An Informal Vector Math Overview








Game use vectors to represent position, orientation, and velocity
Game change vectors via matrix multiplication
What goes into a translation matrix? An offset.
What goes into a rotation matrix? Euler angles or a quaternion.
What are Euler angles?
What’s a quaternion?
How do you tell when a player is in the enemy’s view cone?

The Dot Product of two normalized direction vectors placed tail to tail equals the
cosine of the angle between the vectors
How do you find the axis of rotation for something that needs to rotate at an odd angle, like
a guided missile following a target?

The Cross Product of two vectors placed tail to tail is a third vector that is
perpendicular to the plane defined by both source vectors

The direction of the cross product vector is the same as your thumb when you curl your
hand inward from the first vector to the second vector… whether it is your right hand
or left hand depends on whether you are using the right-handed or left-handed
coordinate system (look it up if you want to know more about the right/left handedness
of coordinate systems).
Today’s Lecture is About…


Optimization Recipes
 Reducing Event System Overhead
 Custom Memory Allocation
 Resource Management
 Load Optimization
 Instancing Data
 Advanced Feature: Streaming Technology
Game Feature: Save/Load
Event System Optimizations





Register functors or function pointers for events
instead of listener classes
Minimize the number of listeners for an event
Unregister listeners that no longer need to listen for
events
Queue up events and eliminate redundancy or
duplicates
If only one thing is going to listen for the event, then
consider eliminating event system usage altogether
Custom Memory Allocation
Why?





1.
2.

“operator new” (or malloc) is more expensive than assigning pointers to pre-allocated heap memory
On a console, you want full control over how much RAM you use and you want to be warned when you pass the
limit, because consoles have no virtual memory.
Fragmented memory leads to slower access due to having to juggle the contents of the CPU cache to access things
that would normally be next to each other in memory
Basic Recipe (The web is full of various implementations of this):
Pre-allocate a huge block of memory on the heap at the very beginning of the game
Instead of allocating new chunks off the global heap when you need a new object, Assign a pointer to an address
within your big giant block by…

Implementing “operator new” as a member of the classes that you want allocated within this big giant block
or…

#define your own version of “new” and “delete” that recognizes your big giant block or…

#define your own version of “NEW” and “DELETE” that recognizes your big giant block and gets used only
when you specifically use it… this way, you don’t collide with other people’s custom memory allocator
usages in your third party libraries
C++ Tip: “Placement new” works like regular “new”, except it constructs your object at an address you specify

Usage Example:
cThing* pMyThing = new(myDesiredAddress) cThing;
//pMyThing==myDesiredAddress after this
Block Loading



What is it?

Loading a single large file from the disc that contains the contents of multiple resources that were packed together
into a single memory-mapped file.

This giant memory-mapped file can be compressed (zipped). This makes loading faster because there is less data to
load, and decompression of a zipped file is typically faster than the extra time it takes to load the uncompressed file.

A memory mapped file is a file that starts with name and offset information followed by consecutive blocks of
resource data packed together so that whatever loads the file can access the resource data it is looking for
Why use it?

Because disc access is your bottleneck during loading, and loading is faster when you load one large file instead of
many small ones

Because it discourages users from mucking with the assets and posting screenshots of their “modded” content on the
internet
Basic Recipe:

Make sure all resources in the game (graphics, sound, etc.) can be converted to/from generic blocks of memory
(address + size)

Creating the Memory-Mapped Resource File

Create an external tool that can pack these files into a single file for you (i.e. wad files used in DOOM)…
this external tool could either be your level editor or a specific tool made just for resource packing

OR write code inside the game to have the game dump all mappable resources into a special resource file for
later loading when you tell it to

Loading the Memory-Mapped Resource File into the Game

Load the block file at the start of the game before the other systems get set up

Instead of reading individual files for a resource, have the game’s initilization code grab the resource data
from this managed resource block to set up its sprites, sounds, textures, models, etc.
Resource Instancing



What is it?

Separating source data from instance data so that multiple objects can use the
same loaded resource for separate instances.

An instance is a unique manifestation of a resource in the game. In the
example of a sprite…

Source data on a sprite is the actual bitmap of the sprite. This can be
shared between multiple sprites

Instance data on a sprite is position, size, and rotation information about
that sprite
Why use it?

Sharing data instead of duplicating data uses up less RAM
Basic Recipe:

Figure out what resources can be shared

Centralize the storage of these shared resources in a central “database” that
can be accessed by other systems

Have the entities (Sprites, AudioBuffers, etc.) that use these shared resources
store only a pointer or reference to the resource, but not own it
Streaming Technology

What is it?


Why use it?


Background loading while the game is still active (as seen in city-roaming
games such as the recent Grand Theft Auto series)
The resources of the game world will not fit in RAM, but you don’t want to
split the world up into sections separated by loading screens
Basic Recipe:



Arrange your dynamically loading resources into groups that will load
together, such as all resources related to a certain geographical sector
Separate your game’s dependency on having these dynamic resources in
memory so that it can still run even if no dynamic resources were currently
loaded… in other words, make sure that the game logic does not depend on
these dynamic resources
Depending on the game, you will be unloading old blocks and loading new
blocks as needed
Resource Manager Class




You can write a central ResourceManager class that can combine block
loading, instancing, and streaming functionality as you see fit
Beware: Some 3rd Party APIs for a resource may not support conversion
to/from a generic block of memory, you might have to exclude that
resource type from your set of managed resources
Sometimes, it is useful during development to be able to run the game
from individual source files instead of the giant “cooked” block-loaded
memory-mapped files, but…
You rarely ever see shipped games with these individual files in the install
directory
Saving/Loading The World State


Don’t wait until the end of the project to implement this
feature!
Basic Recipe:





Define your game state. A game state is a set of properties that define
the state of the game at any one time
Make it so that the game state can be stored into a file
Make it so that the game can read the game state from a file and set
all relevant parts of the game to the proper state
Maintain this functionality during development as new features come
into the game
Expose this functionality with a user interface that the user can use to
save/load the game
Your Project

Milestone 3 (Your syllabus has changed, BTW)



Optional Bonus: Write a resource manager that loads all bitmaps
used in the program into a single memory mapped file. Make it so
that when you call your program with a cook parameter, it basically
creates one giant super-bitmap that holds all bitmaps used in the
game. When the game runs and detects a “cooked” bitmap, it will
load one large file instead of a bunch of tiny files. All sprites will
share a spot on the bitmap so that no graphics data is duplicated.
Optional Bonus: Write a custom memory allocator which you will
use with your versions of NEW and DELETE to ensure that no
memory is leaked and that the number of heap allocation occurences
are minimized
Optional Bonus: Integrate your custom memory allocator with STL
or whatever template library you are using
Final Thought

"You should not have a favorite weapon. To become over-familiar with one weapon is as much a fault as not knowing it
sufficiently well. You should not copy others, but use weapons which you can handle properly. It is bad for commanders
and troops to have likes and dislikes."
--Miyamoto Musashi, Book of Five Rings
Excerpted From http://www.hostallero.com/hostallero_musashi_kojiro.htm
"Musashi’s most well-known duel was in 1612 when he was in the Ogawa, Bunzen province. His opponent was Sasaki
Kojiro, a young man who had developed a strong fencing technique known as Tsubame-gaeshi or “swallow counter”,
inspired by the motion of a swallow’s tail in flight. Kojiro was retained by the lord of the province, Hosokawa Tadaoki.
Musashi applied to Tadaoki for permission to fight Kojiro through the offices of one of the Hosokawa retainers who had
been a pupil of Musashi’s father, one Nagaoka Sato Okinaga. Permission was granted for the contest to be held at eight
o’clock the next morning, and the place was to be an island some few miles from Ogura. That night Musashi left his lodging
and moved to the house of Kobayashi Taro Zaemon. This inspired a rumor that awe of Kojiro’s subtle technique had made
Musashi run away afraid for his life. The next day at eight o’clock Musashi could not be wakened until a prompter came
from the officials assembled on the island. He got up, drank the water they brought to him to wash with, and went straight
down to the shore. As Sato rowed across to the island Musashi fashioned a paper string to tie back the sleeves of his
kimono and cut a wooden sword from the spare oar. When he had done this he lay down to rest.

The boat neared the place of combat and Kojiro and the waiting officials were astounded to see the strange figure of
Musashi leap from the boat brandishing the long wooden oar with his unkempt hair tied up in a towel. He rushed through
the waves up the beach towards his enemy. Kojiro drew his long sword, a fine blade by Nagamitsu of Bizen, and threw away
his scabbard. “You have no more need of that” said Musashi as he rushed forward with his sword held to one side. Kojiro
was provoked into making the first cut and Musashi dashed upward at his blade, bringing the oar down on Kojiro’s head,
killing him. Musashi noted Kojiro’s condition and bowed to the astounded officials before running back to his boat."
In other words, adapt to your environment, and you will prevail… fail to adapt, and your employment status
will remain fragile. It is not the tool that makes the programmer, it is the programmer.