Saturday, March 28, 2020

Family Painting: Arcadia Quest

A few years ago, I bought a copy of Arcadia Quest secondhand from a friend who wasn't playing it. I didn't know much about the game, but I figured it would be a good source of minis at the time. Yeah, this was back before I had cases of unpainted stuff from Kickstarter projects, which wasn't so long ago in absolute terms. My wife, my eldest son, and I played a campaign, which ended gloriously when my son attempted a longshot to defeat the big boss, made it, and won the campaign. A couple of months ago, I brought it back out and played through a campaign with my two eldest sons, and we enjoyed it.


Fast forward to November 2019, and I was trying to think of something fun to do with the family for Christmas, to go along with some of the fun stuff I had to give them. Looking around my office, I thought of Arcadia Quest and its box of unpainted miniatures. Honestly, I'm not very keen on the chibi style. If I were to pull out a set of miniatures from the unpainted archived, I'd probably go with the wonderful monsters of Massive Darkness or Rising Sun. Stuffed Fables was enough of a serious attempt at painting round, smooth surfaces for me. Why not take the Arcadia Quest guys, then, and make it a family painting project?

Between that decision and Christmas, I had to find secret ways to get everything ready. When the family was out or otherwise occupied, I found time to prep, clean, cork-mount, and prime the figures, and then to split them into bags for each family member. For the prep, I did not bother with the occasional seams and mold lines. I was more concerned about the ridiculous chibi cleavage. For the most part, I was able to maintain my sense of being a responsible parent by giving the more exposed characters to my wife and me to paint, but the sculpts of the Sisters of Pleasure were really falling out of their dresses.


I used my Millput to fashion something a bit more presentable to a table full of young boys.


I had some concern that I should have done this work before priming, but the milliput took the paint really well. In the end, I don't think you can tell they have been modded.

Priming was a particular pain because this was in the depths of my frustration with my airbrush. The black was just not coming through properly, so I ended up turning to my old Bob Ross Black Gesso, which I don't think I used since before painting the Descent heroes. I was doing a lot of figures at once, and unfortunately, I did end up with a few unfortunate bubbles. I decided to just move forward with them despite this: we're going for quality family time, not Golden Demons. Once I got the black down, I was able to finish them all with zenithal priming, since my grey and white have worked better from the airbrush than the black.

I put each family member's name on their bag, boxed them up, and put a big label on the box that said something like "For The Crafty Family". Christmas morning, the family opened it, and they were really excited. That night was the night that some of us painted the Clank Legacy figures, but two days later, we did our first Family Painting session, and it was a blast.

In a moment, I'm going to share the photos of each family member's finished set, rather than my usual figure-by-figure photography. First, though, I want to tell you a great story about painting with my youngest son. He was four at the time, and the first figure he wanted to paint was one of his big Hammer Beastmen. He was sitting two seats over from me, so I couldn't really see what he was doing. When he held it up, it was veritably dripping with paint. I can remember my second son doing a similar thing with his first miniature, a dwarf from Reaper Bones. It's quite a testament to how much paints shrink! Before the next family painting session (which I believe was the next day), I gave him a few tips to prevent him from flooding the model. I told him I would sit next to him and help him get a better consistency with his paints. We got him a paper towel to have at his side, and I showed him how to gently dab the brush on the paper towel to soak up the excess. Below, you can see the result of his first miniature on the left and the amazing difference in quality he got with his second one, the goblin on the right.


In terms of materials, the two younger boys were using our collection of craft paints—the kind you get for a dollar or less. My wife, my two older boys, and I used the Vallejo Basic Colors set that we got them for Christmas. You see that there's a method to my madness: getting them nicer paints means that they could get more control and technique with their painting, but it also meant that I could use some reasonable paints when sitting with the family. For a few painting sessions, I brought down my neutral wash base (based on Les' recipe, but without ink) and my brown ink, but for the most part, we just used the Vallejo paints and water.

Now, let's look at the figures! I'll go in increasing age order.

These were done by my youngest son, when he was four-turning-five. I think he did a phenomenal job, given his age. He became very careful about how much paint was on his brush, always remembering to dab it off on paper towel, and this gave him a fine level of control.

The above photo are the figures done by my third son, who is seven. He was really all by himself on this one. I had given everyone a copy of the character art from the game, and I think this son did a good job of color matching with the paints he had available. You can also see him having some fun with the yellow eyes that are prominent in these villain characters.

In my original plan, I had thought that the younger boys would not have the stamina to do as many figures as the older boys, so I had actually given them one fewer orc than are shown above. Those orcs had been given to my older boys. However, as we did more family painting sessions, I realized that I had this upside-down: the younger boys certainly could have done more figures in the amount of time that the rest of us did ours, because they work so much quicker. I talked to #1 and #2 son about this, and they both graciously agreed to donate one orc each to their younger brothers, so that we could all continue to sit together and paint.

These ones shown above were painted by #2 son, who was nine-turning-ten. I think he did a nice job. I feel kind of bad that Grom (the shirtless barbarian in the front middle) had one of the worst cases of bubbles from the priming, right on his face. If my son ever wanted to repaint that figure, we'd certainly strip it down to bare plastic rather than just paint over it.

One of the reasons why this has taken so long to post is that my son started the Minotaur in the back left, then became frustrated and didn't want to finish it. At one point, he had even given it to his older brother to finish. I encouraged them to renege on this deal, trying to get my son to realize that there was more merit in finishing the job as best he could rather than giving up on it. I suspect that part of the problem is that, at his age, he can see that there is a difference between his work and his older brother's work. I remember that feeling! I'm a younger brother, and my father and my older brother are both talented artists. I know that feeling that when we work together, my stuff just doesn't look as good as theirs. I tried to help my son see that the important thing was that we were all learning and growing together. After a few weeks away, we did a final Family Painting session where he finished that Minotaur (and I finished Maryjane from Posthuman Saga, if I recall correctly).

These ones were painted by my oldest son, at age twelve-turning-thirteen. Some of these are really impressive, if you ask me. He did a bang-up job on Spike, the dwarf with the mohawk; the photo here doesn't show all the tattoos that he carefully lined in. His goblin archer on the far right shows some great tattoo/facepaint work as well. He was unhappy with Diva—the blond in pink armor—when he painted her, but he felt better about it after putting it down for a few days. Blonde hair can indeed be tricky, and tinted metallic armor was definitely something he had never tried before. The troll in the back is also noteworthy for his subtle use of contrasting colors in the recesses. I didn't notice it at first, but he shwoed me that in the recesses of the muscles, he put in a different color to get both shade and visual interest. Thanks, Sorastro's Painting!

Above are the figures painted by my lovely wife. Her patience and attention to detail helped her do really amazing work, although if you ask her about it, she will always fruitlessly compare her results to mine. I mean, if I can't paint slightly better for years of practice, then what good is years of practice? Regardless, I think her work on the robes of Zazu is particularly good, and she also mixed up some wonderful flesh tones.

Because the number of figures didn't divide evenly into the size of the family, I had given my wife one fewer figure to paint. Honestly, I thought she would mostly not care and just want to sit with the family—or take the opportunity to have some quiet solitary time. In fact, she was almost always the last one at the table, carefully working her figures and looking for places to touch them up and practice highlighting or shading.

Finally, these are my six figures. I think they turned out nicely, certainly fit for purpose. There are a few things I'll point out that I think are especially nice. I gave Maya (the sorceress holding up what my dad called a cabbage) a pale skin tone that left her looking a bit lifeless. I was happy with the transition over the smooth face, though, so I didn't want to repaint it. I applied a glaze of just red and lots of water over her cheeks in a few layers, and I like how this gave her a little more life; indeed, looking at it after a few weeks, I could have kicked it up a notch. I think I matched the tone on archvillain Lord Fang pretty well, although I still wonder why in the card art, he is wielding a fancy magic sword, but in the sculpt, he has a beat up old one. I think all of these figures would really be enhanced by some ink pin washes, but as one-session, minimal-material figures, I think they're pretty good.

That's all the Arcadia Quest figures from the base set. It was a wonderful experience to paint this with my family, and I think everyone enjoyed it. Now, when I look at miniature-heavy games, I find myself not just thinking, "Would this be fun for me to paint?" but also "Would this make a good second Family Painting project?"

Thanks for reading!

Thursday, March 26, 2020

Online Status Report Meetings in CS222

My four CS222 teams presented their first iterations of their final projects just before the switch to all online instruction. These are projects that are completed in three three-week iterations. Before the weekend was up, I had given considerable written feedback to each team on that first increment. This was probably on par with the level of feedback I would normally give, although I was careful to try to complete each thought rather than leave breadcrumbs intended to point us to conversation.

By Monday of this week, I was worried about them. One of the groups, which was already doing a bang-up job, had reached out to me for help in understanding the feedback and acting on it, but the other three were fairly silent. They had a minimal amount of structured work during the week, work that was designed to help with the online transition; they did this work, but I didn't hear much substantial from most of the teams. So, on Monday (that is, four days ago), I was considering whether or not I should mandate online check-ins: I didn't want to impose, and I know everyone is stressed, but I also wanted to make sure they were all making progress. In a conventional classroom, I could accomplish this by listening in, looking over their shoulders, or even just seeing who was skipping meetings; these affordances disappear online. I decided, late Monday, that we should do it.

Tuesday morning I posted a new group assignment that required each team to pick from a set of times for a 30-minute status report with me. This was halfway through iteration 2, so it seemed a fortuitous time. I heard from each team by Wednesday morning, and I had all the meetings on Wednesday afternoon. Each were conducted via Zoom, which has increasingly become a technology for which I am grateful.

I was quite tired by the end of the day, but it was definitely worth it. The average meeting was closer to 40 minutes than 30, and by sharing screens, we were able to look directly at the code problems currently facing the team. I could answer their questions, and I could also point out problem areas. In one case, a student pair was struggling with model-view separation: they said, "Well, this is model but this is view," which was actually incorrect. By looking at the code, I could not tell what they thought belonged in each layer, but by having a conversation, I could hear where their misconceptions were and then provide tactical guidance. I used Zoom's remote control feature with each team, and one of the teams had no idea this was available... despite my encouragement to adopt Zoom for distributed pair programming because of this feature. Unsurprisingly, this team also struggled with basic patterns of collaboration. Again, this is a great win for me as a teacher, because we got to start having conversations about that as well.

It was a great experience, even though it took all afternoon, and I'll definitely make it a requirement for the next iteration. I hope that it helped break down some barriers so that more students remember that I'm just an email away to help. Indeed, even in my Game Studio class—where I have four teams instead of my traditional one—I plan on asking in tomorrow's all-hands meeting about whether this is something they want to institute. It's certainly another case where I would usually make opportunities to look over shoulders and listen in to conversations, whereas those things are all now invisible to me.


Tuesday, March 24, 2020

Painting Posthuman Saga: The Resistance and The Outcast

I posted back in January about painting the figures from Posthuman Saga. We continue our gentle romp through the post-apocalyptic wasteland with the two figures from The Resistance expansion and The Outcast promo pack. Let's jump right in with the two characters from The Resistance, in the order I painted them.


This is The Hand of the Pure One. Her character art is nice: bedraggled-looking redhead warrior with staff raised for a strike. The sculpt... well, the more I worked with it, the less I liked it. Apologies to the sculptor, but I'm just being honest here. Her hair rests on her head like a lopsided helmet, her arms—especially the right one —are weirdly scrawny, she has brutish cankles, and there are some kind of J-shaped scars or something on her legs. I got it to a point where it would look OK on the table and then stepped away to the next one.


The Technologist is an interesting character design compared to the others. He's outfitted in some kind of solar panels, hooked into batteries and wires and a "stun wrench." I don't have any idea how he plays at the table since this was a paint-first expansion project, but I like how he has a different look and feel than the other characters. The jumpsuit was pretty straightforward to paint, and I did all the accessories in the same kind of muted tones as the character art, just a little metallic for tonal contrast.

There are just those two in The Resistance. I originally backed the project on Kickstarter with the expansion, since I thought the premise sounded pretty good. Shortly before the project shipped, the creators offered a deal on The Outcast promo. In for a penny, in for a pound. I added it to my order. There's a funny thing about some Kickstarter projects where at the time you spend the money, it's like it just disappears into nothing, like you gambled it away or lost it. Many months later, you get a thing for free at your door. That's not really how it works of course, but that's what it feels like.



In the few games of Posthuman Saga, we have definitely felt the sting of mutation cards. I like the idea that this character, too, is significantly different from the rest, both mechanically and conceptually. I guess the photos don't show his mutated arm so well. I tried to keep it from being too exaggerated, as is done in the character art as well: it is pinkish, not glowing green and purple.

The only other piece here that's worthy of comment is his white jacket. I used to wear a white jacket, handed down from my uncle who, no surprise, wore white jackets. I may have even had two of them. I never wore my jacket through the desolate wastelands, but if I did, I'd probably have kept it clean, you know, to keep myself looking good. That's sort of the story I tell myself with The Outcast. In reality, I still have a hard time bringing myself to heavily weather figures. White is hard to paint, and I think I got a nice tone here. I couldn't see myself risking the look of the figure by hitting it with lots of theme-appropriate weathering. The character art even shows a spotless jacket! I know, I should stretch myself. It would be just as valid to say "It's not worth spending that much time on a figure that will rarely see the table" as to say "May as well practice dirtying this up since it will rarely see the table."

Truth is, I have enjoyed my handful of plays of Posthuman Saga, but it just doesn't seem like something I will be able to play regularly. I guess it goes in the same category as Fury of Dracula: interesting idea, not a good fit for my gaming family. The oldest son would have no trouble with the dark overtones of the storybook, but the younger one—who, for scheduling convenience, shares a bedtime—would be seriously freaked out by some of the imagery. This means there's never really a time to play it, unless I had some adult friends over... but if I did that, this isn't the game I'd pull out. I'd probably go with Rising Sun, whose many beautiful figures sit unpainted.

Here's a little bonus to wrap up this post:

The Maryjane doll came with the promo materials for Kickstarter backers of Posthuman Saga. She's meant for use as some kind of tracker for the solo game, I think. This means she will probably never see the light of day for me. I knew she was a low-stakes paint job, and so I ended up doing her at the table during a family painting session. That is, it was at the table with the family, using a subset of paints, one brush, no mediums or ink washes or glazes. What is this family painting session all about, you ask? Well, I think I'll have more to say about that in my next painting post. Same bat-time, same bat-channel! Or, more realistically, same unpredictable blogging schedule!


Oh yeah, and for those who are keeping track, I fixed my airbrush. I should write about that, too. Always more writing ideas than attention paid to writing...

Sunday, March 22, 2020

Fam Jam #1: Joe Johnson Gets Captured

I've been talking to my friend Ian Schreiber off and on for a long time about "fam jamming", or running a game jam with families. I've never actually done one; it always seemed like something else would come up. Now that everyone's stuck at home to stop the spread of COVID-19, it seemed like a great time to try it. Ian's primary advice was twofold: first, he advises to put a kid in charge of the vision while parents do what the kid says. This inverts the usual control structure, empowering the child and fruitfully humbling the parents. Second, he recognizes the different "superpowers" of the two classes: children are endlessly creative, and adults know how to get stuff done. Leverage these powers and use them for good.

Early yesterday morning, I surprised the family by saying we'd be doing a one-day family jam, and that #4 Son (who is five years old) would be in charge. Perhaps I shouldn't have surprised my wife with this; I had mentioned it to her in passing but she didn't know to plan on it for Saturday. However, once again we have the benefit of not really being able to go anywhere else. I encouraged #4 son to take a few minutes to sketch out some ideas, so he left to the crafting table and came back almost immediately with an idea about a mushroom and a turtle who are underwater and shoot at each other. The mushroom's attack shots are blocked by the turtle's block shots and vice versa. That more or less makes sense. Then he told us how after defeating the turtle, there is a crate you have to smash with a chainsaw in order to save Joe Johnson. Well now, this suddenly got much more interesting. I have no idea where Joe Johnson came from, but it was clear that we had to save him.

During this phase, I tried to ask some probing questions to understand what he was expressing. One of the other boys tried pushing toward something he wanted to make, so I jumped in and explained that #4 was the creative director: we could ask questions, but it was only to understand what he wanted us to do. This is a funny spin on Ian's advice for bigger families, since it's not like the other son lacks creativity or is particularly good at getting things done. However, he was very respectful and understood the exercise, and I think that itself was a small blessing from this project.

The original concept art for Joe Johnson Gets Captured
In the center of the image above is the original concept art for the game, showing a mushroom man who shoots circles and a turtle who shoots triangles. It was explained that they are in the water, standing on the ground, and the sky and sun are above them. The seahorse was added later. Around that original rectangle, you can see some of the other pieces that were added as the discussion went forward. On the left center is Joe Johnson, who is wearing a pink dress. In my work, I tended to refer to her as Jo Johnson because of the dress, but the rest seemed happy to have him be Joe Johnson. Fine by me, as the important thing is saving him. In the upper left, you see a "chainsaw", which the careful observer will notice is actually a hacksaw. I wonder if this was inspired by peering over my shoulder as I've been exploring One Finger Death Punch 2. (Wholesome family entertainment.) Across the top right are the original drawings of the triangular turtle bullets and the round player bullets, with an annotation about which button on the controller would fire them.

We talked briefly about platforms and tools. I am most productive with Unreal Engine 4, and my oldest son has some experience with it (such as at Global Game Jam). However, it is tuned for native delivery, and Epic recently removed the capacity for HTML5 export, which means that the artifacts are harder to share with distant family and friends. One can rebuild the engine from source to support HTML5 export, but that was definitely out of scope for a one-day jam. My two older sons have built some lightweight games using the free version of Construct 2, which is great for letting them explore ideas. I have relatively little experience with it, however, and honestly I don't have a lot of incentive to learn it. On the other hand, I have been increasingly curious about Godot Engine and I can see a lot of benefit to learning it. Games from Scratch has been singing its praises (although I know this more from reading the titles of videos than watching them), and I recently talked to Mike Sellers about how it is used in IU's Game Design courses. The whole engine is released under the MIT License, which is also very attractive. In preparation for the fam jam, I had built a very small tech demo the previous day in Godot Engine, before only ever having tinkered with it once to work through one of the stock tutorials with my oldest son. The tech demo was enough to get my head around some of the core ideas and validate how easy the HTML5 export was. I could see that this would probably be enough to go in mostly-blind to build a one-day project designed by a five-year-old. This established, we settled on Godot.

So as not to bury the lede (maybe it's too late for that...), you can play the game online or check out the source code via GitHub. It was a few hours in that we asked the lead designer what to call the game, and he offhandedly came up with Joe Johnson Gets Captured. It's catchy. The result, well, it looks like it was designed by a five-year old, but we're all pretty happy with it.

What I'd like to do next in the blog is provide a few vignettes about the day, rather than continue in a chronological fashion.

Title Screen

Production

One of the major challenges I faced was trying to fulfill the role of a producer on a five-person team with such varying levels of skills. At the beginning of the day, #3 son asked what to work on, and I suggested storyboards... which of course he had never heard of, so I had to provide some guidance. This poor guy was caught in between ages, not being quite advanced enough to do some of the technical work, and not being the youngest one who was sharing vision and giving feedback. My oldest son and I did the technical and integration work from my upstairs home office, while my wife worked in her downstairs home office. Even just this small physical separation kept us out of sync, where we didn't know where things were, and she didn't know what integrated work looked like. #1 son and I used git to share our work, but oh how I miss the asset locking that's so easy in UE4 with Perforce. Also, there seems to be known troubles with working across Linux and Windows machines in Godot because of line ending problems. Seriously, in 2020, in release 3.x of a popular game engine, this is still a problem. Still, between GitHub and Google Drive, spread out across three rooms and four computers of the house, we were able to bring everything together before 9PM.

I'm not entirely sure what I would do differently next time. It would be nice if we could all work together in one room, but I am sure neither my wife nor I want to give up our dual-monitor setups. I think we could get #2 Son at least more actively into Godot Engine in a future project, especially in the post-project exploration I've done of some of the tools as discussed below. I also need to remember to look carefully at that link I shared above to make sure I'm taking the best possible precautions against the silly line-ending problem, which caused us a lot of unnecessary headaches yesterday.

Music

A few weeks ago, I came across this video about using LMMS to make music for games, and my second son happened to watch it with me. He became interested, so we installed it onto the family laptop and he tinkered around a bit. For this fam jam, we put him in charge of the soundtrack. The truth, though, is that he doesn't have the musical knowledge to quite know how to structure a song: common rhythms, intervals, chords, etc. His first original composition is actually used in the loss screen of the game: it's actually a perfect fit for this part of the game, though musically, it's pretty clearly the result of kind of aimless messing around with LMMS.

Our lead designer said that he wanted the game to sound like Istanbul (Not Constantinople), which is a family favorite. I had written out a simple arrangement of that song, and I encouraged #2 son to transcribe the bassline into LMMS as a starting point. He wasn't really sure about this either, in part because I don't think he sees the isomorphism between staff and piano roll representations. I laid down the 1-1-1-5 bassline for him, and then I showed how I would approach the rhythm, setting up separate tracks for a bass drum on the downbeats and a high hat on the upbeats. He got that it sounded good, but maybe still doesn't quite know what to do with that knowledge. We found a lead tone (flute), and I showed how I'd layer a melody on top of these other ones by laying down a simple two-bar line. My son took the next little while to play with adding and removing the tracks, making some modifications to the melody. At one point, he accidentally copied the bass drum line to the highhat; this actually gave a good variation where all the rhythm was on the downbeat, though he didn't actually recognize that he did it. In our last session together, we got rid of the grating flute sound and replaced it with a synth. He had a spot where the drums dropped out, which was a good variation in tone, and I added in a kind of silly furious highhat tapping to bring the drums back in, which is still my favorite part of the song. The result is a fine little loop that runs through most of the game. For the title screen music, I once again laid down a few simple lines that he rearranged into a short loop that sets the tone for the game.

Maybe that's more detail about the music than you cared to hear about. There are very few things I've been doing longer than I've been programming, but playing and writing music is one of them. I'm hoping that perhaps this experience can be a good hook to encourage my son (and perhaps the others) to think some more about how music works and to try to start copying some of those ideas and playing with them. I am reminded of all the hours I spent as a kid copying songs from my piano lessons book or from my imagination into the C64 Music Maker software. I like to think that time wasn't just wasted!

Sound Effects

Fairly late in the project, as we had the core functionality in place, I sat down with the three younger boys to show them how to record sound effects on the family laptop using Audacity. I was surprised how quickly they caught on, not only to the recording, but also how to deal with multiple takes, exporting the selected audio tracks, and uploading them to Drive so we could put them into the game. I told them that this was how I made all the sounds for Kaiju Kaboom, and how pitch shifting could be used for very simple transformations. They put together a suite of sound effects which, truly, are not at all what I had in mind, but which certainly add to the aesthetics of the game.

Spoiler: When you win the game, there is a bit of spoken dialog that is tricky to catch. It's a combination of young kids talking into a laptop microphone and also adopting funny voices. The actual spoken words are: "You saved me, man." "No problemo."

The Mushroom Man and the Turtle in Action

Godot Engine

Let me start with my criticisms. Programming in Godot Engine reminds me in many ways of the things I hated most about programming in Unity ten years ago. The reliance on strings as signals, as method names, as node paths, and as resource paths strikes me as inexcusably fragile. Refactoring anything in Godot is an exercise in frustration. While it's true that one should minimize dependencies, one of the few truisms in programming is that code always changes. Tools without built-in refactoring support make me feel like we lost all the gains the agile software development movement made to modern IDEs. Worse, the reliance on literal strings throughout the architecture inculcates programmers into the idea that this is a good idea. That's really dangerous when compared to tools and processes which encourage constant improvement and refactoring. There's a rule of thumb: if refactoring is hard, people won't do it. On the positive side, this criticism makes me think about potential research opportunities for how to measure or change the environment to promote best practices. 

Another criticism, which should go without saying, is that whitespace should not be significant in a programming language. You cannot see it, so it should not be meaningful. Now, if you're really good, you'll appreciate the irony that this goes without saying. Why should it go without saying? Well, show me your whitespace. Also, if you cannot deal with line break characters properly, maybe you should not rely on whitespace for meaning. 

The node system has grown on me. I am glad I took the time the previous day to understand the relationship between areas, collision shapes, and their shapes, because that did not click for me right away. Now, I have a better appreciation for what I believe is the intended mental model. 

One of the most powerful notions in Godot Engine is instancing scenes. The nomenclature is terrible, however, since a "scene" is actually a class, in the object-oriented programming sense. The documentation even points this out. A "scene" in English has a connotation that is not at all implemented in Godot Engine, but if you think "class of objects" or "blueprint" instead, you get a better understanding. Ignoring the nomenclature for now, the idea that you can instance a scene into another is a powerful way to think about composition: while other parts of the engine encourage bad behavior, this one gives you a way to think about decomposing functionality and responsibilities in a very nice way.

Toward the end of the project, we ran into the classic problem where we wanted one song to play throughout multiple scenes.  The classic problem has a documented solution that we were able to incorporate before shipping: using autoloaded singleton scenes to manage shared state. With a few changes to where we put our songs and responsibilities, we were able to get the music behavior properly. (Well, except for a bug I noticed late last night on mobile, where, depending on where you first tap the screen, you can end up with two songs playing at once.) There is a problem again here though, and it also is mentioned in the documentation: these aren't singletons. The primary point of the design patterns movement was to introduce vocabulary to describe common solution strategies to categories of problems. It's not clear to me why the Godot Engine documentation writers would chose to use the term "singleton" for something that is not a singleton, not when one could just as well use a different word. Still, it's good technique to know, reminiscent of using GameInstance in UE4 to manage information that persists between levels.

We didn't use many advanced feature of Godot Engine. My son and I talked about it this morning, how the first time you use a tool like this, you sort of meander around, building and testing mental models. It's not until after you've built something that you can then really understand some of the other pieces, because then you understand not just the terminology but also the rationale for them. This morning and late last night, I did some reading that revealed some great features that I suppose we could have used, but now I see them as fun and powerful ideas to explore in future projects. These include the Tween node, the animation player, and cutout animation. The first two of those represent things I know how to do readily in UE4—things that add juice that our one-day build is clearly lacking. The cutout animation feature though is really special. I'm already thinking about it enables some of the ideas that have been kicking around to perhaps become more attainable. That is, rather than just seeing how to apply what I know from one tool to another, it's showing me a new way to do new things.

A Story of Code Quality

I'll take a brief aside to share a story that illustrates one of my points above and one of my son's reflections below. My eldest son was responsible for the cooldown timer on the player's mushroom man. Keep in mind that the player can shoot either attack or defense shots, and that these share a cooldown timer. His original implementation looked a bit like this:
 # Shooting attack bullet    
 if cooldown==false:  
   ....
   cooldown = true  
   yield(get_tree().create_timer(.5), 'timeout')  
   cooldown = false  
 # Shooting defense bullet  
 if cooldown==false:  
   ...
   cooldown = true  
   yield(get_tree().create_timer(.5), 'timeout')  
   cooldown = false  

This is the approach encouraged by the tutorial I mentioned earlier that we had worked through. I told him it's not the approach I would have taken, but we left it in. I did ask him, if we wanted to change the cooldown duration, how many places he would have to change it; he recognized that problem and then he replaced the literal 0.5 with a variable.

Originally, we just had input via the keyboard, but later we added the on-screen buttons. We wanted to make the game playable on mobile web browsers without keyboards or gamepads, so he worked on this feature, too. His original implementation, then, simply copied both of those blocks of text into the scripts attached to the buttons. However, the buttons were not connected to the player but to a separate UI, and so they had their own cooldown variable. The result was that, when using keyboard input, the experience was fine, or when using the buttons, the experience was fine, but when mixing the two, one could fire faster than we wanted to allow.

He understood the problem, and I suggested that a simple solution would be to have the buttons watch the player and, each tick, check if shooting is enabled. Their enabled state then could be matched to the player's shooting ability. He acknowledged this but said he had a different approach. His solution was to use signals: the player would emit signals when its shooting ability was enabled or disabled, and the buttons would listen for those signals to update their own state. Did you get that? He deployed the Observer design pattern. Proud Dad moment.

Family Reflection

I made omelettes for lunch today, and as I was preparing them, I told the family that I would ask everyone to share something they learned from yesterday's jam. I've written enough about what I learned, so let's hear what they wanted to share. For simplicity, I'll list the kids by age instead of ordinally.

5-year-old: The way he put it was, "I learned how to draw a computer." Digging more carefully into it, he meant that he learned to draw concept art—to draw something as he would like it to appear on a screen. He didn't have much else to offer besides what we tried to prompt from him, but you know, he's five. He clearly had a great time.

7-year-old: He mentioned storyboarding and recording audio in Audacity. He could not remember the terms for either, but he has brought up both multiple times, so clearly this was impactful. As I mentioned above, he's the one who I think got a bit shorted by the production plan, but he also clearly had a great time.

10-year-old: He also mentioned using Audacity, but he added that he learned how to share the files with the rest of us. My wife was a bit surprised at this, but that's because that whole process was physically and technically hidden from her: I clarified that he had not only recorded the audio, but also exported it and uploaded it to Drive for me to incorporate into the game. This gave me a good opportunity to talk about how a more mature process would be for everyone to have access to Godot Engine so that they could integrate and test their own work, but that I didn't think we would be able to recoup the overhead of that within a one-day jam. It would have required getting at least my wife and the 10-year-old into the engine and, more importantly, acclimated to using git from the command-line (which, incidentally, the 13-year-old did really well with after a brief tutorial).

This son also mentioned that he learned something about the division of windows in LMMS, but we had a hard time sorting it out: it had to do with the relationship between the song editor, the track editor, and the piano roll, but when I tried to assemble these things to see if I understood him, I kept getting it wrong. I need to sit with him and LMMS to see what it really ways. He also interrupted my wife's responses to throw in, "I learned that we should do family game jams more often!"

13-year-old: He learned about how collision handling works in Godot Engine, which was something that was dogging him on a side project. I asked him if he also learned anything about code quality, and emphatically affirmed that he had. In particular, he said that he learned that, to make a change in the behavior, you shouldn't have to change it in many different places. I explained that this was the essence of the DRY principle.

Wife (age withheld): The first thing she mentioned was that it's important to choose a palette at the start of a project. She had attempted a lot of color correction and postprocessing on the boys' hand-drawn images, and she realized that establishing a palette would have made this a lot easier. She also learned how to better use tools like Inkscape. In fact, she was working on processing images and layouts well past when we were done yesterday, and she spent several more hours working on pieces this morning. Later, I may go in and add her revisions and see if I can trap that aforementioned audio bug. Finally, she also noticed how important communication was and how difficult it was, even though we were all in the same building. Better communication would have meant an improved product and less confusion.

Concluding Thoughts

The family was all very excited, and while there were some tense times (mostly when people were asking me for things while I was trying to track down an elusive bug), it was a great day. Everyone is proud of our work, and they should be: together, we went from an idea in the morning to a playable, complete game in the evening. The only thing that we couldn't incorporate was a midday feature request that, when you save Joe, it becomes nighttime. During the day, #3 Son asked if we would do at again soon (I think he wanted to do it today) and if we would be going up in age order as lead designer. All the other boys agreed that they would love to do it again. The older two already spent time this morning tweaking some of their old projects based on what they learned or were excited by in Saturday's jam.

For me, it was a good break from a stressful time at work. In addition to all the stresses brought about by the coronavirus, I also have a major writing project that is due on Wednesday, and I'm not feeling confident about it. Rather than fret about it over the weekend, we took Saturday to make, and that's just about the best thing to do. 

Thanks for reading. I think you'll be hearing about Fam Jam #2 before too long, and I wish you the best in your own game-making adventures.

Tuesday, March 17, 2020

How my classes are moving to distributed teams

I am fortunate that my classes are fairly small and they have all already completed at least one iteration with a team. I want to just leave a quick note here about what we're doing with the transition to distributed work.

In CS490—the game studio—we already have Slack set up for the team. I reached out to my network to ask about good tools for distributed Pair Programming, and the clear winner, given our other constraints, was the paid version of Slack. They handled my request for an academic discount quickly, and so as of yesterday, we were on the Standard plan. Those who sang Slack's praises gave high regard to its ability to "remote control" other team member's computers, which is a requirement for anything like distributed pairing or mobbing. Unfortunately, that feature was removed from Slack a year ago. I'm not sure how that disconnect happened. My university has already paid for WebEx, so I looked into that, but remote control requires installing the Access Anywhere application, and the documentation on how to do that is just wrong—or maybe my university bought a different package or something. In any case, no luck there. Two students mentioned Zoom, so I looked into that, and after doing a little dual-account dance in a test Slack, I was able to confirm that it works fine for allowing remote control. It also seems that we can do it at no cost for our team size, which is great. Unfortunately, I figured all of this out after the regular meeting time for the student teams, so they were not able to try facilitating their meetings with the Zoom add-on.

Meanwhile, in CS222, they just finished their first iteration of the final project. Yesterday, I hung out on Canvas Chat and answered one question. My current plan is to use that during "class hours" and then switch to Canvas Conferences for group voice conversations. It didn't come up yesterday, so I cannot comment on how well it worked. I set up some new assignments for them that more carefully scaffold and make asynchronous some activities that I would have otherwise done in class. Each team had to submit a communication plan last night, which I need to look over today; I already gave them a gentle nudge toward using Slack rather than text messages, and I am curious if they followed my advice. By Wednesday, they need to submit a plan for Iteration 2. I expected more teams to reach out to me with questions about my feedback on Iteration 1, but none did; this could mean that they are not taking it seriously, or it could mean that the extra time I took trying to be as explicit as possible paid off.

UPDATE: A few hours after posting this, the university announced that Canvas Conferences was instituting a limit of 10 concurrent meetings university-wide. Well, that quickly became unusable. I've posted to my class and informed them that I'll plan to use Zoom with them as well.

Tuesday, March 10, 2020

Learning about the Four Stages of Competence

I learned a new model of competence in a meeting with the High Impact Practices Assessment Task Force two weeks ago. I'm glad I jotted it in my notebook, since this brought it back to mind with an intention for a quick blog post.

My colleague Michael O'Hara mentioned a taxonomy of competence that goes, from lowest to highest:

  1. Unconscious incompetence
  2. Conscious incompetence
  3. Conscious competence
  4. Unconscious competence
He told me that this is widely used in his discipline of Theater Education, but I had never seen it before. A bit of searching led me to the Wikipedia entry, which refers to this as the Four Stages of Competence or the Conscious Competence learning model. Michael pointed out an interesting property of this progression: that, except for the lowest level, a learner can usually self-assess accurately.

When he brought this up at the meeting, my mind immediately went to the Dreyfus Model of Skill Acquisition, which is my go-to model for thinking about how learners' skills develop. The conscious incompetence level of the Four Stages of Competence model reminds me of the Competent level of Dreyfus Model: it's the level above second-order ignorance, at which a learner develops the ability to recognize their own errors and self-correct.

It's not immediately clear to me if I have a place to slot in the Four Stages into my current teaching and research. More specifically, it's not yet clear to me that its two-dimensional space captures the what I try to assess in my students, or rather, that it the taxonomy leads me to more effective teaching or assessment. However, it has a nice ring to it, a kind of elegance that's easy to show and explain. I suspect this is where it will be most useful: to help novice learners become more metacognitive, which may in turn make them more receptive to advice on how to learn more effectively.

Friday, February 28, 2020

Managing the lifetime of child actors created from C++ OnConstruction methods in Unreal Engine 4

I have been working on a little example for my UE4 video series based on Space Invaders and designed to talk about some issues in object-oriented decomposition. Along the way, I ran into a technical problem that I know I had seen last summer, but it took me hours to find the solution. I may make a video about this later, but for now, I just want to get the basics explained here on the ol' blog.

The specific modeling problem I am dealing with is the swarms of enemies in Space Invaders. It's pretty clear to even the most novice programmer that "alien" should be an object. The Alien class would be an Actor, and it would be a great place to deal with things like collision detection and explosion effects. However, it gets a bit tricky when dealing with the movement patterns of the aliens: the whole swarm changes direction when one of them on the edge hits the side of the play area. This leads to a less obvious object-oriented modeling idea: that the swarm itself is another kind of Actor.

In my sample solution, I wanted to be able to create a swarm with any number of rows and columns and have it create that many aliens in a grid. In Blueprint, this is pretty easy to do. BP_Swarm has Rows and Columns variables that specify the size of the swarm. Its construction script can loop through all the "cells" of the grid and add a child actor of type BP_Alien for each. Presto, this allows you to drop a BP_Swarm object into a level and configure its placement and size.

The trouble arose when I decided I wanted to do this in C++ instead of in Blueprint. I added what seemed like the right code to the OnConstruction method. Here's the basic idea, leaving out for the moment the code that handles the individual placement of aliens:

void ASwarm::OnConstruction(const FTransform & Transform)
{
    if (AlienClass) {
        check(Columns >= 0 && Rows >= 0);
        for (int i = 0; i < Columns; i++) {
            for (int j = 0; j < Rows; j++) {
                UChildActorComponent* AlienChild = NewObject<UChildActorComponent>(this);
                AlienChild->RegisterComponent();
                AlienChild->SetWorldTransform(GetActorTransform());
            }
        }
    }
}

When I dragged a swarm into the level, it showed up, but its children persisted every time I moved the swarm or changed its parameters. This is clearly a different behavior than in the Blueprint construction script, but it wasn't obvious to me at all how to get that behavior to work in a C++ implementation. I remembered having come across it when working on the building logic in Kaiju Kaboom, but it took me hours to find it again. Indeed, I even posted to the Unreal Engine 4 Developers Community on Facebook, but the best answer I got was one I was aware of and left me unsatisfied: manually check for and destroy child actors at the beginning of each call to OnConstruction. After stepping away and searching again this morning, I found the forum post that I'm sure is the same one I tripped over last Summer—the post that mentions a barely-documented feature of UE4 called the component creation method. Here's the magic line that saved my ability to trust my memory:
AlienChild->CreationMethod = EComponentCreationMethod::UserConstructionScript;

EComponentCreationMethod has four possible values, and this one must be what is used internally by components created via Blueprint construction scripts. It aligns the behavior of the C++ implementation with the Blueprint one.

For reference, here's the full implementation of OnConstruction from my working demo. It uses a designer-configurable Spacing value that specifies the distance between aliens in the grid, and then it makes use of range mapping to translate from array index to geometric space. One other bit of weirdness here that I'll mention is that while UE4 is generally an "X-forward" system, with the X-axis pointing in the direction an actor is facing, UPaperSpriteActor by default has sprites facing in the negative Y direction. Hence, the horizontal placement of aliens is along the X axis and the vertical placement of aliens is in the Z.

void ASwarm::OnConstruction(const FTransform & Transform)
{
    if (AlienClass) {
        const int Width = (Columns-1) * Spacing;
        const int Height = (Rows-1) * Spacing;
        const FVector2D ColumnsRange(0, Columns - 1);
        const FVector2D RowsRange(0, Rows - 1);
        const FVector2D HorizontalRange(-Width/2, Width/2);
        const FVector2D VerticalRange(-Height/2, Height/2);
        const FTransform ActorTransform(GetActorTransform());

        check(Columns >= 0 && Rows >= 0);
        for (int i = 0; i < Columns; i++) {
            for (int j = 0; j < Rows; j++) {
                UChildActorComponent* AlienChild = NewObject<UChildActorComponent>(this);
                AlienChild->RegisterComponent();
                AlienChild->SetChildActorClass(AlienClass);
                const FVector Location(
                    ActorTransform.GetLocation().X + FMath::GetMappedRangeValueUnclamped(ColumnsRange, HorizontalRange, i),
                    ActorTransform.GetLocation().Y,
                    ActorTransform.GetLocation().Z + FMath::GetMappedRangeValueUnclamped(RowsRange, VerticalRange, j)
                );
                FTransform AlienTransform(ActorTransform);
                AlienTransform.SetLocation(Location);
                AlienChild->SetWorldTransform(AlienTransform);
                AlienChild->CreationMethod = EComponentCreationMethod::UserConstructionScript;
            }
        }
    }
}

One other note about this code, potentially for future-me who comes back to remember how I fixed this problem before. I had forgotten for a while to call RegisterComponent, which omission makes the whole thing a bit squirrely. Also, there is temporal coupling in the component's methods: calling RegisterComponent at the end of the loop creates strange editor-time behavior as well, whereas calling it immediately after NewObject gave the expected behavior.