USC is renowned for its School of Cinematic Arts. That’s at best remotely related to my work, though.
But only after I came did I discover that they have equally competitive game design programs.
I once played Cloud when I was in middle school. A beautiful game. And then, a while ago, I found that this game was made in USC and the creator is my compatriot and an alumnus of SJTU! Indie game development definitely was a rare thing back then in China, and arguably still is now.
I’m taking CSCI-522 “Game Engine Development” this semester. I did plan to take a graphics course, but my boss is not teaching this semester, and the other graphics course really is just elementary, so I opted to try something different.
I’m not planning to become a game developer. (Well, strictly speaking that possibility is not ruled out yet.) You don’t need a phd to make games! Actually I doubt whether such courses will make you a “game developer”. My classmates are almost exclusively Master’s students. I don’t know whether they are MSCS or MFA, but either ways, being an expert in game engine is probably only gonna get you in to a big game company to work on their engines. You are still a programmer, just working with some different kind of program. You won’t be the next, say, Notch or Jonathan Blow. Does not sound cool.
But being cool is one thing, actually getting something to work is another thing! I barely know anything about the game development community but I guess in a big company you are guaranteed a good income while making a living as a indie game developer is much harder. If you think you had a great idea about game design but people don’t buy it, as often is the case, you’d probably rather learn to draw cute girls than designing games! At least you know someone’s gonna buy it if there is waifu! (No I’m joking)
But all those sort of things are none of my business. I’m taking this course to gain experience in working on giant complex projects. I heard that CSCI-522 is one of the more demanding courses offered by the compute science department. We are given a game engine that can barely do the basic rendering, animation, scripting, etc. and we will work on it so that in the end it will actually be something workable. Not being bold enough to read the source code of GCC or Linux kernel, this is the most complicated thing I’ve ever get my hands on.
In game engines efficiency is everything. Optimization is everything. That means you will work with a lower level language, and you won’t even want to use standard libraries. You don’t want generic solutions. You want something that works best for this particular program. So you do everything from scratch in C++: from memory management, to data structures, to runtime type information, to event system, and more.
And then, on top of that, you figure out how to abstract out the difference between hardware platforms and graphic APIs. Yes, we are gonna make it work on Windows and PSVita and iPad and more.
Then you do all the computation – physics and linear algebra and computational geometry, move objects around, pass control events around, gather draw calls and send them down the graphics pipeline.
Around that, you also need a script system and some sort of level editor. That really is a lot.
And while doing that, you use all kind of tricks to reduce coding work, do profiling, speed up compilation and help debugging.
Yes. Engineering. But as a graphics researcher, those are very useful skills if you want your research to be more than a paper and become something useful.
Thus far the technical part of the course has not gone beyond my existing knowledge, but I did learn some little tricks.
Here is one pre-class quiz question: you want to count the number of calls to certain functions. Suppose you want to implement several functions that take two integer arguments named a and b and return one integer. Define a macro called PROFILED_FUNC and a class called Tracker, such that
PROFILED_FUNC(func) { //do some computation //return some value }
defines such a function func, and when you call Tracker::stat(), it prints out the number of times each such function has been called.
The macro would be something like
#define PROFILED_FUNC(func) \ int func(int a, int b) { \ static int callCount = 0; \ if (callCount == 0) { \ Tracker::register(#func, &callCount); \ } \ callCount++; \ return _unprofiled_ ## func(a, b); \ } \ int _unprofiled_ ## func(int a, int b)
the # and ## are really alien to me! This made me believe more that I’ll never master C++.
And another trick: if you have a huge class definition in a header, you won’t want to include every time you use the class, since it slows down compilation. Time is money. It is common knowledge that we can forward declare a class, but that way we can only use a pointer to that class and cannot dereference it.
Now suppose you want to allocate a object of that class. Then you need to know its size. How do you avoid including the header?
You forward declare a function that allocate the object and return the pointer and put the definition in the implementation of that class.
And then there are other tricks. Thanks god that we don’t have template meta-programming!