Episode 11: The Mission Maker

In the last episode I talked about missions; now I’m gonna talk about how they’re made.

A mission is just a JavaScript object, and so I originally just saved them in mission files like mission0.json, which looked something like this:

Of course there would be more rows, but I don’t want to waste space. Also, the entity objects wouldn’t be empty, they’d contain a type, preset, and rotation:

Anyway, in order to test stuff, I was opening the mission files and manually changing stats and entering presets and types. It was annoying. I decided to create a tool that would make mission making easy. Enter the mission maker.

The Interface

The mission maker is a graphical editor accessed through the game menu. It lets you edit all of the aspects of a mission…

Mission Maker 2

And customize the entities…

Mission Maker

Patching the mission maker into the game menu was actually pretty tough.

Entities are loaded in rows and columns, so it makes sense to display them as a two-dimensional array (or grid), but the menu uses a tree structure. I ended up creating a new type of object called a grid that contains a two-dimensional array of nodes…

Allowing the player to navigate the mission maker took a lot of time and some crappy programming, but I eventually got it working. Here were the hardest parts:

  • Rolling over between the first and last rows
  • Determining which nodes to show
  • Rendering the entities
  • Saving and loading a 2D array
  • Empty nodes
  • The waiting

After I’m done editing the mission, I just click the PRINT option, and it spits the text out to the console. Pretty neat.

Sharing

Shortly after conceiving of the mission maker, I realized that I could just leave it in the game and let players make their own missions. I suspect that this is what happens with strategy games like StarCraft and its campaign editor. After all, if you’re going to make an editor, why not let player use it?

So I made the mission maker with players in mind, but I had no idea how I was going to have them share their missions. Here were my options:

  • Print the mission object to the screen and have players copy it to a text file
  • Create links that players send to one another
  • Host a page where players post missions

The third option definitely the best, since it could allow players to discuss, rate, tag, name, categorize, and search for missions. However, it would also be quite a bit of work. My focus was (and is) to finish the game, so I went with the second option.

By incorporating a JavaScript version of PHP’s GET function, I can retrieve text from the URL and pass it into a variable. This means players can load missions by clicking a link, and they can share them just as easily. But there’s a problem…

Encoding

Missions have hundreds of entities, and each entity has a type, preset, and rotation. This means that our mission text can be thousands of characters long! Not only is this annoying, it also can cause problems in some browsers.

To get around this, I developed an encoding system that compresses the mission object into a string of text. It’s super simple.

For the mission stats, it just keeps the first letter of the factions, speed, and size. For the entities, it does the same for the type and preset, then it changes the rotation into a single digit. Then it looks for repeating entities and records the count (empty spaces are recorded as dashes).

So an entity changes from this…

Into this…

I was super proud when I got this to work. But then I had to write a decoder that turns it back into a mission object. Ugh.

Rotation

You may have noticed that I’ve mentioned entity rotation a few times, and I’m finally going to explain it.

An entity’s rotation determines what angle it’s facing and, for vessels, what side of the screen it enters from. For turrets and obstacles, rotation merely spins the entity. Drops can’t be rotated at all.

Note: I did end up changing obstacle rotation so that some of them rotate randomly once they are spawned, so they can’t be rotated in the editor.

Rotation can only be done in increments of 90 degrees, so an enemy vessel can enter the screen from straight on, the left, the right, or from behind. And just as if the entity was entering from above, the vessel’s position in the row determines where on that side of the screen it will spawn.

So, for example, a row of vessels like this…

row1

Will enter like this…

row2

And this kind of row…

row3

Will look like so…

row4

I don’t know if this is the best way to handle rotation, but it’s the only way I could think to do it at the time.

There’s much more I want to do with the mission maker, and there are many decisions to be made. Such as:

  • Where is the mission maker located in the menu?
  • Does the player use their current save in a custom mission?
  • Can players keep reward they collect in a custom mission?
  • What are the default custom mission settings?
  • How do I handle sprite size in the mission maker?
  • Can the player put drops into a mission?
  • Shouldn’t large entities take up more than one space in the mission maker?
  • Won’t large entities overlap larger missions?
  • Should the player be able to customize entities in the mission maker?
  • Could we have entities enter from all sides at the same time?

I’ll probably do another episode on the mission maker if I end up making significant changes to it.

Stay tuned!

Episode 10: Missions

Like items and entities, mission information is stored in a JSON file. This file is called missions.json, and it specifies the mission settings.

Unlike items and entities, missions don’t have presets (at least not yet). They just have a few properties that can be customized using the mission maker.

Stats

Here are the stats of a mission:

  • Entities: the entities
  • Size: number of entities
  • Speed: delay between entities
  • Level: level of entities
  • Ally faction: faction of rewards
  • Enemy faction: faction of entities
  • World: background image

I’ll talk more about how the mission maker works in the next episode. In the meantime, here’s how a mission is launched:

The player selects and activates the menu option that launches a mission…

The mission factory then starts the play state…

The reason that the menu doesn’t directly launch the play state is that we want each factory to be responsible only for its own stuff. If you think about it, the menu factory shouldn’t really be launching missions – it should be asking the mission factory to launch a mission.

After figuring out how to store missions as objects, I ended up storing all of the missions in a single file, but I originally had the mission factory pass the index into the play state so that we could read the JSON file for that specific mission. Here’s how that would work:

From the mission’s init function, we remember the index parameter…

Then  we ask the mission factory to load the mission by index from the preload function…

This would probably be more useful for large numbers of large files, but the missions are pretty small and simple.

Entities

Whatever way we choose to lead the mission, we update the mission factory from the play state’s update function…

The mission factory’s update method will create the mission’s entities, which are read row-by-row…

It may not be pretty, but it works.

Size

The mission’s entities are read row-by-row, like a two-dimensional array or a grid. The mission’s size determines how the width and number of rows. Here are the size presets listed in mission.json:

Speed

The mission’s speed determines the delay between the rows as well as the delay at the start of the mission. Here’s what the presets look like:

I’ve also considered having the mission’s speed determine the speed of scrolling entities as well as the background, but I haven’t decided how to implement that.

Level

The mission’s level just determines the level of the entities. For enemies, this determines the level of their items. For obstacles and drops, it affects the stats directly.

The rest of the mission stats are pretty self-explanatory. The enemy faction, like the level, determines the faction of entities. As it stands, obstacles aren’t affected by faction, but that could change.

Stay tuned for the next episode, when I’ll show you how missions are created using the mission maker!

Episode 8: Items

Let’s take a break from the technical stuff and talk about one of the design aspects of Zyrian: items.

As I mentioned in episode 1, I wanted my game to be inspired by Tyrian, but I also wanted improve on and add to the existing features. One of my favorite things about Tyrian is the item system.

tyrian-shop

Tyrian allows players to shop for items between missions. The player uses money earned from destroying enemies and collecting pickups to buy stuff. The types of items in the game are:

  • Ship: determines the look of the player’s sprite and the amount of life the player has (life doesn’t regenerate)
  • Front Gun: the gun that fires ahead of the player (can be upgraded)
  • Rear Gun: the gun that fires to the side or behind the player (can be upgraded)
  • Shield: protects the player by absorbing damage (shields regenerate)
  • Generator: constantly generates power which is used to fire weapons and such
  • Sidekicks: special weapons that can be used separately from the front and rear guns

There are many kinds of ships, guns, shields, generators, and sidekicks, each with their own cool name, icon, and sprite. These items give the player a reason to kill stuff and collect pickups beyond getting a high score.

Shortcomings

Items are the coolest thing about Tyrian, but there are some problems:

  • It’s often very difficult to tell if one weapon is better than another
  • The same items are always for sale at the same points in the game
  • Once the player has bought the most expensive items, money becomes useless
  • The items do not scale at all during the game
  • Ships, shields and generators only have one stat: capacity
  • The player rarely needs to conserve power
  • Many of the weapons and sidekicks are quite terrible

Changes

I decided that I could fix a lot of these problems by creating randomized items. Each item type (ship, weapon, etc.) would have a number of presets, and the presets would determine the base stats of the item. The item’s stats would then be modified by a number of factors, including its level, rarity and faction (I’ll discuss these things more in future episodes).

Because the weapons were so much more diverse and interesting than the other items in Tyrian, I wanted to make every item in my game interesting. To do this, I added more stats to the other items, and I added engine as a new item type, which would determine the player’s movement speed.

My weapon system ended up being quite a bit different. Instead of choosing a front weapon and a rear weapon, the player has a set of primary weapons and a set of secondary weapons. Both sets are triggered independently and are made up of a number of individual weapons. This adds a huge degree of customization to the weapon system.

I also removed upgrading from the front and rear guns, since the player would be replacing and adding new weapons all the time, I added more weapon stats, and I got rid of sidekicks altogether. To replace sidekicks, I decided to add an accessory-type item called a module, which would give a passive bonus to other items and could also be activated to give an additional temporary boost.

In conclusion, here are the items I ended up with and their stats:

  • Ship
    • Crash damage
    • Hull capacity
    • Primary weapon slots
    • Secondary weapon slots
    • Size
  • Weapon
    • Shield damage
    • Hull damage
    • Rate of fire
    • Projectile speed
    • Projectile size
    • Range
    • Blast radius
    • Efficiency
  • Shield
    • Crash damage
    • Capacity
    • Recharge rate
    • Recharge delay
    • Efficiency
  • Engine
    • Forward acceleration
    • Forward speed
    • Lateral acceleration
    • Lateral speed
    • Efficiency
  • Generator
    • Capacity
    • Recharge rate
  • Module
    • Passive bonus
    • Active bonus
    • Duration
    • Delay

This isn’t exactly how the stats were set up when I first chose them, but it’s more-or-less the same. One significant change I made was letting the ship determine the number of primary and secondary weapon slots. Engines also underwent some redesign, which I’ll discuss another time.

Creating an Item

Once the item factory was complete-ish, I exposed one single function: item. This function lets me get any kind of item from the factory based on the parameters I pass in.

By failing to pass in a parameter, or by passing null or undefined, this will cause function to randomize that parameter. For example, if you don’t ask for a specific type of item, you could get a ship, weapon, shield, engine, generator, or module. Rarity works a little different because its based on the chances each rarity has to drop. I might talk more about rarities another time.

Anyway, now when I need to get an item, I just ask for any kind I like…

Stay tuned for the next episode, when we talk about the entities that use these items.

Episode 6: Factories

So initially I had all my code in one file. This was fine at first, after separating my code into states (see previous episode), I continued to add more and more features, most of which were pretty raw. Eventually my JavaScript file was over 3,000 lines long (which seemed huge to me).

This was about the time that I initially called it quits. My code was a jumbled web of noodles, and it was getting more and more difficult to change or add stuff. I was getting less done each time I sat down and coded, and I was losing direction and drive.

As I mentioned in the introduction, I found motivation to pick Zyrian back up after watching some videos on YouTube about the importance of finishing your software projects. I was inspired. I wanted to accomplish something. I wanted to be proud of something. I wanted to show someone something that I forged with my own 10 fingers and have them say, “oh, that’s kinda neat.”

Anyway, when I came back to the project a few months later, I found my code to be borderline incomprehensible – and I’m the one who wrote it! I was pretty ashamed of myself, so I decided the first thing I was going to do was come up with a better way to organize my code.

After reading a bit online about JavaScript programming patterns, I found something called the module pattern. If you don’t care about programming patterns, skip the boring stuff.

Boring Stuff

JavaScript is a powerful language, but if you have a background in a more tightly-controlled language like Java, you may find JavaScript’s freedom frightening. In JavaScript, all of an object’s properties and behaviors are public, which can lead to errors and poor coding. After all, why write accessors and mutators when you can just access your properties directly?

The module pattern is a way of encapsulating code by defining anonymous functions and immediately executing them. Because everything defined in a function is local in scope, and because all functions in JavaScript are objects, we can create an anonymous function and return only the properties and behaviors we want to expose.

As an example, I have a module that controls sound in its own file called sound.js, and it looks kinda like this (except with more things in it):

This example of a factory returns three functions: initplaySFX, and increaseSFXVolume, and it has a property called SFXVolume which it uses internally to determine loudness. At this point we’ve successfully created an object that only exposes the functions we want it to, but things really get interesting when we start tying multiple modules together…

By passing our sound factory as an argument into the projectile factory, we are then able to expose only the init and playSFX functions. Ta-da!

Side note: I know Phaser has some built-in support for things called “plugins”, but I never got the hang of it. Perhaps I’ll investigate more in the future.

Interesting Stuff

I put all my game code in a variable called GameSystem so it wouldn’t interfere with other scripts or libraries. I could have called it Zyrian, but I wasn’t sure I would be sticking with the name (and I’m still not sure). So from now on when you see GameSystem.yadaYada, that’s just referencing some part of my game’s code.

Anyway, I now had a strategy for fixing my problem, so I painstakingly traversed each line of code and transmuted them all into different modules, which I called factories. Here are the factories I ended up with:

  • collisions.js
  • controls.js
  • entities.js
  • helpers.js
  • init.js
  • items.js
  • load.js
  • menu.js
  • nodes.js
  • npcs.js
  • missions.js
  • projectiles.js
  • sound.js
  • storage.js

Some of these were created right away, and some of them spawned from stuff I added later on. You may be able to figure out what they do just by the name, but I’ll explain most of them in future episodes.

Yay better code!

Episode 5: States

I never realized this before working on this project, but there’s more to a game than just the part where you move your character around and shoot stuff. What I mean is that interacting with a game means traversing a number of different modes, menus, and interfaces. Let’s use Rare’s legendary first-person shooter, GoldenEye, as an example. Here’s how a player gets from powering on the system to completing a mission:

  • A number of logo images are shown
  • An animation is played (along with music)
  • The main menu is shown
  • The mission selection menu is shown
  • The mission is loaded and gameplay begins
  • The mission completion menu is shown
  • The main menu is shown

As you can see, the experience of playing GoldenEye is comprised of much more than just the gameplay. And although the gameplay is by far the most complex and important component, the rest of the game is certainly worthy of attention.

All this is to say I realized that I was going to have to create these different components and that I should probably keep them separate. It turns out that Phaser has a system for doing just that, and it calls these components states.

What Are States?

States are cool. In addition to separating the different phases of the game, states allow you to load stuff when it’s needed. Players generally don’t like waiting for their games to load, and states let you be strategic about when and where you load assets.

For example, the menu probably doesn’t need all of the sprites and sounds that are used during gameplay, so you can avoid loading them until you actually launch the gameplay state. However, you don’t want to start loading everything only after the player decides to start the game, so it would probably be smart to start preloading assets in advance. The strategy can be tricky, but the code is pretty straightforward.

States can be quickly and easily created…

And starting them is a breeze…

Phaser’s states come with some functions that will automatically be called at various stages of the game. These include init, preload, create, render, and update. If you define these functions in the state, then Phaser will execute the code at the appropriate time.

We saw this in Episode 3 when we used the preload function to load an image asset…

The create function to enable the keyboard…

And the update function to check for input…

So if we were to start whatever state these functions belong to, the preload and create functions would run as the state started, and the update function would be repeatedly called during the game loop until we started another state. Neat!

My States

I decided to use four states in Zyrian:

  1. Boot: initializes the Phaser engine, creates the game object, and launches the Preload state
  2. Preload: loads game settings, fonts, and all the assets for the Menu state, then launches the Menu state
  3. Menu: loads the menu interface, captures user input, loads all the assets for the Play state, and allows the player to launch the Play state
  4. Play: loads mission data, creates sprites, captures user input, and launches the Menu state if the player aborts or completes the mission

I initially thought of using a fifth state to handle the end of a mission (indicate success or failure, display the player’s score, give some menu options, etc.), but I decided that to just use the Menu state.

In the next episode I’ll talk about factories and how I separated the internal workings of the game from the states.

Episode 2: The Framework

In this post I’m going to talk bit about how and why I chose my programming language, IDE, and framework.

JavaScript

When I started this project, I was familiar with a number of languages including Java, C++, and PHP, but I had recently spent a lot of time using JavaScript for some web stuff, so I was kind of in the JavaScript zone. In addition, I really liked the idea that I could just upload the game to my website and let people play it in a browser, regardless of platform. I also love the fact that rebuilding my project means saving a text file and refreshing the browser. The console is also pretty awesome for debugging.

For these reasons I chose to use JavaScript as my programming language.

Sublime Text

I’m going to say something controversial right now. I use Windows. I’m sorry, and I regret it every time I talk to other programmers. I know I should have a MacBook Pro and be using the Linux terminal for everything, but I’ve always owned a PC with Windows, and I never used the Linux terminal until university.

Anyway, I had used Nodepad++ and other text editors in the past, but a friend had recently told me to check out Sublime Text, so I did, and I liked it. Sublime Text lets you open multiple files at once, save projects, search and replace in multiple files, customize colors and highlighting, and much much more!

Phaser

As I mentioned in the previous post, I had never used a game engine before, so I really had no idea what I was looking for. I basically Googled “JavaScript game engines” and quickly chose one that had good examples and documentation.

Having only used Phaser, I can’t really speak about its strengths or weaknesses. However, it seems easy to use, especially for 2D sprite-based games like Zyrian. I’ll talk more about Phaser in future posts, including examples and everything.

Episode 1: The Idea

In future episodes, I’ll be breaking down individual components, mechanics, features, techniques, and lessons, but now I’m going to talk about the reasons and ideas behind Zyrian. But before I do, let me give you a better picture of where I was at heading into this thing.

I began programming casually in my early teens after stumbling upon an old book on QuickBASIC. Before returning to university in 2014, I had a decent grasp of simple programming concepts like variables, conditionals, and loops, but I knew nothing of software design, algorithm analysis, and object-oriented programming. I had dabbled with Visual Basic, but I still only knew one language.

After a year and a half of both classroom and self-directed learning, I knew a lot more about programming. However, I still had no knowledge of game design. I didn’t even know what a game loop was. The only “games” that I’d made were either text-based or point-and-click and were borderline unplayable.

Like many amateur game programmers, I had previously confused making a game with making a game engine. I couldn’t help it – I really wanted to know how things worked. But after listening to tutorial after tutorial tell me to use an existing game engine, I decided to give it a try. After little to no research, I chose Phaser – an open source JavaScript framework.

Okay, now back to the reasons and ideas behind Zyrian.

The Why

I don’t know if I ever explicitly contemplated the reasons for making this game, but if I had, they would have been something like this:

  • Learn to use a game library
  • Improve on some of Tyrian’s features
  • Make a game that people might actually play
  • Finish something

After numerous half-butted attempts at creating games over the years, this one was different. I had some education behind me, I had a plan, and I was motivated to make something I would be proud of.

Now I’ll talk about some of the main ideas I had about the game I wanted to make.

Features to Keep

There’s a lot of cool stuff in Tyrian. In addition to the beautiful graphics, interesting content, and a neat power consumption mechanism mentioned in the introduction, Tyrian also has engaging music, satisfying sound effects, a simple and effective menu, front and rear weapons, shields, sidekicks, and alternate game modes (including two-player).

I didn’t want to include every feature. After all, some of them seemed pretty advanced for a newbie. I also didn’t want to make my game too similar to the original. Here are the features that I decided were important to keep:

  • Two sets of weapons
  • Power consumption mechanism
  • Shields and crash damage
  • Items, money, and shopping

Numbers & Stats

As a fan of role-playing games, I love stats. I love equipment, leveling, talents, and skills. And so one of my ideas was to bring RPG elements into the scrolling shooter genre, like how Borderlands brought it to the first-person shooter.

Although Tyrian has some RPG-like features, it gives only vague indications about stats and numbers, so it’s extremely difficult to determine whether one item is superior to another. This is mostly true of the weapons, which are by far the coolest and most important items in the game. I believed that incorporating more RPG elements would add depth to my game.

Randomization

Another feature often associated with RPGs is randomization, and I wanted to use it in the game. The main areas that I thought would benefit from randomization were the items, enemies, and missions. This would make the gameplay experience a lot more diverse, which would increase the replay value. I also thought that it might be easier to create a random mission generator than to create dozens of missions.

Item Balancing

In addition to randomizing the items, I also wanted to balance them.

If you’ve ever played Tyrian, you probably know that you should begin the game by upgrading the Pulse-Cannon (which you start with) and getting the Sonic Wave. These weapons aren’t just great for the first mission, they’re great throughout the entire game.

This really sucks, because the game has a ton of other cool weapons, but almost all of them are worse than the Pulse-Cannon and Sonic Wave, and many of them are just terrible.

Economy

Another issue that becomes clear after playing the game for a while is the diminishing value of money.

Early in the game, you’re careful to kill every enemy and pick up every coin in order to gain as much money as possible. And this has a big impact on the game, because it means you can upgrade your weapons and buy other cool stuff.

But once you’ve maxed your weapons and bought the best ship, shield, generator, and sidekicks, there isn’t any reason to get more money. And this makes the game noticeably less fun. Many other games are guilty of this as well, including award-winning modern titles.

I wanted to make sure that the player always wanted to get more money. I thought that randomization, levels, and scaling would help.

Factions

One design idea I had was to introduce factions to the game. Factions would determine the appearance and stats of items, have their own reputation or currency, and also make the story a little more interesting. I decided on five factions:

  • The corrupt empire
  • The angry rebels
  • The peaceful pagans
  • The neutral traders
  • The marauding warriors

I didn’t know what to call them, so I just used some placeholder names of Empire, Revolt, Preserver, Freelancer, and Eclipse.

Mission Maker

I also thought it would be cool to let players design their own levels. I had no idea how it was going to work, but I thought I’d try to make a graphical mission maker and incorporate it into the game somehow.

This post may make it seem like I had everything planned out and knew what I was doing, but all I had was a huge list of ideas and no idea how to implement anything. These were just the core ideas I knew I wanted to have in the game.

Stay tuned for more!

Introduction: Cloning a Classic

Tyrian is a top-down scrolling shooter released in the mid 90s, and it’s one of my favorite games.

It was developed by Epic MegaGames, which produced memorable titles like Jazz Jackrabbit, One Must Fall: 2097, and Solar Winds. Tyrian is beautiful and polished, filled with interesting and diverse enemies, worlds, and weaponry. It also features an interesting mana mechanic that uses generators and power consumption.

into-gameplay

Having grown up playing video games as a kid in the 90s, it’s hard to separate the appreciation for a well-crafted game from nostalgia, but if you’ve never experienced the wonder of DOS games, I highly recommend installing DOSBox and heading over to Abandonia.

I could go on about how much I love Tyrian, and I will in future posts, but the point here isn’t simply to praise the original game, but rather to document the creation of a new game – my game.

Before I talk about this new game, you should probably know that I’m an amateur programmer who enjoys thinking and talking about games more than actually playing them (and I enjoy playing them very much). Rather than tell you my life story, here are some of my stats:

  • Born and raised near Vancouver, BC
  • Can eat the same thing every day
  • Diploma in Computer Information Systems
  • Married with a cat and no kids
  • Terrible at remembering dates
  • Awesome and remembering movie and TV quotes
  • Fisherman and fan of mixed martial arts

Now that we’re close friends, let’s talk about my game.

About a year ago I began writing down my game ideas in a text file. After accumulating over one hundred pages, I finally began to bring one of the ideas to life, and thus Zyrian was born.

game-ideas

That’s right, I called it Zyrian. I chose this name because I wasted a lot of time trying to think of an awesome name, but I couldn’t.

I’ve started many programming projects over the years, and like many amateurs, I finished very few of them. Also like many amateur programmers, I tend to spend more time thinking of cool new features to add rather than working on existing ones. And after working Zyrian for about a month, I dropped the project to pursue other interests.

After watching some presentations on the importance of finishing projects and developing a portfolio, I decided to force myself to finish Zyrian. So 6 months later, I picked up the pieces.

On a side note, it becomes clear just how bad your code is when you have to dive back into an old project.

It’s now 5 months later, and I’m still plugging away at the game. I’m not sure how close I am to being finished (probably because I’ve never done something like this before), but I’ve definitely come a long way.

This is this the story of the making of Zyrian – a Tyrian clone made by an amateur programmer who’s never published a game. I’ve learned a lot so far, and I hope I can pass on some of that knowledge to you.