EAE 6320-001 GameEngII Game Engine Project, Game Dev Adventures!

Assignment 6: Textures and Reference Counting (again)

NancyNewren_ExampleGame 06

(Simple one-click download. Once downloaded, unzip, play the executable, enjoy!)

Press space to change the humerus texture and find your funny!

About the Project

The first thing I did was add files to the Graphics project to manage textures in code, and then added a TextureBuilder project (to build the textures which are then loaded into the cTexture class from the files in the Graphics project added previously). There were no instructions given on how to do this. Normally I panic because on previous assignments I’ve really struggled with this part, but this time I went in with the attitude that I could figure it out! And I did! So there were two obvious references needed to add to the Texture builder: DirectXTex (because it uses function calls), and AssetBuildLibrary (which was glaringly obvious since one of the TextureBuilder classes inherits from one of AssetBuildLibrary’s classes). With those added there were still 10 linker errors, but I knew that this reference didn’t belong on the Texture Builder because the linker errors were having issues with AssetBuildLibrary (ABL), which needed to have a reference to the Platform project. This may seem strange that ABL didn’t need it in our previous assignment, but that’s because the projects that use ABL were adding Platform as a reference to themselves. Once I added Platform as a reference to the ABL (where it actually should have been liked in the first place) I was able to remove the superfluous Platform reference from the other projects.

The other fun thing to figure out was the build dependency for TextureBuilder. Now the AssetBuildExe uses TextureBuilder to build the textures, but AssetBuildExe doesn’t actually need TextureBuilder during the build. No, it only needs TextureBuilder when it is executed. Well AssetBuildExe gets executed by BuildExampleGameAssets. That means that, even though AssetBuildExe needs TextureBuilder to build the textures, it’s actually BuildExampleGameAssets that has the build dependency on TextureBuilder, because BuildExampleGameAssets is what executes AssetBuildExe, which then uses TextureBuilder.

I added textures to the sprites for this assignment. Since Iadded the textures I needed to use uv coordinates to draw the textures on the sprite. Dealing with the uv’s was fairly simple as I just assigned the vertices of my sprite to the normalized device coordinates. For both platforms that is 0->1 for u. Bt for v, in D3D the values go 1->0 top down, and OpenGL is oppisite that. So when I was assigning the values in the sprite for the x,y screen space coordinates, I assigned the u,v coordinates there as well. So the user doesn’t have to do anything for the u,v. Since I did this inside the scope where I defined the x,y values, there was no code sharing between the platforms. (Since I am dealing with vertex winding and now the different normalized device coordinates for uv, it was simpler to keep them separate). But all this is “behind the hood” so to speak for the game programmer, so all I specified for the sprites were exactly the same things I had for the last version of the game.

The other thing I did was use a handle for loading my textures. The handle makes it so that we don’t load more than one asset from file (using the path as the unique identifier), since loading from file is an expensive operation this makes our game run more efficiently. Then when another object asks for that asset, instead of reloading, it just passes a reference. This is why we had to increment the reference count for the handle manually. To think of it in other terms, we were passing to the graphics thread the handle, not the texture itself. So instead of increasing the number of references on the texture, we increase it on the handle.  Really a way to increment the reference count for handle could have been provided, but I think this was not done to emphasize the that the handle wasn’t the object itself.

Now I did use the handle-provided way to decrement the reference count after rendering was done. The reason for this is because when the reference count reaches 0 and you haven’t used the handle appropriate way to decrement the memory won’t be released properly.

The last thing I did was add a space bar press and time change to two of the textures. It’s quite humerous.

Struggles and Helps

This entire project was much more involved than I anticipated it being, and I really struggled with the last requirements. I spent a long time on the first part: determining project dependencies and setting up my shaders correctly for drawing textures on my shaders. But I was able to really help one of my classmates understand the difference between build dependencies and references because of all the thought I put into it, so it was worth it.

I definitely wouldn’t have finished the project on time without Arpit’s help. I could not get submitting textures to work. My game was completely broken and he helped me get it working so I could complete the assignment. He stayed up late to help me do this after he’d completed his assignment.

Advertisements
EAE 6320-001 GameEngII Game Engine Project, Game Dev Adventures!

Assignment 5: Human Editable Settings.ini and Lua for Graphics Building (and more…)

NancyNewren_ExampleGame 05

The user can now set resolution via the settings.ini file. All shaders are now built with lua code. I also added some more pretty sprites. Hooray! (Simple one-click download. Once downloaded, unzip, play the executable, enjoy!)

About the Project

I added a settings.ini file to the download which allows users (like you!) to set the resolution of the game. The file is originally contained as part of the UserSettings project inside the engine, but is copied by Visual Studio into a predetermined output directory, and then the lua asset build script copies it into the final game directory. This is pretty neat as it makes updating the resolution practically trivial: meaning no code recompilation is needed. As everyone’s device is different, this allows the user to set their desired resolution. It also means that there is more we could add to the settings.ini file later that the user could then change as they desired, removing the developer from the updates at hand. As a developer, QA, or even level designer, this also makes it fast to test different resolutions for different platforms.

For gamers, hot loading data into the game takes the settings.ini idea a step further. Hot loading data into the game means (at least how I’ve done it) that game periodically checks for new data while it is running and can import the data during run-time. I actually prototyped a game at EA that did just this. So the player could drop a file specifying more data like having a dinosaur model in the game, put the information in the hotload folder, and then their dinasour would  appear in the game. It was really neat, especially as a player, to see data you created become part of the game during run-time.

Before the settings.ini (or the default resolution):

After a tweak to resolution variables in settings.ini:

The other thing I did was implement a lua script for building the graphics assets (and copying files into the final game directory). In debug I merely copy the lua build assets script which makes debugging and testing simpler. But in release the lua code is compiled and then ran. This makes running the lua code more efficient, but it also makes it hard to debug because, well, this:

It doesn’t really matter in this example though for compiling vs plain text as the assets build lua file is run at build time and so compiling the lua file only helps to build faster. It doesn’t affect the player.

Of course I didn’t compile the settings.ini file into binary because that would completely defeat the purpose of having a human-editable file for changing settings for the game. If a human can’t read it, they can’t edit it!

I find the interesting bugs…

So I ran into an interesting bug: I was getting an “incorrect function” error. It was obvious that there was a path error, but this error message was really throwing me off. After hours of trying to resolve (Zeno and my TA Ameya both helped me in trying to resolve the issue), but ultimately I was stuck. I finally talked with the developer (my professor) and he discovered a bug in his code: he was returning the wrong string variable for the error. Once that was resolved we quickly resolved my bug which to my chagrin was the same bug as his: I too was also returning the wrong string variable.

EAE 6320-001 GameEngII Game Engine Project, Game Dev Adventures!

Assignment 4: Utilizing Game and Render Threads for Improved Performance

NancyNewren_ExampleGame 4

Now we’re getting somewhere! The game can now render an arbitrary amount of sprites per frame. In this instance there are four. I think it’s pretty. 😉 (Simple one-click download. Once downloaded, unzip, play the executable, enjoy!)

About the Project

The simplest part of this project was letting the game submit to the graphics a different background color. This data is cached until the renderer is ready to render.

eae6320::Graphics::SubmitBackgroundColor(eae6320::Graphics::DefaultColor::lightGray);

I moved all the sprites and effects out of the graphics class and created them in the game. Because rendering takes a significant portion of time in games, we utilize threads to render while the game computes data. In this implementation the game submits to the render data it wants rendered, which is then cached by the renderer until it’s ready to render. When the game is done submitting it lets the render thread know. When the renderer has finished rendering all the previously submitted data it cleans up that data and let’s the game know when it can start submitting again. This is the point where the threads sync, which is done each frame. At sync the render thread swaps the submitted cache and the cache it just cleaned. It then uses this data to render, and the game has a clean cache to submit data too. Submitting to the render thread is simple, just send over the sprite with its corresponding effect:

eae6320::Graphics::SubmitToRender(m_sprite[0], m_effect[0]);

Each rectangle needs it’s own sprite, but an effect can be used multiple times. So the second sprite uses the same effect:

eae6320::Graphics::SubmitToRender(m_sprite[1], m_effect[0]);

I am using the stl’s vector to create as many (up to the maximum number that a vector can hold that is) sprites and effects as I want. It’s then fairly trivial to submit sprites and effects to be rendered to the render thread.

Even though we are passing reference pointers around for all the sprites and effects, since we can send an arbitrary amount of sprites and effects to render the memory overhead can get large if we haven’t optimized their size. I had previously optimized the sprite and effect size by ordering member variables from largest to smallest. However when I saw the sEffect size I realized I was passing around unnecessary data. I removed it and the size dropped by the size of the variables I removed.

OpenGL
sizeof(sSprite): 12
sizeof(sEffect): 24, 16

D3D
sizeof(sSprite): 24
sizeof(sEffect): 64, 48

I’d only ever looked at the size of objects via code, so it was interesting to me to look at it during compile time. I opened the Debug->Windows->Immediates window in Visual Studio, put in an obvious breakpoint and when the debugger paused, I typed in “sizeof(ObjectName)” and the immediates window printed it out. Thanks to Mark Smith for helping me find the Immediates window.

I am having a recurring Visual Studio run bug. I spent quite some time trying to resolve it. J.P. tried to help as well for a while with no luck. I finally reverted all our changes, closed VS, and rebuilt and the bug went away. The thing is that I’ve done this multiple times and it keeps coming back. Running and building in Visual Studio haunt me and give me terrible nightmares.

EAE 6320-001 GameEngII Game Engine Project, Game Dev Adventures!

Assignment 3: Graphics Platform Independence, User Input

NancyNewren_ExampleGame 03

This game has TWO sprites with different effects! Aww, the awesomeness!

(Simple one-click download. Once downloaded, unzip, play the executable, enjoy!)

About the Project

In this project I made the graphics functions platform independent by creating a cView class. This class handled initializing, cleaning up, clearing, and presenting. Then all platform dependent code and variables went into cView.[platform].cpp files.

Thus the call for clearing the back buffer code now looks like this:

//When rendering
view.ClearView();

I used a color struct to pass colors, and used this to create the pretty gray background (as opposed to black).

sColor lightGray(0.8f, 0.8f, 0.8f);  //alpha is set to 1.0f when left blank
UpdateClearColor(lightGray);        //The UpdateClearColor can be called at anytime to update the clear color

To create a sprite I allowed the user to just send in a center position, width and height — as opposed to several vertices (Simplified):

eae6320::Graphics::VertexFormats::sSpriteVertex center1(0.0f, 0.5f);
sprite1.Initialize(center1, 0.5f, 0.5f);

To create an effect the user need only pass the name of the shader file to the effect:

eae6320::Graphics::sEffect effect1("shader1");

I also added a second sprite and effect so that I could draw in another sprite with different shader data.

Hmm… Interesting Error

We all got stumped on an interesting linker error I was getting early on when making the graphics code platform independent. I have no idea what caused it and it certainly didn’t feel interesting at the time as it sucked up a bunch of my time. I had actually given up on it for the night — I put in macros to the graphics.cpp and moved on to the rest of the game assignment — when finally after finishing the rest of the requirements I caught some problem solving determination, inspiration hit, and finally hit upon the solution: I did function renaming, code manipulation, and the last thing I did was I moved the included  Graphics.h header to be included before the <Engine/Results/cResult.h> header in my cView class. Once I swapped their positions it worked! I cleaned up the code, and then to test things, I moved it back and guess what: still worked! I couldn’t recreate the linker error. The problem was perhaps a couple things, and it’s possible I’ll never know where or what, but it does go to show you that with three friends, determination, and a cool head you can solve a problem, even if you don’t know the exact cause!

Getting it Done

I was initially stuck on deciding how to implement the platform independent graphics.cpp, but once I decided how it should be done the rest just kind of pounded out itself. That’s also about the time Arpit, Zeno, and I congregated and the work went faster, until it got really late, and then it slowed, but it was fun.

Thanks to Zeno and Arpit for helping all night. We helped each other through the entire project and there is no way I would have completed this on time without their help: there was a lot of help going around and everyone helped each other. Zeno is very knowledgeable: he really helped me with structures, architecture, and lots of random issues and C++ nitty gritty questions (It’s great discussing those c++ ideas with him). Arpit is very good at debugging: he helped me solve my shader errors and kept a cool head as I panicked. 🙂 Chen was helpful too: he stopped in for a bit and tried to help me resolve the aforementioned linker error. With everything they all had me try on that problem, it really helped me rule out what wasn’t wrong so that hours later I was finally able to fix it. I have some pretty cool peers.

I love what I do and I love that I get to work with such talented, intelligent, creative, and willingly helpful people. That’s the games industry! From my work at EA, in the EAE program, and in the serious game industry: I haven’t found a better group of incredibly competent, highly skilled people. I love my game dev peeps. They’re the best!

I feel tempted to do a hashtag: #OneLuckyGirl