effort games

gamedev

stardust frontier

Published March 11th.

Stardust Frontier, One Month In

So, it's been just over a month since I quit my job, uprooted my life, and threw everything into starting an indie game studio. How's that been going?

Last year in September, my close friend Brian and I had the opportunity to go to PAX, and through a series of increasingly absurd coincidences, ended up meeting and making friends with a whole host of industry professionals, one of which ended up investing in us and our idea! That idea is Stardust Frontier, a rogue-like team-based party game played with [two to eight players](Technically you can play with one to infinite players, but we'll get into that another time.). The players are split into two teams, each team controlling a giant mech, and they both get sent to the same rim-world to fight over an exceedingly valuable piece of space-junk. Players contribute to the team's progress by playing micro-games on their phones, in some sort of unholy fusion of Jackbox and WarioWare.

At the time that we went to PAX, Stardust was nothing but an idea in our minds, but it was also an idea that we had a lot of confidence in. I do have to commend the actual real industry professionals we met for taking us seriously, because we could have been just about anybody at that point rambling about our dreams, and they paid attention. I like to hope that means they saw something in us that indicated we would actually succeed. So when PAX ended, we left with lofty promises that by that time next year, we'd have a fully functional beta to show them, and we pledged to do whatever it took to make that happen.

That said, we didn't actually get the investment offer until January of this year, so in the time being, we had to go back and continue our day jobs. Brian's had more experience in the workforce than me; the job I had at the time was the first I'd ever held. I'd been there for about six months at the time, and I was already beginning to go a bit stir-crazy not being able to create things that I felt passionate about, and the experiences we had at PAX just exacerbated that. When we got back, every day felt like like a slog, just knowing there was something I could be making that I just didn't have the time to pursue. It wasn't until late October, when Brian and I attended a local game jam over the course of a weekend, that we had a chance to really see what this could become.

That jam was an experience. Before I moved to Victoria, I'd never participated in an in-person programming event. This was the second I'd ever been to, and it was significantly larger than the last. I was, honestly, in a pretty bad head-space before the jam started, lots of hopeless thoughts dancing around due to work. But there's something just so invigorating about being surrounded by other passionate folks creating cool things, and being there managed to get me into at least some form of functionality. It was still tough, Brian and I were both definitely working through burnout, but we propped each other up and kept ourselves going rather than struggling alone, which reminded me of a huge part of why I like working together in the first place. We clocked a lot less hours during that Jam than I would've liked, only about eleven throughout the whole weekend, but we still managed to work together incredibly well, and by some sort of miracle though, we had a fully functional playable multiplayer prototype by the end of the jam.

Okay, it was fully functional, but not much else. The prototype was really, really rough. It consisted of a lobby, three minigames with about the same depth as something from Among Us, and with far less appealing graphics to go along with it, and the whole thing was being served on my laptop over my mobile phone hot-spot, which could only manage at most ten connected devices. We got a lot of attention at the showcase that night anyways, though, at least in part due to the fact that we were the only networked game there, and the excitement of it all finally pushed us to lock in and find a way to make this project real.

We spent the next two months slamming our heads against every possible wall trying to find a way to fund this project, all the while still holding our jobs. At some points it felt like we were doing just as much work trying to find an opportunity to get a grant or a loan or a something as we were in the office. It was getting pretty dire, the expectations are incredibly high these days when it comes to getting funding for a video game project, and despite being hobbyists for years, our lack of industry experience was closing a lot of doors. I remember at the beginning of December I was having some tense conversations with family, trying to find any way to make this work. We knew our window was quickly closing if we wanted to make good on our promise to be at the next PAX with a game, and neither of us wanted to accept that we might have to drop the project.

It was midway through my Christmas visit to my hometown when we got the call. One of the folks we had kept in contact with hadn't stopped thinking about the idea, and was interested in potentially being an angel investor in the project. We anxiously stumbled through our early talks with them, and secured a meeting to pitch the idea early in January. I left my family mid-vacation, and the two of us traveled to meet them in person and pitch the idea using a PowerPoint slide deck we'd agonized over the weekend before. The pitch went well, and they seemed cautiously interested, Brian and I both headed our separate ways, fingers crossed.

Less than a week later on the 8th, we got confirmation that they were in. That afternoon, I called my boss and let him know that I'd be resigning at the end of January. The rest of that month was, honestly, the most difficult part. Trying to continue to meet my work obligations and close on my remaining projects while knowing full well that I'd be out of there in a matter of weeks was excruciating. But I pulled it off, and at the end of the month we were free.

The beginning of February was a whirlwind. We had contracts to get written, business accounts to start, paperwork to fill in, and before we knew it we were halfway through the month and we still hadn't gotten any work done on the game! But importantly, we had all of the busywork done, which gave us the clearance to start developing. So a new week started, and we sat down together and whipped up a roadmap of the entire game, from prototype to demo to release. And then once we'd done that, all we had left was to actually make the thing!

("All" we had to do, heh.)

The actual "work" part of the job

So what did we end up working on during, once we were able to actually start coding? Well, the first thing we dug into was refactoring the game jam code. Now look, I know what they say about premature optimization, but this goes beyond that. That code reeked. If we let it fester, it was going to destroy the entire system because of us trying to deal with its jank, so it had to be dealt with. When we first started we were trying out side-by-side peer-programming, both cleaning up and refactoring the parts of jam code at the same time, but we quickly realized that ends up taking far too much effort to stay in sync and communicate small details back and forth. Once we figured out that wasn't working, Brian took to working on making something the absolute mess of a mockup-screen I made (pictured below) and I continued to work on improving the codebase.

A lot of our game relies on fairly intricate state management. It's not a traditional experience where you throw a bunch of players into a map and they each have independent state. It's a lot closer to one of those on-rails shooting games at (good) arcades, everyone is going through a roughly equivalent experience in lock-step, and they all need to be in the same game-state at the same time. So a lot of the early work was ironing out how to manage state on the server and the client, and making sure the systems for sending it back and forth are iron-clad against both accidental and potentially intentional protocol breaches.

I for one ended up being very influenced by the functional programming I had been doing for the last eight months before starting the project. A lot of the first few days was spent implementing nice Result and Option monads in Typescript, and then using them along with some in-house lensing code I might eventually release to rebuild the game state management in a completely immutable fashion. What this ended up with was a single monolithic state object for any given room, which is immutably updated when we want to change team locations, scores, etc. For a game like this where a single instance could end up with dozens of clients to be kept in sync, this is hugely helpful, not only for making sure that every client stays in sync, but it also allows us to just resend the entire game payload if a client ever gets disconnected and reconnected, instead of trying to ["catch them up" on the events that they missed](This catch up behavior is actually what our networking library -- Socket.io -- uses if you enable client reconnection, but we bypassed that and implemented our own reconnection behavior as it was ill-suited for our game.).

After I got everything sorted with the state management, we decided it was time to start moving into implementing more of the core systems of the game. Since the game is, at its core, a micro-game engine, it'll have a lot of isolated five-to-ten second experiences hitting you real fast, so we also want to have fairly deep core core mechanics that take place throughout an entire play session, to keep everything tied together. I won't bore you with the whole list of core systems (I'm sure you'll piece them together on your own eventually if you read the coming months' updates), but my next point of address was the voting system.

Given that players are blocked into teams, and each team functions more-or-less as a unit, there'll have to be a lot of voting. Choosing where to head next on the map? Vote. Choosing what to do at an event tile? Vote. Choosing whether or not to buy that expensive relic? Vote! So it was pretty critical that we made a generalizable system for handling team votes: counting them, validating inputs, tie-breaking, and timing out if a decision has been sat on for too long. Most of the core pieces were straightforward, anything data-driven is relatively easy to do with the functional style that we've employed so far, but handling vote timeouts posed more of an issue. A timer is sort of intrinsically mutable, in a sense. Even if you encode the time at which it expires (which is what we did) instead of keeping a ticker that increments upwards, you still need to somehow observe said timer relative to the world time to see when it should fire an event, and then of course trigger the relevant function or callback when that event fires.

After a few iterations, I settled on separating the vote state and timeout into two distinct objects; The vote state stored the decisions being made by the players and nothing else, and the timeout stored one or more timeouts, depending on the type of vote. Some votes could only be completed if the party reached consensus, at which point the timeout object just stored the the three-second consensus-confirm timeout, while others would choose a default option or the most voted option if the party couldn't reach a decision. For that, a second "idle" timeout had to also be stored. The way I set it up, a timeout could have any number of labelled expiry points some time in the future, as well as a single callback. When the first expiry point is reached, it triggers the callback with the label, and then ceases checking any of the other timeouts. That way, if a vote has a 30 second idle timeout, and then the players reach consensus 15 seconds in, the 3 second consensus timeout would take over. But if two seconds into that, a player changed their vote, the idle timeout would still be running with 13 seconds remaining. And if the idle timeout gets to below 3 seconds, the consensus timeout can still be activated, but it won't ever get the chance to fire as the idle timeout will trigger first.

Brian also had a large say in this discussion, he's got a much stronger intuition when it comes to gameplay experience than I do, and so while I handled most of the vote implementation, he helped solidify things that seem far more obvious in retrospect, such as how the idle timeout continues running even when the consensus timeout is active, but that are actually surprisingly hard to reason through on [one's own](On my own, it's me, I'm the problem.).

During this time, Brian's also been putting a ton of work into building up a unique aesthetic for the game's art. I've also had a say on this, but mostly in the technological sense of letting him know how we're actually going to be rendering stuff, what sort of parallaxing and scaling things we can and can't do, etc. He's been properly in the trenches though, making all sorts of environment assets and mech designs. I've been watching him work on mech designs all day while I've been coding and writing this, and it's really exciting seeing it all start to come together. He's also been working really hard at fleshing out the gameplay systems we're going to have, and I have to admit, I'm pretty jealous. I wish I had that sort of mind when it came to creating stuff for Zepha. I won't get too into it right now, as it's all still pretty speculative, but I look forward to writing on these systems more once we have some concrete mechanics to showcase.

While he's been heading the art department, though, I've been heading the feel. I'm a UI designer at heart, and this game is also quite UI-oriented at its heart as well. I love creating interactions and behaviors that make you hum under your breath when you play with them. Buttons that *click* with the haptic motor when you press them, progress bars which smoothly swipe across a button to show voting progress, you name it. I have to keep myself a little under wraps this early on, I don't want to spend a ton of time polishing interfaces that might get completely removed or changed when we realize they don't fit the gameplay anymore, but I do let myself have a little fun here and there. Recently my fixation has been on haptic feedback. I've been so thoroughly enjoying creating vibration responses to in-game interactions that I actually created a whole tool for designing them! It's called the Haptic Playground, and I'm kind of shocked that something like this didn't exist to begin with. Poor navigator.vibrate, always under-appreciated.

The final piece I've been working on is a bit of a doozie: gyroscope and accelerometer reading. Our game is built on the web to make it as dead-simple as we can to join games on your phone, and while there is an API for reading device sensors on every mobile OS and browser, they sure aren't standardized! Working through getting this stuff working is making me feel real good about the $200 second-hand iPhone we purchased for the project, because if I didn't have access to an IOS device while building the motion sensing code, I would be completely lost as to how to use their APIs. But, I'm making progress, and just today I got standardized gyroscope reading across all devices! Accelerometer is a different beast, but I'll get to it in due time. We plan to use these sorts of inputs for motion-controlled games, like actually being able to aim down the sights of your mech's phaser, or playing minigames where you have to balance, shake, or toss things.

So what's next for Effort Games?

Well, that's about it for our first month, and to be frank, I think it was a really strong start. Most of my other projects are hobbyist stuff where I do just about everything, so it was a really nice change to have to have someone else to depend on throughout this time. I'm also not used to the amount of busywork that comes with running a company, we've had a constant (but thinning) stream of legalese tasks to get done this entire span, and they really did just take up the whole first half of the month. But a lot of these things are one-and-done jobs required to make sure the company is set up properly, so I can forgive some minor bureaucratic overhead.

Our immediate next focus as a team is actually traveling to GDC! We've been planning this outing for a while, a lot of our current work has been directed at getting a serviceably playable prototype going for when we're on the convention floor. We've got a bunch of connections both from GDC and otherwise which we're really looking forward to catching up with, and honestly, I think we're both just really excited to meet more cool people. PAX was a rush in that sense. Speaking for myself, as someone who grew up as the only programmer in my age bracket in my hometown, I'll always thoroughly enjoy meeting people who share my interests. So hey, if you're going to be in the San Francisco area during GDC, give us a ring! We might be able to catch up while we're there :)

After GDC, Brian will likely continue working on refining the art direction, so that we can finally get some proper non-Auri assets into the game. One area we've been deeply neglecting for now is the host monitor, which is what we call the screen that gets displayed on the TV when you're playing Jackbox in the living room. We've been ignoring it for now as in all likelihood, if we're demoing in PAX, we won't have a TV or computer screen around. But it does exist, and it's looking pretty barren right now, so it could definitely do with an update.

For myself, I'll be continuing to flesh out the combat system, implementing a lot more of the mechanical complexity that we've prototyped. We're trying very hard to give the game a low skill floor, as we want it to be playable at all ages (and lucidity levels), but we also want the game to have a high skill ceiling, and I think we've come up with some really good systems that meet both of those constraints. I'm excited to talk about that more once we have some of it implemented.

But I don't want to speak too far into the future while everything's still so up in the air! Who knows, maybe we'll get some sort of opportunity at GDC that'll completely change the short-term goals to meet some other sort of demoing opportunity or something. I guess we'll just have to wait and see. For now though, thank you so much for reading through this entire post! We're certainly in the early stages here, but I can tell that there will be good things to come. If you want to keep up with us in the meantime, it would mean a great deal if you'd follow our socials and help us build up a little bit of an online presence so that we can reach more people before our release. Either way though, we'll catch you later.

Join Our Discord!

Effort Games Website
Bluesky
Twitch
YouTube