To what extent did your game concept change from initial concept to what you implemented? If it did change, how did it change and why?
Our initial game concept was a Five Nights at Freddy’s x Night at the Museum game where users get chased by artifacts at night, but we eventually developed the concept and ended up with a ‘security guard vs thieves’ concept. No one really remembers how that happened, but it was probably just the result of a lot of “oh, but what if we added Z too” and “instead of X, why don’t we try Y instead.” I, for one, am glad we didn’t keep the horror game concept because I don’t mesh well with anything horror related :)
Design
How does your final project design compare to the initial design, and what are the reasons for the differences, if any?
The final project design was a little different from the initial design as we didn’t have enough time to put another male thief into our game. Otherwise, the overall design turned out to be quite close to the initial design.
For the security guard, we initially design the character to have multiple “weapons” to help with catching thieves, but due the time, we just give the character a magic ability to catch the thief when getting close enough, without any appearance showing that.
We initially also want to emphasize the storyline behind artifacts to show the reason the thieves want to steal them, but did not work on that part.
Schedule
How does your final schedule compare with your projected schedule, and what are the reasons for the differences, if any?
Our projected schedule was probably a tad too optimistic. Due to various factors we hadn’t really considered when we first came up with our schedule–features being more difficult to implement than we thought, code breaking when switching from Mac to Windows and vice versa, nonstop bugs, assignments for other classes, etc.–we ended up running behind schedule, especially towards the last few weeks. So instead of finishing the core of our game by week 9 and spending week 10 testing like we’d initially planned, we finished our game about twenty minutes before we were due to present.
Development Environment
Describe your development environment. What tools did you use? What was your build workflow? If you supported multiple platforms, how did you support making your project work on all platforms? Do you have any tips or suggestions for future groups for their development environment?
We use visual studio on Windows and VS code on MacOS for our development environment, and we use cmake to manage the build process. To ensure cross platform compatibility, we used preprocessor macros (for example #ifdef _WIN32 #ifdef_APPLE,etc). We also made sure to test our code regularly on both platforms to catch any OS-specific errors.
For future groups, one suggestion would be to keep the platform-specific code isolated and well-documented to avoid errors. And also using git to manage version control to avoid merge conflict when working across different platforms.
Group Mechanics
What group mechanics decisions worked out well, and which ones (if any) did not? Why?
We chose to hold our group meetings over Discord, and I feel that the remote nature prevented us from being able to get to know each other in the first few weeks. We also had technical issues (mainly audio issues) that wouldn’t have resulted if we’d had our meetings in person instead.
We tried to work in modules, but this led to some issues later on during integration because development felt very separate.
Challenges
Which aspects of the implementation were more difficult than you expected, and which were easier? Why?
It was quite difficult to properly export and import 3D models, textures, and animations to our game engine. The format by which the models, textures, and animations had to be exported to display properly in even conventional 3D rendering software was challenging and required significant back and forth between the artist and graphics. We knew it was going to be a tough process, but we weren’t expecting to not have wall and floor import issues fixed by the demo day.
Parsing how Assimp organized its information for animations was more difficult than expected, as information about bones vs. animations were located in different places.
Maintaining integration between Windows and Apple was more difficult than we expected. Differences that we thought wouldn’t exist or resolving would be straightforward often resulted in a wild goose chase that would make progress difficult.
Once ImGUI is imported, it becomes very intuitive to place. However, the positioning of the elements could go off when we resize the window, but since we are only presenting using a full screen, we made sure everything was positioned right on full screen.
Setting up the sound took me a few hours to work properly. That was just to import miniaudio and soloud library to make a sound.
Implementing the 2D game is easier than expected but integrating it into the main game is much more difficult. The first problem is the incompatibility between different OpenGL versions. Initially I(Shuyang) used OpenGL 2.1 system (Core Profile)to implement the minigame, but the main game is using OpenGL 3.3, and some functions no longer work, everything related needs to be rewrite. The second problem is we don’t know why every picture in the game was upside down in the merged new game. Jessie spent more than 2 hours and did not find a solution, so we finally just rotate and flip the imported images. The third problem during merge is when dividing the original part into client and server, some parameters need to change (like the gravity, since it needs time to send and receive signals), and the scale of images also need to adjust because of different window sizes.
April: even though we were provided an example server and client implementation that used raw sockets, getting that code to run and debugging any resulting issues was a lot more difficult than expected. Part of that was because we didn’t know how the code worked, which meant we had a hard time pinpointing where issues in our code were coming from, and part of that was because we kept running face first into firewalls.
NPCs parts were easier than I expected. Because at the beginning, we talked a lot about integrating AI into the game and applying that to NPCs. Worrying about how to do that initially. But then I just realized that instead of using actual AI, I can just simulate that behavior through randomness, which provides a much simpler and effective solution in limited time.
Pride
Which aspects of the project are you particularly proud of? Why?
Heather: I am particularly proud of how fast I was able to create two high-poly + normal map character models in just one week.
Sue: I’m proud of the system I came up with for keeping track of textures and models. My texture system would try to avoid loading in duplicate textures by assessing whether the texture name was identical, which I thought was pretty nice. The structure for the models vs. meshes vs. instances of meshes vs. instances of models was also something I thought was very clean and made future edits and changes easier.
April: I’m proud of our server and client, although I might be a little biased because I helped write a lot of it. We experienced a lot of issues from the get go but were able to figure them out, and our baseline client/server implementation was such that adding additional game logic later was quick and easy (ish).
Jessica: I’m proud of how gameplay components like special abilities finally work out with other parts of the game together. Also proud that we were able to fix so many bugs throughout the process, although still some bugs left.
Shuyang: I’m proud of the whole reasonable storyline of the game (thieves steal, security guard protect, catch, reenter, and winning condition). We blend many components(special abilities, 2D games, Asymmetric confrontation.etc) into the short game and make it reasonable. Almost all game features we discussed at first were achieved.
Angie: Also proud of our server and client and figuring out how to design the packets
Jessie: I like the UI design I came up with, and the sounds I found really suit the game. Though it had problems when integrating with the rest of the game during presentation, I’m glad we still were able to show it off individually and eventually added it to the game (thirty minutes after the demo.)
Difficult Problems
What was the most difficult software problem you faced, and how did you overcome it (if you did)?
April: Once the baseline server and client were completed, I transitioned to working on integration, which meant I was working a lot with code that I didn’t write. As a result, figuring out how to modify said code so that it could be split between the server and client, and subsequently trying to debug those modifications, was difficult because I didn’t really understand the original code. The solution (surprise, surprise) was to spend more time looking through and running the original code until I did understand how it worked, and only then trying to move it to the server and client.
[Shuyang]The incompatible problem. Thanks ChatGPT, or I may spend much more time on finding the problem. The Immediate Mode including `glBegin`, `glVertex2f` and `GL_QUADS` were not supported in Core Profile, and the window would be black without any errors and warnings. I talked about this situation to GPT and it gives me several possible reasons, the last one is that. And I fixed it by replacing every part using Immediate Mode with Core Profile, like VAO, VBO and shader. And for background, character, and platforms, there are three parts that need to change, which cost lots of time.
[Jessica]One software problem I faced was moving from writing local gameplay logic to working on multiplayer features. This required me to understand our networking system in detail, including how packets were sent and received between the client and server. At first, it was overwhelming, but by reading the networking code closely and testing small changes, I was able to figure out how to do those things.
[Angie] Integration between server and client code was also the most difficult part for me as I spent a lot of time debugging until I realized I made a wrong assumption about the client code and needed to spend more time understanding it. The minigame was particularly difficult since it originally used the window width/height for its calculations, which the server shouldn’t need to know about. My approach was to have the server send over its coordinate system to the client, which can then scale based on the window, though I wasn’t able to get this working without bugs before the demo. To have an easier time integrating next time, I’d want to decide on what the server & client would communicate to each other before the feature gets coded
[Sue] The most difficult part for me was getting the animations working. Determining how to organize how animations should be stored and accessed, and how Assimp itself stored its animation and bone information was something that took a lot of time. In particular, debugging animations was something that was quite tedious, and I had to attempt a lot of strategies, like checking the logic by putting the animation logic on the CPU for a while, or disabling animations on the mesh itself and instead checking the value by setting the color of the mesh to be the color of the new computed normal. There was also so much that could be the issue for why an animation wasn’t working. For example, animation code that worked previously would fail, and it would take looking into that specific model’s animation in Blender to find that the reason was that it was using a method of animation that wasn’t supported in Assimp for fbx’s.
[Jessie] Integration with the rest of the code was difficult especially since I am working on Mac and our demo is on windows. Unfortunately, I only started moving stuff and testing on the window last week (which is something I should have done much earlier). Because at the stage our game is pretty huge, it takes a long time to compile everything, and makes it much harder to debug things quickly because we have to wait ten minutes just to fetch all changes from remote and make it run on a local machine.
Toolchain
Please detail your tool chain for modeling, exporting, and loading meshes, textures, and animations. What is your opinion of the tools you used?
Blender was used to create 3D models, textures, and animations. I think one of the most difficult issue I had to solve was to figure out how to export textures properly so that our game engine can render them properly. Since there are a lot of features in texture node system that only work in Blender, I had to bake the texture into image texture and export it as a base color. Overall, I would say Blender is a great tool for those who are interested in learning 3D modeling, as it is free. I was considering using Maya, which is free for students. The reason I chose to use Blender instead was because I have a very limited experience with with Maya despite being the industry standard.
Assimp was used to import in both models and animations, and to locate textures that are attached to the models.
For loading in the models, make sure to observe the diagram in OpenGL for how Assimp organizes its model information closely. To support multiple instances of the same mesh in one model, there are two different structures: “Nodes” that have to be traversed from root to child, and meshes. At each child node, you should be constructing a matrix for the child by multiplying its parent matrix with its local matrix and drawing the mesh linked to that child node with the resulting model matrix.
If you draw only the meshes, if you use a 3D model file type other than simple ones like obj, you may have missing objects in your mesh.
Also, this has to do with Blender, but never put a group marked by an orange triangle (ie. a mesh) within a mesh. This will mess up your export file, at least as an fbx. It will result in a bug where the mesh itself exists in the fbx, but no child node exists for it. So, even if you try to display the .fbx model in another 3D viewr softwares like Blender, those meshes will be invisible.
For animations, it’s… it’s just a head scratcher, no way around it. Look at previous years … good luck. As a quality of life, since you can grab the names for the animations that have been saved to a model, you can keep the names of the animations as strings so that you can streamline the assigning of animations to whatever names or states you link them with.
Another tip, for animations, don’t do the thing where you assign a mesh as a bone for animations, there’s issues with support for that. Instead, just use vertex weights.
If you’re trying to extract texture paths from your model: Unpack all materials. Otherwise, you’re going to have objects that don’t have a texture path, or ask for a folder instead of a texture in a folder. Also, I recommend you export paths as “relative” in Blender, otherwise you either won’t have a path from Assimp or you’ll be left with an absolute path.
Finally, if you’re trying to get compatibility between Apple and Windows, do not export your files from Blender on a Windows computer. Currently, Blender will turn all paths into the Windows path that uses backslashes if you export on a Windows computer. This will cause textures to fail to load on the Mac side. Windows will open files with file paths that have the UNIX-style forward slashes just fine, though.
The documentation for the library is fairly spotty and I recommend you find places that have used the library to track down the particulars of how it functions.
Libraries
Which libraries did you use and would you use them again if you were starting over? What lessons did you learn using them?
[networking] we originally considered using Boost because it’s cross platform, but ultimately chose to stick with raw sockets because we’d heard that Boost has poor documentation; we were concerned that the lack of documentation would make things difficult once we started adding additional features to our server and client. Ultimately, I think we made the right choice, and even though the groups that did use Boost seemed to like it, we still wouldn’t have used it in retrospect. There’s a lot more opportunity to learn when implementing a client and server using raw sockets, and you get to see how the different components all fit together instead of having it all hidden behind library calls.
[GUI library] We used ImGUI and it becomes fairly easy to use after getting familiar with the library. Just to make sure that you are swaping out the buffers only once after rendering both your game and the gui to prevent flickering.
[audio] I started out with using only miniaudio to add sound to our game, but trying to use it directly was such as hassle, I had to import soloud library and using miniaudio as the backend for it, and it become much more easier. However, miniaudio only supports wav format audio, so I used audacity to convert all sound audio to .wav format. I found most of the sound effects/ music on youtube audio, which is free and relatively easy to use.
Language
If you used an implementation language other than C++, describe the environments, libraries, and tools you used to support development in that language. What issues did you run into? Would you recommend the language for future groups?
We only used C++
Lines of Code
How many lines of code did you write for your project? State how you counted.
About 11,908 lines of code; the method used for counting was to make a new branch, delete all code that wasn’t written by us, and run find . \( -name '*.cpp' -o -name '*.h' \) | xargs wc -l
Group Dynamics
What lessons about group dynamics did you learn about working in such a large group over an extended period of time on a challenging project?
We learned about the importance of communication and keeping up with the schedule. For example, Sue could be in a situation where she couldn’t work on her graphics part and test the models out on time if Heather didn’t finish making her models by the scheduled time.
We also learned about how much of a difference bonding can make. We got a lot closer in the later weeks because we were working together more to get the various parts of our game integrated together, and I think that made the last few days go a lot more smoothly: even though we were under a lot of stress, we were able to laugh with each other when things went wrong instead of taking out our frustrations on each other.
Retrospective
Looking back over the past 10 weeks, is there anything you would do differently, and what would you do again in the same situation?
Heather: I think I would definitely make the character models low-poly to save time and make a few more thief characters available for character selection.
Angie: For changes, I would want to settle on code design sooner and integrate in shorter intervals. For example I think it was worth the change going to packet classes for networking, but it took awhile to catch it up to the most recent changes and more time was spent on reworking the newer code until it was ready to merge in
Sue: Definitely integrate the branches earlier, enough so that by week 4 or so it feels more like building on top of what is integrated instead of combining separate modules.
Shuyang: works more on various parts. I want to learn more on imgui and sound effects, but most of the time I focus on my own gameplay and only involve it in the last week. If I do it again, I would like to save time on coding game logic and learn more about GUI and sound.
April: I would’ve liked to be more involved in the other components of our game (game logic, graphics, etc.); I think I could’ve learned a lot if I’d worked on those components directly. That said, I really enjoyed working on networking and integration, and doing so allowed me to have a fairly good understanding of how all the various components of our game worked, both independently and together. One other thing I’d do differently is to not leave key components of the game to the last minute. Turns out it makes for a very stressful few hours leading up to the demo :D
Jessica: Start early, do not wait for others' complete work, just start whatever can be done. And also integrate things early. At least get a chance to test everything on the demo machine before the final presentation.
Jessie: Try to do more team bonding events to get to know each other better. I got to see my teammates more only during the first two weeks and final two weeks. During the other weeks we were mostly working separately.
Courses
Which courses at UCSD do you think best prepared you for CSE 125?
CSE 169 (for graphics and gameplay)
CSE 167/168
Youtube Blender courses
CSE 110, CSE 120
Valuable Learnings
What were the most valuable things that you learned in the class?
Run cmake ..
Mixamo-produced rigged characters may have issues with weighting. Keep in mind that you would have to make changes to the texture painting.
Check the exported models and animations in an established 3D viewing application before tearing into your code for issues.
Course Feedback
For the pizza celebration after the demos, what did you think about having it in the B270 lab so that people can play each other's games?
Yes definitely! It was fun to play others’ games.
Very fun, it was a good way to wind down and ask about how people did stuff in a more casual setting.
Advice
What advice/tips/suggestions would you give students who will take the course next year?
Do not leave everything to the last minute.
Finish making any models until Week 9 so that graphics person has enough time to code & implement them.
Integrate early
Make the whole game process clear early
Suggestions
Do you have any suggestions for improving the course? Any other comments or feedback?