Ryan KubikBlogTwitterGames

Games & Code

I write about things I learn here. Usually these things are related to programming and making games.

UFO 50

4 min read - October 14, 2024

What is it? From the Steam page: UFO 50 is a collection of 50 single and multiplayer games that span a variety of genres, from platformers and shoot 'em ups to puzzle games, roguelites, and RPGs. Our goal is to combine a familiar 8-bit aesthetic with new ideas and modern game design. UFO 50 splas...

Read more...

My Portland Recommendations

8 min read - September 7, 2024

I've lived in Portland for a while now. I've written and lost numerous lists of recommendations over that time. Here's a list of stuff I like in town put somewhere I can stop losing it. I split the list up by area of town (and nearby areas). Here's what the emoji mean, click one to filter just that...

Read more...

What I Played in 2023

27 min read - March 10, 2024

Welcome to The Goaties! <Note icon="🐐">Game of the Year - GOTY - Sounds like "goat" "ie" - ha ha ha?</Note> I logged around <strong>123</strong> games last year. <Note>I switched note-taking systems last year and I haven't bothered ironing out all the duplication. It's almost certainly less than 1...

Read more...

What I Read in 2023

7 min read - March 10, 2024

I like to reflect on the books I read in previous years. 2024 has been off to a pretty busy start for me and it has taken me a long time to get around to this post. Because of that, I'm going to keep my notes on each book short. I read 27 books last year! <Icon>📚</Icon> My favorite books from 202...

Read more...

Hide YouTube Shorts Userscript

2 min read - September 3, 2023

I don't like the "Shorts" feature on YouTube. I recently wrote a usercript to hide the feature. I have a couple other posts about userscripts, which I use via Tampermonkey. Hide Elements Over Games on Itch.io with Tampermonkey Clean up your Twitter Experience with TamperMonkey The UserScript In ...

Read more...

2023 Mid Year Fav Games Check-in

10 min read - July 6, 2023

I have been playing way fewer video games the last few months. I've been working on my own projects, reading, and playing board games instead. <Icon>🎮</Icon> Video Games Hitman: World of Assassination - Freelancer Mode <Badge color="#ffdb63" icon="💡"> I Finally Get It </Badge> I've always he...

Read more...

Reduce Entries: Array Utility Function

2 min read - June 5, 2023

If you've ever needed to break an object into its entries via JavaScript's Object.entries function, you'll sometimes need to put it back together again. I've needed this often enough that I encapsulated this functionality into a little utility function called reduceEntries. Source Example Usage ...

Read more...

Hide Elements Over Games on Itch.io with Tampermonkey

3 min read - May 18, 2023

Itch.io presents a lot of information on its game pages in the upper right corner. Often, these elements can cover up a game and interfere with playing. Prior Work NextLevelBanana made a FireFox extension that hides these elements called itchCleanScreen. It finds the user\_tools element on the pag...

Read more...

Add a Spoiler Tag with Alpine.js

7 min read - May 4, 2023

I was working on patch notes for my game, Island Maker, and I wanted to put some information behind a spoiler tag. I didn't want to add in something heavy with a build step. So I thought it would be a good time to try out Alpine.js. Alpine.js is a lightweight JavaScript framework that describes it...

Read more...

What I Read in 2022

5 min read - January 22, 2023

I like to reflect on the past year over the holidays. These reflection posts end up changing format every year. This year, I'm going to try several smaller focused posts instead of attempting to make sense of one giant rambling post. 📚 My favorite books from 2022 Apparently, I read 28 books this ...

Read more...

What I played in 2021

29 min read - January 23, 2022

Each year I reflect on the games I played in the previous year. Here’s last year’s reflection. This is the first year I’ve tracked all the games I played. You can see them in this Twitter thread. Tracking everything seems to have encouraged me to play a lot more. I clocked in at 81 games this year!...

Read more...

10 Games That Influenced My Tastes

14 min read - December 25, 2021

I listen to a gaming podcast called Gametalk put on by some of my friends. Their 100th episode was titled “The Games That Define Us”. In this episode, they each listed the 10 games that had the largest impact on their tastes. This meant including not just favorite games, but the ones that introduced...

Read more...

Remove Duplicates: Array Utility Function

2 min read - November 2, 2021

I had need to remove duplicate items in an array and thought it would be nice to encapsulate that logic in a removeDuplicates function. Source I initially chose to use JavaScript's Set object for ensuring uniqueness. However, it doesn't guarantee any semblance of the original ordering of the arr...

Read more...

JS13k 2021: Rocket Jockey Postmortem

12 min read - September 21, 2021

The JS13k jam is one of my favorite game jams. The challenge is to make a game in JavaScript, in under 13kb over the course of a month. I really enjoy the explicit challenge of making something small in JavaScript. I love the language, and this jam challenges me to use lighter parts of the ecosystem...

Read more...

useKeyPress: Respond to user key presses in React

6 min read - September 4, 2021

Dealing with keyboard events in React can be tricky to figure out at first. I had a project recently where I wanted to trigger some code in response to a user's key presses. I ended up responding to their events with a combination of useEffect and document.addEventListener in a useKeyPress custom ho...

Read more...

Force date to a given time zone

2 min read - August 14, 2021

Why do I need this? I set the dates for my blog posts in YYYY-MM-DD format, like this 2021-07-09 for July 9th, 2021. I use a package called gray-matter to parse this date out of the frontmatter of my blog posts. Because I omit any timezone information in my dates, they get parsed as UTC-0:00. This ...

Read more...

Slipways Ranked Run: Week #6

4 min read - July 9, 2021

What is Slipways I've been playing a "condensed" space grand strategy game called Slipways over the past few weeks. It's been a lot of fun to return to a genre that I just don't have the time and energy to really get into any more. A run seems to usually fall in the 1.5-3 hours range for me, which ...

Read more...

What branch was I working on last?

TIL - 4 min read - July 6, 2021

Sometimes when I come back to work after the weekend I forget what I was working on the previous week. This gets even worse when I'm working on multiple tasks at once. The good news is that since most of my work accompanies a branch in git I can use some commands to see what I was working on most re...

Read more...

What I played in 2020

8 min read - January 7, 2021

It's that time of year to reminisce about some of the games I've played in the past 12 months. Which games left the biggest impressions on me These are the games I remember the most vividly when I think back about what I played this year. I didn't rank the following games against each other, I pic...

Read more...

Bose QC35 II: Fix Static Issue, Reinstall Firmware, and a Short Review

TIL - 5 min read - September 17, 2020

My problem I was having an ambient static noise in my QC35 II's ONLY when connected to my Macbook Pro, not when connected to my iPhone. Additionally, the "action button" on my headphones that should change noise cancellation levels was non-functional. Skip my debugging steps, and head right to the...

Read more...

Don't Mix React Synthetic Events with Native DOM Events

TIL - 6 min read - June 6, 2020

I was stuck on a problem for a few days on a side project in React that had me questioning my understanding of how event propagation works in JavaScript. This article by Gideon Pyzer saved my sanity. I'm going to summarize my understanding of this issue here so hopefully I can find this quicker in t...

Read more...

Using Design Pillars to Keep Wildfire Swap's Development on Track

6 min read - May 27, 2020

What are design pillars? I'm not sure where I first learned about the concept of design pillars as a game design strategy, but it's definitely been floating around for years. Different sources define design pillars in different ways, so here's the definition I use. Design pillars are the 3-5 core ...

Read more...

Clean up your Twitter Experience with TamperMonkey

10 min read - April 29, 2020

The longer Twitter exists, the more new features appear that I just don't have any interest in using. They're either designed to keep me from ever leaving the website, or I'm just too set in my ways to try something new. Either way, I don't want to see them! With a bit of JavaScript knowledge and a...

Read more...

Wildfire Swap March 2020 Newsletter

NEWSLETTER - 5 min read - April 2, 2020

./wildfire-title-with-logo-trimmed.png Wildfire Swap March News Hey everyone! I think this has been an incredibly weird month for just about everyone in the world. We've been working on Wildfire Swap during these times but its definitely been a little more challenging than usual. Currently, we're...

Read more...

Scale and Center Pixel Art on the Command Line

TIL - 6 min read - March 27, 2020

I've been working on art more often for my game projects. I find a lot of the times, it's inconvenient or impossible to export my art assests in quite the right format. This leads to either a lot of manual fiddling in art programs' export settings or fiddling in image editing tools after the fact. E...

Read more...

Wildfire Swap February 2020 Newsletter

NEWSLETTER - 6 min read - March 3, 2020

./wildfire-title-with-logo-trimmed.png Wildfire Swap February News Happy leap month! We've been meeting regularly this month to get the first draft of Wildfire Swap ready for the end of the month. There are 75 levels in the first draft that we ended up with at the end of this past month along wit...

Read more...

Wildfire Swap January 2020 Newsletter

NEWSLETTER - 5 min read - February 5, 2020

./wildfire-title-with-logo-trimmed.png Hope your first month of 2020 is going well! We're getting back into the swing of things putting Wildfire Swap together. We're on track to have our first rough draft of all the content in the game ready by the end of February! Currently, Drew is working hard ...

Read more...

A review of 2019 and a plan for 2020

15 min read - January 30, 2020

I did my first personal retrospective last year looking back on 2018. I found it useful to spend some time thinking about what I got out of 2018 and how I could make the most of 2019. Looking back on last year's retrospective, I think I was overly focused on being "successful". The trouble was that...

Read more...

Wildfire Swap: A puzzle game inspired by fires in the Pacific Northwest

5 min read - November 27, 2019

./wildfire-title-with-logo-trimmed.png Wildfire Swap is a puzzle game about swapping tiles to prevent fires from burning down people's homes. While showing Wildfire Swap to folks, I've gotten recurring questions about what inspired this game. This post dives into that inspiration story and looks at...

Read more...

Testing for a Race Condition in Async/Await Code

TIL - 2 min read - October 31, 2019

Race Conditions Sometimes a series of asynchronous functions in an application must execute in the correct order for the app to work correctly. If an earlier function in the series does something like make a network request, that request could run slowly sometimes. Since the functions are running a...

Read more...

Showcase Season Retrospective: Wildfire Swap at SIX & XOXO 2019

31 min read - September 30, 2019

Its been a wild couple months of showcasing and preparing to showcase my game, Wildfire Swap. I wanted to take some time to reflect on this experience of showcasing my first commercial project. Hopefully there's some insight other folks can gain from this. This post is a long one already so I won't...

Read more...

🎣 useRefState Hook - Access state outside of a component

TIL - 4 min read - September 3, 2019

What's the current state? I ran into a situation where I needed to use the value state of a useState hook inside an event handler callback. The callback would execute later on after an event was triggered. By this time, the value of my state would have changed. This is where my trouble began. I wa...

Read more...

All the Indie Puzzle Games at PAX West 2019

5 min read - August 29, 2019

I'm headed to PAX West for the first time this year. I put together this list of all the indie puzzley games I'm aware of at the showcase events during PAX weekend. If there are any I've missed, please let me know so I can update the list. If you're into indie puzzlers like me, definitely check out...

Read more...

Accessibility for Games - A Jumping Off Point

TIL - 8 min read - July 4, 2019

I posted an open question on Twitter recently asking for accessibility resources that could help me get a deeper understanding of that world in games. Unexpectedly, I got a ton of helpful links and comments from peers and industry professionals alike! I thought it made sense to catalog these resourc...

Read more...

Using the Regex Global Flag with Test

TIL - 3 min read - June 26, 2019

Using regexes in JavaScript can be tricky! One new gotcha I ran into today involves the usage of the g or global flag. The global flag matches against all occurences of the regex. This can be useful to find how many times a regex is matched inside a phrase. You can enable the g flag in a few ways: ...

Read more...

When was this file added to version control?

TIL - 4 min read - May 11, 2019

Git provides a lot of information to you about the history of your project. Much of this information can be accessed using git log. By default, running git log will show you all the most recent commits on your branch in reverse chronological order. Meaning, the most recent commits show up first. T...

Read more...

Host a simple local web server using http-server

TIL - 3 min read - April 4, 2019

Sometimes when you're developing a application it can be helpful to run your project on a web server. Often running that server on your local machine is easier and faster during development. It lets you avoid uploading your work in progress files and setting up a complex build system. Enter http-se...

Read more...

Create a Custom ESLint Rule: Automatically Share Your Team's Institutional Knowledge

9 min read - March 8, 2019

ESLint is a tool built to provide linting of JavaScript code. Linting is a form of static analysis that detects patterns in code that could cause errors. By running ESLint as you write code you're able to catch these errors without even running your code. This speeds up development time and helps yo...

Read more...

How to Resize Pixel Art on the Command Line

TIL - 3 min read - February 18, 2019

I've been doing a bit of pixel art lately in my gamedev projects, like Wildfire. This generally ends up with me creating art that is something on the scale of 32x32 pixels. But its viewed at resolutions much higher than that in game or when sharing on Twitter. I've been searching for an easy way to ...

Read more...

Deliberate Game Jamming: A Global Game Jam 2019 Retrospective

15 min read - February 4, 2019

Jam With a Plan The more game jams I enter, the more my jam objectives have changed. Early on, I was motivated to learn how a game could be built at all. Then I wondered how to build something with a team. Lately, I've been trying to figure out how to make something that is finished and polished. ...

Read more...

A Personal Retrospective for 2018 and a Goal for 2019

16 min read - January 9, 2019

A Personal Retrospective I read a post by Jason Lengstorf about doing a personal retrospective of his 2018 yearly goals recently. The general idea is to answer three main questions about your previous year and the upcoming year. What went well? What didn't go well? What will we change going forw...

Read more...

Using Jest with Parcel Bundler

TIL - 4 min read - December 31, 2018

What is Parcel? Parcel is a "zero-configuration" web application bundler. Its a very convenient alternative to a tool called Webpack. Using a bundler for your web application provides a lot of useful features like Hot Module Reloading, ES6 Transpilation, splitting your JavaScript into multiple file...

Read more...

Cascadia.js Day Two Notes

TLDR - 16 min read - December 24, 2018

CascadiaJS was a single track conference of 24 amazing speakers discussing the cutting-edge of JavaScript, web development and engineering culture over the course of 2 days in mid November. These notes are from the second day of the event and the accompanying talks are now online. Even Faster: now ...

Read more...

Cascadia.js Day One Notes

TLDR - 10 min read - December 20, 2018

CascadiaJS was a single track conference of 24 amazing speakers discussing the cutting-edge of JavaScript, web development and engineering culture over the course of 2 days in mid November. These notes are from the first day of the event and the accompanying talks are now online. Reclaiming the Web...

Read more...

Modifying the Return Value of a Constructor

TIL - 3 min read - November 30, 2018

The new keyword does a few things behind the scenes to create a new instance of an object. One of these things is to invoke the constructor of the object being used as the source of the new. The constructor is a function responsible for building a new object to the specifications desired by its dev...

Read more...

Remove Local Branches Merged into Remote

TIL - 2 min read - November 5, 2018

git fetch -p (--prune) makes your tracking branches equivalent to those on the remote repository. After that, git branch -r (--remote) will list your tracking branches, freshly pruned. Tracking Branches Tracking branches are local branches that have a direct relationship to a remote branch. Checki...

Read more...

GPU Floating Point Sampling Error (Pixel Bleeding) & Tileset Extrusion

TIL - 2 min read - October 7, 2018

You can visually see the issue in this gif. Notice the black lines that appear as the camera scrolls town the tilemap. Pixel Bleeding GIF This phenomenon is called "Pixel Bleeding". Its caused by the GPU sampling a pixel outside of bounds of the texture, due to floating point rounding errors. You...

Read more...

Generate Array of Increasing Indices

TIL - 2 min read - October 2, 2018

This is a fairly simple function to allow the easy creation of an array of an increasing order of indicies. This was useful for me to set certain indicies of a tilesheet of sprites as collidable while leaving others untouched. new Array(length) lets you create an empty array of the specified length...

Read more...

Parse JSON with JQ

TIL - 2 min read - September 26, 2018

jq is a bash program that assists with the parsing of JSON formatted data. This example shows how to log the start script of an npm package to the terminal. Quickly view NPM Scripts in a repository cat will print contents of package.json to the console. If you pipe data into jq it will pretty p...

Read more...

Conditional Breakpoints in Chrome Dev Tools

TIL - 1 min read - August 28, 2018

Right click on a breakpoint in Chrome dev tools. Click Edit Breakpoint. \--OR-- Right click instead of placing a breakpoint, and choose Add Conditional Breakpoint. \--THEN-- Enter an expression into the popup. When the expression evaluates to true the breakpoint will be triggered. sources http...

Read more...

Choose a Random Number Between Two Values

TIL - 2 min read - August 15, 2018

A simple, but useful utility function to randomly choose a float (whole number with decimal) in a range. The output includes the low number and excludes the high number. From the basic random float in range function, its possible to make a few simple tweaks to guarantee the number is an integer (...

Read more...

You don’t need standup

TLDR - 5 min read - August 15, 2018

Read it on Medium by: palmerj3 Intro They recently became a technical product manager at Spotify and insituted an experiment: No stand-ups No planning at regular intervals No retros All meetings are optional Issues with Agile Ceremonies Trello (or whatever you use) has to be kept in sync wit...

Read more...

Pick Randomly From Array

TIL - 2 min read - August 4, 2018

In game development, especially demos where I'm not using a full library or framework, a very useful utility function is to randomly pick from a set of options. I usually accomplish this by defining an array of the options and using this utility function to randomly choose one. See it in action in ...

Read more...

Npm List Installed Packages

TIL - 2 min read - July 18, 2018

Listing npm dependencies with npm list is a handy feature to checkout what npm packages you've installed. However, by default this lists not only the packages you've explicitly installed but the entire dependency tree too. I usually only find myself looking for the top level packages I've installed ...

Read more...

Shadowhand postmortem – Top ten takeaways

TLDR - 4 min read - July 16, 2018

Read it Here by: Helen Carmichael @bchezza & Jake Birkett @greyalien This article has ten different takeaways the developers learned while working on their solitaire game Shadowhand. I'm going to only mention a few excerpts from these points that I hadn't seen before. If you want to read about all ...

Read more...

The Atan2 Function

TIL - 3 min read - June 16, 2018

The inverse tangent function, Math.atan(), is useful to calculate the angle of a provided ratio of a sides of a triangle (like a velocity vector's x and y values). This can be useful to find the angle an object should be rotated to face in the direction it's moving, Math.atan(velocity.y/velocity.x)....

Read more...

Encode and Decode URIs

TIL - 2 min read - May 20, 2018

JavaScript has a lot of built in functions to handle common issues developers run into like manipulating URLs. I just learned about two pairs of conveninent functions: encodeURI(url) decodeURI(url) encodeURIComponent(url) decodeURIComponent(url) The encode/decodeURIComponent functions encode/d...

Read more...

JavaScript's Array Sort Function

TIL - 3 min read - April 19, 2018

Javascript's array.sort() function converts all objects in the array according to their Unicode code points. This means that by default, lowercase letters will be sorted before uppercase letters of the same value. This also means that numbers are not sorted numerically, but based on the value of ea...

Read more...

Basic JavaScript Finite State Machine

TIL - 5 min read - April 13, 2018

State machines make handling complex combinations of variables more convenient. Instead of handling every possible combination of states and actions you can only handle the particular combinations that make sense in your use case. This document explains the concept of a state machine in much more d...

Read more...

Where the Water Tastes Like Wine

TLDR - 1 min read - April 4, 2018

Read it here by: Johnnemann Nordhagen Good Stuff Hire talented artists, voice actors, composers Bad Stuff Takeaways Don't relegate play testing to an after thought Think about pacing Hire/Try to work with experts in other fields, writers, business folks, editors, hiring people, etc. Don't just t...

Read more...

How to Make Consistently Profitable Indie Games

TLDR - 3 min read - April 3, 2018

Watch it on Youtube by: Ryan Clark Hooks Include as many hooks/unique factors as possible. Compare the hooks of successful and poorly performing games similar to your own to see what good hooks are. Market Analysis look at games most similar to yours to get an idea what types of games are succe...

Read more...

You are spending too long making your game

TLDR - 4 min read - April 3, 2018

Watch on Youtube by: Jake Birkett (@greyalien) Money/Hour spent optimization Question: what about value based pricing? A casual hit A high dollar/hour spent on the game itself (guessing this doesn't count past investment in engine) kept a small scope worked for the target audience money spent...

Read more...

Json File Manipulation with Node

TIL - 2 min read - March 11, 2018

In my office we have some large JSON files that occasionally need duplicated updates in mutliple places. Node.js makes working with these files incredibly easy with two features. The first is that JSON files can be required as you import a module (require('file.json')) and then manipulated as if it...

Read more...

Box-Sizing Property in CSS

TIL - 2 min read - March 1, 2018

The CSS basic box model describes the layout of elemnts on the DOM via content, padding, borders, and margins. The basic model is shown below. In the basic model, the width of an element refers only to its content box. However, with the css property box-sizing you can change this. By setting box-...

Read more...

JavaScript Void Keyword

TIL - 2 min read - February 14, 2018

The void keyword is an operator that evalutes the expression following it as undefined every time. The most common usage of this keyword seems to be as a way to access the JavaScript primitive value undefined as void(0) (it could be any expression, but (0) is convention). In most current development...

Read more...

Git Pull vs Fetch

TIL - 2 min read - February 8, 2018

Branches in git are just a pointer to the most recent commit on their branch. git fetch updates the remote tracking branches and downloads any new file changes into our local repository (but not into our local branch). These changes are not pulled into your current working local branch until you run...

Read more...

Use NPM's .bin directory instead of globally installing dependencies

TIL - 2 min read - February 5, 2018

Until recently, I thought that npm modules with a command line interface needed to be installed globally before they could be used. I found an article (in the sources) that talks about creating an npm run cli-app command instead of globally installing. This works because npm keeps a .bin directory i...

Read more...

JavaScript Bitwise Operators

TIL - 2 min read - February 5, 2018

The tilde (~) operator in JavaScript performs a bitwise not operation on its operand. Every number is represented by a series of 32 ones and zeroes called bits when bitwise operations are being performed. These numbers are represented in two's complement format. Two's complement format means that a ...

Read more...

Mocking a property using getters and setters

TIL - 2 min read - January 19, 2018

This is the getter/setter pattern explained on MDN that I only recently learned existed. Leveraging this pattern its possible to detect when a variable has been set or gotten. By passing in a mocked function as the getter or setter of a property you're interested in, its possible to test for assi...

Read more...

~ vs. $HOME in bash

TIL - 1 min read - January 19, 2018

While writing bash scripts I've noticed the $HOME variable being used instead of ~ . to reference the user's home directory. It turns out that ~ is just being expanded by the terminal into the $HOME variable anyway. Because of this, it appears to be more robust to use $HOME in scripts as it's not gu...

Read more...

Slice with a Negative Index

TIL - 2 min read - January 16, 2018

Slice can take in two parameters for the beginning and end index: arr.slice(\[begin\[, end]]). The array.slice() function has some interesting logic when either of those parameters is a negative value. Positive index values start iterating from the beginning of the array while negative values iterat...

Read more...

Ludum Dare 40 Postmortem: Infinite Desktop Icons

4 min read - December 4, 2017

Friday The theme is "The More You Have, the Worse it Gets"! Of the other top themes, this was not one of the ones I was very excited about. I spent the most of Friday night brainstorming to try and come up with a game idea. This took me hours. ldjam-brainstorm.jpg After that I got a boilerplate p...

Read more...

Core Mechanics & Game Design in Unstable

5 min read - July 16, 2017

I’m going to take a look at the design of a project I’ve been working on off and on for a while now. It was originally created as part of a month long game jam in January. Unstable began its life as a digital art piece. I wanted to use an art style that I felt confident in producing assets for by my...

Read more...

Ludum Dare 38 Postmortem: A Social Network

6 min read - April 29, 2017

Tools & Tech A Social Network was written in Phaser, a javascript game development framework. I used MAMP to host the game locally during development. I wrote all of my code using github’s Atom. Art assets were designed and turned into sprite sheets using Pyxel Edit, picked up for cheap in a humble...

Read more...