7DRL Takeaway Lessons

I promise this will be my last 7DRL post, but I thought I should record some thoughts I’ve had about it now that it is over.

This post could alternately be called “Why I Will Not Use MonoGame in the Foreseeable Future.”

First, the motto of MonoGame is “Write Once, Play Everywhere.” This sounded promising to me, because my first game had issues deploying almost anywhere. Of course, what they mean is that you can play anywhere supported by Windows.

There are ways to get builds onto other platforms so that Mac and Linux users can play, but I only had 7 days, and I’m not a trained computer scientist, so that wasn’t going to happen. This was a little frustrating, and also one Windows user already complained they couldn’t get it installed.

Second, MonoGame is effectively a re-implementation of XNA 4. Unfortunately, some of the pipelines (especially with an up to date Visual Studio) are broken and require hacks to work. This caused major problems with sound. So much so that I scratched all sound from the game.

I know that with enough time, I probably could have gotten this working (because lots of games made with it have sound), but I couldn’t waste the time in those 7 days to fight with it. This was frustrating, because one of the main reasons to use MonoGame was to make all of that streamlined and easy.

I also felt trapped into using Visual Studio as an IDE. This is certainly a fine IDE, but I’m most comfortable with Sublime Text 2. Switching editors wastes a lot of time, especially when you “downgrade.”

By this I mean VS doesn’t have half the great features of ST2 (including my most used feature: multiple cursors). In retrospect, I should have edited in ST2 and built in VS.

All this being said, MonoGame was a good enough framework to produce a full working game in 7 days, so I can’t complain too much. Also, if I were part of a larger team with a longer time frame, many of these issues would disappear. So I admit these complaints come specifically from the 7 day issue.

If I do this again, I will almost certainly try Cocos2d-x. It looks like this will fix all the complaints I had. First, Cocos2d-x is open source. This means I can actually see what the engine is doing if I need to! What a concept.

Second, it is C++, so it will deploy across platforms much easier. Lastly, it isn’t in some transition period like MonoGame where content management seems to use outdated, unsupported pipelines. I’m also more familiar with C++ than C# which would have solved a few headaches.

Theseus: a 7DRL 2015 Completed!

Final Stats:

One week.
About 90 hand drawn 64×64 pixel tiles.
Over 2000 lines of code.
A completed one-hp strategy roguelike.

Proof that it can be beaten happened during my stream where I tested for bugs (quality isn’t the best):

Actually, I think I’ve finally gotten it balanced so that you should be able to win if you know what you are doing every time except for extraordinarily rare scenarios dictated by the randomness.

7DRL 2015 Success.

[Edit:] I’ve set up an itch page: http://hilbert90.itch.io/theseus
Download the game to play for free here: https://www.dropbox.com/sh/1ywjy7s3y72bq5k/AABOZWsPOFBYs0qgcxW5Ccqxa?dl=0

7DRL: Theseus, Alpha Testing Phase

Alright. I have to leave for the day. I’ve thrown a few more things in this morning at the last minute, and then built the whole game.

If anyone wants to test it and give feedback, that would be much appreciated. I’ll still do a lot of polishing tomorrow.

Sorry, as of right now I have a build that I’m 99% positive will work on any Windows 7 or 8 machine. Earlier probably works, but hasn’t been tested. I haven’t made any others (the opposite of my first game which people could only get to work on Linux).

I’ve learned my lesson. If I do this again, I’ll probably switch to Cocos2d-x, which is open source, and easily builds into any machine.

Types of things I’m looking for:

1. The whole thing crashes. If this happens, try to remember exactly what happened and leave a comment.

2. The setup doesn’t install it on your computer, but you are using Windows. Let me know something about your computer if this happens.

3. The game is too easy (for example, you consistently scale up too quickly and bash your way to victory with no thought).

4. You can let me know if it is too hard, but I probably won’t change that.

5. Anything else that seems reasonable to need a fix for being on Day 6 of developing a game (you can say the art is not polished, but that will just hurt my feelings … it’s Day 6 and I had a lot of other things to do for goodness sake).

6. The Readme didn’t have enough information.

Tonight or tomorrow, I’ll probably add 2 more items for reference of what will be added before the final release.

Thanks. Have fun.

I’ll think of a better way of distributing this later. For now, go here: https://github.com/wardm4/Theseus

Press Download Zip (button to right). Ignore all the files except the one called “Theseus.zip” Right click on that and save it somewhere (your Downloads folder or whatever). Unzip it and then double click on setup.exe. That will prompt a standard install.

Better yet. I’ve added just the zip to a Dropbox here if you don’t want to get the source code too: https://www.dropbox.com/sh/1ywjy7s3y72bq5k/AABOZWsPOFBYs0qgcxW5Ccqxa?dl=0

7DRL Dev Log Day 5

Today turned out well. I didn’t get trapped trying to fix some problematic C# syntax like in the past two days. The main improvements were to draw the final boss, get him animated, program his AI, and get the final room set up (which has different design structure than the rest of the labyrinth).

I did some balancing with the boss to figure out how much HP seemed reasonable for what level I thought an average person would be at. I also drew, animated, and designed an AI for a new NPC that will make an appearance later in the game. They are pretty tricky, so I imagine a bunch of deaths for people who dare to make an attempt at them.

The game feels reasonably complete at this point. There is a nice progression leading up to the final boss, and you win the game if you kill it. I made a push to get it to this point before today, because it turns out that tomorrow I’ll have almost no time to work on it at all.

I have two more significant additions I want to make, and then tons of polishing I can do (tons of extra animations, sound, balancing, bug finding and fixing, etc). Overall, I’m finding the game a bit too easy, but my alpha tester hasn’t beaten it yet, so who knows. If you know all the enemy patterns (like I do), then I think it is beatable pretty much every time with caution. I never came across an impossible situation today.

Tomorrow I’ll give a download of the most up-to-date version in case any readers want to volunteer a few playthroughs to give some feedback before the end of the last day.

7DRL Dev Log Day 4

Today I’ve put in some more details, but I still haven’t gotten around to programming the final fight, so the game technically goes on forever right now. I plan to do that first thing tomorrow.

I added another weapon and a bunch more items, which will be one of the main things that keep repeated plays interesting. The weapon was a spear (technically a bident) which can damage enemies at range.

I’ll keep the items a mystery, but I will say that items all have positive effects. This choice came from two places. The first is that in a “one HP” roguelike, you cannot have much by way of negative effects without causing an unfair death.

The second is that I really want everything identifiable on sight, because part of the strategy is to make hard choices about what to use and what to keep. You have a weapon slot and a spacebar item slot (in my head these correspond to what you hold in your two hands).

Since the maze has no backtracking, you can’t bring two really good items with you. Items are fairly sparse, which I like. The game should be beatable without any, so finding something will make the run more enjoyable and safer.

I also implemented the dragon I drew last time into the game. Again, today’s changes were mostly behind the scenes, so there isn’t really a screenshot that helps you see what has happened. Instead, I’ll post a video with sample gameplay.

Don’t watch if you want to experience it yourself. I’ve gotten a lot of standard movement patterns down after playing it a bunch, so I might spoil how to handle lots of situations.

7DRL Dev Log Day 3

Yesterday I got through the hardest coding section of the game. I separated out the zone logic into it’s own class, so I could make repeat calls and chain together the zones to make a large labyrinth.

I also implemented experience points, level up, more of the GUI, and fixed many of the bugs I had from day one like spawining in an instant death situation, enemies occupying the same square, and a permanent stun effect.

Also, there is an annoying bug where the game crashes if I put sound in it on some machines (maybe it is just Windows 7?). I may end up not doing sound and music to be safe.

Most of these changes were under the hood, so it doesn’t look much different right now:

theseus_screen3

Today I got hung up on a few technicalities with C#. I guess I should have practiced some basics more before this week to avoid wasting time. Apparently, when you iterate through a list, you can only read the objects you iterate over (you can’t set them to new values). This caused lots of confusion for a bit while I tried to work out what was wrong.

I had a pretty good day. I realized lots of stuff was hard to see/read with the fancy vector swept background. I’m not sure I like what I’ve switched to, but it is certainly better from a readability standpoint, and makes the various sprites pop a lot more:

theseus_screen4

Other than that, I did a lot of art again. I added some items and a new weapon. This meant drawing the various places the item could be, and then redoing the main character sprite with the new weapon in its various positions. The weapon has a pretty cool mechanic attached: it is a damage multiplier, so super over-powered, but it is heavy, so it costs a turn to turn around while holding it. This drawback may make it too risky to be worth it putting in an interesting choice.

I also completed a new enemy, a dragon. It is the best thing I’ve ever made with pixel art (I only started learning a few weeks ago):

dragonsample

I animated him by just bobbing up and down and breathing fire so that I wouldn’t have to deal with the intricacies of moving the wings. It’s coming together and finally feels like a real game.

7DRL Dev Log Day 1

Today the 7DRL began (for me at least)!

I got through everything I wanted to with time to spare. I mostly built the art today and got some stuff displayed. I settled on a 960×545 window (unchangeable, because I don’t want to deal with scaling at the moment) with each segment of the maze being a 40×20 grid of 64×64 tiles. Once you leave a segment, the previous part will change.

Today I drew the title screen, a “lose” screen, a “win” screen, the background, 3 wall tiles, 3 floor tiles, a fire elemental enemy, a raven enemy, and some of the GUI (health, weapon, and item get displayed).

Here’s two screen shots:

theseus_screen1

theseus_screen2

Both of the enemy types are fully animated, but the fire could use some work later if there is time. I’ve implemented movement patterns for the two enemies, and trigger win/lose conditions if you clear the area (not the real win condition, just testing!) or die.

Overall, this was a wildly successful day, but all of the hard coding is ahead of me, not to mention, I’ve only thought of one weapon and one item so far.

Mistakes From My First Game

We’re headed into the #7DRL Challenge. Last post I described what I was going to make, how I was going to make it, and what I hoped to get out of it. Today I want to describe things that were done terribly in my first game that I hope to do better this time.

I’ve seen a few of these posts popping up. They mostly say things like, “I tried to do too much,” or “I tried to put non-essential things in before the core was done.” I don’t want to get into any of those vague issues. I actually want to get into some hardcore implementation errors I made.

I’m going to use the term “game engine,” so I want to make sure people understand what that means in this context. Roughly speaking a game is a finite state machine simulation that either live updates at a certain rate or updates upon user input. The engine refers to the main pieces that loop to make that machine continue.

To big game developers, there’s probably a lot more parts (like preprocessing the 3D animation pipeline, etc), but for my 7DRL it consists of initializing/loading the pixel art and starting statistics, an update loop, and a draw loop. The way the monogame engine works is that the draw loop will attempt to be called at a fixed fps (I’d guess 60 is default, but have never looked it up).

The update loop is always called at that base fps. User input is captured in a queue and then handled in the update loop. For example, if the player presses the up arrow, the update loop catches this by going through a bunch of if statements. One of those will be “if user presses up: increase the y-position by 1” (actually decrease due to how the screen coordinates go, but let’s not get into that). Then since the draw is independently updated with the most current positions of everything, the avatar will move.

All of this goes on forever unless something causes the big game engine loop to break (e.g. “if player health <= 0: break"). This brings me to my first error. I thought that because my game was turn-based, i.e. nothing on the screen would move or update until the player pressed a key, I didn't have to separate the update logic from the draw logic and I didn’t have to call either until the queue caught new user input.

This is a pretty big error. This meant that my entire engine stalled until the player pressed a key. It didn't cause any issues in the game per say, but it is very bad form. You need at least one moving part, some people would say two, at all times. What if you wanted to implement something that relied on real time and not just game time? What if you wanted to have a resting animation for the sprite? The ways in which this limits the creator are endless, and it is sort of hard to see until you make the mistake yourself and try to expand the game.

Also, keeping the draw and update loop separate is very important when graphics are involved. For example, if you have a lot of processing power needed to render your 3D animations, then you might need to drop frames to prevent lag. If the loops were tied together, then the game engine itself will experience lag and maybe even miss user input. If they are separate, the animation loop is free to lag without the rest of the engine lagging.

My next set of mistakes were object-oriented ones. My hierarchy of objects was poorly designed. Actually, there was no hierarchy. This caused excessive amounts of repeated code. The player had a position, health, attack damage, attack method, takeDamage method, and so on. The enemies did, too. I should have made a superclass with those attributes and methods from which both could inherit.

A related mistake was that I broke encapsulation … a lot. Because I had all these separate objects that needed to know about all the other objects and alter them, I kept passing all these raw values around and changing them. This is very bad, and caused many headaches when something went wrong. A few times I had trouble tracking down how a particular value changed in an incorrect way, because everything had permission to change everything.

I should have made a well-planned, clean hierarchy, and then let the main engine handle making all of the updates and changes that needed to happen.

The last thing I want to talk about is a little subtle. The object-oriented approach at first glance seems well suited for this type of finite state machine. You have a bunch of instances of enemies, each have a bunch of attributes, and the changing of these is essentially the game.

For a small scale project this is fine. What you will find as your game gets more and more diverse is that your hierarchies will get out of control. If you subclass every time there is a split, you will end up with insane code: new Character.Enemy.EnemiesThatFly.FireEnemy.NoMagicSkills….

I know you're thinking that these were just poorly chosen subclasses. It is an art to balance when to subclass. Many of these could be combined, and then leave an attribute null or unused when that particular enemy doesn't use the attribute. But remember, we're talking about a large scale game with lots of diversity.

It is a simple application of the pigeonhole principle that your unused attributes will also get out of control if you don’t subclass enough. This isn't good either. There is simply no way to create a set of well-balanced classes in a pure hierarchy once the attribute size gets large enough.

There is another way! It is called an Entity Component System (ECS). Instead of thinking in terms of objects, think in terms of the components. One component might be health. So you pull this out into a struct or class that has the health attributes and methods (not to mention, if you make your components structs of integers, you can work on the stack which will speed up CPU time rather than allocating on the heap with those classes).

Now everything in the entire game is an Entity, and you make an Entity Interface to interact with these components. Usually people will tag each Entity upon creation with a unique ID. This turns the game machine from updating a bunch of abstract, separate instances of classes to something more like updating a database.

Not only does this provide a cleaner approach from a coding standpoint, but it also makes many things easier. For example, in an RPG, maybe you have an ice spell that only affects flying enemies that are fire based (see subclass issues example above). It could be hard to find these if you've been instantiating them in the level at random and just have a big array of instances of enemies.

With the ECS framework you can query all Entities where the flying and fire based components are set to True. Or maybe you have a weapon which damages the wings of a flying enemy and it no longer possesses the special qualities of a flying enemy. Would you take the same enemy and create a whole new instance of a whole new class to do that? It would no longer be the "same" enemy in the code.

Again. This is really subtle, and probably is hard to tell why it works better from just thinking about it. You have to try the other way first to see what a pain it is to realize why the ECS framework simplifies this.

Since the 7DRL is under such tight time pressure, I'm not going to try a whole new coding framework for the first time during it. But I think I'll try to implement a hybrid OO/ECS approach whenever some obvious component jumps out at me.

Starting Saturday, you can expect this blog to turn into a Dev Log of the game. Hope to see you there.

7DRL Pre-Challenge Post

I’ll be blogging about my progress in the 7DRL Challenge, but I don’t want to waste time during that week posting all the stuff in this post which can be done now. If you don’t recall what a roguelike is why you should play them, see these posts: Why Play Roguelikes? and Thoughts on Permadeath. If you are interested in this challenge, there is still time to pull it together! The week is March 7-15.

Where I’m Starting:

Part of the rules of the 7DRL Challenge allows you to use generic pre-existing graphics/algorithms/game engines/etc. To be fair to the finished game, you should cite these sources. Here’s what I’m starting from (for why, see the sections below).

I’m building the game in C# through the XNA/Monogame framework and using a module called RogueSharp designed for making roguelikes in C#. The main use will be data storage and drawing of the level. For a generic template to start from, I’ve gone through this tutorial. My game will take this sample game and (radically) modify it.

See the section Core Idea for how I plan to build my own map generation if there is time. If there is not time, RogueSharp also has a built in algorithm I will use. As for graphics, I’ve spent some time playing with pixel art and learning to do animation in Monogame.

I will redo every one of these during the 7DRL week, but I needed some practice so that I wasn’t going in both learning to do pixel art and creating the sprites on top of programming the whole game. This seems fair, because anyone that has done any art for a previous game will go in with more experience than the couple weeks of practice I got from this.

Mechanics:

My game will be a traditional grid based movement (only up, down, left, right) and turn based (the enemies don’t move until you do).

I’m choosing to make the game a variant on the “One HP Model.” A pure one HP mechanic says that everything in the game has one hit before they die. This includes you. This makes the game similar to a game of chess. If you move a piece to where another piece is, this “attacks” and the other piece dies.

This turns the game into one of strategic positioning. As more and more enemies appear with various movement patterns, you must figure out places to stand where you will not be killed and a good order to kill the enemies.

Each game will basically be a sequence of increasingly difficult, randomly generated puzzles to solve (so it is completely different every time). Part of the initial fun is that you must work out what the AI movement patterns are for each type of enemy.

I will use a variant on this model that allows certain items to increase your health which will allow you to take two hits (I probably won’t go above two though to keep the pressure on). Also, most enemies will have more than one HP, but various weapons will still let you kill them with one hit. The details have yet to be worked out.

Core Idea:

The core story idea is Theseus in the labyrinth who must find his way to the center to kill the Minotaur. I would like to implement a system where backtracking is impossible. In modern interpretations of the labyrinth, the surrounding area constantly changes. This seems like an interesting procedural generation problem and adds a layer of difficulty to the gameplay since you can’t just leave something laying around to go back for.

I want there to be a punishment for running instead of “solving the puzzle” and killing all the enemies, but I also want the game to be winnable if you do this a few times. This will be a delicate balance that may not get worked out in a week. One easy punishment is to have a basic leveling system.

If you don’t kill the enemies, you don’t get the experience to level up and get stronger. This means that maybe later you need to hit some enemy a few more times making the strategy more complicated. The labyrinth design will also help balance this by not allowing the player to skip something too hard until they are stronger to go back to it.

I also want there to be time pressure. The game would become too easy if you could indefinitely re-position until you get a line of enemies to take out one at a time. There will not be a “hunger clock,” but I won’t spoil how this will be done right now.

What I Hope to Get From 7DRL:

I made a 7DRL before (well, it wasn’t done during the 7DRL or over the course of 7 days, but it is similar in size and scope). I built all the algorithms, data management, procedural generation, game engine, and everything from scratch. I did this to learn how all these pieces worked and interacted together.

I’m proud of the end result, but it isn’t very pretty. I used standard ASCII characters for graphics and made lots of stuff way too slow and clunky. I used python and pygame to do it. This caused lots of distribution issues because of dependencies and python versions.

Because I’ve done the inner workings before, this time I want to focus on some other aspects. I have no problem relying on a pre-built engine (monogame plus the tutorial), pre-built algorithms (RogueSharp), and so on. I want to get graphics, animation, and sound into the game. These are all things that were wholly neglected last time.

Rough Plan:

Day 1: Get a level displayed, redraw some sprites and get those displayed. Best case scenario, I can move through the level and once I’ve cleared the enemies I trigger the win condition.

Day 2: Solve the labyrinth procedural generation problem (i.e. put in multiple “levels”).

Day 3: Items, armor, weapons.

Day 4: Put in the rest of the enemies and start tweaking movement patterns.

Day 5: Catch up on days 1-4. If there is time, make a start screen, win screen, lose screen. Play for balance issues.

Day 6: Sound + animation.

Day 7: Debug + balance.

Most days I’ll try to update progress on this blog. On Day 5, I’ll probably want other play testers if you are interested in giving feedback.