Home Specifications Weekly Status Reports Media

Final Report: June 11, 2020


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?

Compared to our original concept we drafted at the beginning of the quarter, the overall concept didn’t change much. Over the course of the quarter, we added and changed ideas and cut ideas that we decided wouldn’t be feasible to implement within the time constraint, but at its core, the concept is the same (third person tower defense game in arena type map). We implemented the must-haves and should-haves that we came up with in the project specs.


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

[Charles] Around week 4 or 5, I realized the inefficiency of my original design of the server’s communication to the client. The data was unbounded and would be continually read until an ending delimiter was found, but that caused issues with sizing buffers and knowing how much data to send and receive and clients falling behind the server, so I posted on Piazza and Geoff gave a couple examples of designs that would solve these issues. I ended up going with sending the size of the incoming data packet first, and then sending the data immediately after. This way the client could do a non blocking receive to check for a packet size, and then do a blocking receive to get the data.

[Kevin] We initially used OpenGL to render our client in the first four weeks. We eventually transitioned to using the forge to render when we decided that it would be viable for use. This transition was essentially a complete overhaul of the original client codebase


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 stayed on track of the calendar for the first few weeks. We had some delays during midterm seasons. Originally, we had designated the end of week 4 as our deadline for our MVP, and then had planned to spend the remainder of the quarter adding in features from our “should have” list. However, we ended up adding features throughout the entire quarter and ended having a playable game towards the end of the quarter that had all of the features from our “must have” and “should have” lists. In this manner, we deviated from the schedule in that we never had an MVP milestone. However, we still ended up accomplishing our goals with a little speedy development at the end.

[Kevin] Surprisingly, I was able to follow the graphics schedule pretty closely. The only differences were that I didn't get to work on optimizations week 4 or 5 (didn't optimize at all in the end) since I was still refactoring code, and I ended up working on particles weeks 7 and 8 instead of week 5 (hence less cool shader effects). This delay in particles was because I didn't anticipate how differently the Forge would handle uniform data from OpenGL, which is key in the implementation of particle systems.


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

In terms of software methodologies, we tended to agree upon at least two weekly meetings. The first was right after our class meeting with Professor Voelker and Edward, and the second was on Saturdays where we would discuss our weekly progress and any blockers we might have had. I believe this worked out well for us given our unique development circumstances (being remote). We also had group coding sessions every so often so that the entire group could remain caught up with the development, and these were nice because we all got to help each other out with difficult features. Otherwise all other communication was through a Discord server with separate channels for each component of the project (like Slack).

Another thing we executed well was version control. Everyone in the group was good about making new branches for each feature being developed and only merging once everything was tested. Because of this, we were able to avoid breaking any existing features (which was very lucky especially as we approached the demo!).

As far as things we want to improve for next time, we think having more in person interactions would be helpful in making sure everyone was on the same page with development and avoiding having one person debug a nasty bug all by themselves throughout the night! If we had been on campus in person, we would have accomplished this by meeting in the labs to develop at least a couple of times each week.


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

[Jimmy] In the beginning of the quarter, I had never used Visual Studio before and knew nothing about graphics. I started the network code with just using the bash and gcc compiler. Later, we merged the network code with the graphics code written in Visual Studio. It took me sometime to get the code running on my laptop and get used to Visual Studio.

[Charles] Asynchronicity was definitely the biggest hurdle for me. Getting the main server’s game engine thread to communicate with the client handling threads, and the client handling threads to communicate with the clients, making sure data is written and read without race conditions, timing server and client update cycles to have a stable update rate that still renders smoothly, it all added up to a huge system with a lot of moving parts that needed to work together nicely.

[Hao] Networking is more difficult than what I expected when we integrated the networking part with the graphics part. As Charles mentioned, asynchronicity is a big challenge for us. We spent so many hours debugging this part. Besides coding, setting up the coding environment is actually much harder than I expected. Since I do not have a Windows machine and cloudLab does not work very well, I spent almost a week installing Windows and setting up everything on my Mac. Implementing the UI display is actually easier than I expected. The UI utility functions Kevin setted up are easy to use and worked out really well.

[Kevin] Setting up the visual studio solution for the client was a lot harder than I expected. I was adapting it from the Forge's unit tests, so there was a lot of extra bloat and weird file structure. I ended up having to nuke everything 4 times when trying to get baseline code. On the other hand, I found animations to be easier than I thought (not counting the animation asset pipeline). The interface provided by the Forge was pretty simple to figure out.

[Aditi] When we started, it was really difficult for me to visualize the trajectory for the quarter. I didn’t know whether we should focus on graphics first, networking first, modeling first, or all of the above! I also didn’t know what role I would settle into in the group since everyone else seemed to have experience with either graphics or networking or modeling and I didn’t have experience in any of those areas. However, I think throughout the quarter, I learned a lot from my peers and about how the different components of the game interact. I was able to find places that I could contribute well! As far as a specific feature that I found the most difficult to implement, I wouldn’t say there was one that particularly stood out. However, I think making design choices for the gameplay logic was difficult for me (especially since I didn’t have a good idea of how server client communication was going to work at that point).

[Esther] 3-D modelling in general was more difficult than expected. Like I mentioned in the live game demos, Blender isn’t the most intuitive to use for beginners. I originally had thought that it would be easy like graphic design using Adobe Illustrator, for example, but oh boy was I wrong. It was definitely a steep learning curve but once I got the hang of it, through trial and error, mistakes, countless youtube tutorials, it is really fun to do. On the flip side, animations weren’t as hard as I have been warned. They were probably the most fun to do since I could get creative with them. Only issue was that my animations were not being saved due to a Blender quirk when starting out, resulting in losing progress and having to redo some of them.


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

[Charles] I’m proud of our data handling system. The structs and inheritance and abstraction that I set up ended up being quite robust and made it easy to extend and add features. The idea of minions dropping resources on death was a last second addition. We had the idea on Sunday night the week of the demo, but because of the layers of abstraction, it was easy to implement and I had the necessary classes and logic written and tested by Tuesday.

[Jimmy] I’m really proud of the multithreading implementation and how we handled race conditions. I’m also very proud of the models that we have for the game.

[Kevin] I am particularly proud of the scene graph framework I wrote. While it did seem buggy at times and is definitely not optimal, it was robust enough to make scene management straightforward, providing a clean abstraction away from the actual rendering engine so Charles could work with an interface he was relatively familiar with from CSE 167. On the gameplay side, I am pretty satisfied with the amount of strategic diversity our game provides.

[Hao] I’m proud of how everything came together at the end. Since I worked on multiple aspects of the game (networking, game logic and UI display), but I never actually saw everything running together until the last few weeks. I am very proud to see how those different aspects integrated with each other to generate an organic and cohesive whole.

[Aditi] I’m really proud of how all of the features we built in the game came together so well! I was afraid gameplay would be too simple or choppy, but it all made sense and the game interactions were fun! The harvesting of resources, towers spawning minions, and the overall aesthetic of the game made for a fun user experience. At the end of the day, I’m really proud that all of our work came together smoothly and the game showcases all of our skills and hard work.

[Esther] I’m proud of all my models, animations, and maps. Some of the stuff I made didn’t make it to the final game but even so I’m more than pleased as to how things turned out. I’m also proud of the improvised ideas I had throughout the process, such as a claw machine to spawn small minions (I literally had an epiphany when I struggled to come up with a concept for the minion-spawning tower for the longest time). Kudos to my team for bringing life into the models I made. I think our game looks really visually pleasing, especially for the amount of time we had and the circumstances of the quarter.


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

[Kevin] Definitely the biggest software set back for me was an issue with connecting to localhost. This disallowed me from testing the client-server code early in development. I wasn't really able to resolve this, but I was able to get past it with the help of our TA, Edward.

[Jimmy] For me, there are not a lot of software difficulties. I only had a problem with downloading the assets when we were merging the graphics and network. Later, I realized that it was my problem. I fixed it after redownloading the .obj files.

[Charles] We had an issue of the size of our data packet being larger than the internal packet size of tcp sends. Sometimes, and only sometimes, when the send volume was larger than the internal packet size, only the first packet would be valid and the rest would be corrupted. We managed to mitigate this issue because Kevin compressed our data packet enough to the point where our data packet wouldn’t cross over the internal packet size until much later into a game.

[Hao] Working with 1460-byte payload limit of TCP connection via Ethernet. We were not aware of this limit when we designed the server-client communication mechanism. We dropped those updates if the data we received is not complete. Besides that, I personally had issues with setting the environment. I tried using cloudLab but that does not work well because we do not admin access to those machines. Later I installed windows on my local machine. Also group coding sessions via zoom or VS code live share helped a lot. Toward the end of this quarter, I used the demo machines a lot and worked out very well.

[Aditi] I think for me, the biggest software issue I faced was setting up a convenient development environment. I couldn’t run the game unless I booted into Windows, but frequently had issues with my Windows partition being to small and having to repartition, or redownload software that seemed to bug on my dual boot, and just in general having to boot back into mac when I wanted to work on something other than CSE 125. Once the demo machines were up and running, that became much simpler for me and I was able to develop and test my own work a lot faster.

[Esther] Losing my animation actions in Blender. The issue occurs when there are multiple animations for the same mesh, and only the most recent animation was being saved in the file. The common issue and problem can be referred here


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?

N/A


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.

Counts found using “find [code files] | xargs wc -l” in bash (Thank you team Solarware from 2017)

Client Common Server
Line counts
  • *.h: 1,046 lines
  • *.cpp: 3,292 = 4,792-1,500(amount of lines likely copied from the Forge)
  • shaders: ~300 lines (most taken from the Forge)
  • *.h: 943 lines
  • *.cpp: 1,608 lines
  • *.h: 116 lines
  • *.cpp: 1,502 lines

Total: 8,807 lines of code


In developing the media content for your project, you relied upon a number of tools ranging from the DirectX/OpenGL 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?

[Kevin]The pipeline for static objects (like the map and laser tower) was as simple as exporting to gltf (a json like format) in Blender. The Forge uses cgltf to import the mesh (in the Mesh folder) and load the corresponding textures from the Texture folder. For exporting animations from Blender, I used a two step pipeline. First, I wrote a python script loaded into Blender to export the Mesh+Armature and each animation action seperately into a folder. This folder is then moved into the Animation folder in the Assets folder. Next, the Forge has a AssetPipelineCmd project written in c++ that converts Assimp exported gltf to ozz runtime files. I modified this code slightly to convert Blender exported gltf (a restriction that came from this is single mesh, single armature, single material). I created a batch file to call AssetPipelineCmd on all subfolders of the Animation folder to generate the ozz runtime files, which are then loaded by the Forge in their Third Party wrapper code.

[Esther] Using Blender 2.8, I created pretty much all the models in the same file so that it was easy to figure out the relative proportions of the models relative to each other. To save a model for use in our game, I would select the model and export as .gltf (enable “separate .bin and textures” option). Once it came time to do animations, I figured it would be way too clustered to work in the same file so I’d export each model of interest as an OBJ file (had issues importing .gltf in Blender from my experience), and then reimport the OBJ file into a new Blender project file so that the file is only concerned with that one model. To export animations, I loaded and ran Kevin’s python script under Blender’s Scripting tab.


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

[Charles] A game engine definitely would have made things easier in the beginning, but I learned a lot from diving deep into the details of creating a scene and the different tradeoffs for implementation choices. One question we had to answer in the beginning was how complex scene management on the server should be. Should the positions of objects be as complex as on the client-side, using matrices and translation vectors, or should it simply be two floats that are incremented and decremented? How complex should the communicated data be? In having to think about and answer these questions, I got a taste of what kinds of questions are important in a real development environment. Also, because we built it from the ground up, the Forge notwithstanding, I knew all the bits and bolts, which made communication and scene management much easier to debug. They weren’t black boxes that are hard to look inside, they were manageable systems inside which I knew where print statements should go.

[Jimmy] I would prefer working 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?

[Charles] WinSock behaved about as expected for anybody who’s taken 124. For groups who haven’t, find somebody who has haha. The only issue I ran into with it would be the internal packet size thing, so I’d say compress your data and only send deltas.

[Kevin] For rendering, the biggest "library" we used was the Forge. The greatest setback in using this library was most certainly learning the code and refactoring it, which took about one week each. I definitely learned a lot about the graphics pipeline that was abstracted away by OpenGL while doing this, but this did take a lot of time (essentially a quarter of the development time). The hardest part to learn was how the Forge handles the equivalent of OpenGL's uniforms, which combines paradigms from Direct3D and Vulkan (Root Signatures, Descriptor Sets, and Buffers). In retrospect, I might have been able to have more graphical effects had I used OpenGL since I was more familiar with it at the time. However, if I consider the amount of 3D assets we used, I do think that using the Forge was the right choice, since they had a good built in framework for importing static and animated objects with complex materials. Otherwise, I would have likely had to learn to use Assimp and write a bulk of my own shaders, which might have taken a little less time, but may put more restrictions on the types of 3D assets we could import increasing time costs for 3D asset production. Using the Forge, they had example code for asset loading, so I was able to diagnose early what aspects of modeling in Blender would be preserved in our engine. The bar for a MVP graphics engine is much lower than a satisfactory MVP for 3D assets, so I think sacrificing time from developing the rendering side to make asset loading easier is worth it. Aside from that, we also used Imgui for UI. The Forge already included Imgui, so I didn't really experiment with other GUI libraries. Having tried to implement my own GUI in a project in the past, it's most certainly worth it to use a GUI library like Imgui. Mouse handling is a pain to deal with otherwise.

[Hao] The GUI library is very intuitive and easy to use and worked out really very well. For networking, it was the first time for me to use WinSock. It is very similar to other socket libraries I have used before, a very standard socket library and it works properly.


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, what other system would you prefer to use (or even just doing everything on your own using HTML, CSS, and JavaScript)?

We chose not to use wordpress and just used HTML and CSS to maintain our group web page. We found this process to be simple and maintainable. We were able to maintain a git repo with our code, ssh into the cse 125 server and then pull our changes and - voila! One issue we kept having though was group permissions on the cse 125 server. Seems like group permissions were not automatically enabled, so the owner of the file kept having to set permissions so that others can write into a specific directory or file.


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?

[Aditi] I learned that I’ve most likely been very spoiled with having my current teammates. I anticipated having a lot of frustration with communication and delegation of tasks, especially since everything was remote, but we never ran into any problems with that. Our group meetings were always productive and we all left with a clear idea of what we had to accomplish in the given week. If anything, everyone in my group always got done more than they were expected to by the next time that we met.

[Jimmy] I learned that coding with everyone on the team is pretty fun but it always caused bugs on VScode. I like how everyone in our group is very reactive to messages. I think it’s important to communicate immediately with other group members when we have any issue with the code.

[Charles] I liked our group dynamic, everybody did their part. I did occasionally end up having to step in and finish or fix work that others weren’t able to do because of scheduling, but it wasn’t too much trouble. Unfortunately we never got to meet up and work together in person, but the days that we all met up on discord or zoom to code and stayed up until 3 in the morning testing and playing our game were a lot of fun.

[Hao] I really enjoyed the group coding session we had throughout this quarter.

[Kevin] Asking for help on implementing parts of code can really help relieve workload. Near the end of the quarter, I was really swamped with work on other classes, so I reached out to the group to implement the UI. I gave a basic interface to create screenspace images and text, and my group was able to use that interface to create our game UI. Our UI probably wouldn’t have functioned as well if I tried to work that part out myself.

[Esther] At first I thought it would be a bad thing to not have a "product manager" or "leader" type of role in our group. But it worked out quite well because we were all held accountable for our parts, without someone "overseeing" the progress of the entire group. I liked that we were all in it together and checking up on eachother. I think a group of 6 isn't that large, compared to classes like CSE 110/112 where groups were 10+. I definitely enjoyed working in a smaller group like this.


This quarter was particularly difficult having to do everything remotely. What tools and strategies did you use to collaborate, communicate, and work together?

Our development was centered with github and our weekly meetings. To communicate, we used discord and sometimes zoom (on particularly glitchy discord days). We also attempted to use VS code liveshare for our group coding sessions. One thing we threw out of the picture was using some sort of task board. We started off using Github Projects to post and keep track of tasks (like a Trello board) but naturally stopped using it after a week or so because communication over Discord and react emojis were sufficient. Especially given the remote quarter, we were always online on Discord and available to reply.


Looking back over the past 10 weeks, how would you do things differently, and what would you do again in the same situation?

[Aditi] Looking back, I probably would have done some more learning about networking and become more involved in the server client communication at the beginning of the quarter since that’s something I’m interested in and didn’t get too much exposure to until the end of the quarter. Other than that, however, I think all of the features in the game came together nicely and I don’t think there would be any major changes I’d want to make.

[Jimmy] If I were to write the code for networking again, I would have written an object oriented class for networking that’s easier to use.

[Charles] Looking back, I don’t think that there’s anything I would do differently. Maybe I could have gotten more code done earlier in the quarter, but at that point we were still making design decisions and there’s a lot of things that can’t be finished until other things are finished, so I don’t know if starting earlier would have made a difference. I think it all came together nicely.

[Kevin] Learn Vulkan and Direct3D earlier. A lot of the struggles I had with the Forge mostly came from not knowing their APIs.

[Hao] Get a windows machine lol.

[Esther] I felt more like an art major this quarter than a CS major but that’s okay that’s exactly how I wanted to spend my last quarter at UCSD. Looking back I would have set more time aside to contribute to the codebase but modelling already took up all my time. I realized that some groups in previous quarters bought most of their assets, so it is a tradeoff in time I suppose. There is so much more satisfaction in making the models catered to our game!


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

[Kevin] CSE 100 for structuring c++ code, CSE 167 and CSE 169 for graphics, and VIS 143 for asset pipelining

[Jimmy] CSE 100, CSE 110, CSE 123, CSE 120

[Aditi] CSE 100, CSE 110, CSE 120

[Hao] CSE 100 for C++, CSE 124 for networking, CSE 120 for multithreading, CSE 110 for working on a project with large scales

[Esther] CSE 100 for C++, CSE 112 for working in a team and communicating effectively, CSE 167 for understanding some of the client side code. Youtube 101 for Blender tutorials.

[Charles] CSE 167 for graphics, 124 for networking, and 100 and 101 for gameplay and class design

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

[Charles] I learned a lot about working in groups and what it’s like to build a project of this scale with a team this small from almost scratch. I definitely learned to appreciate the importance of designing good, robust, extensible systems and how much time and headaches it can save you down the line. I learned about the time and dedication it takes to build something like this. And most importantly, I learned how great it feels to finish a project this polished that we can show off to our friends and family, and also recruiters haha.

[Aditi] First and foremost, I learned to pay my utmost respects to every game that exists out there, because I didn’t realize just how much work goes into developing even a relatively simple video game. Other than that, I think the most valuable thing I’m going to take from this class is the experience of taking a project of my own design from inception to execution without starter code or clear cut expectations of what my code should do. Even in my past internships, the tasks that I had to execute were part of individual features in a larger project, not entire projects themselves. I think I’ve gained valuable experience in project management, development, and teamwork.

[Jimmy] I learned that building a large project from scratch is not that intimidating. However, we should work on different features separately and test them separately. This way there wouldn’t be so much bugs when we merge them.

[Kevin] I learned how valuable layers of abstraction can be for extending functionality and in working in groups. On a low level, It allows for a lot of polymorphism of game objects, making it easier to group together similar objects under a single data structure. On a higher level, it provides easier interfaces to use relatively complicated objects.

[Hao] I learned how to build a project of this scale from scratch. Even in CSE 110 or from my internship experience, there would also be a guideline or tutorials that I could follow. Starting from scratch and creating everything by yourself is a very valuable experience. Having such an awesome team makes the experience very enjoyable.

[Esther] Starting from nothing, to ideation, to execution in a team setting was a great experience. Also continued to learn about where I lack in communication, and learned to ask questions unapologetically even if I worry that it’s a stupid question.


Please post four final screenshots of your game on your group pages for posterity. I will display them on the group web page. (If you are satisfied with the ones you sent me just before the demos, you can include those and do not need to create new ones.)

splash screen

What books did you find helpful that were not on the recommended list but should be? What books were on the recommended list but were not useful and should be removed?

We didn’t use any books. Was there a recommended list?

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

[Aditi] If there’s anyone who feels like they don’t have specialized knowledge in one area or doesn’t know what part of the project would be the best fit for them, do your research early! Like in the first week! Look through past group’s status reports and see what kind of work goes into each part of the project, google search all of the technical aspects you’re unsure about, and really figure out what skills you want to work on throughout the quarter.

[Kevin] In planning the game, really consider that The demo will be about 15 minutes (I think all the groups this year went a little over), so make sure that the game can be played a couple times in the window. I think we got lucky with our games lasting 4-8 minutes.

[Charles] Find people who are experienced in the different aspects like graphics and networking and system design. And if you can’t, then become that person. Not having to worry about learning how to establish a server-client connection or implement a scene graph on top of actually developing the game was a huge weight that I didn’t have to worry about. And don’t cut corners. You’ll thank yourself later.

[Hao] Don’t be afraid if you don’t know all parts of developing a game. Teamwork makes the magic happen. My teammates the greatest people I ever worked with.

[Jimmy] It’s very lucky for me to get into this class in this special time period. I think pulling all nighters with some friends to work on something that you are interested in is a lot of fun, especially in the last quarter of college.

[Esther] If you hoped to take the class with a group of friends, it’s a realistic situation that not everyone will get into the class. But I encourage you to not drop the class if you did get in, because this will be the most rewarding group project experience you’ll have at UCSD, and you will end up making more friends :D Your teammates will be guaranteed to be dedicated and great to work with. Also, if you are working on modelling, I highly suggest having an organized directory to separate textures, meshes, backup files, animations, exports, etc. to keep yourself organized. Be committed to being organized early because things will get clustered really quickly. Also, start modelling simple things first and test them on the client before committing to more complicated structures. This way you can catch issues early.


How can the course be improved for next year?

[Aditi] I think the structure of the course itself is great! I think the guest lectures were awesome too, so definitely keep those! I don’t think there’s anything I can think of in terms of course improvements.

[Charles] The class is a great class that will be very challenging but also very rewarding. Given the unprecedented circumstances, I don’t have any thoughts on improvements since I don’t really have anything to compare it to.

[Hao] I think the course structure is very good and I enjoyed it. It would be great if students can admin access to the CloudLab.

[Esther] Maybe more lectures from the professor Voelker himself would have been interesting as well.


Any other comments or feedback?

[Charles] Thanks for making the class run so smoothly Geoff! A lot of things could’ve gone wrong, but none of them did. And thanks Edward for helping us out and cheering us on throughout the quarter!

[Kevin] Thank you for running this course despite the circumstances this quarter. I was honestly afraid that the class might’ve been cancelled. This class definitely kept me busy throughout quarantine.

[Aditi] A huge thank you to Professor Voelker and Edward! Both of you were so helpful and amazing at boosting our team morale! We couldn’t have done it without you both!

[Hao] Thank you Professor Voelker for making this class run smoothly during this unprecedented time. Thank you Edward for helping us on various technical issues.

[Jimmy] Thanks for Professor Voelker and everyone on our team. This class helped me to get through this difficult time.

[Esther] Thank you for making this class possible this quarter! Like Kevin said, it kept me busy throughout quarantine and gave me a sense of purpose during these 24/7 times spent at home. Thank you Professor Voelker and of course Edward for being our cheerleaders :')