Casual slot-style gambling games are great distractions while working out because they’re addictive and take little to no mental effort to play and enjoy – a perfect fit for the [adult-swim] show FishCenter Live. Tropical Treasures is such a game, and I succeeded in taking it from concept to production in less than a week. This is a look into the process and experience.
FishCenter Live is an hour-long live-streaming call-in show. It clearly has low production value compared to the rest of the network’s programming, but that’s part of its charm. Every weekday, “upwards of 20-30 people,” as co-host Matt Harrigan would sarcastically estimate, watch the program. Many participate in live chats on tlk.io and twitch.tv, and some call in to play games and win points for a fish of their choice. It’s akin to hangin’ around with “the guys” as the day winds down.
A few of FishCenter’s games are luck-driven – some played by fish, others played by callers. Matt had briefly mentioned on last Thursday’s show that he’d like to see more gambling-type games on the show, and having played workout session slot games daily for the last few weeks, “Tropical Treasures” quickly came to mind.
FishCenter Live’s flagship game is Coin Quest, where various coin are keyed over the tank and fish gain or lose points as they “hit” them. Tropical Treasures works similarly. When a fish “hits” one of the red negative coins, they lose a point and trigger a spin with the active pay line corresponding to the position of the coin they hit.
While I envisioned this being played like a round of Coin Quest, with fish taking turns spinning, on Wednesday’s show, the hosts adapted the game and asked a caller to choose a fish to play. This worked out well, and the fish Tang spun twice and won 15 points, netting 13 points, slightly higher than the typical bonus win.
FishCenter is generally focused on fish winning points, not losing them, so I knew I had to gear the game to pay out far more than a profitable slot machine. The Wizard of Odds is a tremendous resource for all things probability, so I used their Australian Reels slot game analysis as a starting point for this game’s design. In the end, I wound up with a game that statistically pays out 400% return. If you’re a stats geek, you may be interested in the spreadsheet.
[adult swim] content, regardless of production value, embraces nostalgic 8-bit, glitch and low-fi themes in its graphic design – often well-made but rarely polished. FishCenter is no exception, so I felt comfortable keeping this game’s graphics simple but not plain. All of the slot symbols were re-purposed from the show’s main webpage, and everything else was stitched together from miscellaneous fonts and clip art using Photoshop.
The final product has three trigger coins, but the initial plan was to have coins surrounding the reels, allowing both horizontal and vertical spins to be triggered. The three coins were chosen due to lack of screen real estate.
Angular truly lives up to its goal of speeding up development time. As a framework, it’s very much overkill for a simple game like Tropical Treasures, but it’s a framework I know and have used before. Plus, it works.
With that, there are a couple of pitfalls I’ve learned to avoid that came up with this project.
The most noticeable Angular-related issue was in the way I chose to highlight the active pay line – by changing the background-url with ng-style. Because ng-style can’t know all of the background images it will ever set, it doesn’t request them until it changes or at initialization. There are some JS-based solutions for preloading the image nodes and including them in the directive, but for a project this small, I figured preloading them directly via HTML wouldn’t be an issue. (see commit)
Angular is doing a lot in the background, particularly watching variables for changes. The reel arrays are the main variable for this game, and they’re generated separately. Originally, I pushed each new reel to $scope.reels in the controller. This created some slight performance issues, so I broke it off into a new function that mutates $scope.reels once instead of three times. When working with Angular controllers, it’s best to build your objects outside of $scope so as to change the $scope object as infrequently as possible. (see commit)
Programming is compelling because it allows your ideas to come to life. Instead of having the vision and wishing, you can have the vision and execute it.
This is the first time I’ve deliberately started coding with unit tests, and it was great yet unfamiliar. When you’re used to a workflow without testing tools, forcing yourself to learn and use them feels like a burden. In the most literal sense, it is more work to do as it can double the amount of code you write.
But in the end, testing really helped development along. The first draft of scoreLine() wasn’t written to account for all wild values. I hadn’t written a test specifically for all wilds, but the other tests brought the issue to light much sooner than I would have noticed otherwise. Who would want to spend time playing the game until all combinations have been verified to pay correctly?
Test-driven development really compelled me to modularize and more intimately know my code. What I didn’t get to with this project, which is fine for its purposes, is end-to-end testing. The next project will be sure to include end-to-end tests including angular, not just the functions I write.