🏁

Final Report

Official Meeting Time

Project Review

Game concept: 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 game concept has remained largely the same since the first day of the course, when we sat in those cool rolling chairs. We set out to make a chair racing game, and our final product has remained faithful to our vision for it as that. Audience interaction was also central to our initial vision and remained a major part of the game experience.

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

Time constraints and wanting to make a more innovative concept were big factors in the changing of our initial design. Our idea to include powerups was scrapped around week 7 in favor of focusing on improving the audience interaction, which was a more original of the two ideas. Aside from this, however, our final project realized most of the initial design ideas: We implemented all of our original chair ideas, and even gave them different play styles. Additionally, a lot of the early concepts for potential audience interactions have made their way into the final iteration of the game.

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.)

We originally sought to have an MVP done by the end of week 6. This didn’t happen - we didn’t come close to this until week 10. I think we didn’t revisit our plan each week which I think would have helped us to better define what work we needed to do early on. There was alot more time earlier spent ‘waiting’ for code, and we could have prioritized building out features that unblocked us earlier then (ie unlocking everyone to work on ui graphics stuff earlier).

General Questions

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

  1. Our biggest departure from traditional 125 projects was our use of Rust, and we think that this overall was a great decision that made many parts of the project better. In particular, Rust has an excellent package management system, compiles fairly well across different problems, and of course by design has many fewer memory errors than you’d expect from C++. Rust libraries are also very mature and we were able to find libraries for everything we needed without difficulty (see later for specifics).
  1. We also took a very “industry-like” approach to pull requests and merging: we (mostly) reviewed each other’s pull requests thoroughly, (mostly) kept all work on branches off of main, etc. (Check out our commit history!) This was less true for graphics code, where we didn’t have a second person besides Nick with a ton of expertise in the weeds of graphics such that we could really do detailed graphics review; we also had peer review become much more cursory in the last few days of the project, although we still reviewed code semantics. Nevertheless, we think that this was overall a good choice; it saved us some headaches on code that multiple people touched. We only broke the code once with a hasty merge, and we were able to fix the issue relatively easily.
  1. We also had a lot of CI/CD going on, with automated testing (although, truth be told, that was not particularly useful - game code doesn’t usually work well with unit testing), automated build packaging, and packing our resources into the binary - those last two in particular meant that our demo day experience was relatively smooth; we just had to download the pre-built executables and the one asset (the racetrack) too big to fit in the binary.
  1. organizing everything into a core / client / server / web structure. core shared types between client and server, making it really easy to build things together. This structure overall just made development clean + organized.

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

None of us were very experienced in Rust before starting, so we didn’t really think about the fact that the data structures and general approaches we had to use should have been tailored to the constraints of Rust. For example, we initially used a tree-based scene graph for our graphics code; unfortunately, getting ownership and mutability right for a tree when you’re trying to mutate some of the nodes in the tree turned out to be pretty difficult in Rust, so we switched to a flat indexed vector-like data structure instead, which turned out to be a better fit for Rust’s memory model. Another example is that the physics backend for moving players around is awkwardly split between immutable and mutable functions to get around Rust constraints around mutability - in an ideal world, the one small section of that code that needed to operate immutability wouldn’t have condemned all the processing code after it to be immutable as well. (For anyone trying to use Rust in the future: watch this talk and/or read the linked blog post! I really wish we had seen this; we probably would have avoided some of the annoying false starts we had in developing) (Alistair)

UI implementation was weirder than expected for me personally, but it was cool to figure out a solution by heavy use of putting the ui in the background + using images for everything. (Ronak)

Networking was stupid easy to pull off and there was almost no additional work to do on that side after week 2, which was unexpected. (Aaron)

Graphics ended up being quite a bit more time consuming then expected since WGPU is a bit lower level then OpenGL. (Aaron)

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

  1. Our networking approach was very nice, Aaron set up a nice setup with enums that made adding datatypes to send data super smoothly
  1. web client + web socket worked quite well, and it was awesome to see 45+ people connect and vote in real time with the players (and see their votes change the game in real time)
  1. I’m proud of my team for supporting me with helpful feedback & guidance when writing the audio engine. I had never written any Rust before I had started work on the engine, nor had I ever worked on an audio engine before. I was able to learn so much from their critiques. (Peter)
  1. I’m really proud of the chair variety. While they certainly weren’t all balanced, each one was really special and fun, especially with the quirks each one had (like the rotating chair independent of the wheels, S P I N on beanbag/plastic, etc)
  1. Nick was able to implement some bomb graphics, I loved the way the game looked at the end. (Aaron)

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

figuring out placement was definitely very tricky - there were a variety of bugs we faced, and we ended up just barely figuring it out by rewriting our original system. @Alistair Gray and @Josh Cross wrote a lot of this code.

The old code written here was fairly outdated and from an early state of the project. Due to the way in which it was being stored and calculated, the same values were being stored in multiple places, but it wasn’t necessarily the case that this information would be fully updated in every location in every edge case. Notably, interactions that caused players to swap locations (and thus places) were notably buggy. So we redid the entire thing, to ensure only the proper values were used, and no cached values were kept behind when it didn’t make sense.

Additionally, we had to adjust the strategy we were using for map placement logic with triggers. Ideally, we would have checkpoints that could help us keep track of placement mid zone, and zones were few and far between to ensure steady progress, but in the end, to keep things more simple, we simply used a bunch of zones instead to keep track of progress and placement, that way we didn’t need to interpolate between triggers to determine placement at all.

The render graph architecture also started to get annoying real fast because each shader required its own technique class. A lot of the techniques for pixel shader post-processing passes were very similar, so there was a lot of code duplication. I would have preferred that more things be stored by the resource manager so less data would have to be stored per-technique. Looking at other render graphs, I also like it more when the render graph api allows the pass to be written in a single function, like in kajiya (I believe UE has a similar API as well)

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?

  1. RUST GAMING! The major Rust libraries we used were:
    1. font-kit (fonts, client) - because we wrote our own text renderer lol
      1. By the way, don’t do this, just use this. Unless you WANNA learn about text rendering (Aaron)
    1. gilrs (controller support, client)
    1. glam (linear algebra, client and server) - we rejected nalgebra, which was more complex than we needed
    1. gltf (model loading, client and server)
    1. image (images, client)
    1. naga (shaders, client)
    1. rodio (audio, client)
    1. serde_json (JSON serialization/deserialization; client and server)
      1. serde in general is the networking secret sauce of Rust and its 👍
    1. wgpu (Vulkan-based graphics, client)
    1. winit (windowing, client)
    1. an interesting one that we probably would have used if we had discovered it earlier is live_reload (but we didn’t use it, to be clear)
  1. As for environments and tools, we mostly used either VS Code with the rust-analyzer plugin (don’t use the default rust plugin, it’s literally just broken) or CLion with its Rust plugin. The nature of Rust is that we didn’t need to all have elaborate Visual Studio setups with embedded libraries or whatever; libraries and compilation just got handled by cargo. We had relatively good cross-platform compatibility (developing on our own Mac and Linux machines was mostly viable, but the client especially was quite slow and the windowing library on both platforms had some glitches).
    1. Note about IDEs and tools: you’ll have a better developer experience if your environment is configured to use Cargo Check and Rustfmt rather than any other tool that claims to do the same thing. These tools are essentially standard. CLion supports leveraging both of these. By default, CLion won’t catch every error before compiling unless you enable Cargo Check, which is very annoying. (Aaron)
  1. We heartily recommend Rust to future groups. The tooling and environment is excellent, and at its best the developer experience feels like writing code which is really performant and nearly-bare-metal while simultaneously intelligently high-level; constructs like if-let and match, traits, enums, and the surprisingly functional default idiom of much Rust code all made sense and felt good to us. A potentially surprising thing that also felt good is much cleaner linkage - Rust allows you to define methods for classes in different files (!!), so code organization was generally easier, and we didn’t have to deal with header files, pragma ONCEs, etc. Rust release mode is also incredibly good - you get speedups of like 100x over debug builds.
    1. The converse of this is true: you might find that even simple game code runs rather poorly in debug mode. You’ll be shocked at how much smoother your game will run in release.
  1. We’ve already touched on our biggest issue with Rust - memory management is kinda annoying, especially if you’re not architectured with Rust’s memory model in mind; you do get better with it over time, though. That’s really a design and implementation problem, though. Frankly, from a tooling perspective it’s already straightforward to use the language - you kinda just declare the right libraries, use the proper IDE plugins, and you’re good.
    1. The main pitfall of trying to learn Rust for this class is that at the beginning of the project, you will not be writing “”rusty”” code due to your lack of experience and it can bite you later in development. Do not be overly attached to the structure or conventions of traditional game development, by coding in Rust, you have already left that path. (Aaron)
    1. ONCE AGAIN: WATCH THIS TALK (Alistair)
  1. What should future groups avoid? Our joking answer is C++. Honestly, all the libraries and tooling we used worked pretty great with minimal fuss, so our serious answer is also C++.
    1. Unless you have substantially large number of team members that work on graphics or you have a GRAPHICS GOD LIKE NICK NEBEL on your team, it might be a better idea to use a slightly higher-up graphics library than wgpu since that's basically just Vulkan. As is the case with trade offs, choosing to use wgpu means you will want to shrink the scope of your game to compensate. (Aaron)

How many lines of code did you write for your project?

  1. We ended up writing around 18 thousand lines, counted using wc. We used wc because most of the more fine-grained tools (e.g. loc) don’t count wgsl (shader) files correctly.
  1. https://docs.google.com/spreadsheets/d/1jh5TkfhyblU9VFMCai5N7ej7iAt9x0bPcFDjB9VCncE/edit?usp=sharing

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 tool chain 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?

Would you have rather started with a game engine or would you still prefer to work from scratch?

For those who used a networking library (e.g., RakNet or Boost), a physics library (e.g., Bullet), or a GUI library, would you use it 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, judging from the experiences of the groups that did, would you have used it in retrospect?

We rolled our own graphics, networking, physics, audio, and UI, and we’d probably choose to do the same again if we were starting over. We needed to roll our own physics to be able to handle some of the fun audience interactions, and networking and audio were relatively straightforward to write and using a library would probably have been more trouble than it was worth. We did have a few annoying moments with writing our own UI code (and text renderer!), but ultimately that was probably a choice we’d make again as well.

In particular, serde + rust enums makes the hard part of networking so stupid easy there really isn’t any reason to use a networking library with rust. It would just be more unnecessary complexity. (Aaron)

For your group web pages, we used wordpress. Were you satisfied with wordpress, or would you rather have used some other system for maintaining your group web pages? If you had a choice, is there another system would you have preferred to use (or even just doing everything on your own using HTML, CSS, and JavaScript)?

We didn’t use Wordpress; we just embedded our Notion page, and that was quite neat because we had non-public parts of our Notion that we could use as a wiki/scratchpad and for generally persistent text. This worked well for us.

This is the second year we've used a discord server for the class. Would you recommend that we continue using discord in the future?

All the kids are using Discord! We actually had our own server (preexisting, since most of us had chosen to be in a group together before the start of the class) - if we hadn’t had one previously, though, we probably would have used the private channels in the class one. It’s a good platform for communicating, definitely recommend using it in the future.

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?

I definitely learned the importance of facetime - we worked a lot async early on, but I got unblocked a lot earlier when I met IRL (Ronak)

I think it really just highlighted how important it is to keep in contact with each other and know exactly what things are looking like. Additionally, I (Josh) had the tendency to scope creep my PRs, which would cause library stuff I added to enable functionality to be unavailable to other people for long periods of time. It was definitely nice to have that kept in check by some others, but it’s definitely something to keep in mind in the future too.

Using our structure of having extensive peer review does a lot to overcome the limitations of remote collaboration, I highly recommend it. (Aaron)

Looking back over the past 10 weeks, is there anything you would do differently, and what would you do again in the same situation?

A bunch of us were independent workers and would work in the labs earlier + would like to have work sessions earlier in the course rather than just at the end of the course.

Which courses at UCSD do you think best prepared you for CSE 125?

CSE 120 - systems architecture definitely helped

I also think the inherently project based nature of it is REALLY helpful for the adjustment to an entirely project based class

Honestly my internships are the best things that prepped me for this class, as they taught me stuff about communicating, building huge systems (ty startups), maintaining huge systems (ty established companies), and best practices (ty all companies).

CSE 130 - learning about Haskell made Rust appealing ;P

What were the most valuable things that you learned in the class?

Please post four final screenshots of your game on your group pages for posterity. I will display them on the group web page.

Course Feedback

What advice/tips/suggestions would you give students who will take the course next year?

  1. use rust, c++ isn’t as much fun, and rust is such a cool language
    1. but genuinely
    1. think about how trendy and hip you’ll feel using rust
    1. watch this talk first tho

How can the course be improved for next year?

  1. more socials! would have been nice to meet other groups sooner rather than later

Any other comments or feedback?

  1. RUST