Pixels and Tactics: Building a 2D RPG in the browser
Continuing with my tradition of belatedly writing blog posts after talks, I'm super excited to be reviving my blog with a post about a game I'm working on.
As most of my friends already know, I love games (of both the board and video variety). I've wanted to write a game for a really long time and have actually started a few text-based RPGs over the years, but I've never gone deep into any particular one. Around a year ago, me and my friend James decided we wanted to try again, and thus our game and this talk were born!
I gave this talk last year at a meetup called WaffleJS where you listen to JS talks and eat waffles (highly recommend; it's pretty great). Enjoy!
I really like (J-) RPGs.
My favorite games are old-school Japanese RPGs on GBA / SNES like Golden Sun, Tales of Phantasia, Chrono Cross/Trigger, Fire Emblem, etc. Anyone else?
We spent hours doing, uh, "competitive research", which distracted us at times but gave us tons of ideas for battle mechanics, crafting and refining systems, and menu aesthetics that we knew we'd want in our game. Whatever you end up doing, you should have a pretty clear idea of what you want to build. Play games or look at screenshots / videos for inspiration!
Our game
Text-first
We knew our game was going to end up being fairly complex: we got overly excited and chose to go with a full tactics RPG for our first game ever (talk about scope creep). Given the number of features we needed to build, we thought it'd be nice to build and test our logic before getting drawn into the time-sucking world of pixel art, so we started building a text-based game first.
In hindsight, this was a great strategy: we were able to decouple the aesthetics, for now, and focus on the actual gameplay and battle mechanics we needed. It's the equivalent of building an MVP and testing out a product hypothesis — assets end up being a huge time sink, however fun and exciting they may be to look at initially.
Code-wise this meant separating our views from the logic as much as possible.
This is a pretty standard practice nowadays in most frameworks, but I didn't
fully appreciate it until it came time to swap out the text frontend
(console.log
s) for an actual graphics engine. (We still have our "CLI" files in our repo, for when we want to test something out quickly without the graphical interface!)
If you're into text-based games you can stop here, and there are a lot of small polishes you can do to make your game delightful. Here are a few of our early screenshots! (Yes, those are command line progress bars repurposed as HP bars. I also went a little crazy with custom terminal colors.)
2D onward!
I looked around at several different browser game engines and settled on CraftyJS (more on this in the next section). Coupled with a graphics pack, we were able to start building out our game look and feel:
This is the current stage we're at and there's lots to do in terms of defining the storyline, mechanics, building out the menu and battle interfaces, and so on. It's really fun. (:
We're working toward the first "release" of our game, so if you're interested in following along with the progress, you can sign up to be notified. (I'll also post any updates, along with any new posts here and on Twitter.)
What even goes into a game?
This was my first time building anything like this! We had to learn all of the fundamental bits ("how are tilesets formed") and dug up a ton of resources that we found really useful and would love to share.
At the highest level: what goes into a game, or at least a game like ours? The main areas are the framework, assets, and your actual game mechanics.
Framework
First, you need something to actually write your game in. Think of this as the skeleton that supports your assets and game logic. It also provides handy standard functions for you (e.g. rendering graphics, collision detection, event handling).
If you care most about the end result, you might want to consider using a fully featured game engine like Unity or Unreal Engine (these support cross-platform compilation and have more of a WYSIWIG / GUI interface for game development; they're used for many professional games), or even something like RPGMaker which is software specifically for creating RPGs.
I was personally most interested in the game development (hopefully you are too if you are reading this post!), and wanted more of the ability to learn how to architect a game and string all of the pieces together myself first. We were also looking for a JS/HTML5 framework because we wanted to build in the browser given the ease of distribution and ability to show our friends.
I personally liked Crafty both because of the framework itself but also because it's being actively developed on, including third-party extensions. It felt like there was a good balance between existing standard functions and customizability: we ended up writing all of the interaction logic, menu displays, and so on, but it was easy to take advantage of the primitives that already existed.
With Crafty, the way you write your game might look something like this:
// I've included a working demo / code at the end of this post! (:
// Load assets
Crafty.sprite(32, 32, "assets/player.png", {
player: [0, 0] // specify size & index of image sprite
});
// Write some custom components
Crafty.c("PlayerControl", {
PlayerControl: function() {
this.bind("KeyDown", function(e) {
this.resetWalking();
if (e.keyCode === Keys.RIGHT) this.moveRight();
if (e.keyCode === Keys.LEFT) this.moveLeft();
if (e.keyCode === Keys.UP) this.moveUp();
if (e.keyCode === Keys.DOWN) this.moveDown();
// Player-specific commands
if (e.keyCode === Keys.SELECT) {
interactableObjects.trigger("interact");
}
})
})
// Set and load the first scene
Crafty.scene("start", function() {
// Set map tiles, populate enemies, etc
// ...
// Create player entity and properties
var player = Crafty.e("2D, DOM, PlayerControl, player")
.attr({currentMap: "start"})
.PlayerControl() // custom component to handle keyboard control commands
.Collision(Crafty.polygon(points)) // automatically handle collisions
.reel("walk_left", 600, 0, 1, 4) // set animation speed & sprite frame indexes
.reel("walk_right", 600, 0, 2, 4)
.reel("walk_up", 600, 0, 3, 4)
.reel("walk_down", 600, 0, 0, 4)
});
We use the component system (e.g. PlayerControl
) extensively as a design
pattern. Components are extremely composable so we use them to represent logic
for everything from menu UI to how sprites walk around. This topic by itself is enough to fill several blog posts — stay tuned!
Assets
Assets are the other large and obvious (because they're what you see) part of game development.
The first thing I learned was that assets are hard, particularly if you're not an artist or composer yourself. They're really important because they represent the look and feel of your game and very often are what players will initially judge your game by, but you can end up spending a lot of time and money here.
This is admittedly another infinite bucket (welcome to gamedev!). I can really only speak to 2D graphics here, but the main things I've worked with so far are sprites and tilesets.
Sprites and tilesets are probably best explained with a game we're all familiar with. Take Zelda, for example:
Tilesets are repeatable assets which compose what you typically think of as the "background": grass, trees, flowers, houses, and so on. You often use special software (like Tiled, a map editor for Mac) to "draw" the map with tilesets or else it's impossible to manage.
Sprites are more of "foreground" objects: players themselves, monsters, items, etc. They're also very often animated, which adds additional complexity: you want your character to look like it's walking, talking, attacking, casting spells, leveling up, whatever.
If you're not an amazing pixel / 3D artist yourself (I am not!), there are a ton of really great resources out there — from open source to marketplaces and commissions.
Here are a few of my favorites:
- Open Game Art: Totally free and open tilesets, sprite, music, you name it. The descriptions will usually tell you if they can be used for commercial purposes or not; most can be.
- Kenney: A gaming studio that made a ton of their high-quality assets free for use by the public. Our tileset actually came from here — see if you can spot it!
- Game Dev Market: Lots of nice, high-quality asset packs available for purchase. They're not too expensive, though it is pretty tempting to purchase many of them!
- RMN Music Pack: Large, free selection of great background / battle music (mostly RPG-sounding).
- as3sfxr: Make your own sound effects (particularly good for things like beeps, lasers, etc) and export them.
You can also find a fair number of independent artists by Googling or looking at DeviantArt. Here's one I drooled over for quite some time and hope to be able to use sometime in the future.
Happy hunting!
Game logic and data
Finally, there's the actual lifeblood of your game: the style of game you're building, and the resulting logic, mechanics, and data.
This section is pretty much as complex as you want it to be. Something like Pong is relatively simple, whereas a full-fledged tactics RPG (sigh) is going to require significantly more work both in terms of brainstorming and implementation.
Our game started off very Pokemon-esque (you can tell what generation we grew up in...) and it evolved more into a classic J-RPG. As we worked, we ended up pulling bits from other games we've played such as crafting, taming companions, weapon mastery, and so on.
For most games, there are a few main areas you'll need to consider:
Player
Every game has some sense of the "player" and the more complex you get the more state this player will need to contain. In our game we had a notion of a level, HP / MP, intrinsic stats and stat growths, skill trees, and inventory.
World
What does the map or setting for your game look like? If you have monsters that spawn, do they spawn randomly and how do they walk around? Many RPGs follow the pattern of having the map you're currently on (whether it be a town, cave, or forest) and the "world map" where you can travel between maps.
Depending on your game you may have in-game characters or objects you can interact with or stores that your character can buy equipment from.
Mechanics
Are you building a platformer? Puzzle game? Shooter? How do battles work, how do interact with other characters, and how do you use consumable items? Is there a skill / spell system? How do you win the game? Is it real-time?
Another thing think to keep in mind is if your game feel balanced: is it too hard or easy, does the progression feel right? You'll likely need some set of data files to contain all of this information. We have spreadsheets for each type of item, monster, and spell complete with their properties, and our set of algorithms for things like calculating how much damage is dealt or how to randomly roll the loot you collect.
This part is a lot of fun and where some of the best games are most creative. You can also do hybrids of different mechanics you see! For example, I once played a game that was half RTS (real-time strategy, like Starcraft or Warcraft) and half FPS (first person shooter, like Halo).
When you're building a game, it's important to keep playing it yourself! Trust your instincts; when something doesn't feel fun, you should tweak it. We're building an "endless dungeon"-style of game first (no plotline, just battling monsters), which will give us a test arena for development going forward and can also act as our first release. There won't be a story, but we'll get to test out how the game progression feels: are the skills we pick exciting, does the leveling curve flatten out at some point, are the bosses impossibly hard?
Try it yourself
I found it hard to find any actual up-to-date Crafty tutorials / examples when I was starting out, so I made one that you can fork and start playing around with that covers some basic mechanics hooked up with some of our assets. Let me know if it's useful or if you run into any issues!
Game development is infinite
There are many areas I can sense on the horizon, but don't know much about yet: from AI to networking in a multi-player game.
This is something I find fascinating about game development — you can go as infinitely deep as you want. You can code a text-based game, then expand into the world of 2D graphics, then explore 3D. As if that wasn't enough, there's optimizations (on the graphics layer but also in the game itself), AI (for anything more complicated than A* / simple heuristic rules), realistic map generation, and networking. In the not-so-distant future, we'll also have virtual reality and augmented reality.
There's so much surface area I'm excited to learn about and I'll continue to write about my adventures here. (If you are too, holler! I'd love to chat and trade notes.)