Untitled

At the start of the class, you wrote a game concept document, a project design specification, and a schedule for completing the project. These were all projections looking forward. Now that the class is ending, you can look back and compare what actually happened with what you planned.

Project review

Game concept: To what extent did your game concept change from the initial concept to what you implemented? If it did change, how did it change and why?

Our game concept stayed mostly the same from weeks 2 to 10: A character-based ability shooter 2v2 heavily inspired by Four Seasons. The only real “major” changes were the character abilities, but that was partially a result of time constraints, and the particle system looking better than expected.

Design: How does your final project design compare to the initial design, and what are the reasons for the differences, if any?

It stayed mostly the same. We didn’t have time to implement some nice-to-haves such as more ways to interact with the environment. On the brighter side, some new ideas sparked (e.g. dance bomb, ambient particles) at week 8 and we managed to get into the game. Overall, we’re happy that we got all of our main features in and even a few nice-to-haves such as season blending.

Schedule: How does your final schedule compare with your projected schedule, and what are the reasons for the differences, if any? (You should be able to glean this from your status reports.)

[Ben]: We did not follow our projected schedule at all. Some aspects such as model loading were originally planned to be done in week 6, but we had it done during weeks 1 or 2. Other aspects such as UI weren’t even started until week 9, or completed until week 10 when we originally wanted it done in week 5.

[Alan] We didn’t plan start-game and end-game UIs in the projected schedule. GG. But we had good progress so we still managed to get it done a week before demo. However that took away precious playtest time.

[Anh] We don’t really optimize our networking. On the project spec we plan to optimize our networking by sending only necessary, but because we already sent very little, we just leave that as is

[Rana] I don’t think we did a bad job making the schedule, but it was in no way accurate whatsoever.

[Melody] I think the original schedule had reasonable overall pace, but we weren’t able to anticipate which parts would be the most challenging, so our progress doesn’t match up well at all.

[Matthew] I thought our schedule was fairly accurate in the first half of the quarter. However, once we got past all the basic features, we definitely started prioritizing different tasks compared to our initial schedule.

[Joanne] I followed my projected schedule in the first 3-4 weeks, but as the project went we had new ideas and adjustments to the plans. I started doing animations in week 5 while not finishing all the map assets until week 8.

General questions

Describe your development environment. What tools did you use? What was your build workflow? If you supported multiple platforms (e.g., MacOS and/or Linux), 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 relied on Microsoft Visual Studio C++ (MSVC) to build our project. This was mainly a choice of convenience since we didn’t want to have separate build instructions for Windows vs. MacOS vs. Apple Silicon MacOS. Some platforms like MacOS (Apple Silicon) don’t even have gdb support, and it’s a pain to get g++ installed on Windows (Yes MSYS2 exists but it’s more annoying to install compared to Visual Studio).

To get libraries working on multiple platforms we also ended up essentially copy-pasting whatever libraries we wanted into the repository, and building it from source on each of our machines by adding them as subdirectories to CMakeLists.txt. We do not recommend doing this, it would’ve been much cleaner to use CMake’s fetchcontent instead of letting our repository, but we didn’t know about that when we set up the repository… so… yeah.

To account for differences in syscall interfaces, we also added in a bunch of #ifdef _WIN32 ’s in our code to switch between Winsock and UNIX sockets to get networking working across operating systems (sort of). This worked, but there’s a problem: all machines running our game (servers and all clients) must be running on the same operating system since there’s some compatibility issue between Winsock and UNIX sockets we didn’t quite nail down.

[Anh] we only notice this incompatibility on the night before the demo - good things all demo machines use Windows

[Melody] Sometimes things worked on Windows but not on Mac or vice versa (even when we didn’t anticipate that being relevant). I think we always caught this at the PR stage, but it would have been bad if we had merged something with this problem. To future groups, make sure you have one reviewer from each platform you’re supporting!

[Alan] I developed purely on MacOS (Apple Silicon) with VSCode. Just download CMake, install CMake Extension in VSCode, and ur good to go.

(not serious) To any future groups, we’d recommend using a language like Haskell due to its memory safety, and to simplify the process of setting up libraries with its easy-to-use package manager: Stack! (for legal reasons, this is a joke)

What group mechanics decisions worked out well, and which ones (if any) did not? Why?

Our group mainly used a majority-vote system to decide on game features and mechanics. To be fair, we didn’t have that many conflicting opinions after deciding on our core game design. Our group had great cohesion, so this system worked smoothly for us. Any disagreements we had were quickly resolved through compromise.

We agreed to meet in person in the lab during both lecture timeslots and at 1pm on Fridays. We were all often a little late because we all have very normal, and perfectly healthy sleeping schedules, and occasionally someone couldn’t make it to one of those times at all, but it ensured that we were in regular, in-person contact. That helped us stay in sync about the project.

regular, in-person contact

regular, in-person contact

meeting at 9:30 (pm) (Alan taking the picture)

meeting at 9:30 (pm) (Alan taking the picture)

Which aspects of the implementation were more difficult than you expected, and which were easier? Why?

  1. Graphics

    UI: [Alan] Rendering text and images for UI wasn’t as straightforward as I expected. Coming from CSE110, I thought it’s as easy as putting <p> and <image/>, but actually, I had to go through converting font files into distinct OpenGL textures and bind them to each character; loading images into textures and getting the orientation correct is also tricky. Aside from this, I painfully discovered that Mac’s retina screen display would arbitrarily double the GLFW window sizes we set, resulting in UI stuff rendering outside of the screen, i.e. randomly disappearing. This bug was damn hard to find and it wasn’t consistent across Mac and Windows. If I were to do CSE125 again, I would use a UI lib and buy more time for playtesting.

    [Anh] For me, the experience is different, partly because we use different ways to render UI in the game versus in the lobby and start screen. For in-game UI, see the above pain. For lobby and start, it’s easier than I thought as the library we use allows us to build all text and button-like blocks - specify where we want to put the block and that is it

    Shading: [Ben] Getting the cel-shading (toon-shading) to look good was surprisingly difficult. This was mostly because of the amount of learning we had to do on the side on framebuffers and such. We had to tear apart our existing rendering pipeline and then stitch it back together to get cartoon outlines working. We also had to do a few math tricks to remove some of the artifacts that came with our depth-buffer image gradient approach to rendering outlines involving scaling the outline score by the dot product between the viewing direction and surface normal so “outlines” don’t render on steep surfaces.

    Animations: [Ben] Please do not use FBX files please do not use FBX files please do not use FBX files please do not use FBX files. The code for loading animations was correct, but Assimp loaded our FBX files wrong so nothing ended up looking like how they were supposed to. Overall, I think this ended up being easier than expected, which is not to say it wasn’t extremely difficult.

    [Joanne] As Ben said, do not use FBX to export animations. GLB file format works fine for us, recommend. Regarding rigging and animation themselves, they were actually easier than I thought considering I had never done animations in Blender before. My suggestion would be designing smartly, don’t make the models too complex, and you’ll be fine.

    Model Loading (Graphics): [Ben] ****Surprisingly straightforward since we used Assimp (Open Asset Import Library), so all we had to do was define our own data structures for storing vertices and textures, and then render them as normal. This was much easier than expected thanks to Assimp.

    Note on Assimp: while it works well and pretty easily for use in OpenGL, the tree hierarchy with multiple meshes made it a pain to work for collisions. Assimp is super useful and really quick and dirty to use, but understanding the tree hierarchy sucks, and my recommendation is to only look into it if you already have some issues related to it.

  2. Game Engine / Logic

    ECS (Entity Component System): This was overall pretty easy to set up. I think an important rule to keep in mind if you are planning to use such a system is “don’t let perfection get in the way of progress”. Our finalized ECS design is definitely not 100% pure ECS, but it worked! [Rana] ECS was interesting. I think it has some good principles that should be followed, and if we had a more complex game with a lot more collidable objects, and some that were affected by physics, and y’know just more complexities, I think it would have made things feel a lot more worthwhile. However, I found it to be really cumbersome to work with, and just have a lot of boilerplate code for like anything. I don’t think I ever really felt the payoff of most of that boilerplate code, because we didn’t reuse components much (like our collision system was extended to a couple extra things, but since we only ever had like 3 types of entities and they were all statically allocated, it never felt worth). If I did it again, I’m not sure if I’d use ECS again, I’d need to think about that. My biggest advice in deciding whether or not to use ECS is to think about how many layers of abstraction you need for entities, and mostly, how many types of entities with different behavior are you going to have. If it’s not many, ECS is going to be excessive, but if it’s a lot, it’ll help with organization.

    [Alan] I advocated for switching to ECS in week 1. But after week 7, as our game was in a good shape and I grew very sick of ECS boilerplates, I started doing things quick and dirty. I found a hack to get rid of many redundant ECS stuffs when I built the dance bomb system and the lerping system. It made things a lot simpler. Apart from the downsides, I do like the fact that ECS separates everything into systems and components. It requires some art of designing.

Which aspects of the project are you particularly proud of? Why?

[Rana] I think this is a really personal question, so I’ll answer with what I personally am most proud of. I think we did an extremely good job with developing a cohesive and pretty environment. I am also particularly proud of this because I had a hand in a lot of the things that helped add to this effect. The main features in question are the changing seasons (which shout out to Ben for the dynamic texturing and Melody for the high level interface, and particle systems which again were Ben and then Melody and I for the interfacing) and more subtly, the collisions. The collisions are my favorite individual addition, and I think really added to how interactive and real the world felt, and also just made the entire thing feel more polished.

[Matthew] Our core gameplay. In my opinion, our game is quite easy to understand and learn, yet is still fun to play.

[Ben] I’m proud that we got a working game together, and all managed to exceed our original expectations to some extent. We managed to get all of our core features in, as well as some bonus features such as the dance bomb and having the map actually change with the seasons. As for individual contributions, I’m proud of the animation system since I refused to write code that I didn’t understand, speedran a significant portion of CSE 169 (Computer Animation), and wrote the animation system working on and off over a weekend. Other groups that got 2-3 graphics people that took 3+ different graphics classes got nothin’ on us.

[Alan] Dance bomb, bullet, and the music (biased cuz I worked on those). I’m also very proud of every team member we have.

[Joanne] I’m proud of our game map, especially season transitions. Or I should say I’m particularly proud of my teammates as they tried and managed to implement the designing ideas I had as an artist and all worked out so fine. I was wishing for a lot of features (texture blending, sky box, etc.) to make the map look good while have no idea how to implement them in our game engine. Those work are easy to do in 3D software but to implement in our code involves a lot of study that nobody had ever learned before. I’m glad that we figured them out and ended up with adding most stuff as we planned.

What was the most difficult software problem you faced, and how did you overcome it (if you did)?

[Anh] I would say setting up the Cmake to work properly on Visual Studio is an absolute pain. Because we have all libraries instead of fetching on build, the setup in Cmake is very annoying. Additionally, on Visual Studio you always have to Ctrl + S on the CMakeList file in order for all libraries to properly setup. Also curse ChatGPT. When I was working on the imgui it gave me deprecated code that works perfectly fine on Windows but completely crashes on MacOS. Trying to debug that on a Windows machine is a very “fun” time.

[Ben] Most of my issues were self-contained since I worked on isolated stuff compared to the rest of the codebase. But the most difficult problem probably was loading in animations, curse FBX files, but I already wrote about this in other sections of our report (I wrote this section last).

In developing the media content for your project, you relied upon a number of tools ranging from the underlying graphics libraries to modeling software. And you likely did some troubleshooting to make it all work. So that students in future years can benefit from what you learned, please detail your toolchain for modeling, exporting, and loading meshes, textures, and animations. Be specific about the tools and versions, any non-obvious steps you had to take to make it work (e.g., exporting from the tool in a specific manner), and any features or operations you specifically had to avoid — in other words, imagine that you were tutoring someone on how to use the toolchain you used to make it all work. Also, for the tools you did use, what is your opinion of them? Would you use them again, or look elsewhere? Are there any tools that you used but, looking back, you would avoid?

For those who used a networking library (e.g., RakNet or Boost), a physics library (e.g., Rapier or Bullet), an audio library (e.g., SFML or SoLoud), or a GUI library (e.g., imgui or nanovg), which libraries did you use and would you use them again if you were starting over knowing what you know now? Describe any lessons you learned using it (problems that you had to troubleshoot and how you addressed them) for future groups who may use it. If you did not use a library for any of those modules, judging from the experiences of the groups that did, would you have used it in retrospect?

Graphics: Like many other groups, we used OpenGL for our graphics. We used a relatively “standard” suite of libraries as other groups (historically). Open Asset Import Library (aka Assimp, why is “Asset Import” its acronym?) to load in Joanne’s .obj 3d models and textures, paired with stb_image to handle some image loading (for textures, UI, and whatnot). Overall it was quite a smooth experience to load in models and textures, aside from Ben’s skill issues in certain instances with loading textures. There are a few (small) inconsistencies between Assimp’s method of loading material properties/textures and .mtl files, such as bump maps in .mtl files being imported as height maps in Assimp, though this is relatively small and can easily be debugged. We found loading in animated .fbx files with Assimp to be a bit of a nightmare, though we’re aware that other groups have found some success with them, it’s possible that some of these troubles were simply due to how the models were exported. For one, Assimp loads bone indices relative to the first vertex of each mesh (which is small, but was a little annoying), it also just added random linear transformations to binding matrices, such as scaling everything by 100x, and then some of the animation channels would try to compensate for this with 0.01x scaling. Now on paper this seems inconsequential, but for some reason, the results were… horrific.

Untitled

This was our summer bear model, by the way.

We literally just changed the model formats to .glb’s and everything worked magically. Nothing in our code changed, just the file format. In short: Be careful with using Assimp.

Assimp also sometimes struggles with loading compressed .jpg and .png files, so we needed stb_image to load some textures in. stb_image was super easy to use, we highly recommend it. Thanks to Melody for setting that up for us.

Networking: we use Winsock for Windows and UNIX socket for MacOS

Physics: We did the physics ourselves (mainly using raycasts to detect collisions), and it turned out pretty well. The collisions were challenging but rewarding to work on. The end result is very close to exactly what we wanted.

Audio: we use SFML for sound. This works pretty well for us as they have example on how to use it. The hardest part about SFML is to set it up to work with our existing CMakeList file - this took longer to get working than the actual programming the sound

GUI: we use dear imgui for the lobby and start screen. I really like this library because all you need to setup is to copy all the necessary files from the imgui repo (the docs tell explicitly what you need to do) and no need to touch CMake. imgui is quite easy to use: all components are treated as “block” and we just need to specify the location on the screen for that block.

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 when developing in that language? Would you recommend groups use the language in the future? If so, how would you recommend groups best proceed to make it as straightforward as possible to use the language? And what should groups avoid?

We used C++. Please make sure you have a CMake guru like Tyler from group 3 (or have someone be willing to learn) or your repository will become a mess like ours.

How many lines of code did you write for your project? (Do not include code you did not write, such as library source.) Use any convenient mechanism for counting, but state how you counted.

Untitled

Joanne (luoluobuli) is our MVP, with 6.6 million lines of code committed! (this count includes lines for models and libraries)