Downloadable
Controls:
Exit: ESC or click X
Pause/Resume: Space
Key Points
Basically, Assignment 1 is to develop a game in which a triangle constantly changes color. It should be able to run on both x64 platform, with DirectX being its graphics library, and x86 platform, with OpenGL being its graphics Library.
Briefly, I think the key points of completing this assignment are as follows:
● How to make your code run on different platforms?
● How to build a clear structure?
● What’s inside a shader file?
● How to make a game based on windows application?
Run On Different Platforms!
We sometimes run into this problem: our project is done and finally, it’s time to publish it, however, we don’t know whether the player has a PS4 or an Xbox.
Abstractions! You may say. Certainly, it’s a good way to deal with changes, however, though some of the project can remain unchanged, there are still situations where we have to write platform-specific code, for example, using a 32-bit or 64-bit pointer.
There are two ways of solving this problem. One is to use preprocessor. The other is to use separate files for each platform.
I am more used to preprocessor and have already written a lot in my previous work. Simply using #if defined(...) and #elif defined(...), we can put everything into one file but make each build separately. By the way, this is what I did when I put all constant buffer code into a header file. However, what if the difference is too big, let's say, different implementations of a function. Though they may share the same interface, those functions have totally different logic, involve different libraries, and use different APIs. In this situation, we should put them into different files, and most importantly, to avoid being built on a platform that they are not designed for, we should change Excluded From Build in Properties under certain platforms to Yes. In our case, DirectX-specific code and OpenGL-specific code needs to go into different files. We can use .d3d and .gl to tell which is from which.
The Clearer, The Better
I always have trouble organizing my project. At first, it’s always clean and nice. But as I add more and more functions, one day, when I open my Visual Studio, I suddenly realize it’s a mess again!
To avoid seeing all this clutter, first of all, we need to make sure the structure of our project in the file system is the same as the one in Visual Studio. Then, to always keep our build and the data it needs in a separate place, we need property sheets. Property sheets work the same as right-clicking on a file and choosing properties, but it helps to share the same and consistent information among projects.
I used this method when adding the graphics library and my game project, and it worked perfectly. Always check you have the correct references when you are managing tons of projects. I notice that the graphics library only needs Asserts, Logging, Concurrency, Platform, OpenGLExtension, and Math. Though Time, Results, Assets, UserOutput, Windows also appear in some files, either they are only included for a variable/enum, or they don't have any function calls from CPP files. In such cases, we don't need to add them to references. What's more, I got two strange errors when I ran my game for the first time. After doing some research, I realized that there was something missing. The solution to this was to add d3d.lib(for DirectX) and glu32.lib(for OpenGL) to additional dependencies.
Though Editing A Shader May Sound Scary…
Finally, it’s time to edit a shader. I’ve never done this before and when I saw the .shader extension, I thought it would be a totally different language. But after I took a look at the code inside a shader file, I realized there weren’t a lot of differences from a normal C/C++ file.
Constant buffers are declared to store variables, such as system time, and simulation time. Since it's just a declaration and was redeclared in a lot of shader files, I decided to move all of them into a .h file. Therefore, every time I need to create a new shader, I can just include that .h file.
The main() function is just like other main() functions we've coped with before. Currently, this logic is not complicated. For a fragment shader, we only need to generate a random color. In this case, we need to make use of simulation time. The way I did this was to use sin() and cos(). Then there comes the problem: we can get negative values. To make sure I have different values for RGB, sometimes I plus one, and sometimes I negate these values. Now, we can reset RGB, while simulation time is changing, the color is also changing.
To pause or slow down the game, all we need to do is to “slow down” simulation time. To figure out how to do that, I looked for where simulation time was used and finally found that in iApplication.cpp. The simulation time we receive is multiplied by a rate, so that we can decide how fast it runs. Therefore, all we need to do is to adjust the rate when a player presses a button. By the way, I spent quite an amount of time thinking about where to put my pause function. In the end, I thought other games might have different ways of interpreting input, so I put it in MyGame.
A Windows Application Game
Though this assignment doesn’t require us to learn much about how to make a windows application game from scratch and some really nice features were already implemented in the base class, I still learned some by changing names and icons of MyGame.
Making my own icon was a fun thing to do and it was when I could be creative. After adding my icon to the resource file folder, the next thing I did was to open Resource.h to assign an id and open MyGame.rc to add a path for my icon. At first, I tried to do it in the resource management page but eventually gave up, because it was confusing and the project became a mess. Files are absolutely more straightforward and are easier to edit.
My Opinion
I was amazed at how the base code was organized when I first opened the project. We’ve been told that we should have a clear structure but nobody had ever taught us a practical and efficient way of doing so. Though I like how it was organized, I sometimes think managing these projects may sometimes cost too much time. For example, when I want to look for some definition or add a reference. But considering one day we’ll be in a much bigger team, I think this is still necessary. Comments and logs help a lot when I try to comprehend each module.
I’ve studied digital image process before, but I think this course stresses more on a higher level of using graphics and shaders. It’s exciting to see the color of the triangle changing and I hope to learn more about how each shader works and what's needed to show images on the screen.
Comments