FanGraphs Arcade: Find Some Quarters!

Let’s do something completely different and have some fun! Over the course of the past year, I created an arcade game that can be played on a Nintendo Entertainment System (NES) from 1985! The game might looks familiar, but it’s been adapted for baseball.

This is an actual NES game; it is a .nes ROM file that you can play on original hardware. I found a JavaScript emulator, so you can more easily play it online. You can download the ROM here and use it in your emulator, flash cart, or your retro gaming setup of choice.

Below you can click on the photo, which will take you to the online emulator. It works best on desktops running Chrome, Firefox, or the new Edge. Safari is playable but it gives a soft picture without sound. Gameplay suffers on mobile, especially smaller devices. It’s best to use your keyboard to control everything, but there is a virtual controller available, too.

(Click to open FanGraphs Arcade)

Game Play

I don’t want to give too much away about the game, because half of the fun of an arcade game is trying things out, failing, then trying again until you succeed, though I will answer questions in the comments or on Twitter if anyone has any.

This game is a short arcade-style video game with no real ending. You control the FanGraphs logo as you try to collect all the dots and round the bases to advance to the next inning. Most of the controls and game play are what you would expect, but there are definitely some baseball-centric twists. In the online emulator, you can customize the keyboard controls by clicking the keyboard icon in the lower right-hand corner of the TV once it’s been “powered on”. Your browser should remember your key mappings if you change them.

I honestly don’t know how far you can get without breaking the game. I really hopes someone finds the limits, like the 256th stage of PacMan.

There will be bugs; have fun finding them!

Why?

Like most older millennial kids growing up in the late 1980s and early 1990s, I really liked the NES. After I got into web and software development, I became curious how games were developed for early video game systems. I had a vague idea that they might have been developed using assembly, which is very different from the JavaScript, R, Python, .NET, and SQL I use day-to-day. In the summer of 2019, I was looking at the NES in my basement after playing Super Mario Bros. and Duck Hunt and decided I was going to figure out how these are made, then make an NES game of my own.

At SaberSeminar last August, I showed my first demo to David Appelman and found that he shared an enthusiasm for retro gaming. He suggested if I made it FanGraphs-related, we could make it into a post. After learning more and figuring out what was feasible to make as a game, I settled on a PacMan clone. It was a simple concept that worked well with baseball. I didn’t have to deal with scrolling, and the collision detection is relatively simple.

The goal of this exercise was to learn the technical foundations of NES games and to play a game I built on original hardware.

Tech

You can find the entire source code for this game on my GitHub.

I wanted to highlight some of the technical aspects of NES game development, since it was my goal to learn them.

First, if you are really interested in NES development, there are plenty of forums and tutorials that do a better and more comprehensive job than I can do. NesDev.com has a lot of resources, forums, and documentation. There is also a Nerdy Nights tutorial series that I and many others started with. There isn’t a lack of information on the internet, but a lot time and tenacity is required to synthesize all of it into a working game.

Basic 6502 Assembly

I used 8-bit 6502 assembly language to write the game, because it was fun to learn and helped me understand computing more deeply. 6502 is the type of processor used in the NES, and was also used in many 1980s-era computers.

If you are unfamiliar with computer programming languages, they aren’t all the same. The ones used today for most applications (and found in many postings for baseball front office jobs) are high-level languages, with many layers of abstraction between your code and the hardware. As an analogy, a car has layers of abstraction between the mechanical parts and the driver. The driver doesn’t concern themselves with how the component parts accelerate, break, or steer the car, just how to operate the pedals and steering wheel.

Assembly, however, is a low-level language that brings you closer to the hardware. You are essentially writing operations for the processor to execute and explicitly moving bytes in and out of RAM. Using the car analogy, you would concern yourself with all the parts and telling them exactly what to do.

If you are interested in learning 6502 assembly, there is an “easy” web tutorial that lets you write some assembly and run it to see the results in what’s essentially a debugger.

Let me illustrate the difference using a really simple math problem. Let’s add Mike Trout’s hits from 2019 (137 hits) and 2020 (through August 16, he has 22 hits), then store that in a variable (or predefined RAM location) labeled totalHits.

First JavaScript:

const totalHits = 137 + 22;

Simple — without any coding knowledge, you understand that.

Let’s rewrite that in 6502 assembly. (Most assemblers use hexadecimal.)

; create "variable" at address $0000 in RAM.
; define totalHits $0000 ; syntax used in Easy 6502
totalHits = $0000        ; syntax for my project

CLC             ; clears carry flag
LDA #$89        ; loads 137 into Accumulator 
ADC #$16        ; adds 22 to 137 in the Accumulator
STA totalHits   ; stores the sum into defined RAM address

This probably makes no sense unless you are familiar with assembly. $89 and $16 is the hexadecimal equivalent for 137 and 22. LDA loads the value onto the Accumulator, which is the one byte register that is involved in computation. ADC is the operation for addition. And STA stores whatever value is in the Accumulator.

I also choose stats that produce a sum that’s less than 256. If you want to see how to add Trout’s 2018 hits (147) and 2019 hits (137), or his plate appearances in those years, look up 16-bit math on an 8-bit processor.

More Advanced

The collision detection system is a simple grid. Basically we compute an 8×8 pixel grid (x,y) coordinates from the actual pixel coordinates. Then we find if two entities are occupying the same space. The player is checked against the background, dots, power ups and enemies, and the enemies are checked against the background and the player, but not against other enemies.

The sprites are centered on their grid position, but they occupy more space than 8×8 pixels so there is some graphical overflow. You can see this when there are two sprites next to each other — there is a little overlap. I could have accounted for this, but this makes the game a little more forgiving.

Most NES games that you are familiar with use a more sophisticated collision detection system, but this suited the game and was easy for me to implement.

Given that basic math isn’t easy, creating the AI for the baseball “enemies” was probably one of the hardest parts for me. I used this video about the PacMan AI as inspiration for the enemy AI for the FanGraphs Arcade game. It’s definitely worth a watch, but it does get into the weeds of bugs and the code.

For the most part, the AI, when in attack mode, is constantly finding available directions then finding the Euclidean distance between the enemy’s hypothetical move and the player’s target tile then minimizes that distance. Each enemy has a different target tile relative to the player, so they don’t always head for the same location. This is similar to the PacMan AI, but it’s a simpler implementation.

When the player has a power up, the AI changes and pseudo-randomly chooses between maximizing the distance between the enemy and the target, and not maximizing the distance.

The Web Emulator

I was able to find a JavaScript emulator that we could use to play the game without having to deal with finding an emulator and loading a ROM file, etc. I used JSNES, and they had a React-based interface project that I was able to adapt with the TV screen and virtual controller.

We hoped you liked reading FanGraphs Arcade: Find Some Quarters! by Sean Dolinar!

Please support FanGraphs by becoming a member. We publish thousands of articles a year, host multiple podcasts, and have an ever growing database of baseball stats.

FanGraphs does not have a paywall. With your membership, we can continue to offer the content you've come to rely on and add to our unique baseball coverage.

Support FanGraphs




I code a bunch of things here. I really need to update my blog about statistics at stats.seandolinar.com.

newest oldest most voted
spycake
Member
Member
spycake

Anyone interested in making similar games, without figuring out assembly, there is a cool new tool called NESmaker: http://makenesgames.com/