Saturday, December 24, 2022

Flutter, Godot, Plans, and Regrets

A conversation last summer put a bug in my head for a game design. It's been flitting around for months, and I feel like the idea could be fun for a niche audience. In fact, it's the same idea I wrote about last July, when I tried some exercises from Justin Gary's book. Two or three weeks ago, I got out my paper prototyping supplies and whipped up a minimally playable version. Although the paper version was anemic, it showed that the core ideas could be fun. My intention though had always been for it to be a digital experience, and I knew that a lot of the experimenting would require trying different content and interactions in digital form. 

This led to me to explore two different options for digital prototyping. My first option was Flutter, which I continue to be fascinated by. I have used it for several side projects and a few classes, and I am particularly interested in the elegance of Dart and the separation of UI and model-layer concerns. My other option is, of course, Godot Engine, which I have used for most of my game development the past several years. A significant benefit of Godot Engine over Flutter is that I just have a lot of it in my head right now, so I don't have to spend as much time scouring documentation for just the right thing.

The game design itself is, fundamentally, a single-player card game. At this point, I've made several different prototypes in both Flutter and Godot Engine. Indeed, I've made so many, with enough variations on their directory names, that I've had to set up a separate directory just for abandoned prototypes. What I've come to realize just recently, though, is that I have spent a lot of time on the wrong things. To be honest, it's not clear if these things are wrong since I did learn what I wanted to learn from them, but on the other hand, they are wrong because, six months and many hours of labor later, I don't have a version of the game that I can send to my friends to playtest.

In particular, I've been having serial headaches with a fundamental card game interaction problem: I want to drag cards from one area (e.g. a hand of cards) to another. I want this to feel good to the player, so the cards should animate nicely into position. If they are over an area where they make sense to play, the player should get some feedback. If they are dropped in an illegal area, they should go back to where they came from. 

Note that none of these issues are core mechanisms: they are UI design problems. They are important UI design problems indeed, and one of my concerns going into the project was that, if I was going to sink personal time into it, I wanted to invest in the right tool stack so I would have to do minimal re-engineering. However, reading Lemarchand's A Playful Production Process—which I am doing in preparation to teach CS390 next semester (blog post coming soon)—got me thinking that I am trying to solve a production problem while I should be focusing on preproduction problems. That is, my goal right now should be to determine if the game should be pursued at all, not whether it should feel good. This means making a toy, a playful artifact, rather than a vertical slice.

Rather than regale you with the chronological narrative of my discoveries, I will summarize some of what I found for each of my engine options.

Flutter:

  • The dev tool support here is incredible, with easy refactoring and convenient language constructs.
  • The Draggable and DropTarget widgets are really nice for most drag-and-drop purposes, but not for my case. When dragging a widget, a separate element is made for the version that is following the mouse, and it is irrevocably lost on release. This makes it impossible (or at least impracticable) for handling my case where a card animates smoothly into position or returns to the player's hand. 
  • A custom drag-and-drop system can be built out of Stack, using Positioned widgets. That is, rather than nesting widgets in the normal Flutter way, one can get complete control over an entire canvas of widgets. AnimatedPositioned makes animating these into position a breeze. Indeed, I was pleasantly surprised at how easy this was to express things like, "Keep all my cards in my hand evenly distributed across this widget." The problem is that, when recognizing the drag gesture, the mouse position is consumed by the widget on top: one cannot get mouse entry/exit events for the widgets underneath. 
  • It seems like, at this point, I'm just building my own UI framework and may as well just be using Flame. The trouble is that then there's yet another piece that I don't know, and development is slow and awkward for me.
As always, if any of you readers knows more about Flutter than I do, please feel free to correct any of these misconceptions.

Now, Godot Engine:
  • Of course, Godot Engine has the benefit of its visual editor for building scenes, including composing them. This makes it very easy to break up a project into pieces that are individually, but manually, tested.
  • Godot Control nodes do have drag-and-drop support, which I had not come across before. Like Flutter, you make a separate view node that is visible just while dragging. It would be great for normal drag-and-drop interfaces, but not for something like a card game. 
  • Which controls receive mouse focus is again a problem, but it's solved by keeping track of all the geometries in a "tableau" class. It watches for the mouse and, at the level of the table, keeps track of where the mouse is, which areas should be highlighted, when cards should be animated, and so on.
  • One of the things I built in a Godot prototype was an EventQueue to manage some of the in-game events, such as waiting to start a round until an animation was finished. That was something I found particularly awkward to do in Flutter. None of my past projects used an EventQueue, and I suspect that if I finish this project, it will need something like that. 
  • Refactoring in Godot Engine is a huge hassle. It is easy to build a thing. It is almost impossible to rebuild a thing differently.
How much of this really matters right now? I'm not sure. It's Christmas Eve, and I want to spend most of the next several days with family and friends. I'll have some time to dive into code if I want to. I still have significant prep to do for this new class I'm teaching in Spring, and of my other two classes, one is almost ready to go, and the other needs maybe a half day more of work. If I do dive into code, I think I will have to make yet another new project though, and I will have to hold myself accountable to making something simply playable. I need to stop myself from getting distracted by these interesting problems of software architecture and player experience so that I can determine better whether this game is fundamentally worth pursuing or not. I suspect this means I will turn back to Flutter, where I can easily refactor and whip up UIs that respond to model-level changes.

Merry Christmas!

Thursday, December 22, 2022

Reflecting on CS215 Game Design, Fall 2022 Edition

I do enjoy teaching my introduction to game design class, and partnering with Minnetrista through the Immersive Learning program is always a treat. I want to capture a few thoughts here before the Fall semester disappears in a haze of planning for Spring.

Three things that went well

I still like following Schreiber's online Game Design Concepts book. Despite its age, which means that it doesn't have examples that resonate with the students nor touch on more modern phenomena like MOBAs, the fundamental ideas in it are good. You also can't beat the price. I have two new books here that I will flip through soon, but I continue to be impressed by how well Schreiber's online massive teaching experiment has held up.

The transition to a larger class size was not as bad as I feared. I love to teach the class in a manner that has everyone putting posters up on the wall for discussion, but there were too many students for that. The exercises had to move to other formats. I don't think it was as good, honestly, but it was also not so bad.

Having students track their time in their final project using labor logging was much smoother this year than last. Regular readers may recall that, last year, I tried to combine design logs and labor logs, and this confused the students at both the logistical and the epistemological level. This year, it was much clearer whether students were putting in the time being asked of them for the final project. As usual, the projects were graded on process rather than product, and putting effort in is an important part of the process (he says, as he writes his blog post rather than working on his side project).

Three things that could be improved

I am sure I have said this before, but I need to find ways to help students better integrate the first half of the semester into the projects of their second half. The final exam asks the students to connect some of the dots, and it's obvious from their answers that they are doing post hoc reasoning: they talk about these final projects using terms from the reading that never came up in their design logs or presentations. Put another way, I think it's fair to say that most of the student projects would be exactly the same with or without the studies from the first half of the semester. I need to get them reflecting about these ideas in a more structured way, perhaps by adding some additional writing or discussion assignments.

Compounding the issue above is an observation that shocked me early this semester: I don't think I've ever had a class with worse reading comprehension skills. The students and I talked about this more than once during the semester, how they did not understand simple reading assignments. This runs into a fundamental problem with being a university professor: it's almost impossible to distinguish between cannot and won't. That is, if they can read for comprehension but are choosing not to, then that is their problem, but if they cannot read for comprehension, then I have a responsibility to them to scaffold this better. Seeing how poor college students' reading skills are, it makes me wonder if I need to design some interventions here. For example, in my draft Spring CS222 course plans, I am requiring students to take notes while reading and then write summaries of those notes; I think the very notion of taking notes while reading is foreign to them, but I am hopeful that this will bear fruit.

Given the confusion around the tasks in the first half of the semester, it's also possible that allowing resubmission would help. Many students got fundamental things wrong around the basic theories, but very few students are motivated to actually correct these misunderstandings, opting instead to charge forward with muck in their eyes. I'd rather not have an exponential increase in the number of things I have to grade, but on the other hand, I also want them to understand these theories so that they can apply them in their own work and in looking at their classmates' work.

Tuesday, December 13, 2022

Reflecting on CS315 Game Programming, Fall 2022 Edition

Following up on my previous post, here is another short reflection on one of the courses I regularly teach: Game Programming, also known as CS315. My students are taking the final exam right now, so it seems a good time to record some of my own thoughts about the class.

I did not make any major changes to this class, and it continues to be one of my favorite classes to teach. Godot Engine is just the right level of abstraction for junior-level CS students who are just getting into game development: they can make things reasonably good-looking and fast while still getting into some serious details of game programming. Checklist-based evaluation means that the work is fairly easy to grade and the students by and large understand what is expected of them. Yes, there are always some hiccups here, but there's not enough to warrant radical change.

The class involves several sessions where I am demonstrating concepts and students are thinking about how the pieces fit together. They did a good job with that this year, and they asked better questions than I remember past students asking. Of course, some of the questions could just be answered with, "Try it and let us know," but still, I didn't want to prevent their asking questions. The flip side of this, however, is that they were terrible at taking notes. The fallacy that they will remember lectures is strong with them. I am not sure how I can use the class to help fight against this ridiculous misconception that plagues so many students.

There were a few sessions that I expected to finish in one class period that ended up taking more than two. For example, I put together an interactive lesson on shaders, and for some reason, it filled up a lot more time than I expected. I'm simply noting this here so that I can keep that in mind for the future.

There are some bolts yet to be tightened on the course. The final project has too many checklist items that are easy to cheese. For example, given an item like "Add pop to your UI using AnimationPlayer," some students do a lame fly-in and call it done. I am not quite sure how to invert this. That is, what I want is for them to do something they are motivated to do, and I give it course credit. One of the downsides of checklist-based grading is that some will do the minimum required and present this as if it demonstrates mastery. It's not obvious to me where the dividing line is between those two, especially in the absence of a game design prerequisite. That is, for this course, they can want to make something pretty dumb, and it's hard to distinguish then between whether what they wanted was dumb or whether they were bad at making something better.

I look forward to continuing to teach this course as a generation of students comes up through the Game Design & Development concentration. I am hopeful that we are bringing students who are even more excited to excel at these ideas rather than just barely pass the bar. I expect I will continue to use Godot Engine, and I am hopeful that next year, it will be Godot 4. Indeed, right now I am evaluating whether I want to build a prototype in Flutter or in Godot, and a large part of it is because Dart is just such a nicer language to express ideas than GDScript 1.0.

Reflecting on CS222 Advanced Programming, Fall 2022 edition

My students have not yet taken their final exam in CS222, but I feel like I am in a good position to share a few thoughts about the course. 

Three things that went well

Using Dart and Flutter was a success. I did not get the impression that the students were any more lost using Dart and Flutter than they traditionally have been with Java and JavaFX. There is so much good documentation around Flutter that I suspect it was actually much easier for them to deal with it. I plan to keep this change to the course next semester, when I will be teaching CS222 once again.

Around the middle of the semester, I presented a series of two workshops comparing Java and Dart. I had hoped for more students to come, but the fact is that preparing and executing the workshops helped me better understand where the students were. I plan to bring this experience into next semester's class, potentially rearranging some of the first-week material to give these workshops in class. I have been inspired by Robert Talbert's latest blog post about 12-week plans for 15-week courses: while his target audience is not teachers like me, it still got me thinking about how the first week of CS222 might be structured as more of a review of past material.

Incorporating the mob programming game got my students thinking and talking about mobbing, and adding the achievement gave my students something to pursue. I look forward to using my classroom mob programming game next semester.

Three things that require consideration

I think I had less participation in the resubmission and achievement system this semester than usual, or if it wasn't actually less, it was still disappointingly low. I have had some conversations with others who use similar methods, and I wonder if the students would be better served by having a handful of concrete deadlines rather than rolling weekly ones. Undergraduates are notoriously bad at time management, and so maybe it is a double whammy for them to have to deal with both managing resubmissions/achievements and remembering weekly submissions.

I use a simple grading scheme that, despite my efforts, students do not understand. On one hand, I do not blame them but rather the school system that has damaged their thinking around learning. Again inspired by some of Talbert's other writings, as well as some recent conversations with colleagues, I have been wondering how much of my class I can get away with not grading. This would be an uphill battle since students are trained to be anxious about grades. 

In the final iteration of the final project, some teams included fundamental errors, such as not having passing tests or naming classes as verbs. I have already provided checklists to help with such things, but nobody uses these. I could ask students to turn in more artifacts such as checklists and CRC cards, but this runs counter to the previous point. I wish I had a better view into the students' behavior and how it is that a team of four smart students can run multiple code reviews and not see simple, fundamental Clean Code violations such as naming problems.

Something like conclusions

That's all I have for today. I need to do significant work during the winter break to pull together changes to this course. I hope to be able to share some thoughts about it in under three weeks. Ack, this is a short break.

Friday, December 9, 2022

What we learned in CS222 (Fall 2022 edition)

Regular readers will know what time it is: it's time for the next installment of What We Learned in CS222. As has been my recent custom, I moved this exercise from the final exam timeslot into the penultimate day of class, the final day of class being reserved for students' final presentations. We only had seven students in class this morning, which is less than half the enrollment but not far from what I've been getting the last several weeks.

I had them start by quickly making mind maps on the theme of programming. I only gave them three minutes to sketch them out, telling them afterward that it would be a great study exercise to compare your current map to the one made on the first day of class. The exercise was really to just prime the pump for them to answer the question, "What did you learn this semester?"

Here are the 71 responses, sorted by the number of votes earned at the end of the process. Each student had four votes, but either someone misunderstood the instruction or I lost a sticker in transit.

  • Clean Code (7)
  • TDD (6)
  • GitHub (3)
  • Code Review (3)
  • Agile fundamentals (1)
  • Version control (1)
  • User stories (1)
  • Model-View Separation (1)
  • Flutter + Dart (1)
  • Naming (1)
  • Requirements analysis (1)
  • Software architecture (1)
  • SRP
  • Acceptance testing
  • CRC cards
  • CI/CD
  • Pair programming
  • Mob programming
  • Using APIs
  • Using Android Studio / IDEs
  • Forking repositories
  • Feature branching
  • Committing in git
  • Commit messages
  • Pushing in git
  • Pulling in git
  • Licensing
  • API keys
  • Defensive programming
  • README.md
  • Pubspec.yaml
  • Achievements system
  • Pitching project ideas
  • Incremental development
  • Sprint
  • Project demos
  • Iterations
  • Breaking down epic stories
  • Emulators
  • Red-Green-Refactor
  • Comments
  • Test data files
  • Functions (especially parameters, in a Clean way)
  • Null safety
  • Async/Await
  • Stateful & Stateless widgets
  • DRY
  • gitignore
  • Reading package documentation
  • Using outside resources
  • Local saves
  • Save/Load features
  • Export/Import features
  • git commands
  • Dependencies
  • Project time management
  • File names
  • Simple, clear class names
  • Encapsulation
  • Software craftsmanship
  • Making UI buttons
  • Code side-effects
  • Delegating (in Software)
  • Delegating tasks
  • Wrappers
  • Polymorphism
  • Defensive copies
  • Text wrapping in a UI
  • Text wrapping in code
  • Test coverage
  • Non-programming skills

There are a few interesting things in this list. I was surprised that there was relatively little about Flutter and Dart in particular. I was glad to see it show up as a concept itself but more excited to see that a student recognized how very cool async and await are. Breaking down epic stories is important since just yesterday we did an in-class exercise where no one remembered that conditions of satisfaction are part of user stories, despite this being a recurring topic of the semester. Specific Clean Code ideas seem to be less represented here than in past years, more emphasis here being placed on technological issues of version control. Unfortunately, there is nothing funny in the list.

We found it easy to draw a line in the list and see that the top four items were selected by the community as the most important. I explained to them that these four will feature on the final exam, and it's up to them whether they want to share this information with their missing teammates or not. This elicited the expected nervous laughter.

Wednesday, December 7, 2022

NaGaDeMon 2022: The Classroom Mob Programming Game

In a rare inversion of media, I already announced my 2022 National Game Design Month project on YouTube before writing about it here. The project is Classroom Mob Programming Game. Visit the site for all the details.

My inspiration came from playing Willem Larson's Mob Programming RPG with my students in CS222. I played it last Spring for the first time, prompted a pair of blog posts about the experience [1, 2]. I played it again this Fall with my students and had a similar experience. I wrote some about how I framed the project in my only other NaGaDeMon 2022 blog post. Here, I want to talk a little about how I brought the pieces together to finish my project last week.

I did not make a lot of progress on the project for the first part of November. I kept ideas simmering but did not put pen to paper very often. As I pulled my notes together, I also had to determine how I would playtest it. Normally, my family provides a convenient testing group, but this game was designed very specifically for my CS222 class. That is, the game was designed for sophomore Computer Science majors and minors who are studying techniques of agile software development. I also didn't want to use my own CS222 class as testers since we already spent two days on Larson's game plus another class meeting to debrief and review from the experience. Also, my students would not be good testers because they already know what the game is supposed to teach: fundamentals of mobbing.

I reached out to my two colleagues who are teaching the other two sections of CS222 this semester to find out if they would send students to an after-hours playtesting session. Turns out, they both independently invited me to come to their class meetings to present the game to the whole class. This was invaluable for two reasons: first, it gave me two opportunities on sequential days to do testing; second, it gave me deadlines by which I had to have iterations ready.

Here are some of the most important properties of my game as viewed in comparison to Larson's.

  • Support multiple teams mobbing in the same classroom at once.
  • More deliberately scaffold students toward good TDD practices along with introducing mobbing
  • Fully completable in a 50-minute class session
  • Rather than add new playbooks as players level up, they unlock new actions that earn them XP, but the number of XP needed for the next level also increases
My game has some PbtA sensibilities, but it looks less like one than Larson's. It's more of a traditional RPG in that you have a role and earn XP, but without the emphasis on playbooks and actions.

The first test went well, but there were several loose ends that needed to be tied up. I had created an ostensibly balanced scoring system to support competition between teams. In practice, it was too fiddly to compute, and some individuals computed their scores incorrectly while others simply threw up their hands and guessed. I almost completely removed scoring from the game for the second playtest, and I don't think anyone missed it. I wrote up a much simpler scoring system that is provided as an optional addition to the game. I fixed some errors on the handouts, but more importantly, I made significant revisions to the actions. The first group of testers had a hard time getting into a red-green-refactor rhythm, even with some gentle prodding from their instructor.

The second playtest went much better, with simpler scoring and better actions. Players don't just get more actions as they level up, but some of the actions actually change forms for better scaffolding. The best example is in the Navigator role, where there is a series of actions that evolves like this:

  • Level 0: Describe a desirable, failing unit test--the "Red" in "Red-Green-Refactor"
  • Level 1-2: Hold the team to the appropriate step of "Red-Green-Refactor"
  • Level 3: Complete a "Red-Green-Refactor" cycle

After the second playtest, I also completely rewrote the game's instructions to follow a more logical flow. Those interested in the details of the game evolution can always check out the commits made on Nov 29 and 30, the dates of the playtestings.

I am eager to use this variation on the game with my CS222 class next semester. I am also considering framing it as a research project, but I need to determine if I will have the spare cycles to pull that off, given my other responsibilities in Spring.

Thanks for reading! I would appreciate if you can help spread the word about this game to folks who may be interested.