Godot 3.0: Exporting game data from Google Sheets into a staticData .gd file using node.js

If you’re making a Godot game with a bunch of “static data” such as items with stats and effects, quests, characters with stats, enemies, loot tables, spawn tables, etc. – then you might be wondering where to put your game’s data (and how to format it) in a Godot project.

When I first set out to do this I couldn’t find a great guide so I decided to figure it out and make one. My way probably isn’t perfect, but it gets the job done. 

My goals (and what I ultimately built):

  • Organize my game’s data into separate tabs in a Google Sheets spreadsheet.  Advantages: I would get to use Sheets’s validation features, I can access/edit my data from any computer anywhere, working in Sheets is easy and familiar to me and anyone who has used Excel.
  • Export from Sheets into something I can process into Godot objects. I went with JSON. (More on this later)
  • Turn the exported JSON into a game data file, which would be “globally” available for my game’s code to use
  • Easily access items, mobs, etc. by ID from within the game’s code. I want to do something like this: var sword = allItems[“Rusty Sword”].duplicate()

Setting up the game data in Google Sheets

If you’re doing something similar feel free to build your data however you like. I liked rows, with the thing’s id in the first column. 

This first example is the items sheet. These are all the swords, robes, armor pieces, crafting items, quest items, etc. in the game. Every item has a name, a “slot” it goes into, class restrictions, and stat bonuses. Typical RPG stuff. This sheet is very large, but it’s easy to search and I color coded by slot to help make it easier to find things. 

The next example is my game’s enemy (mob) data. Enemies (mobs) in my game just have a few stats, but you can see how the data could be built out to support much more complex monsters.

You might have noticed that the mobs have loot tables. Loot tables are yet another tab in the data sheet.

Google Sheets lets you set up “validation” so that some cells can only contain data from another sheet. (You can type the loot table name or pick it out of the dropdown that Google Sheets generates when you use validation.)

Adding a simple validation here helps cut down on typos and errors that result from things getting renamed. 

There are more data sheets for my game, but this should be enough to give you an idea of how to put your game data in a spreadsheet. Next up, exporting.

Exporting the game data as .json

I picked .json for a few simple reasons:

  • It’s easy to find Google Sheets to JSON exporters
  • I’m already familiar with JSON and it’s fairly human readable
  • Godot has some built-in capabilities for parsing JSON

For the export itself, I used the free “Export Sheet Data” Google Sheets add-on (link). Just install it and find it in the Add-ons dropdown.

There are a bunch of settings in here to play with depending how you want your data formatted.

I wanted mine to be an array of objects, so the settings I checked are:

Checked settings: JSON format, current sheet only, Replace existing file(s), Export cell arrays, Export contents as array.

The exported data looks like this. (This is a super truncated version of what the items tab gets exported as.)

    "name": "Novice's Blade",
    "icon": "sword1.png",
    "bodySprite": "sword1.png",
    "itemType": "sword",
    "consumable": false,
    "prestige": 0,
    "slot": "mainHand",
    "rarity": "common",
    "classRestriction1": "warrior",
    "classRestriction2": "",
    "classRestriction3": "",
    "classRestriction4": "",
    "classRestriction5": "",
    "hpRaw": 0,
    "manaRaw": 0,
    "dps": 2,
    "armor": 0,
    "strength": 0,
    "defense": 0,
    "intelligence": 0,
    "noDrop": false
    "name": "Rusty Mace",
    "icon": "mace1.png",
    "bodySprite": "mace1.png",
    "itemType": "mace",
    "consumable": false,
    "prestige": 0,
    "slot": "mainHand",
    "rarity": "common",
    "classRestriction1": "cleric",
    "classRestriction2": "paladin",
    "classRestriction3": "",
    "classRestriction4": "",
    "classRestriction5": "",
    "hpRaw": 0,
    "manaRaw": 0,
    "dps": 2,
    "armor": 0,
    "strength": 0,
    "defense": 0,
    "intelligence": 0,
    "noDrop": false

Turning the exported .json into a .gd file for Godot 

Here’s what we need to do:

  • Open the .json file(s) (remember there’s one .json for every tab in the spreadsheet)
  • Parse it line by line and make any formatting changes necessary
  • Write the parsed and modified data to a .gd file that contains all of the game’s “static” data
  • Access the static data in the .gd file from the game’s code 

There are practically infinite number of ways to accomplish these steps (it’s just some file i/o and text parsing), but I went with what I already knew – Javascript. My quick-n-dirty parser (named “Parsely”) is far from beautiful code but it gets the job done.

You can see it in its entirety here: Parsely.js gist.

Parsely’s code is written specifically for my project, but one thing I want to point out is the way it transforms my objects. 

An object comes out of the Google Sheets exporter like this simplified example:

    "name": "Novice's Blade",
    "icon": "sword1.png"
    "name": "Awesome Weapon",
    "icon": "sword2.png"

But what I really need is this:

  "Novice's Blade": {
    "name": "Novice's Blade",
    "icon": "sword1.png"
  "Awesome Weapon": {
    "name": "Awesome Weapon",
    "icon": "sword2.png"

Notice the array has become one giant object, and each object is a property within that object. I want to grab my item by its name, ie: “Novice’s Blade”, and get the associated object data. I also want all this stuff to be in one giant object so I can grab objects directly without having to iterate through it (as I would have to if it were an array). 

So that’s what Parsely is doing when it does this:

for (var value of fromJSON) {
  var key = "";
  if (file == "items.json") {
    key = value["name"];
    formatted[key] = value;
  } ...

It’s getting the name and making that the key, and it’s getting the whole object and making that the value. Now I have a giant object full of smaller objects, where each smaller object is a unique item in the game (like the second JSON example above).

Also, sometimes I wanted to add more parameters to an item at runtime, such as a unique ID or a boolean representing whether it was an enhanced item or not. Those things don’t exist in my spreadsheet, they’re just slapped on when this script is run. 

Here’s an example from parsely.js of three new params (“itemID”, “improved”, and “improvement”) being added to each item as it is processed.

For the sake of keeping everything related to my project in one place, I placed parsely.js and the .json files it processes in my Godot project folder like so:

When I export from Google Sheets, I download the .json file it generates and place the .json file in the appropriate folder (names, staticData, or timedNodeData). Parsely handles files from different source folders slightly differently, ie: files from names get built into arrays, files from timedNodeData get some “inProgress”, “readyToCollect” booleans attached, etc.

Finally, we can run it! I open a Terminal window and navigate to the Parsely folder. To run, I type:

node parsely.js

It then grabs those json files, processes them, and places them in res://gameData (which is where I want them to go).

Inside each of these .gd files is an object or an array formatted as one long line.

This is staticData.gd:

Here’s our data, organized into separate objects.

Using the data in my Godot project

Finally, make the staticData.gd file global by adding it in Project Settings > Auto Load. Now it’s accessible everywhere in the project. 

Now, throughout the project items, mobs, loot tables, etc. are all accessed from staticData like in these examples:

var newItem = staticData.items[itemNameStr].duplicate()

var loadout = staticData.loadouts[loadoutIDStr]

And that’s it! Now my game has all of its items, spawn tables, loot tables, quests, crafting recipes, and more pre-loaded as data objects and universally available anywhere in the game’s code.

Godot 3.0 Tutorial: Building a simple character creation menu screen

In this tutorial: structuring and scripting a simple RPG-style character creation screen using Godot’s built-in containers and Godot script

What we’re building

I recently added a menu to my game that lets the player create their own custom character for the game. In the context of my game, that means getting to name the character, choose the character’s head sprite, and choose the character’s class. It sounds simple but this work managed to touch on a lot of things, so I thought I’d share my work here in hopes that it’ll help someone else. I’ve been working in Godot on a hobby project for about 5 months now and I think the engine is great but could use a few more tutorials and “here’s how I did it” type stuff, so here we go. 

Some of the things covered in this guide include:

  • Godot’s container system (VBoxContainer, HBoxContainer, etc)
  • Building a simple menu out of Godot nodes
  • Hooking that menu up to the rest of the game
  • Changing scenes
  • Altering aspects of a “hero” scene, such as its name and head sprite
  • Lots of Godot script examples

PS: The project I’m using for this guide already exists (in some capacity), so there are references to things that are already built prior to this guide. Hopefully this “slice” of the game’s development is still helpful to someone, even if it doesn’t start from scratch. 

Structuring the scene: Godot container types explained

The first thing I did was make a new scene and add a Node2D to serve as the parent node and a VBoxContainer as its child to hold all of the major elements of this menu. The first child of the VBoxContainer is a label.

My new scene is called createHero.tscn

Let’s talk about structuring a menu in Godot.

For a menu with many “sections” or “elements” that read top-to-bottom, use a VBoxContainer. The VBox stacks its children elements vertically (one on top of the other) which saves you from having to position each one individually and from having to worry about overlapping elements. You can also control the VBox’s width and the spacing between its child elements.

Each element in the stack can be something simple, such as a label or a button, and it will occupy as much vertical space as it is tall. Nothing will overlap it. Or, each element could be something more complex, such as an HBox (which would let you create a row of buttons, labels, or similar).

This system takes a little practice to get used to, but hopefully this diagram made of children’s blocks helps clarify the general concepts.

This stack represents a VBox with child elements. Each “row” is a container, element (such as a label or a button), or an HBox with child elements of its own.

For the sake of brevity I’ve skipped ahead to my assembled scene. This builds on the concepts already explained.

My scene now contains a VBox parent with three children: a label, an HBox, and another HBox.

For now, it’s just made out of unskinned/unstyled Godot nodes.

Some things of note:

  • There’s an open space below the “Create Hero” label that I will use to display the hero art later on
  • “container_spacer” is a generic Container node. I set its minimum width to 420 so that the other thing in the HBoxContainer2, the “Rename” button, gets pushed to the right side of the screen.
  • The hero class (Cleric, Druid, Ranger, etc.) buttons are in an HBox that manages their left-to-right spacing 

Getting to this new scene

I made a little button on the main screen of my game to access createHero.tscn.

This is just temporary so that I can access the new menu for testing.

Eventually, this “Create a character” screen will be the first thing the player sees when starting a new game, but I don’t want to clutter the new game startup flow with an unfinished (possibly broken) menu yet. 

Here’s the button on my main game scene:

I hooked up its button press signal (I just go with the default function name Godot suggests):

And the code:

If you’re following along at home, all you need is the last line, the one that begins get_tree()… as the other two lines are specific to my game.

With that button hooked up, I can now run my game and click the temporary button to get into my new menu. 

Here it is in-game. No, it’s not beautiful. but we gotta start somewhere!

Creating a script file for this menu

For this menu to actually do anything I’m going to need a script file for this menu (or this scene, to use Godot’s parlance). To create a script file for the scene I click on Node2D and go into the Inspector tab. I selected New Script and let Godot create a new script for me.

With Node2D selected, go down to Script and selected New Script.
I just take the defaults most of the time in Godot. This stuff is all fine as-is. I click “Create” and let it make the new script file for me.

Adding an instance of the Hero scene to the Create Hero menu

Usually with a character creator you want to show a preview of the character being created. For the game I’m working on, that means making an instance of the Hero scene and attaching it to the menu so the player can see their character preview.

(The Hero scene already exists in my project. I won’t cover it in this tutorial, but you can see the code that makes up a Hero scene and the hero generator by viewing these gists I made for the sake of this guide: hero.gd, baseHero.gd, heroGenerator.gd. You don’t need to look at or understand these files to follow this guide, but you may find them helpful if you are trying to build something similar.)

Here’s how hero.tscn looks in my project, structurally speaking:

Back in createHero.gd, we have to add some code in order to see the hero scene in the menu. The project already has a heroGenerator file that I use to make random heroes for the player’s guild. Here, the heroGenerator file is used to make a single hero and present it to the user in this menu. The general idea here is to generate a random hero, show it to the player, and then let the player customize it to their liking (just like how “create a new character” works in a lot of MMO type games).

Code for generating a hero, adding it to the guild roster, creating a scene instance for that hero, and adding the instance to the menu scene. View this code as a gist.

Here’s how it looks in-game:

Ta-dah: a hero character instance now exists in the menu.

Making the “Rename” popup and functionality

There are a few things we have to do to get the rename popup working:

  • Add the popup node itself (a ConfirmDialog node)
  • Give the popup a TextEdit field so the player can enter a name
  • Make the popup appear when the user taps the Rename button
  • Write the script that accepts the new hero name
  • Update the hero’s data to keep the new name
  • Add a random name generator button
  • Name validation (not part of this tutorial but for a real game you’d probably want this)

First, the popup.

Godot has some dialogs (popups) built in. The “Rename” popup is going to be a ConfirmDialog with a child LineEdit. The LineEdit is a field for the user to type in. This guide’s game is imagined as an Android/iOS game, and LineEdit conveniently brings up the keyboard on those devices.

I made this confirmation dialog into its own scene since the rename functionality will be used elsewhere in the game. (To do that, right click the ConfirmDialog in the Scene tree, click Save Branch As Tree, and save it as its own scene.)

If you don’t make a ConfirmDialog its own scene, its Ok button script can just go in your parent scene’s .gd file.

If you do make ConfirmDialog its own scene, its Ok script will be in its own file.

Either way works, I just like to make anything used in more than one place into a scene so I don’t have to maintain code in two places.

Hooking up the Rename button to open the popup

Now that we have the confirm popup scene made, let’s make it so the “Rename” button actually opens the ConfirmDialog (which I’ve named confirm_rename_dialog). Godot makes this really simple.

Select the Rename button and navigate to its pressed() signal.

Select the “Rename” button and navigate to its Node signals. Highlight pressed() and click the Connect… button in the lower right.
I’m happy with the method name Godot suggests, so I click Connect and let it create the method.
Here’s the empty method Godot created.
And here’s all the code it needs to open the dialog.

If we tried it in-game now, we would be able to open the popup and type a name but not actually save our new hero name. 

Saving the user’s input to the hero

To make the “OK” button actually do something, we have to go into the confirm_rename_dialog scene and attach a script file to the scene. I made a new script file for this ConfirmationDialog.

In the Node signals panel, the confirmed() entry is what is triggered when the user presses OK. I connected it to an empty function.

Click confirmed() and then click Connect to generate a function in the popup’s script file.

Godot makes it realy easy to grab the user’s input from the LineEdit. Just write:

var newName = $LineEdit.text

and then do something with newName. In my case, that meant updating the selected hero’s heroName to be the value of newName. 

(Note there’s no attempt at validation in this example, so the user can enter anything they want right now. For a real game, you’d probably want to keep names under a certain length and filter out numbers, special characters, symbols, emoji, and possibly dictionary words and profanities.)

But what’s this signal business? Well, the popup is a separate scene from createHero, so it has to communicate with its parent scene. Godot does that with signals.

Declare the signal (line 3) and then emit it (line 12). It’ll be caught by the code up in createHero.gd.

Back in createHero.gd I’ve had to make a few changes. There’s now a draw_hero_scene() method because I think we need to clear and redraw the hero scene from at least two places in the code, so I took it out of _ready and made it its own function.

I also attached the redrawHeroName signal to the confirm_rename_dialog instance, so that it can “listen” for the signal and call “update_hero_name” when the signal is “heard”. All update_hero_name() does is free the existing hero scene (clear it from the stage) and make a new one. This draws a new hero instance with the new name.

I’ll probably rename update_hero_name() to something more generic once I give the user the ability to modify the hero’s appearance and class.

Let’s try it out in game before moving on:

User types anything they want (seriously there’s no validation yet)
Success! And it doesn’t even flicker. I was afraid it would flicker.

Making the “hero class” buttons (radio buttons)

Next up: changing this hero’s class.

A hero can only be one of the available classes (ie: she can be a Wizard, or a Warrior, or a Cleric, but not more than one of those options). When the player picks a choice, the others are “deselected”. 

This is a lot like how “radio buttons” on the web work. Pick one choice, the others are “un-picked”. Godot actually has something for this: a button group! A button group is somewhat convoluted to set up.

First, select one of the buttons we want to add to the (not-yet-created) button group. In the inspector tab, scroll down to Group. Click where it says <null> and then choose New ButtonGroup. 

Click on New ButtonGroup to view its inspector pane. Go to Save As… to save it as a .tres.

Saving it lets us load it onto all the other buttons.

Select all of the remaining buttons and click the field next to Group. Choose Load and then choose the saved .tres file. Now all of the buttons are in the createHero_classButtonGroup.

Let’s try it in-game.

Here we have Cleric selected.
…and here we have Druid selected. (The faint blue border indicates which one is selected.)

Making these buttons mutually exclusive will help with styling later on and allows us to quickly “deselect” the user’s previous choice and highlight the new current choice. (The highlight on these default Godot buttons is a thin blue border that might be difficult to spot at first.)

Changing the hero’s class (in data)

This step is going to require some refactoring. Currently, there is no mechanism in the game to change a hero’s class. A hero is given a class and a matching gear loadout by the heroGenerator.gd file and that’s it. 

Our refactor will need to:

  • Change the hero’s class
  • Change the hero’s starting gear to match that class
  • Change the hero’s starting stats
  • Do not change the hero’s name or head (these might already be set by the player, but if we just generate a new hero they will also be re-generated)

I had to do some refactoring here…

So this next part is kind of a tangent and really specific to my project, but I wanted to include it and not just hand-wave it in case it’s valuable to someone who reads this (hello, future me, probably).

Currently, the hero’s starting gear is handed out in heroGenerator. A hero already has a “give_new_item” method that accepts a string (must match an item in the game’s static data) to create an instance of the item and assign it to the hero’s equipment object. Here, giving a character its starting gear is done with multiple calls to give_new_item on the hero class.

The old way of giving gear was done line-by-line.
Hero.gd has this method to find the item (by its name as a string) in staticData.items and stick it on the hero in the correct equipment slot.

The problem with how this is currently done is that this “gear assignment” step happens when the hero is generated for the first time, and then does not (or cannot) happen again. But if you change a brand-new character from a warrior to a wizard, you need to wipe the warrior gear and replace it with wizard gear. I could probably do this out of methods that already exist on the hero for giving and taking equipment, but I have an idea for something cleaner: a “gear loadout” system, whereby gear sets exist in staticData and are assigned to a hero in one fell swoop.

Here’s a quick look at the changes I did during this refactor. I won’t cover every last step, just a high level of how this stuff works in my game.

Added a new data sheet: In my game data Google Sheet, I made a new tab and set up some gear loadouts like so. (The fields are restricted to just items that actually exist in the Items tab of the game data workbook.)

This gets exported as a json:

And then I go over to the tool I wrote to process individual JSON files into my Godot project’s staticData.gd file. (This deserves its own tutorial, but for now you can check it out as a gist here if you like.)

Parsely (a tool I wrote for this project to turn .json data into objects in a .gd file) now handles this new loadouts.json file
And now var loadouts is an object in staticData.gd.

And now var loadouts = {…} exists in staticData.gd. Since staticData.gd is an AutoLoaded file, this means that my game’s code can retrieve a specific loadout by id like so, from anywhere in the project:

var gearSet = staticData.loadouts[“clericNew”]

Updating hero.gd Now that we have the concept of gear loadouts, it’s time to update the hero class with the ability to use them.

Now you can call hero.give_loadout(“clericNew”) and get all the gear associated with that loadout.

For now, the give_loadout() method is also going to delete any armor already on the hero, since this feature is only used during the creation of a new hero and we don’t want to keep all the gear generated by changing class. I don’t think give_loadout() will be used outside of character creation and testing purposes so for now this is fine.

Writing the change_class() method in hero.gd

Finally, I have everything needed to write change_class(). Now we can write hero.change_class(“Cleric” and that hero will become a cleric, complete with the default newbie cleric gear. 

One last thing to do before calling this refactor complete: update the heroGenerator.gd code to use loadouts instead of one-by-one gear gifting like we saw earlier in this guide.

heroGenerator.gd now uses give_gear_loadout() to assign gear sets to newbies. Remember, the gear loadouts themselves are stored in the spreadsheet data now, so there’s even some validation (in the Google Sheet) that the user picked a gear item that actually exists. Win-win all around.

Okay, NOW we can finish what we came here to do: clicking the class buttons should change the new hero’s class and change all of its starting gear to match.

Back in createHero.gd, we hook up each hero class button to a bit of code that calls change_class on the selected hero (the one we are viewing). I’m sure there’s some more efficient way to do this but for a small set of buttons this makes it pretty clear what’s going on. Remember how I thought we might change “update_hero_name()” to something more generic? Well now it’s “update_hero_preview()” because we also call it after changing the hero’s class.

Let’s try it out in game. Here our new hero is a Wizard.

And now she’s a Warrior, with the right gear and without losing the head graphic or name the user picked for her.

Phew – the refactoring detour is done. Yay! 

There’s just one thing I want to do before calling this particular piece of work (and this little guide) done, and that’s give the user the ability to change the hero’s head. 

Selecting a head sprite and saving that choice

There’s lots of head sprites in the game already. Currently, the only “race” (in the fantasy sense) you can play as is humans.

The game already has a concept of “male” and “female” head sprites. The lists of those sprite filenames are kept in two separate arrays, like so:

The heads are already in two arrays for the sake of the random hero generator, but the player gets to pick from all possible heads.

There’s no gameplay concept of gender, and separating heads into two arrays was just something I did to help the random hero generator pair the more masculine-looking (bearded, balding) heads with the more masculine names, and vice versa with the more feminine-looking heads and names.

This is important because when the player makes their own character the player gets to pick from ALL the heads, not just a subset of heads. So I’m going to have to combine them into one array for the sake of cycling through them in the create hero menu, while still keeping them as two separate arrays for the hero generator.

Originally, the head arrays were in heroGenerator.gd. That wouldn’t work going forward, though, since I now needed to access them from createHero.gd (the create hero menu scene) and by the time we’re in createHero, the generator is done doing its thing and we don’t want to go back “into” it and access some arrays in it.

I realize that sounds confusing: the goal is to make the head arrays exist on the hero so they can be accessed from both createHero and heroGenerator.

I moved the head arrays to baseHero.gd, which is where I keep all the base hero stats data (hero.gd extends baseHero.gd and inherits everything in it).

baseHero.gd now contains all the head sprite data

I had to make a minor update to heroGenerator.gd, telling it to look on the hero itself for the head sprite arrays instead of at a variable local to itself. Now that the arrays are on the hero, though, they can be grabbed by either heroGenerator or createHero.gd.

heroGenerator.gd before
heroGenerator.gd after – the humanMaleHeads and humanFemaleHeads are now on newHero

Over in createHero.gd, I added two new vars: allHumanHeads = [] and headIndex = -1.

I added code in _ready() to build a new array, allHumanHeads, out of the two separate male and female head arrays. It also figures out which index the hero’s starting head is at, so we can use that head as the starting point in the array when we press the “Previous Head” and “Next Head” buttons.

Adding the buttons

This part should look familiar – in the createHero scene I added another HBox (HBoxContainer3 in the screenshot) and centered two buttons inside it.

These buttons have to cycle through all the possible heads. Still in createHero.gd, I attached the “Prev Head” and “Next Head” buttons to two new functions:

I also added some logic to handle the “wrap around” effect that should occur if the user clicks “prev” or “next” enough to reach the end of the head array.

Finally, in hero.gd I added a very short method called change_head. All it does is take the string of the new head sprite (such as “female_head_01.png” and update headSprite on that hero.

Pass in a string representing the filename of the new head sprite and this method updates the hero instance to use that new head sprite.

End result: changeable heads!

This menu could be prettier, but styling it is a topic in and of itself and this guide is already huge.

Final steps: testing the results of the character creator

The very last step is to hook up the “Create hero!” button at the bottom of the menu. Technically, the hero was already created. All we did was modify that already-created hero’s class, head, and name. This button just has to take the player to the main scene. 

I hooked up the Create hero! button to this script in createHero.gd…

I customized a hero… (she was originally a warrior with a different name and head)

And confirmed she is now part of my guild. Here she is with the group:

There she is!

Checking in the Guild Management screen…

And checking her hero page (to ensure she has the correct stats):

Looks good!

I wanted to make a guide showing some of the work I’ve done in Godot, mostly just to help support what I think is a great game engine for indies and hobbyists. If you found this helpful, let me know in the comments!

Godot 3: How to disable a button and tint its sprite icon a darker color

In this tutorial: disabling buttons and tinting their icons (sprites) a darker color to indicate that they cannot be interacted with by the player.

What we’re making

Here’s my game’s item vault. It displays a grid of buttons, each one representing an inventory “slot” and each button can be used to display an item the player actually owns. There’s an icon and a slot label to help the player understand what each item is (ie: a sword, a robe, a pair of boots, etc.)

This is great for viewing all the items, but sometimes the player wants to fill a specific slot on their character. Here’s what the character page looks like:

When the player goes to select, for example, a “jewelry” item for their character to wear, I want to make it easy to spot which items in the inventory vault are actually jewelry.

To do this, I will write script that figures out which items are not jewelry, disable their buttons, and tint their icons a darker color. The end result should look something like this:

(I could have just hidden all the non-jewelry items, but I think having items “move around” on the player would be confusing. Tinting the non-jewelry items seemed, to me, anyway, like the better user experience.)

Setting it up in script

The initial creation of the inventory button instances takes place in my game’s “vault” scene. Below is a simplified version of my game’s code that (hopefully) demonstrates how the grid of buttons is created and populated with icons and labels. (PS: I have a separate tutorial specific to making a grid of buttons just like this.)

Thematically, the vault represents a shared inventory across all of the player’s characters in my RPG-style game. The shared inventory is represented as an array named global.guildItems.

Each inventory “slot” is represented as an itemButton instance (itemButton is a scene I created, we’ll look at it more closely in a bit).

The first method, _position_vault_buttons(), creates the blank buttons and places them in a grid, the second method, _draw_vault_items(), “populates” them with actual items from the inventory.

This way, we always get X number of buttons, where X is the total capacity of the player’s inventory, and only some of them are used to “hold” the items the player actually owns.

(A lengthier explanation of how I know which item slot to filter by is outside the scope of this tutorial, but it’s done with a global flag set by the heroPage and you can see evidence of it in this code sample below about 6 lines from the end. It’s the one that goes “if (global.guildItems[i].slot != global.browsingForSlot):”)


func _ready():
  #display inventory size and capacity

func _position_vault_buttons():
  #this method handles the STRUCTURE of the buttons
  #it places the empty buttons in the grid
  #use _draw_vault_items() to put icons and data into buttons
  for i in range(global.vaultSpace):
    var itemButton = preload("res://menus/itemButton.tscn").instance()
    itemButton.connect("updateSourceButtonArt", self, "_draw_vault_items")

func _draw_vault_items():
  #now we pair each physical button with data from global.guildItems array 
  #grab each button from buttonArray and "decorate" it 
  var currentButton = null
  for i in range(buttonArray.size()):
    currentButton = buttonArray[i]
    if (global.guildItems[i]):
      if (global.currentMenu == "vaultViaHeroPage"):
        if (global.guildItems[i].slot != global.browsingForSlot):
          currentButton._set_disabled() #script I wrote in itemButton.gd 

About 4 lines up from the bottom is this line of code:


That _set_disabled() method is a method I wrote on the itemButton’s script, it’s not something built into Godot.

Let’s take a look at the itemButton scene and see how it works.

itemButton scene and script

An itemButton, in my game, is made up of a Button node along with a couple labels and a sprite.

Here is the scene’s structure:

Here is the script that disables the button and dims the sprite over the button:

func _set_disabled():
  $Button.disabled = true
  $Button.modulate = Color(0.5,0.5,0.5,1)
  $Button/sprite_itemIcon.modulate = Color(0.25,0.25,0.25)

The tricky part here, for me, was figuring out how modulate works. The Godot docs are thin on examples and it took some Googling just to figure out that the key word here was “modulate”, not “tint” or “color” or other terms I was initially guessing.

Some things to note about “modulate”:

  • Modulate is a property, so you can set it using “dot” notation.
  • It uses Color, which is built into Godot.
  • set_modulate and get_modulate are the old way of working with modulate (if you see reference to them the guide you’re reading/watching was probably made prior to Godot 3)

There’s a bunch of ways to work with Color, my example is just one of them. Mine is Color(R, G, B, alpha). Here are some more examples of working with Color in Godot.

This method could be expanded to a near-infinite number of uses, my example is just one tiny, specific use case.

References and more reading:

Godot 3: Centering a grid of evenly-spaced buttons on screen

In this tutorial: The scene structure and settings I used in the Godot 3 engine to achieve this amazing centered grid of evenly-spaced buttons. The buttons themselves are all instances of the same scene and are placed in the grid programmatically.

This is my “finished” result (pardon the placeholder assets). It’s a simple hero inventory page for an RPG. The buttons that make up the hero inventory are evenly spaced in a grid, and that grid is centered horizontally on the screen:

This guide will show you the code and the scene structure used to achieve this centered-grid-of-centered-buttons, but it assumes some familiarity with the Godot engine and will skip over some of the basics.

Scene hierarchy and container settings

This “Hero Page” is its own scene. This scene is named heroPage.tscn (and its script is in heroPage.gd). We’ll come back to its script at the end of the tutorial.  For now, we’re working in the scene’s hierarchy.

The parent-most node is a Node2D, and the important bits here for the centered grid of inventory items are:

  • a CenterContainer (which I renamed to centerContainer)
  • a GridContainer (which I renamed to grid)

(You could make this stuff programatically if you prefer but I like to see a certain amount of my UI in the viewport – at least the outlines of containers, where possible.)

I positioned my CenterContainer where I wanted it on the Y axis and gave it a width equal to that of my screen and left the rest alone.

Doesn’t look like much in the viewport yet – just a thin horizontal line.

That’s okay – the buttons themselves will bulk it out.

The next step is to adjust the grid’s settings. I changed the number of columns to 4 and under Custom Constants, I changed Vseparation and Hseparation to 24 (to put some space between each of the buttons).

The button instances

The square buttons are all instances of the same “itemButton” scene (that I made myself). That scene looks like this in the 2D viewport and scene hierarchy:

Unlike the grid or center container, I gave the button’s Control parent a size and a minimum size.

Generating the buttons with script

Finally, the code that adds the buttons to the grid is in the heroPage.gd file itself. This code goes in the _ready() method.

for i in range(heroEquipmentSlots.size()):
   slot = heroEquipmentSlots[i]

   var inventoryBtn = preload("res://menus/itemButton.tscn").instance()
   #only set icon if the hero actually has an item in this slot
   #otherwise leave it empty
   if (global.selectedHero["equipment"][slot] != null):


I simplified some of the above code from my actual project for readability. The important parts are where it generates an instance of each inventory button and pushes the label and data into that instance, then adds the button to the grid.

The end result

The hero’s eight inventory slots are now in a grid and neatly centered. (I can’t say the same for the rest of the elements on this page yet, but it’s a start!)

OSU eCampus CS290 Web Development review & recap

This post is part of an ongoing series recapping my experience in Oregon State University’s eCampus (online) post-baccalaureate Computer Science degree program. You can learn more about the program here.

Six-word summary:  :(  :(  :(  :(  :(  :( 

Web dev is, for some reason, this really polarizing thing in tech. I’ve certainly heard a lot of devs go “Ewww, JavaScript!” (both in my real life job and from my classmates). That’s too bad, because I think the web is really cool and it’s where a lot of people spend a lot of their time these days! I like building web apps, but I can see why some people don’t – it’s prone to “flavor of the week” syndrome, the tooling isn’t great, JavaScript does some things “weird”, etc.

I went into this class curious to see what aspects of web would be taught, since it’s such a broad topic to stuff into just 8 (or 11) weeks. Here’s some of what we covered in CS 290:


This is the first OSU class I’ve had that covers git in any capacity (I’m halfway through the program). This is awesome – hooray, CS290, for introducing git!

I wish the OSU program covered it sooner. It has been frustrating to group with people in my previous classes who have never used it before and would rather use things like email (!!!) to share files because they don’t know git.

Unfortunately, 290 didn’t go very in-depth with git. We pushed two files to a Github repo in the first week and called it good. We literally never used git again. I think this was a huge missed opportunity: the class could easily include a group project of some sort that focuses on collaborating in a git repo, or require us to post incremental work on a project to our github repos, or something.

Quirks of JavaScript

The first three weeks of CS290 focused heavily on “this weird thing JavaScript does”. The usual suspects are here: lack of strict typing, hoisting, closures. It’s not that these things aren’t important, it’s that they aren’t what makes web development compelling or useful. Starting the class out by spending three weeks on these topics just seemed to make JavaScript look weird and annoying, when in practice, these things aren’t that big a deal.

I think it’d have been cooler if they set us to actually making things and learning the tools of the trade in those first three weeks. In the accelerated schedule, week 4 is when it got interesting: we made an HTML website with JavaScript methods to navigate around in a table and mark cells yellow. 

Week 4 homework: a bare-bones interactive “website”. This is the first step in building the kind of stuff that makes the web compelling!

Installing npm packages on a server

They had us do this in week 1 – OSU provides some server space, and everyone was tasked with claiming a port and setting up a little server on it.

We never came back to it. I don’t know why we did this so early in the class. Node and its (infinite) packages is an interesting topic and it’s weird to just install it and never come back to it. It was like a story that someone started telling and never finished. 

Some light database stuff and routing with Express

This part was fun – make routes (like “/get”) and make them return data from a class-provided database. This work will be extremely useful as starter code when you take CS340 (Databases) so keep it somewhere safe. 

The biggest, most complex project of this class is the one where you develop backend routes for database interaction. You’ll spend a lot of time on form validation and making rows in a table switch between a read-only state and an editable state. This is also the project I thought was the most interesting of all of them, since it was the most like a real site. 

What CS290 didn’t cover

Sadly, there was no mention of Chrome’s various debugging tools, running node locally, front-end frameworks like React, the difference between running JavaScript on the front end and the backend, the staggering quantity of problems that have already been solved with neat existing NPM packages, unit testing, integration testing, and deployment.

Somewhat irritatingly, some of the assignments had what I would consider poor coding practices. The second assignment (sorting automobiles) in particular irked me because it makes unnecessary copies of an array:

/*This function sorts arrays using an arbitrary comparator. You pass it a comparator and an array of objects
appropriate for that comparator and it will return a new array which is sorted with the largest object in index 0
and the smallest in the last index*/
function sortArr( comparator, array ){
//returning a new array to satisfy assignment requirements; we could have run sort on array itself (it's passed by reference)
var sortedArr = array.sort(comparator, array);
return sortedArr;

Arrays are passed by reference; there was no need to create a new one and return the new one. In fact, we could have run .sort() in place instead of calling a completely separate method for it. Maybe I’m just cranky, though.

The workload in weeks 1, 2, 3, and 4 is very low, but then things pick up after that. 

CS290 final exam

Whoever wrote this exam does not know what is important in web development.

I’ve used JavaScript (both as a hobbyist and a professional) for over half a decade, and I got one of the lowest scores I’ve ever gotten on a test here. I don’t know what to say – expect a ton of oddly-worded bullshit questions about tricky trivia that have no relevance to how JavaScript is used or real life web development practices. 

CS290 parting thoughts

I can only guess what this class is like for someone who is new to web development. It’s probably a disjointed pastiche of topics that get introduced in a vacuum and then quickly abandoned. I’m sure this class isn’t helping anyone become enthusiastic about web development, which is too bad. 

For a better introduction to modern web development consider building your own site. I think that’s how a lot of us got started – we wanted a website for some reason or another and set one up. There’s plenty of project starters (known as ‘boilerplate’) out there to pick from. Here’s what I would recommend…

  • Buy some $5/month shared hosting and make your own portfolio site out of HTML and your own CSS. Once you’ve got that…
  • Start up a node server on your own computer and get it to serve your own project
  • Build a simple one-page app that does a simple job using a front-end framework such as Angular or React (here are some ideas: a text capitalizer, a shipping price calculator, an anagram solver)
  • Use a popular front-end styling framework, such as Bootstrap
  • Realize what you made is garbage and start over
  • Repeat a bunch of times
  • Keep Googling any time you get stuck
  • If you build something decent, deploy it somewhere like Heroku and show it off!

Creating an item inventory array in GameMaker Studio 2 from a Google Spreadsheet exported as JSON

In this article: creating a Google spreadsheet of items for my RPG-style GameMaker game, exporting the spreadsheet as JSON, importing the JSON into GameMaker Studio 2, processing the item data into a usable format, and managing the player’s collection of “owned” items.

I’ve been building a hobby project in GameMaker Studio 2 for about a month now. I wanted to add the concept of “items” to my game – stuff like swords, armor, etc. – that grant stats and can be won via quests, managed in an inventory, and assigned to individual heroes. (Typical RPG stuff.)

The game itself might have hundreds or thousands of items (in theory), but the player is likely to have just a small selection of the available items in their inventory. This feature calls for two separate data structures: one to hold all of the game’s items, and one to hold the items the player has in their possession.

Note: I’m pretty new to GameMaker, and I’m documenting my findings as I go for future reference and ease of sharing with friends who are also using GameMaker. There’s quite possibly a better/easier way to do this than the method I’ve cobbled together here. 

Creating the items spreadsheet

For the items themselves, I created a spreadsheet in Google Sheets. The items are arranged in rows, and they have a collection of stats.

Some of them are restricted to certain classes, and Google Sheets lets you restrict choices in a particular field to a predefined list of options so you don’t make typos or introduce inconsistencies where you didn’t want them.

Exporting the data from the spreadsheet

I used Export Sheet Data to export my items as a JSON object. I checked these two settings:

  • Export sheet arrays
  • Export contents as array

Checking these two settings simplifies the structure of the JSON object I’ll be working with inside GameMaker.

Export sheet arrays

With “Export sheet arrays” checked:

    "name": "Rusty Broadsword",
    "prestige": 0,

Without “Export sheet arrays” checked:

    "Rusty Broadsword": {
      "name": "Rusty Broadsword",
      "prestige": 0,

As you can see, leaving this setting unchecked creates another layer of nesting. I found deeply nested JSON difficult to deal with inside GameMaker, so I wanted to minimize how many “layers” my data set had.

Export contents as array 

With “Export contents as array” checked:

    "name": "Rusty Broadsword",
    "prestige": 0,

Without “Export contents as array” checked”:

  "items": [
      "name": "Rusty Broadsword",
      "prestige": 0,

With this setting off, you still get all your items in an array but that array is itself a property and it’s contained within an object. This is just more “layers” to drill through in GameMaker and I prefer the simplified data structure.

The end result was this JSON object, which I’ve pasted into a gist:

Bringing the item JSON data into GameMaker Studio 2

My main room has a controller object that I use to set up gameplay globals. In its Create script, I currently just use a flag to see if the init script has run yet (so it doesn’t run every time I re-enter the main room).

For loading the JSON data line by line, I used Jason Lee Elliott’s method he describes on his blog here.

if (!initGameDone) {
  //currency defaults
  global.gold = 100;
  global.diamonds = 10;

  //load all the game items from json
  var theJsonFile = file_text_open_read("items.json");
  var theData = "";
  while (!file_text_eof(theJsonFile)) {
    theData += file_text_read_string(theJsonFile);

  var decodedData = json_decode(theData);
  var defaultStuff = ds_map_find_value(decodedData, "default"); 
  //see "default" explanation below 

This is where it started to get weird. theData is an array of objects (makes sense). decodedData is a ds_map made from that array of objects (still making sense). Looking in the debugger, though, with a breakpoint on the line that creates defaultStuff, we can see there’s ds_list in here called “default”:

Weird, I didn’t put that there…  GameMaker did, and it’s documented here. From GameMaker’s documentation:

NOTE: When decoding arrays, there is a map with the key “default” ONLY when an array is the top level structure, and ONLY for that top-level array. Internal lists decode directly to ds_lists without being enclosed in a ds_map.

That’s why defaultStuff is made from finding the “default” value within decodedData.

The next I did was create a global variable to hold all the game’s possible items. This global variable is a ds_map. I wanted it to be a map so that each item in the game could be looked up by its name (I think “Rusty Broadsword” is more memorable and easier to work with than something like an ID number or a position in an array).

  global.allGameItems = ds_map_create();

  for (var i = 0; i < ds_list_size(defaultStuff); i++) {
    var rawItemMap = ds_list_find_value(defaultStuff, i);
    var newKeyName = ds_map_find_value(rawItemMap, "name");
    ds_map_add(global.allGameItems, newKeyName, rawItemMap);

This is just a classic for-loop that looks at each item (represented as a map) in defaultStuff. It grabs the name property out of the map to serve as the key, and uses the item’s map as the value.

Putting items in the player’s inventory

The last step is to actually give a couple items to the player.

The player’s inventory is as ds_list (array) of ds_maps. In this code, item1 and item2 are actual items from the allGameItems ds_map that are found by their name.

  global.playerInventory = ds_list_create();
  var item1 = ds_map_find_value(global.allGameItems, "Rusty Broadsword"); 
  var item2 = ds_map_find_value(global.allGameItems, "Blue Cotton Robe");
  ds_list_add(global.playerInventory, item1);
  ds_list_add(global.playerInventory, item2);

  show_debug_message("player inventory size: " + string(ds_list_size(global.playerInventory)));

  //print what's in the player's inventory
  show_debug_message("PLAYER INVENTORY:");
  for (var i = 0; i < ds_list_size(global.playerInventory); i++) {
    var itemi = ds_list_find_value(global.playerInventory, i); 
    show_debug_message(ds_map_find_value(itemi, "name"));

  initGameDone = true;

Since I haven’t yet implemented the player’s inventory screen, I wrote a for-loop to print the name of every item in the player’s inventory to the console. Hopefully this is self-explanatory: it just iterates through the player’s inventory and prints the name property of each item it finds in the inventory.

And there we have it: these items are managed in Google Sheets, exported as JSON, imported into GameMaker, and placed in the player’s inventory by name.

Adapting an extension written for GameMaker Studio 1.4 for use in GameMaker Studio 2.0

In this article: how I adapted an extension written for GameMaker Studio 1.4 (the free version) so that it worked in GameMaker Studio 2 (the new/paid license version).

I wanted to use dicksonlaw583‘s JSOnion extension in GameMaker Studio 2, but the extension was written for GameMaker Studio 1.4. Compiling with the extension in use kept giving me a vague “invalid token” error in 4 different places (luckily, line numbers were included) but no clues as to what token, exactly, was invalid.

It took a lot of trial and error and digging on Google to figure it all out, so I’ve documented what I needed to do here in case it helps someone else.

Importing the Extension

First thing I got confused on was how, exactly, to bring the extension code into GameMaker 2.

The JSOnion instructions say “drag JSOnion.gml into your open project”, but that doesn’t work (or at least it didn’t for me, no matter where I tried to drop).

What I actually had to do is go to the Resources panel and right click on Extensions. Select Create Extension.

Escaping characters

Next, I tried to run my game but the build failed due to a number of “invalid token” errors.

Each error looks like this:

Error : gml_Script__jso_decode_map(84) : invalid token

I was pretty lost here, and the GameMaker docs provided little help.  Searching for “invalid token” comes up with nothing and this list of GML compiler errors offers only a vague hint:

You have an invalid character in your game code, which can happen with foreign language characters or Unicode

Hmm. The extension code looked okay to me…at least, it wasn’t full of bizarre characters and nothing looked weird at the line numbers GameMaker was complaining about.

This particular forum post gave me an important clue: single quotes are considered invalid characters in GML 2! Okay, that was something to go with. I went through the JSOnion.gml code and replaced single quotes with double quotes and, in order to do things like a set of double quotes within double quotes, escaped the interior set of double quotes with a backslash.

I also discovered (through more trial and error) that backslashes used for purposes other than escaping things are also considered invalid characters, so I had to escape those, too.

In summary, to adapt an extension meant for 1.4 to work with 2.0, you have to go into the .gml file and: 

  • Remove usages of single quotes
  • Escape \ and ” characters
    • escaped slash looks like this: “\\”
    • escaped double quotes looks like this: “\””

Note: each time I wanted to test a change I made to JSOnion.gml, I had to go into the JSOnion extension, delete the reference to the file, and re-add the file to get the changes.

Adding macros (constants)

One more thing to do: add the macros.

JSOnion came with a file, constants.txt, that I wasn’t sure how to use. The repo instructions gave a clue: “import constants.txt as macros”, but I think there might’ve been some UI changes since GML 1.4, because I couldn’t figure out how to import this file in the version I’m using.

What I ended up doing was adding the constants manually in the “Macros” section of the extension properties. (See screenshot below).

(These are indeed required, too – if you don’t add the macros and you try to use JSOnion methods, you’ll get errors when trying to read a variable that wasn’t set.)

With the extension code cleaned of “invalid tokens” and the macros in place I can now build.

Was this the right way to do it? I don’t know – I’ve only worked in GameMaker for a few weeks and this was my first attempt at bringing in an extension, so I am far from an “expert” at this point.

Also, I haven’t had a chance to actually use the extension code yet (that’s a subject for another post), but I did get it building so I wanted to share the process in case anyone else is also trying to adapt an old/free extension for the newer/paid version of GameMaker.

OSU eCampus CS361 Software Engineering I review & recap

This post is part of an ongoing series recapping my experience in Oregon State University’s eCampus (online) post-baccalaureate Computer Science degree program. You can learn more about the program here.

Six-word summary: Group work group work group work

In CS361 you’ll get a high level look at “real world” scheduling methodologies (mostly waterfall and agile) and you’ll work in a group with 3-4 other students to meet weekly milestones designing and implementing parts of some other student’s “Vision Statement”.

CS361 Review

You don’t have to spend long on the OSU CS subreddit to realize that virtually no one likes this class. It’s not awful, but I understand the frustrations people voice on various forums around the web.

The heavy reliance on group work was frustrating more often than not and the course materials felt dated or like they were specific to a certain industry, but I didn’t dislike this class as much as most people seem to. I think it helped that I already have design and software development experience and enjoy writing and making diagrams/mockups, so this class played to some of my strengths.

The materials that introduce common planning and scheduling techniques for software projects were a welcome inclusion – I’m glad this stuff is covered somewhere in OSU’s CS program – but I thought they didn’t go nearly in depth enough to prepare students for the realities of working on an agile team. There wasn’t enough story writing, requirements gathering, pointing exercises, or customer involvement.

I thought the weekly homework assignments were a little lackluster. Working in a group is tough even in the best situations – some parts of the homework depended on other parts being done first, and some people’s schedules didn’t seem to allow for them to start the homework early in the week.

The documents we wrote as a group seemed excessively heavy on diagrams and put too much emphasis on satisfying a very specific set of expectations. For example, there’s a lot of emphasis placed on terminology such as “functional requirements” and “functional definitions”, which I had never heard outside of this class or seen used so religiously, but the concepts they represent were familiar. That describes a lot of this class’s materials: heavy focus on overly-specific methods and terms that probably don’t translate to every industry.

Maybe the course’s materials would be improved by taking a step back from strict terminology and definitions and talking instead about how to write good step-by-step documentation, how to write a good bug, how to write a good feature design that someone else can implement from – skills that can be applied to a variety of specific methodologies, since it’s impossible to predict which ones your future company or team might be using. There are so many skills that have nothing to do with programming that programmers still need to develop, and this class could be a good place to start learning them.

Class structure

  • In the first week of the class, everyone in the class writes a 2000 word “Vision Statement” for a software product that solves some lofty real-world problem. Forget about making a simple app to solve a simple problem, your idea for this vision statement should be utterly epic. They are surprisingly strict about the 2000 word count, but you should be able to hit that easily by showing off your design skills and covering every topic imaginable in relation to your app idea. You really can’t write too much, and no topic is too trivial to not write a page about. (I thought I’d covered security pretty well with the half page I wrote on it, but I got got dinged for not writing enough on the topic. I got the feeling the TA had to find something wrong with my document and if it wasn’t that, it’d have been something else.)
  • In the second week of the class, everyone votes on which ideas they think are best.
  • It doesn’t matter what you vote for. Your voting has no bearing on what project you get assigned. But you should vote anyway to help lift decent-sounding projects to the top, so that nobody has to work on the duds.
  • Expect to be assigned to a project you didn’t vote for because you thought it sounded stupid or impossible (or both).
  • You’ll then get grouped with 3-4 classmates based on absolutely no criteria whatsoever, so expect clashing schedules/mismatched interests/time zone incompatibilities. The instructor says this is part of life, and I agree (and every single software team I’ve been on has had an off-shore counterpart on the other side of the globe), but don’t expect your teammates to be so understanding. My group insisted that the only time we could meet was what was usually my bedtime, which sucked for me.
  • You’ll get to know these people very well as you meet 1-2 times a week (probably over a voice chat if your group is keyboard-phobic or generally unavailable at any time of day outside of the specific meeting window)
  • Every week you’ll work with these people to produce a lengthy document in response to a lengthy prompt. It will require diagrams and lots and lots of writing.
  • This assignment will be graded by a TA who might have limited English skills or a general lack of interest in reading 12+ pages of rather dry writing. We lost points on things that were present and the TA missed and we lost points on things that were never part of the requirements in the first place.
  • The last two weeks of the term are spent coding a small portion of the stuff you designed thus far; your group members may or may not participate in this process depending on whether they’re dirtbags or not
  • The final is made up of rather vague questions, but you should review the slides anyway to scoop up whatever points you can here

CS361 Tips

Vision statement tips

The grading requirements on the vision statement draft are really vague, but you can get full credit by writing a ton on every design topic you can think of and meeting the 2000 minimum word requirement.

Some ideas of what to include (beyond what the assignment suggests):

  • What differentiates your app from similar ones – do some market research and write comparisons. Someone’s probably already made a product like the one you’re imagining. What makes yours better? 
  • User profiles – Imagine some hypothetical users for your app and write about them. Are they young? Old? Tech-savvy? Tech-illiterate? How is your app designed to appeal to them and meet their needs?
  • Accessibility features – imagine how your app might work on a screen reader or to someone with limited vision and write about how accessibility concerns are addressed in your app.
  • Security features – I wrote like half a page on security, which wasn’t enough according to my TA. Maybe you can do better!
  • Mockups! I made mine in mockflow

Journal tips

Work on the journal regularly – every other day is a good pace. The class’s instructor looks at these himself (or at least he looked at mine himself and commented on it) and he’s very good at detecting who wrote theirs in one fell swoop the night before it was due.

If you don’t know what to write, here are some ideas I used throughout the course to inspire myself:

  • Draw a comparison between the class’s material and your experiences working in a team – you ought to have some from your previous career or OSU classes
  • Talk about any previous software development experience you have; maybe throw in a bit about how you think CS361’s teachings on topics like agile will help you on future projects you develop
  • Talk about how your group work is going
  • Relate the lecture material to outside reading you’ve done or things you’ve heard
  • Sometimes the lecturer asks questions in the video; respond to those
  • Respond to the weekly learning topics: early in the week, write what you think they mean, then, after you do the lectures and your part of the homework, write again about what you’ve learned about those topics and correct any misinterpretations you had initially

Track your group members’ contributions

Yes, it feels creepy to keep secret notes about who in your group isn’t attending meetings, who turned in their part just hours before it was due, etc., but in the last week you’ll be asked to produce a very long, very detailed document rating each group member on a half-dozen criteria and justifying your rating in writing, so having kept track of this stuff will help you earn full credit on the assignment. I did my group member tracking in a Google Spreadsheet with a column for each week of the class and a row for each group member.

A lot of people in the Slack channel reported getting dinged for not being detailed enough, so keep regular notes and you should have plenty of material for this document and you should be able to write it in very little time. (Mine was 14 pages and included screenshots and data about meeting attendance and how close to the weekly deadline each person submitted their work; I got full credit on the group evaluation.)

Pick a programming language / framework that plays to your group’s strengths

Three people in my group inexplicably voted in favor of a framework they had little to no familiarity with – and majority ruled. I spent 2 weeks giving myself a crash course in JavaFX, coding as I went, which was fine but our development weeks would have gone so much better if the group had just picked something we already knew and could’ve hit the ground running in. The end result: some group members struggled to produce anything at all during the coding weeks.

Here’s what we ended up with: a clickable map of the United States that colors states according to how they voted in the 2016 presidential election and, alternatively, according to how gerrymandered they are.

This screenshot best represents my portion of the work: building the map and hooking it up to real data.

Implementing this much functionality posed plenty of interesting challenges to work through. Things like building a complete map out of individual SVG boundaries, figuring out how to make them clickable, altering their color based on data from the project’s database, and fitting containers within containers to get everything fitting in the application window kept me busy for the two weeks.

For some people in my group this was their first exposure to Git as well, so this project came with a side-helping of Git training. (Note to any future students out there: if you don’t know git yet, start learning it now – don’t wait until you’re in a time crunch of a group project with multiple people counting on you.)

And finally…

Don’t be a dick

Show up to meetings. Do your part and do it early enough so that your group can review it. Don’t disappear during the coding weeks. Be a good team member and make connections on LinkedIn once the class is over.

An educational program like this one is a huge opportunity to network and make friends; you never know who might end up at a great company someday and put in a good word for you. You can gripe about 361 and sandbag for two months, or you can impress a bunch of future industry peers by knocking it out of the park every week.

It’s only 10 weeks – you can do it!

OSU eCampus CS271 Computer Architecture and Assembly Language review & recap

This post is part of an ongoing series recapping my experience in Oregon State University’s eCampus (online) post-baccalaureate Computer Science degree program. You can learn more about the program here.

Six-word summary: Where my 4.0 GPA went to die

CS271 is a pedantic deep-dive into your computer’s inner workings and an opportunity to enjoy coding in a highly restrictive language. There’s special emphasis on going step-by-step through the stack frame and understanding what’s in every register and even some much-appreciated training on “what order to do things in” when building a program.

CS271 Review

CS271 often felt like it was made of two distinct halves that ran in parallel: the first half is made up of the cute little MASM programs you write for the homework that’s due every other week. The other half is the mountains of computer architecture trivia and methods for calculating various things you learn for the bi-weekly exams, such as binary/hex conversions, Hamming codes, memory usage, optimization, recursive output, stack frame changes, the step-by-step changes in registers as a program runs or steps through a loop, and so on.

The class is very well organized. They tell you precisely what to do for the homework and what the output should look like, line by line. Unlike many classes in OSU’s CS program thus far, you won’t need to do a ton of Googling to learn the material – the lectures and the book reading are actually adequate preparation for most of the class’s homework and quiz questions. The workload is consistent. Each week follows the same pattern, and the homework’s complexity ramps up slowly.

However, the homework (in which you write some Assembly language code) is rather light and may give you a false sense of security come quiz and exam time. The true heavy hitters in this class are the self-checks you do after the lectures, the weekly exercises, and the bi-weekly quizzes. Mastering the material found in all of these is essential for surviving the midterm and the final.

Whether 271’s material is interesting is going to depend on your own likes and dislikes. I thought most of it was squarely in the “hey, that’s neat” category, but I thought it focused too much over low-level details that (probably) won’t directly enhance my career in software. (And that’s just like, my opinion, man – I’m sure some people who take 271 find their calling and never resurface from the depths of CPU architecture, binary math, hex addresses, and bit ordering.)

Class structure

  • 10 weeks
  • Multiple briskly-paced weekly lectures
  • An ungraded/untimed “self-check” exercise worksheet for every single lecture – you should actually do these, the quizzes and exams pull from them
  • A weekly exercise quiz with a 6 hour time limit – you get two attempts and they keep the best score, but each attempt has a different batch of questions so it is advised to take it twice to see both question banks
  • 4 bi-weekly tests, 1-hour time limit, each worth 2.5% of your final grade
  • 6 Assembly-language coding projects (homework assignments) total – each one gives you two full weeks to work on it, with the grading rubric released at the start of the 2nd week
  • Proctored midterm, proctored final
  • Steady, even workload
  • Less self-teaching than some OSU classes (still quite a bit of rote memorization and practice, though)

Tips for CS271

This was my first OSU CS class where I couldn’t quite earn a solid A (I got an A-). It certainly wasn’t for lack of effort or time put in – I think I cleared 20 hours of practice most weeks and I worked on this class’s stuff daily.

There’s a ton of material and the tests are very picky – they’re not multiple choice where half the answers are obviously silly, they’re fill-in-the-blank or multiple choice where all the options seem like they could be right. (The tests are also almost half your final grade. Ouch.)

When I look back on what I could’ve done better and what I would advise future students, these are the things that come to mind.

CS271 tip #1: Get the book, it doesn’t suck!

This is one of the books that’s worth buying. It’s approachable with many  examples to follow and, surprisingly, many quiz questions are lifted line-for-line from the book.

See Assembly Language for x86 Processors on Amazon.com

I liked having a physical book because it freed up screen space during quizzes and while working on homework. I found it helpful to read on paper, practice in a notebook, and really work problems over and over until I had the process down cold. (That’s just my personal preference; I seem to retain more if I read and work on paper.)

CS271 tip #2: Make yourself some worksheets and grade yourself

Speaking of rote memorization and brute-force practice, I highly recommend making yourself some worksheets out of the weekly self-checks and bi-weekly quizzes. Print them out and work through them (over and over) until you can do all of them quickly and perfectly.

This technique was time-consuming but it went a long way to cementing the steps to solving all the various types of CS271 problems. As I mentioned earlier, the homework is borderline useless for the exams. The exams draw their questions almost entirely from the weekly self-checks and bi-weekly quizzes.

The exams tend to layer multiple concepts together into one question and they’re autograded, not graded by a potentially generous TA, so your goal for CS271’s tests should be to become very fast at solving every kind of problem you encounter in the practice materials.

CS271 tip #3: Get a binary/hex calculator

The Casio fx-115ES can do math in binary and hex: addition, subtraction, and conversions between binary/hex and back again.

I had no idea this kind of calculator even existed and the course materials make no mention of it. Frustratingly, I only found out about it through the class’s Slack chat. I was doing conversions by hand like a total chump, which would have cost me dearly on the midterm either in terms of time spent or stupid mistakes or both. The hex and binary questions on the exam were made trivial by having this calculator. I don’t know why the syllabus doesn’t open with “GET THIS CALCULATOR”.

As an alternative to the physical calculator, the course lets you use your operating system’s built-in calculator. (I did this course’s work on my PC but I take tests via ProctorU on Macbook since that’s where my webcam is, so I preferred the physical calculator over having to get familiar with multiple OS calculators.)

CS271 tip #4: Pack that cheat sheet to the density of a neutron star

I made mine in Google Docs, which will let you pick a font size as small as 6 (you have to type it in, it’s not in the dropdown).

One side of my CS271 cheat sheet – the back side was all code examples.

I don’t care for exam cheat sheets. I think allowing cheat sheets drives students to put their efforts into guessing what details should be on the sheet, which sets the student up for an inevitable wave of frustration and disappointment when they realize 2 seconds into the exam that they guessed wrong. Letting students bring a cheat sheet seems to inspire instructors feel free to ask all kinds of minutia-focused questions instead of testing for a more general understanding of the concepts.

But… nobody asked my opinion, and I doubt the cheat sheets are going away any time soon, so my advice here is to pack your sheet as full as you can get it. I think a good cheat sheet for CS271’s midterm and final would be at least 50% code examples, which is what the back side of my sheet was full of.

CS271 tip #5: The extra credit on the homework was generally a waste of time for me

I tried to do the extra credit (of which there are 1-3 points up for grabs on every bi-weekly assignment), but for the most part I found the extra credit opportunities frustrating and almost as time-consuming as the rest of the assignment itself. Your mileage may vary, but I should’ve spent the time on worksheet drills instead.

CS271 tip #6: If I could do one thing differently…

I’d spend more time studying all the nuances of what happens in the system stack while a program runs a loop. Here’s me practicing on a whiteboard, but despite all this preparation I still think this is where I lost points on the exam. I was probably off by 4 on some memory address or miscounted loops somewhere.

And that’s it for CS271! I’m glad I’m done with it; I’ve heard it’s one of the tougher courses and for me, that was definitely true. I worked very hard in this class and I advise all future students to do the same. The tests are no joke and your ability to track and manage tiny details will be tested like never before.

Next up: CS290 – Web Development. See you all next quarter!

Fixing WordPress site’s low mobile score in Google’s PageInsights with W3 Total Cache

In this article: Steps I took to optimize a WordPress-based site for Google’s upcoming mobile search prioritization. It started with a PageSpeed Insights score of 8/100 and ended at 62/100.

Plugins used: W3 Total Cache

Time spent: Several hours of trial and error, but this guide should help you through it much quicker.

Google announced in January that they’re going to take a site’s mobile speed into account for searches beginning July 2018. I’ve always tried to make my WordPress sites mobile-friendly, but it looks like there’s some room for improvement.

One of my biggest (and highest-earning) sites scored just an 8 out of 100 for mobile optimization. Ouch.

(You can test your own site here: https://developers.google.com/speed/pagespeed/insights/ )

What I’ve already done to optimize this WordPress site

I’ve managed this site for a few years and have already put some effort into optimizing it for search and mobile.

The site already scores well for these categories:

  • Avoid landing page redirects
  • Enable compression
  • Minify CSS
  • Minify HTML
  • Minify JavaScript
  • Optimize images
  • Prioritize visible content

Some of those scores are probably due to the site already using a CDN, lazy loading, a good caching plugin, and a good hosting plan. Here’s what the site uses:

However, there’s more work to be done! Here’s what I did to raise my Google Insights mobile score.

Fixing render-blocking JavaScript on above-the-fold content on a WordPress site using W3 Total Cache and a CDN

Let’s look at this render-blocking JS/CSS problem first:

Eliminate render-blocking JavaScript and CSS in above-the-fold content. 

Your page has 8 blocking script resources and 12 blocking CSS resources. This causes a delay in rendering your page.

None of the above-the-fold content on your page could be rendered without waiting for the following resources to load. Try to defer or asynchronosly load blocking resources, or inline the critical portions of those resources directly in the HTML.

This message is followed by a list of all the JS and CSS scripts causing the render blocking, which were 8 JavaScript files and 3 CSS files in my site’s case.

These guides were helpful to me while working on this problem:

To fix the blocking JavaScript files I had to do a number of things to configure W3 Total Cache. This part took a couple hours of trial and error and some steps were not covered in the guides I used (or my situation was different from theirs), so I’ve attempted to document the process as I experienced it in this guide.

First, I enabled Minify in the general W3 Total Cache settings. Go to Performance > General Settings > Minify > check the “Enable” box and select the “Manual” radio button.

Next, go to Performance > Minify to work on minify settings as they pertain to JavaScript and CSS. You’ll need the list of blocking files from PageSpeed Insights report. 

Watch out! The file paths shown in the PageSpeed Insights results might be truncated. To get the full path, you have to hover over the truncated path and copy the path from the tool tip

In other words, make sure you are copying a complete path:


and not a path with … in it:


In Performance > Minify there are a variety of options that apply to all the script in a particular area (before head, after body begins, before end of body). In my case, code in the head tag was already minified, so I set it to “Combine only” (rather than re-minify it). I also needed to keep it blocking, or else my page filled Chrome’s console with “can’t find JQuery!” errors.

Next, under JS file management, add all of the blocking files from the PageSpeed Insights results – be sure to get the full file path, not the truncated version.

Also! If you’re using a CDN, you’ll have to change the domain in the file paths that you paste. 

Instead of this:


You need to use your website’s actual domain. For each path you paste, change the CDN part to be your site’s domain instead, like this:


Or you can remove that part of the url entirely and go with something like:


…which is what I did for mine:

Note: I needed to set the jquery files to embed in <head> to avoid a slew of console errors when visiting the site. As per the earlier settings, anything embedded in head is going to be blocking. I think some blocking files might be inevitable; the point of these settings is to tease out which files belong where in the load sequence.

Save settings and purge all caches, then test again in PageSpeed Insights.

Woohoo – no JS files blocking loading. I also tested the site manually, and verified that it doesn’t look like garbage and doesn’t fill the console with errors. So far, so good.

Fixing render-blocking CSS with Autoptimize

I initially set up all the CSS file paths in W3 Total Cache but ran into these two cases that I couldn’t figure out how deal with through W3 Total Cache alone:

One blocking css file is from w3tc itself:


And another is from Google Fonts:


To fix the Google Fonts, I installed the very lightweight plugin Autoptimize and checked these boxes:

I also used Autoptimize to disable Google Fonts. Whether you want to do this is up to you, but I went ahead with it because I am happy with a default system font for this site.

To fix the w3tc minify, I disabled CSS in W3TC and let Autoptimize handle it. I also had to uncheck this setting:

Finally, for the sake of completeness, here’s what my HTML minify settings look like:

At this point, I loaded my site and found it was using serif typefaces on buttons and it wasn’t scaling the hero (header) image correctly. To fix this, I added custom CSS to Autoptimize’s custom CSS section. This CSS gets loaded right away, so the page doesn’t get stuck waiting on the js or css to “fix” certain issues that are visible right away to a visitor.

.button {
   font-family: "Open Sans", sans-serif !important;

.header-homepage {
   padding-top: 120px !important;

One more thing: I also uploaded a significantly more compressed “hero” banner image jpg to the site (old size: about 350kb, new size: about 110kb).

The reward for all these optimizations:

Note that I still have one render-blocking w3tc js file. For now, I’m going to call this “good enough”, since I don’t know how to fix this last one without breaking some fundamental aspect of the site, so I’m going to move onto the expiry problems and see if I can get the score higher that way.

Fixing “leverage browser caching” with W3 Total Cache

PageSpeed Insights found a few files it thinks could leverage browser caching. These files are all .js files.

I found this guide helpful and accurate at the time of this writing: Leverage Browser Caching with W3 Total Cache

The first step is to enable browser caching in W3 Total Cache’s settings. Go to Performance > General Settings and make sure Browser Cache is enabled.

Then, go to the actual Browser Cache section of the plugin. As per the guide, I ensured these boxes were checked:

  • Set expires header
  • Set cache control header
  • Set entity tag (eTag)
  • Set W3 Total Cache Header – this one was not already checked for me
  • Enable HTTP (gzip) compression

(I re-ran the PageSpeed Insights test at this time just in case that one checkbox was all it took. Alas, there was no change in the results.)

The next thing I did was scroll down a little bit to the CSS & JS section. My “expires header lifetime” was set to 172800, which is way less than the recommended 604800 (2 weeks) the guide recommends. I saved that change, cleared cache, and ran the test again.

Now I have just three files with unsuitable caching times:

Alas, two of the remaining files are out of my hands: they are Google Analytics’s own .js files. After reading this guide to browser caching Google Analytics, I decided not to try to cache the analytics js file myself. Doing so would require manually updating it periodically. Even the guide’s author says they don’t recommend this method. That’s fine by me.

But how about this emoji js file? I don’t use emojis on my site, so I wouldn’t mind removing them and reaping a small page speed boost.

Normally, removing them is as simple as adding these two lines in your site’s functions.php:

remove_action( 'wp_head', 'print_emoji_detection_script', 7 );

remove_action( 'wp_print_styles', 'print_emoji_styles' );

But I’m using a pro theme that gets automatic updates (which will clobber this code if I add it to functions.php), and I don’t want to make a child theme for the express purpose of removing emojis.

So, I did what any good WP user does and installed yet another plugin: Disable Emojis. (Yes, I also canceled Christmas and summer break while I was heartlessly removing emojis from my very srs blog.)

I ran PageSpeed Insights again and….

Woohoo! (It initially came out worse, but network latency has some affect on the score, too. I tried again and got a 62/100).

My report has never looked better:

PSI estimates this page requires 2 render-blocking round trips and ~26 resources (0.4MB) to load. The median page requires 4 render-blocking round trips and ~75 resources (1MB) to load. Fewer round trips and bytes results in faster pages.

Fixing the “flash of unstyled content”

A new problem has been introduced by all this work: now my page looks unstyled for half a second or so while it’s loading.

I used this tool: Critical Path CSS to identify a the “minimum” CSS needed to make the “above the fold” content look good (it’s a huge block, I’m sure a human could produce something more elegant but for now, it’ll do).

I put this CSS into Autoptimize’s “above the fold” CSS section and the flash of unstyled content seems to look better now, though I still see the fonts looking bad before the preferred “open sans” style comes into effect.

Done… for now

At this point, I’ve gotta call it good enough for now. My site’s score went from 8/100 to about 62/100. I still have a one blocking JS file that I don’t know what to do with and two files from Google Analytics with unsuitable cache expiration times.

I’ll update this page when I make further improvements to the site.