Archive
Zero to One Hundred Thousand Tests
When I started at StrongDM five years ago (woah), we had zero automated tests. Last year we had 50,000 tests. Today, around 70% of our code is covered by over 100,000 tests, most of which run on every pull request.
What follows is my personal opinion about what constitutes a “good” automated test based on my observation of this colossal increase in test coverage. The goal is not to convince you I’m right, but to draw some contrasts and provoke you to question assumptions and form your own opinions.
Catch Your Dream
When I was young, my dad had a Power Macintosh 6500 and a copy of a game called MechWarrior 2: 31st Century Combat. By my estimation, it was not very good. It was slow and boring and I mostly got confused and died.
However.
It had the absolute coolest intro cinematic of all time. It still gives me goosebumps.
After the intro and a minute or two of listening to the 12X CD-ROM drive spin, I had to face the menus. If I was lucky (what’s a “campaign”?), I would eventually blunder my way into the actual game and then the real frustration began. Nuclear submarines have more intuitive controls.
The start of a game development journal
I am starting a journal for my game development work because I spend a lot of development time thinking and staring into space, and those thoughts don’t always make it into the game. I need an outlet to direct those thoughts and hopefully make them more useful. The project I am working on is also personal and necessarily relates to my feelings about life and art and God, and I need a place to write those things down too. I may publish some of these entries on my blog.
The Identity Problem
Disclaimer: views expressed are my own and are not endorsed by my employer.
It’s a famous joke that naming things is one of the hardest problems in computer science. I think this alludes to a fundamental truth behind so many of the problems I encounter every day as a software engineer. Let me ruin the joke and reword it a bit.
The hardest problem in computer science is deciding whether two things are the same thing, or different. I don’t know if there’s already a name for this concept, but I’ll just call it the “identity problem”.
Waiting on Tests
Disclaimer: views expressed are my own and are not endorsed by my employer.
In 2019 we had roughly zero automated tests at StrongDM. We did manual quality assurance testing on every release. Today we have 56,343 tests.
Anecdotally, the rate of bugs and failures has not decreased by a commensurate amount. Instead I think it correlates with focused efforts we’ve made at various times to either ship big new features (resulting in many unforeseen bugs), or stabilize existing features (resulting in fewer bugs).
Making Games
In March 2018, I had been a full-time indie game developer for four years. My heroes were Jonathan Blow, Lucas Pope, and Robyn and Rand Miller. I had 2,500 Twitter followers, an ambitious title under my belt with thousands of sales, and a free office in a hip coworking space near downtown Columbus, generously provided by some friends at a local game studio. I distinctly remember wondering why anyone would want to be something other than an indie game developer. I joked that I had a “disease” that compelled me to make games (my dad once told me that what people joke about speaks volumes). One month later, I was living in Los Angeles, working as a software engineer, and realizing I had just burned out of the game industry.
There and Back Again: GraphQL at strongDM
This post originally appeared on the strongDM engineering blog.
Once upon a time, strongDM had no dedicated frontend engineers. We backend engineers dipped our toes in the React frontend as infrequently as possible. It relied on dusty, bespoke, private REST endpoints that returned schema-less JSON blobs. We let these languish while we built a shiny new public API with code-generated SDKs in five languages. Occasionally I was forced to write a new private endpoint for the frontend. I did so with shame, dreaming of a future when the whole frontend would only talk to the public API. Then one day, we hired a frontend engineer, and everything changed.
How to Exfiltrate Code from Bitbucket
Every year or so, something compels me to start over with a fresh OS image. Most recently, that something was an unfortunate water bottle incident. Once again, I need to pull down my digital life from the internet.
The code and assets for this blog currently live in a 500 MB Git repository, which was hosted on Bitbucket until earlier today. Let's try cloning it!
evantodd@HW-0063 ~ % git clone git@bitbucket.org:etodd/etodd.io.git
Cloning into 'etodd.io'...
remote: Enumerating objects: 2237, done.
remote: Counting objects: 100% (2237/2237), done.
remote: Compressing objects: 99% (1885/1903)
# hang
No worries, we can clone over HTTPS!
The Poor Man's Netcode
The more you know about a given topic, the more you realize that no one knows anything.
For some reason (why God, why?) my topic of choice is game development. Everyone in that field agrees: don't add networked multiplayer to an existing game, you drunken clown.
Well, I did it anyway because I hate myself. Somehow it turned out great. None of us know anything.
Problem #1: assets
My first question was: how do I tell a client to use such-and-such mesh to render an object? Serialize the whole mesh? Nah, they already have it on disk. Send its filename? Nah, that's inefficient and insecure. Okay, just a string identifier then?
The Poor Man's 3D Camera
Each of us have our own giants to face. This is a story about one of my giants. Something I never imagined could make a grown man cry, until it did.
A 3D camera.
No one can face your giants for you. This is a story, not a walkthrough. Expect no useful information. For that I recommend 50 Game Camera Mistakes by thatgamecompany's John Nesky. His job title is literally "camera designer".
Thirteen Years of Bad Game Code
Alone on a Friday night, in need of some inspiration, you decide to relive some of your past programming conquests.
The old archive hard drive slowly spins up, and the source code of the glory days scrolls by...
Oh no. This is not at all what you expected. Were things really this bad? Why did no one tell you? Why were you like this? Is it even possible to have that many gotos in a single function? You quickly close the project. For a brief second, you consider deleting it and scrubbing the hard drive.
The Poor Man's Voice Acting
Allow me to regale you with an exciting tale: the birth of a janky dialogue and voice system.
I have a JSON file with all the localized strings in my game, like this:
{
"danger": "Danger",
"level": "Level %d",
...
}
A preprocessor takes this and generates a header file with integer constants for each string, like this:
namespace strings
{
const int danger = 0;
const int level = 1;
// ...
}
At runtime, it loads the JSON file and hooks up the integer IDs to localized strings. A function called "_" takes an integer ID and returns the corresponding localized string. I use it like this:
The Poor Man's Threading Architecture
The game industry hit Peak Advice Blog a while ago. Every day I read
skim ten articles telling me how to live.
Fear not! I would never give you useful advice. This series is about me writing bad code and you laughing at my pain.
First Contact
Say you have some voxels which occasionally get modified. You regenerate their geometry like so:
voxel.Regenerate();
Because you are a masochist, you want to do this on a separate thread.
Ludum Dare 34 Postmortem
Friday 21:15
Fifteen minutes after the theme announcement, my friend Ben Homan walks through my front door. Not really my front door, I'm just a subletter. But this is a first. Normally he ignores our instructions to walk in without knocking. The first time, he texted me from the driveway.
21:30
Jesse Kooner walks in, also unannounced, bearing frozen pizza. Before he can even kick his shoes off, I loudly explain the theme: a never-before-seen tie between "growing" and "two-button controls".
One Weird Trick to Write Better Code
Developers hate him!
We'll cover some standard tips and tricks here, but we're not really interested in those. We're looking for the One Weird Trick to rule them all. Hopefully each trick we encounter brings us closer to coding Mecca.
In the beginning
The first video game I ever wrote was called Ninja Wars.
Yes, that is an HTML table of images. I changed the src attribute to move stuff around.
The Poor Man's Postmortem - Lemma
The big secret of our industry is, we don't actually enjoy making games. We slave away in obscurity for years in anticipation of one glorious day.
Not release day, no. The day we can finally write a postmortem full of pretentious anecdotes, bad jokes, and unsolicited advice.
Well I just finished a game, and doggone it, I am going to exercise my inalienable rights as a developer.Things to do when making a game
Ancient gamedev postmortem traditions mandate that this section be titled "what went right". Unfortunately, the game was so shockingly good and so many things went right that a full overview would stretch on endlessly.
The Poor Man's Character Controller
Let's say that, like so many of us, you want to make a surreal voxel-based first-person parkour game. You're trying to figure out a production schedule. What will take the longest? Graphics? Sound? Level design? I bet it will be the character controller. And I bet it will take 4½ years. Why?
- In running/jumping games, player movement is paramount. It takes forever to nail the right feeling.
- Each game is a unique snowflake. You will not find an article explaining how to design the controls for your specific game. You're flying blind.
That said, each game offers a few transferrable bits of wisdom. Here's my story.
Screenshot Saturday 213
It's the end of February and this game is supposed to be content-complete. In a sense, it actually is. All the levels are done. Twenty in all. I thought this month would never end!
Just so you know, there are sixty of those lights and I had to hook up each one individually. It fell just barely beneath the "worth it to automate" threshold.
Don't look too closely at this next one, it's a bit spoilery.
The Poor Man's Voxel Engine
This is not a tutorial. It's a story. A Voxel Odyssey.
The story starts with 19 year old me in a dorm room next to the Ohio State stadium. I don't have the repo from this stage of development (SVN at the time), but I remember the process clearly.
XNA 4 comes out in September 2010. I immediately dive in. This turns out to be a poor life decision.
Screenshot Saturday 211
Last Saturday we had the Short North gallery hop. Hundreds of people came through our gallery to see art. The guys helped me set up the Oculus and a projector on the wall.
Sometimes I had to go out and pull people in, but most of the time, there was a line. My favorite customer by far was this kid:
He jumped right in and played like a pro. The mother (recording video) was super supportive and excited.
Screenshot Saturday 210
I finished last week's map. It has some spinny things.
Then I made this week's map.
Who knew purple and green could look so... not terrible?
Anyway, this puts me ahead of schedule. There are three levels remaining. My goal is to for the game to be playable from start to finish by the end of February. It's ambitious, but I'm confident I can do it!
Screenshot Saturday 209
This week was crazy productive. I finished last week's level, finished another level, which looks like this:
...which also included some story-related writing and scripting, and actually started working on NEXT week's level, which looks like this:
I seem to be on a purple streak lately. Actually, purple may rise unintentionally to be the most prominent color in the game. Also, this last level is apparently a subconscious ode to Monument Valley.
Screenshot Saturday 208
This week's level is not quite done yet, but I have an excuse! Power was out at the incubator for two days, and the internet didn't come up fully until just yesterday.
Still, the level should be done some time this weekend and is already looking pretty good.
I finalized the promotional graphics and published the game to Steam in "coming soon" mode. I'm incredibly grateful to Sam Gebhardt for contributing his Hollywood artistic talent!
Achilles
This past weekend I participated in the CivicHacks "Game Jam for Good". The goal was to raise awareness of the global water crisis and ultimately promote PackH2O, a Columbus-based startup that designs water backpacks for developing water-stressed regions.
The jam lasted 48 hours. My entry is called "Achilles".
Achilles is a multiplayer text-based simulation. You the player must manage a village in a third-world country experiencing a water crisis. You can play it here (bit.ly/waterjamachilles) assuming I haven't stopped paying for the cloud server.
Screenshot Saturday 207
Records continue to be broken. This week's map was actually done on Wednesday!
Although most of Lemma is a strange hybrid of natural and alien-looking architecture, my design calls for a few "industrial / man-made" themed maps. For story reasons, and also because I just want to parkour through a skyscraper.
So on Monday I asked Twitter this question:
Would people be upset if I do a few levels in the visual style of Mirror's Edge? Would that be tribute or rip-off?
Screenshot Saturday 206
I moved my office into an incubator / art gallery this week.
The move is mostly for my own sanity. Turns out, working alone in your apartment for 9 months isn't the most fun in the world. It's a Herculean effort just to stay motivated. I also lost all semblance of a disciplined sleep schedule.
Productivity has been great since the move, and I'm back on a normal sleep schedule. Having people around is great, even if I mostly tune them out to focus on work (sorry guys).
Screenshot Saturday 205
For the first time in the history of Lemma, I'm actually keeping up with my self-assigned pace of one new level per week.
These past two weeks I made two more frost levels. The plan calls for one more frost level, then it's on to the other two biomes.
Both of these levels have interesting quirks and unique features. They're probably too tough right now, but I'm scheduling plenty of time to playtest and sand down the sharp edges.
Screenshot Saturday 203
Big update this week!
My voxel renderer now has the capability to overlay everything with any texture I want. I'm using it on a new set of interconnected winter levels. This way I don't have to manually come up with a frosty version of each texture.
Without giving away too much, this week I built a new system that has implications for both puzzle solving and movement mechanics.
Screenshot Saturday 202
I've come to several realizations this week.
- Lemma is going to be good, but not great. I have to accept my limitations and finish the thing to the best of my ability.
- Lemma is more of an experience than a traditional video game.
With these two ideas in mind, I am focusing the next few months on making Lemma the least frustrating, most enjoyable experience I can.
So I'm trying to come up with puzzles that seem difficult but are actually simple to solve. The wonderful Monument Valley did a great job of this.
New blog, new app, new screenshots
Lots of stuff going on this week.
New dev blog
First off, my website got a much-needed overhaul. The horrible slowness of Wordpress.com was driving me nuts, so I switched to a custom-built site.
I used Jekyll, which is a static site generator. It spits out a bunch of HTML files which you can upload to a server, as opposed to Wordpress, which generates fresh HTML every time someone loads your page.
Advantages:
Screenshot Saturday 199
"Level design for days" has been my motto for several months now, and this week is no different.
Behold, new challenge levels! These are timed, bite-sized maps with simple goals that can be completed in under a minute. They're the kind of things you can create in the level editor and share on Steam.
I need to find a new texture for that garish green material.
Lots of other things are happening, but they're more like a million tiny updates rather than a few conveniently screenshot-worthy ones. So that's it for this week! Thanks for reading.
grepr - 7DFPS 2014
I survived 7DFPS, barely. Here are some fascinating statistics:
- Days to create an FPS: 7
- Hours spent: 93
- Levels built: 5
- Lines of code written: 2313
- Hours to spare before deadline: 2
- Functioning brain cells remaining: approximately 4
I'm happy with the result, though. Jack did a great job on the audio as usual, although at the last minute I had to throw in some clunky placeholder sfxr sounds. Blame me for those! Maybe we'll replace them later.
7dfps work in progress
I'm participating in 7dfps this year, which means I'm making an FPS game in 7 days. Here's what I've got so far:
In Soviet Russia, you are bullet.
In my 7dfps entry, moving and shooting are the same thing.
Here's my favorite form of humor: physics glitches.
Here's me getting killed:
Screenshot Saturday 196
This past weekend I exhibited Lemma at the Ohio Game Dev Expo. It was an awesome time. Extra Life raised over $9,000 for charity (yes, it is in fact over 9000).
The Oculus Rift was a huge hit!
I worked on various improvements right up to the expo. First, some new textures for moving platforms and doors:
This is the first texture I've created that has any kind of directional meaning. The reason is that until this week, I had no control over how the textures mapped to the voxels. It was all procedural. So if I put an arrow graphic in a texture, there was no guarantee which way it would face.
Screenshot Saturday 194
Just a quick update this week to confirm that I am in fact alive. The iOS contract game is just about done. I'm pretty happy with it.
Now it's back to work on Lemma:
I'll be running a booth, speaking, and participating in a panel at the Ohio Game Dev Expo next weekend! Come on out and hang with us!
Shaders: How Do They Work?
Yesterday I gave a talk at Dev Workshop Conf introducing the basic concepts of vertex and fragment shaders. Unfortunately I don't have a video, just this one potato picture:
It's probably for the best, because Chrome locked up on me halfway through. The slide deck is pretty cool though. It includes over 20 interactive WebGL samples, complete with source code. Check it out and let me know what you think!
Screenshot Saturday 190
Well friends, Lemma is still on pause while I do some contract work. I also have only a few slides done for my shader presentation next week. This whole month is crazy. But I thought I'd hijack this dev blog to show you the game I'm working on, because it's starting to look kinda cool!
It's a top-down iOS survival shooter designed as a sort of franchise tie-in. The budget is pretty low so most of the assets are pulled from the Unity asset store. I've only done a few models myself, mostly just weapons.
Screenshot Saturday 188
I'm taking September off to work for some clients, so Lemma is temporarily on the back-burner.
HOWEVER. Wednesday night a certain something arrived in the mail.
I immediately tried it out with Half-Life 2 and was shocked at the massive improvement over DK1. I was so impressed that I've spent pretty much every waking minute since then trying to get it working in Lemma.
Current status? It's very, very close. The VR itself is 100% functional now, I just need to make some UI tweaks. The Oculus SDK makes an incredibly difficult thing as simple as it possibly can be. For Unity users it's almost plug and play, but because I'm still stuck in 2008 with XNA I had to rip out the Unity plugin and hook it up on my own (similar to what I did for Wwise). I discovered that it's very easy to get a somewhat passable result that's actually incorrect. You have to learn about crazy things like chromatic aberration and time warping to get the best result.
Screenshot Saturday 185
Hello friends. Yesterday I finished the 5th level! It took much longer than anticipated because it's actually 10 separate maps connected together. It includes some simple but hopefully interesting puzzle mechanics.
It also advances the story through notes and several text conversations scattered throughout.
It's hard to see in screenshots, but I added a subtle cloud shadow effect as well. It doesn't respond to the actual clouds, so in a sense it's slightly faked. Because of that I was able to do the projection easily with a ray-plane intersection rather than a full matrix multiplication. Here's the shader code, edited for clarity:
Screenshot Saturday 184
This week was a lot of level design. I'm working on a group of "fractured" but interconnected worlds that the player has to progress through.
Here's a screenshot:
Here's the thread where I got that rock texture. It's a gold mine with a bunch of totally free diffuse, specular, normal, and even displacement maps.
Unfortunately that's all I have time to talk about today. Thanks for reading!
Screenshot Saturday 183
I hit a milestone today.
Three of the four levels so far in Lemma (Rain, Dawn, and Forest) have undergone at least one massive redesign in their short lifetimes. This week I finally gave the same treatment to the fourth level, Monolith. It is aptly named. Let me try to convey just how monolithic this level is now.
This is a perfect example of my patent-pending Design by Trial and Error™ process.
Screenshot Saturday 182
What's that you say? You didn't even notice the absence of Screenshot Saturday last week? How convenient. Let's pretend it never happened. Or rather, pretend that it did. Whatever.
MGDS was a huge success! There was almost always a line to play the game, and I got a ton of useful feedback. Here are some pictures:
Most of the feedback was related to level design. I came home with a phone full of "todo" items. Here are some screenshots of overhauled or brand new sections that resulted:
New trailer!
Gearing up for Midwest Game Developers Summit this weekend. Tune in next week for my first expo post-mortem.
In the mean time, the old trailer was looking woefully outdated, so here's a brand new one!
Screenshot Saturday 178
Small update. This week was bug fixes and more improvements to the level editor (more on that here).
In other news, we were grateful to get some coverage from Monday Night Indie! Unfortunately the stream highlighted some pretty major issues with the tutorial, so...
Brand new level design!
That's it for this week. Thanks for reading.
Screenshot Saturday 177
Our animator Antonio has been hard at work on new animations. Check it out!
Guys, the level editor is really close to being done. Here's some cool features:
You can link entities together. For example, you can have a door open when the player enters a trigger volume. Or have a light turn on. Or both.
The UI now displays buttons for all available commands at any given moment, and their keyboard shortcuts. Different commands are available depending on what mode you're in, and what entities are selected.
Screenshot Saturday 174
First, a couple project updates. I pre-ordered an Oculus DK2! Come August, Lemma will have Oculus VR support. Huzzah!
I also got a sign for our booth at the Midwest Game Developer summit . Got it from eSigns, whom I highly recommend! Insanely cheap, fast, and high quality.
I am currently scrambling madly to complete a build for the Indie Megabooth submission deadline on Sunday. Stuff that's done:
Screenshot Saturday 173
Last week was a huge update, so this week is a bit smaller.
First, we're hard at work on the animations. Here are some early WIP animations:
There are also a ton of new player sounds to accompany those animations, but those aren't very screenshotable. :)
I also vastly improved the god ray effect from last week, so everything is much smoother. Here's another 4K screenshot of it:
Screenshot Saturday 172
Big update this week!
First, I updated the logo. I rotated the cubes 45 degrees to try and convey a better sense of speed and movement. What do you think?
Next, I added support for 4K screenshots. Now I can hit Alt-S and my renderer resizes all of its buffers to 4096x2304 (biggest 16:9 resolution supported by XNA), renders the scene, saves it to a PNG, then resizes everything back to normal.
The Poor Man's Dialogue Tree
As some of you may know, Lemma has an interactive dialogue system that lets you exchange text messages with an AI character.
I implemented every conversation manually in code (well, scripts) until this week, when I got fed up and decided to automate the process!
Like the last article in this series, my system has all the hallmarks of a Poor Man's solution: developed in-house, tailor-made, simple, and based on free and open source software.
Screenshot Saturday 170
Hello and welcome to another week of Lemma development progress updates!
This time I did a lot more work on the player character. I spent a ton of time in GIMP working on the texture map. I didn't skimp on memory space, it's a full 4096x4096. The GIMP file is over 150MB.
I also split the model into three distinct materials: a shiny one for the chest, neck, and pants, a less shiny one for the hands, and a completely dull one for the hoodie. I stored the mappings for these materials in the texture's alpha channel.
Screenshot Saturday 169
This week I finally implemented SSAO! It's pretty basic, but it works.
Check out the effect source code here.
It's a big deal for me because I tried it once before and it came out like this:
I'm also still working on the player model. I think it's close to being in a usable state. What do you think? Is that a ponytail, or a brain slug?
Screenshot Saturday 168
This week was a ton of performance optimizations and graphics upgrades.
Cascading shadow maps! Basically that means all the shadows are much sharper. It was surprisingly easy to implement and barely impacts performance.
Here's a screenshot showing off the new shadows, plus a new character modeling experiment. Just testing things out for now. What do you think?
Turns out, Blender has something called Rigify that can automatically generate an absolutely kick butt IK rig for your character, complete with blend weights for skinning. It's not perfect, especially when there are separate disconnected pieces (eyeballs, for example), but the few problem areas are easy to correct manually. Here's the character animated with the default calculated weights. I haven't touched them at all yet:
Screenshot Saturday 167
With the Kickstarter finished, it's back to our regularly scheduled programming!
I am in the middle of a major graphics engine upgrade. This whole time I've been using fake HDR. Basically I divide every color by 2 when storing it in a texture, then multiply it by 2 whenever I read it from the texture. It works but you end up with lower color fidelity.
Now everything is done in full 64-bit floating point textures. Here's an exaggerated before/after shot so you can see the difference. Notice the color banding on the left.
Final hours
Here we are folks, counting down the last remaining Kickstarter hours!
I'm happy to announce that regardless of the Kickstarter outcome, production of Lemma will continue.
To be honest, I originally planned to cancel everything if the campaign failed. I figured a failed Kickstarter would be a sign that people aren't interested, and that I should cut my losses (nearly 4 years of work) and move on. But in the past month I realized a few things:
FINAL WEEK!
We are now in the midst of the final week of Kickstarter funding! With the campaign nearing the end, I thought I would give you another development update.
First, I spent a few days completely rewriting every bit of text in the game to support multiple languages. You can now change the language from this nifty selector on the main menu, and the whole game instantly switches:
Now all we have to do is translate ALL the things!
GREENLIT!
It's not every day you see this email in your inbox.
WE ARE ON STEAM! Thanks everyone for your votes! We were part of a batch of 75 titles, even though we hadn't reached the top 100 yet. Go check out the other games that were greenlit today!
Here are the statistics for anyone interested:
Cheat your way through life
From the Kickstarter: Just an update on development progress for Lemma! Thank you so much everyone for your support. I'm still getting tons of useful feedback from people playing the demo. Levels have been tweaked, bugs have been fixed, writing has been edited, and graphics have been tightened. Expect a new build very soon! Here's some new features to look forward to:
First, a minor technical detail. Saved games do not carry over between builds. If you run a newer build, all your old saves will be lost. It's a major drag for beta testers, which is why I've added a new CHEAT menu to skip parts you've already mastered!
Player model and animations
An update from the Kickstarter:
One concern that pops up a lot on Greenlight is the low quality of the player model and animations in Lemma. The reason it's so bad is that I did all of it myself, and I'm not a character artist. People ask, "but couldn't you just try harder? What's so hard about modeling and animating a character anyway? Also, couldn't you just borrow an existing public domain model?"
Movement in-depth
Update from the Kickstarter: I know it's only been 24 hours since the last update, but Lemma is now over 61% of the way to the top 100 games on Greenlight with well over 4,500 yes votes. Thank you all for being a part of this project!
I realized that the 30 seconds of gameplay from the Kickstarter trailer is not enough to really see what's going on, so here's a more in-depth video explanation of the movement in Lemma. Skip to 2:15 to see an explanation of the magical wall-creating, environment-modifying bits.
Looking forward
From the Kickstarter, a quick status update before I talk more about Lemma:
- At the current rate, we are just minutes away from 4,200 yes votes on Greenlight! 56% of the way to the top 100.
- A big thank you to our new backers! There are now 174 of you lovely people (wow) and we're over 32% funded.
- Rock Paper Shotgun covered Lemma yesterday! And with that headline, we've added Bastion to the incredibly long and disparate list of games it's been compared to.
- Kill Streak Media posted a fairly in-depth interview.
- Death By Beta also ran a nice little article.
- In case you missed Caitlin Clark's comment earlier, Lemma was her top pick for Kickstarter games that are "Worth the Wait", along with several other promising-looking games!
- Another great "let's play" video from YouTuber Shake4ndbake.
Okay, let's talk about future plans!
Greenlight update + streaming tomorrow
Hello!
First: I wanted to thank everyone for the amazing support you've shown so far. We're already over 24% funded, which is more than I was expecting this early, so thank you!
Second: A quick update on the Greenlight campaign. We are 26% of the way to the top 100, with 1,918 "yes" votes! Keep on voting, we'll be on Steam in no time.
Third: If you wanted to see more gameplay from Lemma but didn't have time to check out the demo, several YouTubers have posted "let's play" videos of the demo. Draegast has a good one right here.
Lemma: first-person parkour demo
After an unexpected 24 hour delay, the demo is finally out, and the Kickstarter is live! I'm running on 3 hours of sleep, but here's some things you might not have seen since the last release:
The bouncy cubes are now more like crumbly cubes. They crumble when you touch them.
Screenshot Saturday 162
The Kickstarter for Lemma launches on Monday! Keep an eye out, and tell your friends!
Prepare yourself for tons of giant GIFs. You can click each one to watch a much faster HTML5 version (can't wait until the internet ecosystem finally lets us embed HTML5 gifs...)
This week I revamped the materials... again. Check it out:
It had some interesting implications for the "snake" enemy:
Screenshot Saturday 161
This week I finished what will probably be the last map in the Kickstarter demo. It teaches the player about the "extended wall-run" ability, demonstrated here:
Normally, you hold Shift to wall-run. Now you can just keep holding Shift after you run out of wall, and you'll keep going.
I also fixed the water bugs from last week, so it looks much better now:
I've been worried that I don't have time in the demo to introduce every idea I have at a reasonable pace, so I'm thinking of including a "sandbox" map that just enables every ability and throws every idea at the player and lets them play around.
Screenshot Saturday 160
This week I finally fixed my water code to allow finite bodies of water like this:
(It's so dark because I still have a pesky rendering bug)
I also realized I accidentally had pre-multiplied alpha turned on for my cloud texture. Here's what it looks like when you use pre-multiplied alpha incorrectly:
And here it is fixed (I also made the clouds fade in over distant objects):
Screenshot Saturday 159
This week I overhauled the menu. It's very Valve-ish now:
I also distributed a number of mysterious notes around the levels to help flesh out the back story. They're actual 3D objects rendered and lit in the game world.
WHAT COULD IT MEAN? THIS REVELATORY NOTE HAS ADDED HEFTY NUANCE TO THE PLOT AND SIGNIFICANTLY INCREASED MY IMMERSION IN THE STORY.
Other than that, just lots of level design iteration, scripting, and tweaking.
The Poor Man's Gameplay Analytics
You don't want to take time away from your awesome game to write boring analytics code. So you either call up some friends, hire playtesters, integrate some 3rd party SDK (ugh), or just do without.
WRONG. You roll your own solution. Here's why.
Why you don't do without
The OODA loop models the way human individuals and groups operate. It goes like this:
- Observe the situation
- Orient your observations in the context of goals, past experience, etc.
- Decide what to do
- Act on your decision
- Repeat!
After the initial act of creation, game developers operate under the same principle. You play the game and observe it, orient that data in the context of your goals, decide what to do, open your IDE, and put your plan in action. Rinse and repeat.
All Ahead Full
Progress report. Sir, we have inbound screenshots from the first two weeks of full-time development. Bearing zero nine five, range three hundred. Prepare countermeasures.
I added motion blur around the screen edges when the player is at their maximum speed:
The phone has returned, but now it's in full 3D glory:
Some parts of the levels now build up dynamically when the player reaches them.
Ramping Up
I'm sorry, I've been terrible at keeping everyone up to date with Lemma. If you want to see what I've been up to since Alpha 3, my TIGSource DevLog has a few posts you might have missed. Starting now I'll be focusing more on blogging, so expect more posts in the coming days!
Here are some highlights from the past... gosh. Seven months? Wow.
- Player movement has been drastically improved. No more floaty, slow acceleration.
- New auto-respawn system. No more backtracking 10 minutes to the last checkpoint.
- Full Xbox 360 gamepad support
- Major gameplay overhauls. The pistol and energy pickups are gone.
- Major level design overhauls. All but the first level has been thrown out.
- Four new types of enemies
- New, cleaner textures
- New logo
- New website
This is just the beginning. As the title suggests, I'm getting ready to ramp up development in a big way. As such, I found it necessary to upgrade my workspace. I've been using a standing desk at work, and I love it so much that I decided to build one of my own out of $200 of IKEA parts:
Auto-generating JSON serialization code in Objective C
I wrote this article for the Sidebolt company blog. Reposting it here for your reading pleasure!
Our latest game Skyward Slots makes extensive use of JSON. We send Gigabytes of it flying back and forth haphazardly between client and server over a WebSocket connection. At first, we wrote code by hand to pack and unpack each message. Later on we decided that life is too short for that.
In the beginning, we just dove into the JSON right where we needed it.
Simulating UIScrollView in Cocos2D
I wrote this article for the Sidebolt company blog. Reposting it here for your reading pleasure!
We publish our games on both Mac and iOS. Since UIKit is not available on Mac, we have to build all of our UI by hand in Cocos2D. One of the hardest parts to get right was emulating the UIScrollView bouncy scroll formula. Here it is in action:
There are tons of implementations available in nearly every language and framework, but few of them nail all the important properties of the UIKit scroll:
Lemma - Alpha 3 Ready to Play
After seven months of hard work, Alpha 3 is ready to play!
Some interesting statistics:
- 28,000+ lines of code
- 29 MB of compressed voxel data
- 63 MB of sounds and music
- 38 animations
- 60+ textures and normal maps
- 220+ revisions since Alpha 1
Incidentally, most of that is open source! If you're a developer, check it out on GitHub.
Quantity Brings Quality
As I suspected, I have an almost insurmountable case of coder's block after a full day at work. Nevertheless, things are getting done. In fact, this might be the best thing that's happened for Lemma because it's forced me to cut a lot out of the design and focus on core things. It's the only way I'll ever finish.
Screenshot below gives an idea of the new direction. I've dropped any pretense that the game occurs in our world as we know it. It was a restriction that existed only to service the story, and it was limiting the gameplay and visual style a lot. Now I'm free to do a lot more, and I'm not precluded from telling a story just because it's fantasy rather than sci-fi.
Anecdotes ahoy
A smorgasbord of anecdotes carefully compiled just for you, dear reader. This is #2 in a series of three posts which were originally one, before I decided I just had too dang much to say.
OpenStack
I spent a few weeks at work building a fully operational death star OpenStack cluster. What does that mean? Basically, we have our own little private version of Amazon Web Services. We can create virtual machines, virtual hard drives, even virtual IP addresses, all with just a few clicks. It also includes an S3-alike called Swift.
My Biggest Fear for the Future of Human-Computer Interfaces
I recently had to install and configure an 18-node OpenStack cluster, a process which involved a lot of SSHing and text-editing in terminals. I thought about learning Vim, but I was afraid of the incredibly steep learning curve, so I made do with GNU nano. It's not at all powerful, but it's easy.
Eventually I realized, "This is my job. This is what I do every day. Why am I holding off on learning something now, thinking it will slow me down, and that I'll have time to learn it later? It's not like I'm anticipating a major career shift any time soon."
Internet is Back
I just got internet back after being without it since before Christmas. It was a tearful reunion, to be sure. Turns out, I was actually more productive than usual without internet. There's a one-word explanation for that, and it rhymes with "edit".
ANYway, here's what got done:
Analytics
When you finish a play session, you'll see something like this:
I haven't figured out the server side of this system yet, but all it really needs to do is accept plain text file uploads. Once I have the files, it's easy to load them into the editor, yielding data like this:
Progress Report
Lemma has been radio silent recently, but that does NOT mean things aren't happening! I've been able to do a ton of work almost every day these past few weeks. Here's what's going on:
- Did some massive surgery on the very first tutorial section after getting some feedback from a limited alpha release. It introduces, jumping, climbing, vertical wall-running, and rolling/crouching.
- Added a second, underground section that introduces horizontal wall-running, wall-jumping, and some important story elements.
- Added a THIRD section, which you will see in a moment, that reviews everything and introduces the flying kick move.
- Wrote a small chunk of dialog for the text-message system. It's harder than I anticipated, making the conversations truly interactive without having the dialog tree explode exponentially in size.
- Simplified and consolidated the controls. Everything is on Shift, Spacebar, and Control now, should be very intuitive for FPS players.
- Overhauled some of the animations and added new ones for some new parkour abilities.
- Made the menu a lot more user-friendly.
- Committed approximately 15 million bug-fixes and tweaks.
TL;DR: Things are happening. Here's a video that shows one of several ways to get through the third tutorial section in quick fashion.
Mac and Linux Support
How's everyone doing? I'm doing okay. It's a Monday. Hope you're doing okay too. Surviving Sandy aftermath, school, work, and whatever other forms of oppression you may be under.
I don't have anything pretty to show for the past... wow, it's been three weeks. I've been working on a very lofty addition to Lemma's feature bullet list. And that is Mac and Linux support, via the awesome MonoGame project.
Don't get too excited. There is a ton of work left to do before this becomes a reality. But after a few weeks' work, I do know a few things:
Voxel Levitation and Rain
I present to you, "Voxel Levitation: a Step-by-Step Guide".
Step 1:
Step 2:
Step 3:
Step 4:
Also, check it out. Hurricane Sandy has spilled over into Lemma. It's raining!
That is all.
Allocating large arrays in .NET
I experienced a strange memory issue with Lemma this week. Memory usage skyrocketed each time I loaded a level; it never dropped back down.
Now granted, I am definitely the garbage collector's worst nightmare. (I'll just say this: closures. Closures everywhere.) But at this point I am setting fields to null all over the place and manually calling GC.Collect() after unloading a level, all to no avail.
Enter the .NET Large Object Heap. See, the .NET garbage collector actually compacts the regular .NET heap by relocating small objects to fill the fragments. For exceptionally large objects, it's simply too expensive to relocate them, so the runtime allocates them on the Large Object Heap, which is not compacted.
Slowmo! Stamina! Sprint! Socialism! What?
Stamina and Sprint
I finally realized that speed is perhaps the most important resource in a Parkour game. Up until now, Lemma hasn't really understood the concept of "faster" and "slower"; you were always going the same speed. Acceleration from a dead stop was almost instantaneous and the Parkour moves didn't change your speed (with the exception of wall-running).
With this in mind, I decreased the acceleration a lot and made all the moves preserve your momentum. To make a longer jump, you'll need a running start. I also put in some simple combos. For example, doing a roll immediately followed by a jump lets you jump a lot farther.
Scary Monsters and Nice Clouds
Nice Clouds
I got sick of my old pixelated skybox powered by Google Images and decided to make a real one. I used Spacescape to generate a sufficiently trippy outer space skybox, chopped up some cloud photos in Gimp, fought with my code for a couple hours, and wha-la:
Scary Monsters
What's that glowy green thing you say? It's the new monster I just added, creatively named "the vine". See that string of dark blocks coming out of it? It snakes its way to you and basically tries to constrict you to death. Here's another screenshot of its handiwork after running for a minute or two.
Now with 100% more frame buffer distortion!
Flying in the face of midterms and other IRL issues, Lemma boldly marches on!
Spawn Point Graphics
I realized you need a way to know where you'll respawn if you die, so I added some spawn point graphics. Got the idea from Borderlands. Actually can we talk about Borderlands? Man, every time I play a good game I have to resist the urge to start incorporating its ideas into my projects. If I ever announce that Lemma will feature randomly generated weapons, just slap me until I snap out of it please.
Story Design and Loading/Saving
I now have the complete backstory and in-game story options written out!
After the initial tutorial, you'll get to a central area of the island which connects to four other areas. At that point, you'll be able to leave the island whenever you want, or you can visit one or more of the four adjacent areas before leaving. In each area you'll have to make a yes/no decision. You'll get a different ending depending on which decisions you make and at what point you exit the island. Your choices also affect how many parkour abilities you unlock. There are 5 major possible outcomes, and each outcome has a number of variations, for a total of 15.
Lemma Release 2
Here's an extremely cut-down demo! No tutorial, no story, no explanation, just showing off new moves, new enemies, and the new weapon.
Download it here for free. Please let me know what you think!
Super-Awesome Change List
- Totally new block dissolve effects and sounds. Preeeettty
- A new move that builds a platform of blocks and jumps you to the end of it.
- The kick is gone; instead you can now roll at any time, which not only prevents you from receiving fall damage, but also blasts through any breakable blocks in front of you and if you're in mid-air, tries to build a platform beneath you.
- New aiming system that lets you know if you're able to jump to the target or not.
- A new type of exploding block.
- A "tower" enemy that falls on you if you get too close.
- Brand-new pistol, complete with reload animation, iron sight functionality, and magazine pick-ups.
- When you die, you now drop the pistol and phone, so you have to go pick them up again.
- You can now change the mouse sensitivity and key bindings.
- The MSI installer was replaced by a simple Zip archive with a separate executable that makes sure everything is installed. Now it will be easier for me to push out more frequent updates.
- More tweaks than I have time to list, including animation improvements, lots of new and improved sounds, performance optimizations, and bug fixes.
Stuff To Look Forward To
Brace yourselves
Everyone pretend this blog didn't die for six months, okay? Okay. Here's a brain-dump of random things I've learned while not blogging.
- Distributed programming is tough but really, really fun.
- gevent, Couchbase, Fabric, and pyzmq are awesome.
- Django's admin interface can be twisted fairly easily into a CMS for a dynamic website.
- Bed bugs + week-long power outage + another week with still-broken A/C = fun summer.
- Leaky washing machine + computer in basement directly beneath = new computer.
- A bike is the best thing ever when you're in college.
- Spotify is the best thing ever regardless of time or space.
- Batman was eh.
- Bourne was great.
- Game of Thrones, holy crap! Both the books and TV show. Amazing.
- Buy a Mosin-Nagant. Best $100 you'll ever spend.
- Girls, how do they work?
- Writing HTML5 games is a thing which I can do.
- Don't submit your cover design contest entry a month early, they might totally forget you.
- Tribes is fun and free.
- Battlefield 3 added Counterstrike's gun-game mode. Best ever.
- In December, Lord willing I'll be graduated, living in a new apartment, working full-time for an iPhone game studio. Holy crap.
Life's been busy, but this last semester is pretty easy, so I've had lots of time to work on Lemma. No time to talk about it now, but keep an eye out for a juicy trailer / alpha download soon. For now, I'll just tease you with this!
Finals week
Sorry, no news to report on Lemma this week. School is keeping me busy. But I thought I'd share some of the projects I'm working on for school, since they're kind of cool and actually somewhat related to Lemma. First up: a 3D rapid prototype of the original toon-style Parkour Ninja!
Here's the model rendered in Cinema 4D:
And here it is printed out in 3D:
Alpha feedback
Thanks so much to everyone who made the alpha a great success! I'm blown away that people were able to look past the bugs and crashes and clunky controls and somehow get a positive experience out of it! It gives me hope and motivation to press on.
I got a ton of very useful feedback. Here's a quick summary of what I learned:
- The atmosphere and tone is cool and unique.
- The text-message-driven story works pretty well.
- Everyone immediately says "Mirror's Edge + Minecraft"... but then realize they're okay with that! :)
- The physics is kinda buggy.
- Mouse inversion, gamma settings, and vsync toggling are a must.
- The controls are unnecessarily complex. Too many keys.
- Buggy physics. Player gets stuck in the environment a lot. Large objects occasionally start floating around on their own. Swimming doesn't really work at all.
- Combat is weak. You left-click once and hope that kills the enemy before it kills you.
- It's rather disconcerting being able to look down your own nose. Also, everyone thinks the player model is a female when in fact it's a male with big pecs. Yikes.
- Oh yes, there's lots of physics bugs.
- The tutorials are sometimes easy to miss, and the game expects you to have a move fully mastered immediately after learning it.
- Handling publicity and responding to feedback is a lot more work than I originally thought! And hosting large downloads on "pay for what you use" web hosts is a baaad idea. Good problems to have though. :)
I've already set to work fixing a lot of these issues, especially with the controls and physics. My number one priority is getting the player animation and movement perfect, which is a pretty long way from where we are now.
Lemma Release 1!
It's finally here! Alright I'm just going to dump everything here. Prepare for face melting.
Windows MSI Installer (60 MB)
Note: You might get a malicious file warning. It's because I can't afford a code signing signature at the moment, so the installer has not been signed.
If you're NOT reading this on the shiny new website, did you know that you COULD BE? It's right here: lemmagame.com
Please play the alpha and leave your comments! Your feedback is greatly appreciated!
Help me pick a logo!
I'm going to try and post smaller, more frequent articles. This whole "two months between massive walls of text and screenshots" thing is not working out.
So, the alpha I promised is *still* inbound. I'm working as fast as I can! And I think it's paying off. For a while I was very worried about performance. In my last post I talked about how I optimized the renderer, but there were still issues with the physics engine. I was putting each cube into the physics space as a separate entity, which was making it absolutely crawl, even on my eight core i7.
Global Game Jam 2012 Liveblog
Update: Snakes in a Tower is complete! Downloads with source available for Mac and PC.
Friday 4:59pm
This is my first Global Game Jam. Super excited. So I'm going to liveblog it. I'll be working on a MacBook, so I decided to port the essentials of my XNA component entity system over to MonoGame. Here's what I got so far!
Breathtaking, I know.
Saturday 12:20am
Opening meeting was awesome. Heard some fantastic keynotes from fantastic people. We got to hear some great insight from Ian Schreiber before starting (I'm at the Ohio State jam). The theme has been given to everyone by now, so I'll go ahead and say that the theme is this:
Quick update - Alpha inbound soon!
This week was a lot of under the hood improvements. The voxel engine got a TON of performance optimizations, which allow my Nvidia GTX 260 to render my test scene at 100-200 FPS.
Screenshots:
New features:
- Rough-draft tutorial level with instructions and whatnot.
- Fullscreen toggling on-the-fly by hitting F11
- Rudimentary fog effect
Performance optimizations:
- Voxels are now rendered as surfaces, rather than complete cubes. This lets me cull a lot of unnecessary geometry.
- Voxels are now split into chunks. This lets me easily implement frustum culling and view distance, which helps tremendously with shadow map rendering as well.
- I fixed some bugs in the voxel modification code, making voxel modifications of up to 100-150 cells practically instantaneous.
- Shadow maps and reflections are now rendered every other frame. It's a hack, but the important thing is that the gameplay is responsive.
My biggest development challenge was my battle with fullscreen toggling and graphics resource management. Switching from fullscreen to windowed mode, the entire XNA GraphicsDevice is invalidated, along with every vertex buffer, texture, shader, everything. So that was interesting.
Digital art, Facebook 3D Graph Explorer, and more Project Lemma
My last two posts focused on general game development topics, but no longer. It's the end of the year, time to look back and review before looking forward to the new year!
Digital Art
First off, some fun diversions. In my pursuit of an art minor at Ohio State, I took a digital art class autumn quarter. The instructor let me use software I was already familiar with, so I didn't learn much. But the class gave me the motivation to plonck my butt down and make some art, which is all I really wanted.
C# for scripting - runtime compilation
I set out to add scripting support to Project Lemma the other day. End result: I can recompile C# scripts on the fly and cache the bytecode in DLLs. The best part: there's no special binding code, and no performance hit.
There are a lot of .NET scripting solutions out there. Here's a few I found in my research:
- IronPython. Fully dynamic, kinda slow. Requires marshalling of some kind between the script world and .NET.
- CSScript. Very well supported, includes Visual Studio extensions and shell extensions. Compiles C# to bytecode at runtime, with caching. Scripts cannot be changed once loaded.
- Lua. The industry standard in scripting. From what I understand, a little challenging to get working with .NET.
I decided to try out C# runtime compilation. Really, C# is the best scripting language I could ask for. If I succeeded, I could keep writing the same code I've been writing, but I could recompile it and see it in action with a keystroke instead of restarting the game!
Tools are everything
You've probably heard the whole "don't make engines, make games" shtick. As I progress I am learning another important lesson: tools are the most important aspect of any project, game or engine. Whether you're rolling a custom engine or shopping around for middleware, tools should be absolutely top priority. Seriously.
The question should not be "how many shiny graphics techniques can I incorporate?". It should be "how easy is it to create content for this game?". Content is the center of every game, whether that content is an AI algorithm, a map layout, or an art asset. If the content pipeline is even a little inefficient, it will prevent you from making the game you want to, whether you realize it or not. If you have to jump through hoops to create a new level or script a story sequence, you're going to put it off and focus instead on adding another feature that provides tangible results, like a new lighting technique. Problem is, those features don't make the game. Content does.
Physics and lighting fun
Sorry to post two videos in quick succession, but this was too fun not to record!
Parkour Ninja update: first-person camera, physics, deferred rendering
Parkour Ninja is still alive! And it's looking more like Mirror's Edge now, complete with first-person camera. The old direction of the game just had too much frustration and not enough fun. Hopefully things will change now.
I re-integrated a physics engine, this time BEPU physics, which is a screaming fast open-source XNA physics engine with unbelievable support. I was able to get my existing block simplification/rendering code to work with BEPU, so now you can add/remove blocks to/from existing objects on the fly. One cool side-effect of this ability is that I can also blast objects into smaller chunks... full-blown destruction is #1 on my list right now.
As promised: Component Binding "BEHIND THE SCENES"
In the wake of this brief description of my component binding system, I was asked to provide more details on its implementation. This article is my best attempt to do so!
This is a tale of intrigue, excitement, and wonder, in which I try to implement a component-entity system in C#, and stumble upon a remarkable paradigm that merges components with data binding.
Note: If you don't have at least a vague concept of component-entity design, read this article first.
Game dev job, Macs, and re-focusing my project
Apologies for the lack of Parkour Ninja updates. I do have fresh info about it somewhere in this post. But first! A list of potentially interesting goings-on of late:
- School's out for summer! And I'm one year closer to a Computer Science & Engineering undergrad degree from Ohio State. I'll graduate in about a year and a half, right around my 21st birthday actually. I haven't the foggiest idea what to do after that. I'm looking at grad school, but I've heard it's not as important for CS people.
- I got a job making iPhone games! I'm working for a small studio in Columbus with three other interns. The original plan was to have the four of us collaborate on a single game, but now they've given us each a separate project (at various stages of development) to work on. I wish they had kept us together because a) I doubt we'll finish all the games now, and b) I need experience collaborating on a game instead of my usual lone wolf habits; I was hoping this job would put me out of my comfort zone a little. On the other hand, where else would I got almost full control over every aspect of a professional title? That's pretty cool.
- On a random note, I'm getting into shooting this summer. After a few more weeks of saving up I plan to buy an assault rifle (still researching what to buy there) but until then my buddy is lending me his AR-15 for the summer. :)
Pistol: Part 2 - Texturing
And here's episode 2 of the Sig Sauer Saga! In which I attempt to UV map and texture the model from Part 1. And do lighting and compositing for a decent somewhat photo-realistic render. Take a gander. Feedback appreciated!
Pistol - Part 1: Modeling
Poking my head in here to confirm that I am in fact not dead. I humbly offer this nifty time-lapse video as proof.
Started a small project to brush up on Blender skills. Modeling a Sig Sauer P220 in Blender 2.57. The model is low-poly and incomplete (need to finish the other side, the magazine, some bullets, etc.), but it's close. Next up, textures, materials, lighting, rigging, and animation!
Parkour Ninja Alpha 1
It's here, and it needs lots of play-testing! Please help me out and play it. You'll need a Windows machine with a Shader Model 3.0 graphics card.
I'm anticipating some technical issues with this release (it is an alpha after all), so if you run the game and no window appears and the process dies, please do the following:
- Run the game in administrator mode.
- In the game installation folder (C:\Program Files (x86)\Parkour Ninja\) open the file "Lemma.log" in Notepad, copy the contents, and send it to me! I need bug reports :)
Back on track
I finished refactoring with components, added a reflection-enabled editor and XML serialization, finally got real PCF shadow filtering, and started experimenting with a somewhat cel-shaded visual style. I've been busy.
The refactoring had a lot of positive side effects. Serialization is now relatively easy, as the state of each component is determined by its properties, which are usually simple, easily serializable value types. One interesting side effect of serialization is that object creation is now split into two parts: initialization, and binding. When creating a new object at runtime, a factory performs the initialization. When loading objects from XML, the XmlSerializer performs initialization. In both cases, the factory creates the necessary bindings between properties afterward.
Refactoring with components
Update: check this article for more in-depth details on Component Binding!
I've been refactoring my engine with the component-entity model, and things are turning out quite nicely. The one problem I always had with components was the way inter-component dependencies were handled. In the article I linked (one of the classics on the subject), the author says his components originally referenced each other through a component manager, but eventually they allowed components to store pointers to each other for performance reasons. In my mind, that's way too many concrete dependencies.
Prepping for alpha release
[These posts are now being mirrored on my GameDev.net developer journal. Check out their new revamped site, it's pretty sweet.]
I am getting ready for an alpha release soon, very basic, with one tutorial level and a level editor. So looking at installer options for XNA games, this WiX XNA installer appears to be the best choice. It's designed for SharpDevelop, and it creates an installer that checks for all the required libraries and even the required shader model. Unfortunately it's kind of a pain to set up. There's a massive XML file that needs a reference to every single file in your release.
Parkour Ninja animations
I'm going to poke my head in here to reassure everyone that the game is making steady progress. The environment now turns transparent when it gets in the way of the camera, and the player has some nifty new moves and mechanics, plus a very shnazzy looking power bar to indicate how much "juice" you have to perform special moves. The latest addition here is the skill roll, which prevents you from slowing down or dying when falling long distances. Take a gander!
December 2010 Tech Demo
I finally got animations working! I'm using a Blender to FBX script, along with this fantastic multi-take FBX importer. Apparently XNA depends on the actual FBX API for importing, and the API changed drastically just before XNA 4 released, so they didn't have time to get multiple takes (animation clips) working in one file. This importer automagically splits out the takes from the FBX file, processes them independently, then combines them into the original model. I encountered a bug with the Blender to FBX script, but as of today it's been fixed and committed. You can get the Blender export script here and the importer here. (edit: here's a sample project, including a .blend file, .fbx file, and all necessary code)
Further deets
Okay, it's time to shed some light on this project.
First off, my goal is to release on Xbox and, if possible, Steam (if not, I'll be looking at other online stores). I figure these are the two largest, most practical target markets. The release price will be between $1 and $5, with 100% of the proceeds going to charity (more on this later...).
There are two main themes I want to nail in this game. The first is giving the player freedom to alter the game world; to literally change the world geometry by performing sweet parkour moves (jumps, flips, slides, etc.). The idea is, to create a wall, you simply jump into mid-air and perform a wall jump as if the wall was there, and poof, it's there. Need to get through that annoying concrete barrier? No problem, slide right through it like it's butter.
Back at it!
That's right kids. I's back with a new game project. I will post these two tantalizing morsels for you. Let the wild speculation begin!
I realize the chill music in the video doesn't exactly match the motif of the above image, or the whole game really, but hey, it's just a tech demo. No need to start murdering people just yet.
Tricksy closures
Do not be fooled by the elegant simplicity of the mighty closure! Behind its shiny dynamic veneer lies a powerful machine capable of destroying your immortal soul. Behold:
function GetOutputFunctions()
{
var outputFunctions = new Array();
for(var i = 0; i < 4; i++)
{
var x = i * 2;
outputFunctions.push(function() { alert(x); });
}
return outputFunctions;
}
var functions = GetOutputFunctions();
for (var i = 0; i < functions.length; i++)
functions[i]();
This will not output the first three multiples of two, as presumably expected. Instead it will output "6" three times, because the variable "x" is only allocated once.
Phew
Well, I submitted A3P to IndieCade on Friday. It's also currently in QA testing for an online gaming portal (BigPoint, still free of course).
I won't say that A3P is done, but I think it's pretty stable. I need to do a bit more work on the connection establishment process (it seems a little fragile), but other than that, there's not much else to do. I also packaged the game into a standalone version available here: Windows (68 Mb) and Debian Linux (77 Mb). Speaking of packaging, if anyone with a Mac is interested in creating a Mac installer, please contact me. It should be pretty easy, the only reason I haven't done it is because I don't have a Mac.
Moar physics entities
Drop pods no longer sit in one place, they now roll around, freely dispersing their monetary goodness among the citizenry. They're quite light too, which means a single grenade can send one flying across the map, with your bots following in hot pursuit. Speaking of maps, Sector X is just about done! It's definitely our most massive map to date, and it has some interesting moments. So far the ring around the top has been great for sniping.
More maps
The main menu now has a global chat room, powered by some simple PHP/MySQL. The tutorial has been updated (it looks a LOT better), and the website received a makeover too! A lot of behind-the-scenes updates have been happening as well... the network code is becoming increasingly bulletproof, and several more physics bugs have been addressed.
And now for the fun stuff... more multiplayer maps! The first one is called Gold, it's adapted directly from the gg_halo_gold CS:S map. It's basically already done, and it promises to offer some intense 4-player action. The other two are works in progress, but both are looking like they could facilitate some epic battles.
Feedback from beta 2
Hey everyone, it's me again. I'm happy to report that Beta 2 turned out pretty well! We got a bit of publicity for the final release, and more importantly, some valuable feedback. It sounds like people had trouble with the browser plugin, so in addition to the browser-based game, I'm also going to release a stand-alone version with a self-contained installer. This also re-opens the possibility of LAN parties in the absence of an internet connection.
Beta 2 is out!
A3P Beta 2 is live, go check it out! This release has a whole slew of new features, some of which have been covered on this blog. To recap:
- New camera angle and aiming methods. Should be familiar to fans of Gears of War and loads of other third person shooters.
- New money system (the return of drop pods!) with a whole new UI for purchasing items to boot.
- Massive AI overhaul using navigation meshes rather than waypoints.
- A whole new game type called Survival. Think Nazi Zombies or Dawn of War 2's Last Stand, although maybe not quite as awesome.
- Three new fabulous maps created by the excellent Bobpoblo. Seriously, check out his CS:S maps, he's a genius with Hammer.
- The molotov cocktail is the latest addition to our assortment of weapons available. Use it wisely.
- Revamped online lobby complete with a nifty global chat box.
- At least 3.7 million other tiny little updates and bug fixes. Like the spawn points and home bases, which have been modified to be much less annoying.
So go hang out in the lobby and check out the new features! This will be the last beta release before the final version, so get your feedback in now!
Meshes of navigation
Update 8/23/2011: the source/executable for the navigation mesh .obj exporter is here. Import a mesh, set up the parameters (only simple mode is supported right now), and have it generate the mesh. It should output a .obj file in the directory where it was executed.
The AI system has finally received a massive and desperately needed update: support for navigation meshes. That means the bots shouldn't get stuck running into walls all the time, or running back and forth between waypoints like machines. I think this was probably the biggest weakness of the game up until now; the AI is still something of a problem, but it's much better.
More stuff!
We are closing in on a new release here... in the mean time a lot of new features have been added!
First, and most notably, I'm experimenting with a new camera strategy. If you've played the excellent Just Cause 2, it's very similar. By default your character is off center to the right, with a wide, inaccurate crosshair on the screen. You can right-click to zoom in and increase your accuracy and damage. So far I think it's a major improvement over the old system.
Drop pods are back
And they're much more interesting now. Instead of delivering reinforcements, they now act as cash dispensers. So rather than receiving a flat sum every match, you'll have to earn your money by remaining near a drop pod. Currently, the pod doesn't make you wait and then dump all the cash on you in one transaction; the money is deposited in $10 increments every second. We'll see whether that changes or not.
New maps, new weapon, new money system, new game mode!
I've been silent here for a while, but that's just because I've been busy getting some glamorous new features in! Things are really starting to shape up.
First things first. Bobpoblo has joined the team as a mapper/tester! He's been working hard on some new maps made in Hammer, textures courtesy of [-B-]. The original maps will likely be remade as well. Unfortunately the content pipeline is a little convoluted: I open the Source map in Crafty, export it to Wavefront OBJ format, and import it into Blender. From there I fix import errors, remove degenerate triangles, apply lightmaps, etc. before exporting to .egg format.
New command system and social portal
Quick update just to keep this blog alive. I've made some improvements to the command/AI system. It's now much simpler and easier to tell your units to attack a specific enemy. The closest enemy you're aiming at is highlighted, and you can hit Q or E (depending on which one of your two units you want to command) to order an attack on that enemy. Special abilities are also mapped to Q or E, when tapped twice in quick succession.
Spawn points and more networking
Networking has received yet another performance boost. I discarded Panda3D's network classes in favor of Python's sockets. I also switched to a single-threaded, non-blocking system that performs significantly better and clears up the messy Panda3D threads that were acting very strangely. I also improved the connection process; both the client and server now send packets to each other while connecting, in an attempt to punch through even the most draconian of NAT schemes.
Finally, online multiplayer!
I've updated the browser plugin to finally support full online multiplayer! Go try it! I think the plugin is now stable enough that I am promoting it as the officially recommended method of playing the game. :)
Of course, there are still some problems. Namely, in Internet Explorer the mouse control doesn't work. Testing so far has shown Firefox 3 and Chrome (on Windows) handle the game very well.
So give it a whirl, and please post any errors or bugs you get, along with your OS and browser!
Update
Not dead... just really busy. Been doing a lot of network debugging and optimization; I added zlib compression to the network packets, which cut down network bandwidth by about a fourth. I also streamlined a few network issues, added a simple network performance logger, and implemented simple client-side interpolation; everything moves much smoother now, even if there is a slight delay. It's basically a fact of life these days in online games; as long as hit detection is still accurate, a small delay is practically unnoticeable.
Gameplay trailer
Finally got sound working in these videos, yay! New features in this video include the aforementioned shadow mapping and reloading, a brand new three player map called Orbit, and heavy modifications to the original Impact level.
I really cannot wait to get the multiplayer up and running, and get people playing the beta. Next on my to-do list are a few standard online features: basic match-making, in-game chat, etc.
Without further ado:
Reloading, shadow mapping
Thanks to the Panda3D 1.7.0 shader generator supporting shadow mapping, and the awesome new BuildBot service set up on the Panda3D website, A3P now supports basic shadow mapping! Actually, the sun is just implemented as a giant spotlight with a 2048x2048 shadow buffer. Definitely not the most efficient or high-quality method, but certainly the easiest, and the results are acceptable.
Also new in SVN is a reloading mechanic. The shotgun, chaingun, and sniper rifle all have to be reloaded, with varying clip sizes and reload times. Of course, reloading units are highlighted as vulnerable, and they also beep furiously to make it perfectly clear they need to be shot at.
Schedule delays
It's time to face the facts. While the game is progressing at an incredible pace, it's not going to be ready by January 9, or even the end of January. So, I guess I failed to meet my deadline.
But! I'm not giving up. I'll still be releasing regular updates, and especially once the multiplayer lobby server is set up, things will start getting a lot more polish. My new goal will be to finish the game before school lets out for the summer. Of course it will be online and playable well before then, but I won't consider it "finished" until I'm satisfied.
v0.5a released
That "a" stands for "not quite ready yet". This is sort of an intermediate release that focuses mainly on online multiplayer, which is largely functional, but needs more testing. Aside from polish and bug fixes, the only other things I'm going to add are more weapons and special abilities. And maybe a new level. We'll see.
This release went much smoother than the last two, as I used Panda3D's built-in packpanda to make the installer. I also cut the installer size down by scaling images, deleting unused files, and resampling music and sounds into the Ogg Vorbis format. It's incredible what Ogg Vorbis can do; without sacrificing any quality at all, I cut down the music size by about 20%. With a bit of downsampling, it was about 50%. The final installer is 80 Mb, a far cry from the 176 Mb v0.3 installer!
New name: A3P
Goodbye Stainless, hello A3P. I spent a good chunk of time creating new A3P material and switching everything over to the new name. Unfortunately, SourceForge's UNIX rename feature is down, so I created a new project for web hosting purposes only. The code and file releases are still on the Stainless SourceForge project. Which, to be extra confusing, I renamed as well, but again, I couldn't change the UNIX name.
New gameplay
Sorry for the distinct lack of updates this blog has. A lot is happening right now with Stainless, and most of it's good. :)
First off, Stainless is going to have online multiplayer! Woot. Thanks to the fabulous work by the guys over at Panda3D, it may even live in a browser plugin on the SourceForge website. Either way, I came across a problem I never anticipated with online multiplayer: NAT punch-through.
Stainless v0.4
Available on the new website: stainless.sf.net
There's a whole bunch of new stuff in v0.4 that I don't have time to talk about. So check out the website to see the new HD trailer.
Replay functionality, new icons
Yes, you can now view the last five games you played as a spectator! All I did was save each network packet that's sent out into a big list, then use Python's pickle module to serialize the list to a file. Each packet has a timestamp, so I just read the packets back in order, checking the timestamps to make sure it reads the packets back at the right speed. Fast forwarding is not implemented, but it would be pretty easy. Rewinding/seeking would be more difficult, so I'm not sure I'll get to implement those.
November update
This month's release will start to show more of the Real-Time Strategy side of Stainless. One new feature that unfortunately will exclude a section of the target audience is speech recognition. I'm using the MS Speech API, which obviously only works on Windows. Sorry Linux and Mac users. :(
Still, it's going to be worth it. Right now the level design and AI are not quite advanced enough to benefit from speech commands, but the potential is there. Also, the game has a new system for money management, which means players will have to start rationing their money and deciding which units to buy. Basically, you'll buy the right to use a certain unit for one round in a game, and no matter how many times that unit dies that round, he'll respawn for free. But then the next round, you have to buy all new units.
Stainless v0.3 beta released!
Along with an HD trailer. Free download here!
Prepping for first release
Less than one week away from release! Looking at the to-do list from last week, I actually haven't worked a lot on the items listed. I've been ironing out a lot of bugs and adding polish. The multiplayer scoring is now working, and you can see everyone's scores on the top of the screen, conveniently color-coded. I killed the ugly black boxes around the scores and added drop shadows instead, and I moved your current balance to the right side of the screen, to avoid confusion. Take a gander:
Production schedule
Yes, I have a schedule/deadline now. I'M SO NERVOUS. :)
Here's the plan. And when I say "forum", I am of course referring to the fabulous GameDev.net forums.
- October build - Release 0.3, Oct 31 - with the following AI droids: shotgun, sniper, shield, cloaker, melee, chaingun. Virtual file system, XML map format, working multiplayer with scoring and simple "game over" condition. No ability to choose units yet. First forum announcement.
- November build - Release 0.4, Nov 30 - implement unit suppression from grenades and melee jump jet. Complete match/round logic. Simple squad orders. Unit selection screen at match start. Rough draft YouTube trailer. Forum announcement update.
- Official release - Release 0.5, Jan 9 - special abilities, finalize multiplayer maps, finalize YouTube trailer, overall polish, official website goes live. Image of the Day post / official forum announcement.
January 9 final release! Which means Stainless will have been in development for exactly one year! Quite impressive for a guy who never seems to finish these things.
More shiny!
Three updates, one in graphics and two in gameplay.
Graphics: new water shader! Thanks to Panda3D's new built-in support for user clip planes in the shader generator, the reflections were a piece of cake. It's a very basic shader that simply deforms the render buffer and the reflected render buffer, then blends the results 50-50. No fresnel, no lighting, nothing. It works, though.
Using the distortion shader from my last post, I added a shield droid that puts little shields around team entities in its vicinity. The shields decreases ranged damage by 25%.
Panda3D distortion sample
For any Panda3D users out there, this is an improved version of the frame-buffer distortion sample currently shipping with Panda3D 1.6.2. Whereas the original sample just samples a wave texture to offset the frame-buffer sample location, the shader in this version actually uses normals from the Egg model. It also gives a slight tint to the object. You can easily adjust the color and intensity of the tint at the top of the "distortion.sha" file.
New artwork
Yeah, I'm back to art now. I am ashamed. But I'm starting to get the hang of this Blender stuff. Check it out:
And here it is in-game. Don't worry, I fixed the clamped textures on the bottom after I took this screenshot.
And now for something completely different...
I actually planned a full-fledged single-player campaign for Stainless, before I came to my senses and downgraded it to a much simpler multiplayer game. However, I'm still considering a short (2-4 hours) campaign. What I have in mind is similar to Valve's strategy with Left 4 Dead: a short, highly replayable campaign designed for 2-4 players. With one catch: the players are fighting against each other.
With my limited marketing and branding skills, I have dubbed my idea an "anti-cooperative campaign". It would be best with 1v1 or 2v2, but regardless of the player count, the computer would balance the teams by bestowing various power-ups. Which means, if I ever add an online component beyond LAN, matchmaking would be unnecessary.
Network system description
As promised. :)
First, a small disclaimer. This network system is designed for a very specific task: handling networked physics/gameplay over a LAN network. The structure described here might be useful in other scenarios, but the actual Python code is certainly not fit for much else.
The system follows a modified Model-View-Controller pattern that focuses on two main types of objects: Entities and Controllers. The "View" part is split between the Entity and Controller. Entities handle most of the assets tied to a standard object in the game world: namely, the physics geometry and graphical representation. Each Entity has exactly one Controller, which handles all (and I mean all) actions the Entity can perform. The Entity will not move at all without a Controller.
Perfunctory postage
Wow, so many updates to cover. I've been without internet for awhile, so... deal with it. :)
Let's start with a list of new improvements:
- Networked gameplay is now fully functional. Weapons, grenades, springboards that propel players around the map, it's all there. I'll make a bigger post one of these days that describes the whole system in more detail. It was quite educational for me, and I'll still be modifying it for awhile.
- The main arena level has received an upgrade in the form of a massive tower thing in the middle, with bridges going out to springboards on either side. Which makes it now completely incompatible with my primitive AI system. Oh darn.
- I'm using a nifty particle effect when the player spawns and to highlight the springboards. Kinda slow without the Panda3D MeshDrawer class though.
- The generic physics object, known as "Block" has received a visual overhaul. This was my first experiment with dirty textures, and it turned out not too bad. Textures were done in Inkscape and Gimp (with a normal map filter plugin).
- There is now a functional main menu! Well, more like 50% functional. Still on the to-do list: allowing the user to specify what server to connect to (possibly with a server auto-detect function), and allowing the host to choose which map to load. Also farther out on the roadmap is usernames and logins. And can anyone tell me how to deal with Blender's ridiculous smooth/solid mesh setting!? I can't get the continents to be smooth-shaded without screwing up the normals on the edges. It's passable for now though.
Behold!
Networking and better particles
Network code is working reasonably well now. The server generates a unique MD5 hash (only six characters) for an entity, then broadcasts a packet to the clients instructing them to spawn an entity of the correct type, and assign the same hash as its ID. From then on, the server turns over the reigns to the entity's controller, which can send any information it wants in its own sandboxed data packet.
Done with art for a while
I've spent way too much time fooling with the Blender-Panda3D content pipeline, so I'm moving back to working on gameplay and coding.
That being said, the art was fun while it lasted. Here's a sample of the results:
All art in this screenshot was created by me. The arena geometry enclosing the map was created by extruding individual faces of an icosphere. The texture maps were drawn in the excellent Inkscape, then touched up in the lightweight-but-useful Paint.NET, then crunched by the incredibly flexible and powerful CrazyBump for the normal maps. The whole process is recorded here for posterity:
First major update
Mmm. Been a while, hasn't it.
Latest and greatest feature list:
- Nifty particle effects for bullet impacts
- Decent AI pathfinding
- Grenades don't go through walls any more :D
- New test map with spiffy baked lighting courtesy of Blender
Current project: revamping the orbital dock model seen on the front page screenshot. First up: my first shot at a rusty grungy metal texture. Made from scratch in Photoshop in about a half hour with four layers of noise, airbrushing, blurring, burning, and dodging.