Last week's progress is listed here

I spent a while running through the game in its current state and think that it's fitting to add at least a few of the following features.

Priority One:

  • Main menu with start/settings/quit.
  • The 'fighter body' should broadcast the "damage taken" event to child nodes so they can record whether or not they're dead.  Dead enemies should be despawned.
  • End-of-level triggers need to fire.

Good to haves:

  • Motion feels very limited right now.  Jumping would go a good ways to helping that, as would having different attacked based on whether or not one was jumping or moving.
  • Perfect-time parrying.  Right now a user can cancel into a block at certain times, but there's no reward for having anything above 'okay' timing.
  • Rebindable keys would be very nice.

I know I should work on having a level completion and a main menu before adding any of the extras, and I expect I'll do as much, but I want to keep track of these items to I can refer back here and see how much I set out to accomplish and how much I actually accomplished.

It's the end of the first weekend. I managed to finish a few important pieces and numerous unimportant pieces. Here are some hiccups and what I did to work around them.

I started by making a walk cycle to get into the swing of things. Moving around is an important first step, pun intended.

Immediately after this I encountered a problem where moving left would cause the character to spaz out and flip left and right once per frame for as long as the left button was held. It turns out that Godot does not like having a KinematicBody flipped horizontally (scale.x = -1) and will override that. It was not, as I suspected, an issue with the animation resetting scale. The workaround here was to move the skeleton beneath a Node2D and flip that. It means the hitboxes won't be flipped correctly, but I'll have to keep them centered and balanced.

The next thing I worked on was analog stick input and variable speed walk cycles. I wanted to cool off a bit from that bug, so I spent a short while setting up key and controller inputs, then tweaking the scaling between the walk rate and the animation rate. I have a move speed and an animation multiplier speed. The move speed can vary by character, but the animation multiplier stays fixed. If a character moves 20 units per second, the animation plays at (20*animation_multiplier)x normal speed. I just have to play with the multiplier until the feet look right. One problem that comes from this is scaling. If the models change scale (or I change animation) I'll need to readjust the animation_multiplier. Could prove tricky.

The last issue I ran into was broadcasting events. I had originally set up the Fighter scene as a child of another Node2D, so a player node, for example, could have a script which handled input and called into Fighter to strike or block or move. This worked well enough, but when it came to detecting and broadcasting hit events, I found that selecting the overlapping areas with an area 2D (at the hit point) yielded the root nodes (i.e. player, npc, etc) and NOT the fighter nodes which could handle 'hit'. I struggled in part because Godot does not allow one to attach multiple scripts to the same node. I didn't want to put more logic into the fighting controller, but it didn't seem graceful to select all the nodes of a given type and then seek the first child with name "Fighter". The solution turned out to be flipping around the hierarchy. Instead of having PlayerNode -> FighterBody, I had FighterBody -> PlayerController. All on-screen fighters have this same root type which means I can simply have the animation call 'strike' and the event will propagate.

func strike():
for b in strike_area.get_overlapping_bodies():
if b.is_in_group(target_group) and b.has_method("hit"):
b.hit(self, strike_area, damage)

func hit(striker, damage_area, damage):
# TODO: Face correct direction.
hit_recovery_time_remaining = hit_recovery_time"Hit_Front")
# TODO: Report the hit to child nodes.

All that comes together to make a nice striking system.

It's happening!

This year's theme: Sequels!

After spitballing in Discord for a while, I decided to make a sequel/spinoff to Enter the Matrix. The Matrix really needed sequels, right?

Gameplay: A side-scrolling 2D platformer/beat 'em up.

Minimum Viable Product:

  1. 2D character controls with jumping and collision (weekend 1)
  2. Punching and kicking with some visual indicator (weekend 1)
  3. Enemies that respond to punches (weekend 1)
  4. A start and end state with menus, spawning, death, and completion (weekend 2)
  5. An environment the player can traverse from start to end (weekend 2)

Stretch goals:

  1. JUICE for enemy impacts.
  2. Animated player moves.
  3. A combo system.
  4. Backstory and dialog systems.

Let's roll.

It's done enough!

tl;dr: Download a Runnable Jar Here

Standalone PC/OSX builds are pending.

Kudos to Peter Queckenstedt (@scutanddestroy) for doing an amazing job on the Proctor, Hillary, and Trump.


​This has been a positive experience. I love games that actually have nontrivial interactions in them and completely open-ended text inputs. I'm a fan of interactive fiction, but hate that feeling when you're digging around and grasping for action words like some sort of textual pixel-hunt.

The language processing systems in DS2016 aren't particularly complicated, but they're more simple than I'd like. In the first week of the jam I started writing a recurrent neural network to parse and analyze the sentiment of the player's comments. I realized, perhaps too late, that there wasn't enough clean data for me to use to accurately gauge the sentiment and map it to social groups. Instead, I wrote a basic multinomial naive bayes classifier that takes a sentence, tokenizes it, and maps it to 'like' or 'dislike'. Each group has its own classifier and tokenizer, so I could program demographics with a base voting likelihood and give each of them a few sentences on the "agrees with" and "disagrees with" sides, then have them automatically parse and change their feelings towards the player.

A usability change that came in later than one would guess was as follows: I had originally grabbed the demographic with the largest emotional response to a comment and displayed them with the sentiment change. Unfortunately, this turned out to over-exaggerate one particularly noisy group. Another change, shortly thereafter, was masking the exact amount of the change. Instead of saying +1.05% opinion, it simply became "+Conservatives" or "-Hipsters". This was visually far easier to parse and I think helped the overall readability of the game.

There is still a call to add some more direct public opinion tracking in the game, letting players know in closer to real time how they're doing among the demographics. I may find it in myself to introduce that.

The last interesting aspect that I noticed during playtesting: I had slightly over-tuned the language models to my style of writing. Instead of opining on matters at any length, people were making enormous run-on sentences which appealed to every demographic at the same time. These statements, often self-contradictory, were not something I expected or handled well. I found the game to be rather difficult, but it looks like playtesters had a dandy time making the states go all blue.

It's time again for Little Awful Jam! The theme is 'Weird History'. Make a game about folk lore, something strange that happened in history, or some corruption of events. This is my game design doc.

Game Design Doc

The Pitch: The idea on which I've settled is Debate Simulator 2016, where you play a presidential candidate stepping up to the podium to square off against our current commander-in-chief.

The Gameplay: The gameplay consists of prompts and free responses. Your goal is to appeal to your voting base and to excite them enough to go out and vote. Alternatively, you can go 100% offensive and do nothing but verbally tear down your opponent. Your feedback will consist of your approval rating and your citizen motivation. Don't motivate people and they won't get out and vote, even if they like you. Motivate people to vote and don't get them to like you and you're sure to lose.

The Challenge: Do you know your stuff? Can you overcome the Evangelical block? How do you tacitly approve of bodily autonomy without making it seem like you approve of bodily autonomy?

Free-form Ideas:

  • Pick your alignment. Left-Democrat. Centrist-Democrat. Independent. Centrist-Republican. This will change the difficulty by having different demographic groups start with different opinions of you.
  • End of game: show the election map and the polls. Use real demographic data to show how things played out.
  • Generate realistic text for Donald Trump by randomly mashing together words.
  • Simple NLP for the player to classify sentiment and subject, including prompt text for context.

Look and Feel: 2D single-stage pixel art with largely static sprites and a camera that pans between the player and the challenger. Aiming for 640x480 resolution with 2x upscaling. No fancy particles. Minimal sprite talking animation. Animated text.

Tools: Sadly, I won't be using Godot for this. Much as I love the engine, there is so much here that requires a more robust coding language that I need to do it in libGDX with Kotlin.

Project Progression:

  • Skeleton libGDX game with Kotlin. 'Hello World'.
  • Scene stack and placeholder sprites. Basic game loop.
  • Demographic data and player input processing + scoring.
  • Opponent responses + emotional meter.
  • Minimum Viable Product