About Mark Hildreth

Entries

 
Ludum Dare 26

Mark Hildreth's Trophies

Mark Hildreth's Archive

Post-Mortem: Scout Droid Bravo 325 Jr

Posted by
Sunday, May 5th, 2013 11:20 am

“Mama Don’t Let Your Programmers Grow Up to be Puzzle Level Designers”

imacharacter
This is the post-mortem for Scout Droid Bravo 325 Jr. I’ll go through the highs (“Hey this works!”), the lows (“HOW MANY more levels do I need to write dialog for in the next HOUR?”) and the ugly (“You know what I should do? I should write a program to finish making the game for me!”) of my first completed Ludum Dare.

In the spirit of Minimalism, this post will be anything but. However, for the abridged version:

What Went Right

  • Rather than trying to bury myself in the game making for weeks running up to the contest, I allowed myself to relax, and had more energy going into the weekend.
  • I found a game I wanted to make, got a working version early on, and had almost a complete game (mechanic wise) on the first day. This meant that the entire second day could have been used for polish and content.

What went Wrong

  • While I did like the dialog, and received mostly good comments on it, I did heavily skew my second day making all the dialog, which meant I didn’t have time for other polish.
  • Sorely underestimated the time that it takes to make good puzzle levels
  • Probably could have removed some levels so that I didn’t have to spend less time coming up with dialog for all of them

Game Description

In the end, the game is a puzzle game that involves the player moving the title character around a level. The player needs to activate “devices” from the map. Each activation causes the player to change their location on the map, with the end goal being to remove all the devices from the level. This requires the user to plan out the order in which they hit the devices.

level2

The image above is level two. If you move your character to the right, you will hit the “up-jet” (the thing that is actually drawn as a trampoline that I never retextured) which causes you to fly up to the platform on the right. There, you will be able to hit the up-jet on the far right. However, you won’t be able to get back to the original platform to hit the far left up-jet. The correct solution is to hit the far left “up jet”, fall to the ground, then go to the right and hit the middle up-jet. Later levels get more difficult, and with different types of devices (trap doors, teleporters, etc.)

Development Backstory

LD#24 was to be my first LD. I had everything ready: the Python build script for deployment, a self-made engine built on pygame (an engine which housed some, erm, “interesting” design decisions). For a good two weeks I forced myself behind a desk readying for the competition. “I’m a good programmer who can build reusable software to reduce boilerplate tedium without sacrificing flexability!”, I said. “I have an advantage with my years of experience of coding and project management!”, I said. “I know when to stop the feature creep!”, I said. Of course, I also made sure to get acquainted with the bare minimum to make my games look… okay….

In short: I was prepared. No: I was OVER-prepared.

Then the law turned inside out, the world upside down, and the long-time runner-up/silver-winner/bridesmaid “Evolution” shocked the LD world by finally becoming the topic.

“Perfect”, I said”. “Evolution means complexity, writing software with complex rules is my speciality!”, I said.

In a moment of gusto I… promptly broke down. I had an idea for a game, but just couldn’t get myself to actually start writing the code. Later, looking back, I realized that I had burnt myself out before the contest (duh, you’re supposed to burn yourself out DURING the contest!).

LD26 Development Plan

fastfoodplan

Going into this LD, I made a few changes to my gameplan.

Just RELAX beforehand

I changed over to Javascript/HTML5 (which I had been meaning to do for awhile), but did minor experimenting over the course of a few weeks. The warmup “weekend” was really a warmup “a few hours spread over the preceding week” for me. I didn’t even start thinking about the finalist themes during the runup to the announced themes. I only started thinking of game ideas when it was announced. But unlike last time, I was now fully focused and full of energy.

Realistic Goals

My goal was to complete a game, no matter how silly it ended up being. Also, right at the very beginning, I told myself that I would NOT be adding any music or sounds. Right away, that was a burden off of my back. To be sure, the game is quite boring without those sounds, and they surely would have made it better. But that is one more thing off my mind, and my goal was the finish (not to win first prize).

“Minimalism”

“Minimalism” was announced at 10pm local time. The goal was to come up with the game idea, then pop a melatonin, head to bed and start fresh in the morning. Well, that was the plan.

I had four different ideas in the first hour, the fourth one eventually became what I wrote. The other three were:

  • A game where you controlled a number of cities (or factories, or buildings, or something) and needed to find ways to gain efficiencies to provide the same output out of fewer and fewer buildings. This was my favorite of the ideas, but I couldn’t really think of how the mechanics would work well enough. I wanted to pick an idea early, and not need to develop it too much.
  • A puzzle/platformer where you need to get from one end of the puzzle to the other. You can place a “tool” anywhere you want onto the level (like a springboard, or a platform) to help you navigate the level, but in the spirit of minimalism, you can only place ONE tool per level. This really wasn’t too different from the actual game I made, I really could have gone this way as well.
  • A game in which you control a person who is trying to remove distractions (television, fashion, etc.) from their life and achieve a minimal lifestyle slowly by making choices of when to engage in distracting activities, and when to cut a little slack. I just didn’t feel like I’d have fun making this one.

The inspiration for this idea actually came from a quote I saw in one of the links from google’s search results for “minimalism quotes”.

I started sketching out on a whiteboard the various types of “devices” that could be used for the current game. Then, I sketched out a simple puzzle using the devices. It took me all of ten minutes. “Well, that was simple: just code this up in a few hours, then make a bunch of levels”.

And so, code I did…

Early Development

A few hours in, my game looked like the image below (which, through the magic of version control, you can play here):

tplus4hours

It works, and from there I was able to continue on creating more “devices”. By the end of the Friday night (just before I went to bed at 2am), I had the following game, which included an additional device and a level loader.

So much for “go to bed and work on it in the morning”.

Level Loading

One thing I knew going into making a game with levels is needing the ability to create new levels very easily. If you don’t have some sort of program that you can create your level in and import into your game, ascii art is just as good. I wrote the level loader early on, and never really needed to change it much.

levels

Each character represents a different tile. Underscores (“_”) are ground, the asterisk (“*”) is the players starting location, an “S” is an up-jet (originally, I called it a “springboard”), an “R” is a rickity bridge. A space is air.

Saturday Day

Saturday was spent trying to make graphics. Saturday is also when I noticed that the game is pretty much done, and just needs more levels, and perhaps better graphics. You can view the results of the end of the first day here. Notice that, graphics and mechanics-wise, there is almost NO CHANGE from the final game. Really, the only thing I added after that point was the star field and landscape background images. I also only had dialog for the first couple of levels, and about 10 or so levels. Since the mechanics seemed to be going in pretty easy, I also decided that I would add Lost Vikings-style dialog before and after the level. In these development releases you can skip to the end dialog by pressing “S”, or skip a level by pressing “N”.

Just before going to bed Saturday night (well, Sunday morning) I noticed a trend in the day’s development. Basically, I ended up doing the following:

  • Realize my game needed more levels (or more difficult levels)
  • Do something other than design levels

While I had ten levels, they weren’t what you called “challenging”. Part of it was that I really didn’t know what I was doing. I had never designed puzzle levels before. Do I think of how I WANT the level to be solved, then end up throwing in red herrings to throw the user off the scent? Do I just throw stuff onto the level haphazardly, play the level, then make tweaks? Also, if I just throw together a level and then try it out and can’t complete it, how can I tell if the level I made is impossible to beat, or just really really good?

A Better Way to Design Puzzle Levels

So, Saturday night, unable to fall asleep, I started thinking about if I could come up with a better way to build these levels. Surely I could just create a tree of possible things the user can do, then create a level from that tree…

tree

I experimented with this strategy a bit, but wasn’t able to bring it anywhere.

Writing an AI to play my game

I decided that the second day, I was just going to have to just continue creating the levels manually, and haphazardly. However, to make the task a little less arduous, I decided to write an AI that would solve the level that I created. In addition to telling me if it was actually a solvable puzzle or not, perhaps I could get some sort of metric to its difficulty (for example, how many correct paths are there to the solution? How many incorrect paths?)

You can view the git repository for the AI. Consider the first level:

firstlevel

A very early version of the AI would see the following list of steps as a “winning path”:

  • Move Right -> Move Right (Hitting device, moving the character up to next platform) -> Move Right (Hit device, move up) -> Move Right (Hit final device)

However, even though it’s a simple puzzle, an AI that brute-forces this puzzle will still have a bunch of ways to lose. Here are some losing scenarios:

  • Right -> Left -> Right -> Left -> Right -> …. (Basically, going back and forth)
  • Right -> Right -> (Hitting device, moving up to next platform) -> Left (Falling off of platform, killing all chances of winning).

I soon realized that sticking with simple “move left” and “move right” as my actions would be difficult (I would need to be careful about infinite loops in the AI, etc.) So, I switched to using two different actions: “move left until something happens” or “move right until something happens”. “Something happens” would be one of…

  • Hitting device
  • Hitting an “air block” (in other words, falling off of a platform)
  • Hitting the walls of the game

Thus, the AI would do a combination of “move left until something happens” or “move right until something happens”. If the movement caused the unit to hit a wall, I considered that a “losing” path. Going back to the first level, here are ALL of the losing paths (R for “move right until something happens”, L for “move left until something happens”).

  • R (Hit device) -> L (Fall off platform) -> L (Hit wall)
  • R (Hit device) -> L (Fall off platform) -> R (Hit wall)
  • R (Hit device) -> R (Hit device) -> L (Fall off platform) -> L (Fall off platform) -> L (Hit wall)
  • R (Hit device) -> R (Hit device) -> L (Fall off platform) -> L (Fall off platform) -> R (Hit wall)
  • R (Hit device) -> R (Hit device) -> L (Fall off platform) -> R (Fall off platform) -> L (Hit wall)
  • R (Hit device) -> R (Hit device) -> L (Fall off platform) -> R (Fall off platform) -> R (Hit wall)
  • R (Hit device) -> R (Hit device) -> L (Fall off platform) -> R (Fall off platform) -> L (Hit wall)
  • R (Hit device) -> R (Hit device) -> L (Fall off platform) -> R (Fall off platform) -> R (Hit wall)

Unless I missed some, there are 8 losing paths to go along with the one winning path. Originally, I tried to determine level complexity from the “winning percent” (the percent of paths that are winning paths). For the first level, the winning percent would have been 11% (only 11% of paths would win). However, when I ran this algorithm on some of my other puzzles, I started noticing that this didn’t really give me a good indication of how hard the level was. My second level (which isn’t “hard” by any stretch of the imagination, but certainly not as obvious as the first) actually showed a HIGHER win percent (due to the fact that it didn’t have as many platforms for the AI to jump off of and cause new loss paths).

Improving the Algorithm

I continued tweaking out various algorithms, with one major change that made it better. A “path” is only the order in which you hit the devices. There could be multiple paths to hit the devices in the same order, or you could hit the devices in the right order so that all you need to do is hit the last one, but you still have 50 ways to lose (by ignoring the last device and jumping off of various platforms).

Finally, I was able to run this algorithm on a level and get output like the following:

mark@gobo:~/projects/games/ld26-helper$ python run.py 
'       _            ',
'                    ',
'     _S             ',
'                    ',
'   _S               ',
'                    ',
'*_S_________________',
WINS:
((2, 0), (4, 2), (6, 4))
1 Wins
0 Losses
100% Win Prcnt

The script will run a map (showing the ASCII art), show me the various winning paths (the list of tile coordinates of the devices to hit). The first level is a 100% win percent, even though you COULD theoretically lose the level. Here’s the result of the run on the second level:

mark@gobo:~/projects/games/ld26-helper$ python run.py 
'                    ',
'                    ',
'            _S      ',
'        S_*         ',
'___________S________',
WINS:
((8, 1), (11, 0), (13, 2))
1 Wins
1 Losses
50% Win Prcnt

Here, we see there is one loss path that the user could take.

Analyzing Level Complexity

For these early levels, the AI wasn’t that helpful, but it was ENORMOUSLY helpful for later levels. Here are two levels, 13 and 15. You can use this slightly older version of the game to play. In this version, pressing the “N” key skips to the next level.

Level 13:
Level 13

Level 15:
Level 15

At first glance, they both seem about equal in complexity, right? If anything level13, with more devices, actually seems harder. So I put on my robe and wizard hat….

Level 13:

'                    ',
'     E              ',
'           ___      ',
'__T_RR_TT_          ',
'_RRRR_ _S_          ',
'______SS*_____E_____',
WINS:
((14, 0), (7, 2), (6, 0), (5, 2), (4, 2), (2, 2), (2, 1), (1, 1), (7, 0), (8, 2), (8, 1), (4, 1), (3, 1))
((7, 0), (7, 2), (8, 1), (8, 2), (14, 0), (5, 2), (4, 2), (2, 2), (2, 1), (1, 1), (6, 0), (4, 1), (3, 1))
((14, 0), (5, 2), (4, 2), (2, 2), (2, 1), (1, 1), (6, 0), (7, 2), (8, 1), (8, 2), (7, 0), (4, 1), (3, 1))
((14, 0), (4, 2), (2, 2), (2, 1), (1, 1), (6, 0), (7, 2), (7, 0), (8, 2), (8, 1), (5, 2), (4, 1), (3, 1))
((14, 0), (7, 2), (8, 1), (8, 2), (6, 0), (5, 2), (4, 2), (2, 2), (2, 1), (1, 1), (7, 0), (4, 1), (3, 1))
((7, 0), (7, 2), (6, 0), (5, 2), (4, 2), (2, 2), (2, 1), (1, 1), (14, 0), (8, 2), (8, 1), (4, 1), (3, 1))
((7, 0), (7, 2), (8, 1), (8, 2), (14, 0), (4, 2), (2, 2), (2, 1), (1, 1), (6, 0), (5, 2), (4, 1), (3, 1))
((7, 0), (7, 2), (8, 1), (8, 2), (6, 0), (5, 2), (4, 2), (2, 2), (2, 1), (1, 1), (14, 0), (4, 1), (3, 1))
((14, 0), (7, 2), (8, 1), (8, 2), (7, 0), (5, 2), (4, 2), (2, 2), (2, 1), (1, 1), (6, 0), (4, 1), (3, 1))
((7, 0), (5, 2), (4, 2), (2, 2), (2, 1), (1, 1), (6, 0), (7, 2), (14, 0), (8, 2), (8, 1), (4, 1), (3, 1))
((7, 0), (5, 2), (4, 2), (2, 2), (2, 1), (1, 1), (6, 0), (7, 2), (8, 1), (8, 2), (14, 0), (4, 1), (3, 1))
((14, 0), (4, 2), (2, 2), (2, 1), (1, 1), (6, 0), (7, 2), (8, 1), (8, 2), (7, 0), (5, 2), (4, 1), (3, 1))
((14, 0), (5, 2), (4, 2), (2, 2), (2, 1), (1, 1), (6, 0), (7, 2), (7, 0), (8, 2), (8, 1), (4, 1), (3, 1))
13 Wins
20 Losses
39% Win Prcnt

Level 15:

'                    ',
'                    ',
'       RRTRR_       ',
'    _E_SS__TRT__    ',
'        ST*__       ',
'__________E_________',
WINS:
((9, 1), (10, 0), (7, 2), (8, 3), (9, 3), (11, 2), (8, 1), (7, 3), (8, 2), (10, 3), (11, 3), (12, 2), (13, 2))
1 Wins
4 Losses
20% Win Prcnt

On the one hand, level 13 has many more ways to fail. On the other hand, level 15 only has one way to win, and a lower win percentage. So, which ones harder? I’m still not sure what a good algorithm would be for this.

Let the Computer do the Work

I decided that, ideally, a hard puzzle should have exactly one win path and a high number of loss paths. So, I would come up with SOME puzzle, throw it through the AI, and tweak the results. I realized there was a better way to do this: let the computer generate levels, run the AI, and spit out when it found a “hard” one. It would take too long to just have it really generate one (if I did that, most of the levels would be impossible to beat because of a device in the upper left corner of the map or something), so I created something of a template with question marks in the parts of the level that I wanted a device randomly generated for. For example, here is level 18…

level18 = [
    '                    ',
    '                    ',
    '    _SRSE           ',
    '   _T_TT_T_         ',
    '   SSR_R___TSR_     ',
    '  _S___SR*_R        ',
    '________E___________',
]

Here is something like what the final level looked like when I originally wrote it…

new_level = [
    '                    ',
    '                    ',
    '    _???E           ',
    '   _?_??_?_         ',
    '   ???_?___???_     ',
    '  _?___??*_?        ',
    '________E___________',
]

Notice the question marks for some devices. I added a function to the script to take the level, and randomly generate devices for the question marks, then solve the puzzle until it found a puzzle with only one victory condition. Here is the output of a run…

0
0
0
0
0
0
0
0
0
0
0
0
411
0
0
0
0
0
0
0
0
0
0
0
0
0
1
'                    ',
'                    ',
'    _RTSE           ',
'   _T_SR_R_         ',
'   STR_R___SRT_     ',
'  _S___RS*_T        ',
'________E___________',
WINS:
((11, 1), (8, 0), (7, 4), (6, 4), (6, 3), (5, 4), (4, 3), (4, 2), (7, 1), (8, 1), (9, 3), (7, 2), (5, 2), (3, 2), (3, 1), (7, 3), (11, 2), (12, 2), (13, 2))
1 Wins
7 Losses
12% Win Prcnt

At first, it dumps out one number per line. Each of those numbers represents a level that was generated, and the number of winning paths. In this case, most of the levels were impossible (0 winning paths). One of the levels it generated had 411 winning paths. Finally, it generated a level with 1 winning path, and 7 losing paths. For the curious, the final level of the game has 1 winning path and 17 losing paths.

Oh, that’s right, I’m supposed to be making a game here

So I spent the rest of Sunday tweaking the algorithm so that it could generate good levels. However, I went a bit overboard, and had 22 levels. The remaining 6 hours or so was spent just writing dialog.

In total, I would estimate that half of my waking time was spent writing either dialog, or the AI (which isn’t even part of the game!).

Of course, this last-second race meant a few things:

  • I wasn’t playing my game. Afterwards I would realize that having to restart the level and go through all of the dialog again was annoying
  • The dialog would sometimes make sense when I wrote it, but because the user actually had to play the game, some dialog that makes sense read seconds apart became confusing when spaced out by minutes

Conclusion

As I mentioned earlier, my main problems here was an under-appreciation of the amount of work it takes to DESIGN good puzzle levels. Even the lower-win-percentage auto-generated levels were really only gaining in complexity because there was more devices in them, not because they required more clever, outside-the-box thinking.

I kept the game mechanics simple, and that allowed me the ability to not use effeciently much of the second day and still come up with a decent game. I’m hoping in the next LD I will have the opportunity to try out creating audio/sound. I really did like the dialog, so I want to keep doing stuff like that, although I might need to reduce the scope of it a bit.

Also, this was a good test for my Canvas library and I have ideas of how I want to change it.

Okay, I think I’ve written enough for one day. If you’re still with me, thanks! I hope this proved an interesting read.

Posted by
Sunday, April 28th, 2013 7:02 pm

I’ve officially been working nearly non-stop for the last 12 hours. The majority of my time has been spent creating levels and adding storyline. Note so self: it takes a long time to write dialog!

I didn’t get to add a lot of polish (no music, no sound fx, etc.). However, it is a done game, and as far as I can tell, it’s fun.

I’ll probably write a longer postmortem, but I’m just exhausted. I need a shower and some food. However, I stayed on task and did what I set out to, so I’m feeling pretty good about that.

This is quite possibly the WORST use of my time right now, but it was fun, so I did it.

My LD entry is a puzzle game, and I overestimated how hard it was to design puzzle levels (read my last post for more info). So, I went ahead and wrote an AI to brute-force my levels, and give me the number of success and failure paths that the user could take, with “harder” levels probably having better ratio of failure/success paths. It also means that I can put the level into the solver and actually see if the level I made really is solvable and I was just beaten by my own game :)

The solver is on github. In the time I wrote this I could have gotten sound effects or just plain been making more levels (as easy as they would probably end up being), but I thought the idea of writing the AI was a fun challenge so I did it anyway. I might write a post about the AI after the contest.

Though I’m not happy with the graphics/sound/music (bad, none, and none, respectively), I think I’m going to ignore those as casualties of my first LD experience.

Plan today:

* Eat more leftover pizza.
* Add the remaining device types to my solver (right now it only can “solve” levels with SOME device types from the game)
* Use the solver to help create the remaining levels
* Continue adding dialog. Maybe actually have a plot!
* Add a background texture to replace the dull “black” background.
* Add an intro screen.
* Add an intro screen for each level.

Time permitting:

* Eat more pizza

How hard is it to make a puzzle game for LD?

Posted by
Saturday, April 27th, 2013 10:31 pm

At first look, making a puzzle game isn’t hard. Basically…

1.) Write a bunch of simple rules that work for one level.
2.) Write 20 more levels that use the same rules (no more coding necessary!)
3.) ????
4.) Profit!

The problem is that trying to create levels that are difficult (but not impossible) is… well.. difficult.

So far, the tactic has been:

1.) Place a bunch of stuff randomly on the screen.
2.) Try to (myself) solve the puzzle I just randomly created. If it takes me a few tries before I finally get it: awesome!
3.) If I solve it right away, add some stuff to where I went to try to make it less obvious.
4.) Continue this method of tweaking things until I break the level and make it impossible to finish.
5.) Start over from scratch with a different random level.

There has to be a better way (maybe there is some higher-level math that can use graph theory to create levels that have many possible routes, but very few “winning” routes). The worst part about this ad-hoc method is that it’s very possible I’ve made a level that is impossible to beat, and I WOULDN’T KNOW IT until it beats me many times. Also, I might have already thrown away a bunch of levels that I thought were impossible, but might have been really good candidates for some of the final levels.

Part of me wants to build an AI that brute forces the level and gives me an idea of difficulty/possibility of them. If this wasn’t for a 48-hour contest, I’d consider it. For now, I’ll just keep scrapping away.

So yeah, in theory, a puzzle is pretty straightforward. On the other hand, the amount of time it will take to create levels for a puzzle game should NOT be underestimated.

Posted by
Saturday, April 27th, 2013 5:13 pm

With the exception of one of the animations, I think I have all the coding done. The graphics aren’t great, but they can pass if I don’t find time to sharpen them up tomorrow. If necessary, I can put in the levels / character speeches and call it a game. Of course, tomorrow I’m going to try to add some polish:

1.) Smooth out the controls a bit.
2.) Intro / Finish Screen
3.) Sound Effects
4.) Polish the UI (rounded corners, amirite?)

If I can do all this, I’ll be happy. If I knock these things out, I can try working on…

5.) See if I can spice up the graphics some more (there’s only so much that I can do :P)
6.) Music

screenie

Pulled Pork BBQ Quesedillas

Posted by
Saturday, April 27th, 2013 12:27 pm

Walked into town to grab Lunch at Beuno y Sano. Definitely check it out if you’re ever in the Western MA area.

It felt nice to step away from the apartment/computer. Of course, I have a notebook by me so that I could continue designing more levels.

20130427_144728

14 hours: Make one good graphic, get 6 bad ones free!

Posted by
Saturday, April 27th, 2013 11:24 am

Just about to head off to lunch. I’ll leave the laptop behind and bring my notepad to do some level design and maybe come up with slightly better drawings to turn into textures for the rest of the items in the game. I might skip out on the animation stuff, and work on changing levels / ui / story / sound. If I find time by the end of tomorrow, I’ll consider putting the animations in.

second

4 hours in: working prototype

Posted by
Friday, April 26th, 2013 11:05 pm

I’m now four hours into LD, and I have a prototype. This is farther than I got last time (at this point, I had quit :P)

 

The prototype has a level-loading capability so I can easily make levels using ascii art…

var levels = {
		'0' : [
			'                ',
			'   _            ',
			'                ',
			'__S_____________',
		],
		'1' : [
			'     _          ',
			'                ',
			'   _ST___       ',
			'                ',
			'__S____S________',
		],
	}

You can kind of make oue the ground (underscores). S is a springboard, T is a trap door. The result (level ‘1’) is on github, where there is also a link to run the prototype. Use left and right arrows to move.

Going to sleep now (well, going to bed with my notepad, but you know..). Goals tomorrow:

1.) Eat and Shower

2.) Start putting together actual levels using the prototype, including additional types of items.

3.) Once I feel comfortable with a few levels, build some graphics (including animations).

Idea Solidified!

Posted by
Friday, April 26th, 2013 9:24 pm

In attempting to come up with something for the theme, I scoured the internet and found this quote:

Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. – Antoine de Saint-Exupe

Basing on this, I started thinking about a game where you needed to take things away from the game to win. I had a few different ideas, and decided on a platform/puzzle style game where you need to walk around removing the obstacles as you go.

I’m a code-first-make-horrible-art-later type, but what the heck, first screenshot..

 

first

 

 

Also, due to the magic of github, my game should be up to date as I push code…

https://github.com/markhildreth/ld26

Just jumped on to say “I’m in”, but seriously…

Posted by
Monday, April 22nd, 2013 6:43 pm

So, I’m planning on trying to throw some stuff together in HTML5. Not planning on anything fancy, just gonna’ try to FINISH something this time.

I should be continuing on my warmup stuff, but, the only thing I can really think is…

 

3u1qet

 

 

(PS: If you’re confused like me, be sure to read the stickied “Theme Voting Begins” post)

Status Report: 33 Hours Left – Starting from Scratch :(

Posted by
Saturday, August 25th, 2012 8:27 am

I slept on my other idea, then promptly got to work making it after waking up.

About 45 minutes in, I was already sick of working on it. The game itself might have been an okay idea, but I figured I would need to do a lot of work just to get it playable, and that scared me.

There will be future LDs (where I will perhaps have a better plan going in), so I’m going to try to keep it a bit simpler. I’m going to make a platform/puzzle hybrid. Basically, it’s pretty simple platformer. You play the level, although finishing it is optional. Then you get to choose from one or more “positive” rule changes. Something like “your character jumps higher”. You need to be able to finish the level with this rule. Once you do, you will now need to choose from a list of “negative” rule change (like “you can only jump three times”). All the rules you have picked in the past affect the levels in the future.

First things first: get the platformer going. This should be pretty simple. Then I can build up some more rules and start implementing them one by one.

Status Report: (43 Hours Remaining)

Posted by
Friday, August 24th, 2012 11:19 pm

I received the theme by mail on my phone while at the bowling alley with some co-workers. I promptly looked for the rest of the e-mail where it would say “Just kidding! It’s XXX”. I also checked the website. No, it really is evolution.

At a loud bowling alley, I tried to steal some moments away to think about possible game mechanics, but all I could come up with is “evolution of bowling”. Yeah, I got nothing there.

Anyway, on the ride home I decided I would start naming occupations. Just trying to do SOMETHING other than just repeating “evolution… evolution” over and over, like that would somehow help.

The first occupation I came up with was “Pilot”. I thought about a game where you are a pilot, and the course had a number of different obstacles. Some obstacles you might be better at than others, and the ones you do worse on are the ones you’ll encounter more of in the future. Of course, this being my first idea I immediately threw it out.

I also figured it likely that biological evolution would be pretty standard, as it was another idea I had. So I started trying to concentrate on other definitions of “evolution”. Really, in the end, it came down to the fact that many small changes occur that will eventually produce a large result.

Somehow, I thought about the “large result” as the “goal”, and the “small actions” as what the player does. I instantly thought about a game idea I had a year or so ago where I would create an entire town and allow the player to interact with various characters at various times. These small interactions would change the way people view other people. I went down this road for awhile:

The game makes you the “Ghost of Fate” in a town, and you have to get people interested in topics. For example, Little Frankie should grow up to become a scientist, while Suzy and Derek should fall in love.

I started to realize that there would be a TON of graphics and interactions that would need to occur for this to work. I soon just rubbished the entire idea, and tried to move on.

I eventually came back to it, though. At some point (I’m not sure how) I came up with the idea of a “Summer Camp”. Rather than an entire town, you are a lead counselor of a summer camp, and are given a goal (“win the water marathon race against the rival camp at the end of the week”, “help Derek have his first kiss”, etc.) You do this by interacting with the the campers to find out their various likes/dislikes, who their friends are, picking up rumors of love triangles, and convincing them to participate in different activities throughout the week. If you want to win the water marathon against the rival camp, you might want to get Steve to anchor your canoeing team. But Steve probably won’t want to do the canoeing activity during the week, because his friends seem to prefer swimming. If you could convince Stephanie (the girl Steven has a crush on) to join Canoeing, then we might have a different story.

I have some worries:

1.) Game Complexity. I’m mocking the entire game idea on paper, and I think if I limit the amount of interactions, the code for this shouldn’t be that hard.

2.) Graphics: It’s a game about a lot people doing a lot of activities. I suck at drawing. If I can find a good way around drawing a bunch of people, I will, but I might need to spend a lot of time just doing graphics of faces. This seems entirely ok to me, since I think I could get away with cartoony-style faces alright. The environments might be a bit different though.

 

Well, I got a few hours late start, but at least I have an idea. It’s not entirely fleshed out, but it’s ready for me to start coding. However, it’s 2AM, so I’ll give myself some rest, then start tomorrow.

I’m in, but WTF happened to July and August

Posted by
Monday, August 20th, 2012 12:25 pm

So yeah, that whole “I’m going to make some libraries and learn my tools”. Never happened. Oh well.
Here’s what I’ll be using:

  • Python and Pygame
  • Either cx_freeze or pyinstaller to build executables
  • Some home-grown libraries: (Funcompose as a rendering engine on top of pygame, Pythfinding is a pathfinding library written in pure python that has the feature of sometimes working correctly, pyinstaller_tools as a layer on top of pyinstaller if I go that way, and calcui to help with laying out user interfaces (if I start getting fancy with them).
  • One of the sound effects generators in the Ludum Dare tools section.
  • FL Studio for music.

Creating Executables for PyGame

Posted by
Tuesday, July 24th, 2012 6:04 pm

I’ve continued working on my prototype games using my overengineered game engine (ffld). In the last few weeks, I’ve started work on improving how I can build interfaces for games, as well as packaging the game into its final form. This post will discuss the latter.

My plan is as follows:

Code all of my project on Linux, using virtualenv and pip to install smaller dependencies

I’m a big fan of using virtualenv and pip to control my dependencies. One really nice thing is that I can keep my various projects and libraries in separate directories, then install them into eachother as necessary without having to move them around. If I install using “python setup.py develop”, then I can make changes to one library and have those changes instantly usable for another project (no need to reinstall the library). This means I don’t need to worry about moving directories around, or setting up symlinks, or anything like that. pip also makes it very easy to install a specific version of third-party software from pypi on a per-project basis.

Use two Windows virtualbox machines

To build to Windows, I’ll need one machine to actually perform the build. This machine needs to have all the software that is used to build the game. After the build is complete, it is packaged into a zip file, and I will transfer the zip file to a second Windows machine. This second windows machine has a “clean” build; it has nothing installed on it (no Python, no Pygame, no Microsoft Redistribution Package). Basically, if my build works on that computer, it should work on most computers of the same Windows Version.

I will once again use virtualenv and pip on Windows to handle all the dependencies. Of course, this will need to be a separate folder, but I don’t need to copy any code over since I can still access the code from a shared drive.

Use Pyinstaller

I’ve never had much luck with py2exe, so I tried out Pyinstaller, and it has worked pretty well. (Note: the name “pyinstaller” is actually a bit of a misnomer… it doesn’t actually build an installer; it just builds the exe and data structure needed for the exe to run standalone). I was able to use the default options of the tool to build an .exe with all the dependencies needed (including my custom dependencies like ffld, as well as dependencies that require DLLs like pygame). It even worked with virtualenv-installed dependencies.

The only issue that I had with it was that you needed to run the scripts inside of the pyinstaller directory. I really wanted to run the script from the directory where my virtualenv is. There was additionally a three-step process to create the exe, which I reduced to two (and hope to soon reduce to one). In the end, I wrote a script that wraps around pyinstaller. You can find that script (builder.py) on github. Now, I can do the following…


# Create a new 1942 directory. This sets up a new folder with a virtualenv.
# It saves the name of the main script (which pyinstaller needs)
# for later commands.
# This needs to be done once for a project.
python builder.py create 1942 E:\games\1942\1942\main.py

# Now I activate the 1942 virtualenv and install dependencies as I need to
# using the windows command line. This needs to be done once, although
# if I later add new dependencies, I need to install the dependencies
# to the virtualenv.

# Finally, build the game!
# This runs pyinstaller’s Configure.py, Makespec.py and Build.py
# scripts. When done, it adds the “data” directory that was found
# for the game to the distribution folder, then zips up the
# distribution folder and plops it out into the current directory.
python builder.py build 1942

I try to get any software I write close to a one step build. As Joel Spolsky writes in his post, your entire program should be able to be checked out of source control, compiled and packaged into the final format in exactly one step (typically, clicking or running a build script). Any more steps than that and you will waste time (both in running the steps and making user errors in the process). This is true of any software, but it would seem especially so of Ludum Dare. I don’t mind a few set up steps, so long as after I make that set up, I can rebuild the entire program later with just one command.

Feel free to use the script, although realize that it’s not going to work for you out of the box. I assume that pyinstaller is in a specific location, and that the script being used as the “main” script has a “data” directory next to it that will house all data.

Graduating from Programmer Art

Posted by
Saturday, July 7th, 2012 2:00 pm

As I discussed in my previous post, my largest perceived weakness going into an event such as Ludum Dare was my graphic-making abilities. This past weekend, I took my first step toward exercising that particular skill. Prior to this weekend, I had never created a sprite in my life (that wasn’t entirely one color). Heck, I never even doodled in my notebook in middle school.

Where to Start?

At first, I really didn’t know how I would go about improving myself. Isn’t the designing of sprites just art? Isn’t visual artistic ability just something you’re born with? My brain is so imbalanced to the left hemisphere that I’m constantly falling into traffic. What kind of fool’s errand am I going on here? However, throwing doubt to the wind, I set out to build a sprite.

The first task I gave myself was to pick a graphics tool. I tried some of the ones list in the Ludum Dare Tools section, but didn’t see anything that struck my fancy. At one point I was on Chapter Two of a PyGTK Tutorial in the hopes to build my own tool. Luckily I shut down that bit of insanity. Eventually, I decided to just work with good ole’ Gimp, which worked better than expected.

Next, I went scrounging for tutorials. I didn’t think I’d actually find anything worthwhile, but I was badly mistaken. If you’re a programmer looking to get started with Pixel Art, you MUST read Derek Yu’s Pixel Art Tutorial. It breaks things down step-by-step, which is extremely helpful. Don’t be afraid by Derek’s amazing looking image, the ideas transplanted just as easily into my practice images.

I started very simple: following the tutorial to create a dead-simple picture (a machete). It wasn’t too shabby, but it was also a pretty simple image to begin with. So I decided to go with something a little more advanced to really test myself. I already had some sprites pulled from the NES Game “1942” to use for graphics in a game I’m screwing around with, but maybe I could replace them with some sprites of my own. So, I would use the tutorial’s lessons to create my own sprite of a fighter plane.

Step One: Draw a Concept

Some Clip Art I found to use as inspiration

For me, step one was to get an idea of what I wanted to draw. For Derek, this is Part Three (yeah, I’ve purposefully renumbered the steps to make things confusing for you). First, I googled for a top-down view of a plane, and found something to use as a concept. Next, I tried to draw with pencil and paper a likeness of this plane. I’m not really sure why I decided to do this (after all, I already have some concept art in front of me) but it just felt right. Later I decided that this worked pretty well, as the image I drew was something that I knew I could at the very least draw, which gave me a boost of confidence. It also allowed me to customize the image a bit more to what I wanted. Now to be sure, my drawing abilities are very sub-par (and fortunately for you, I didn’t scan the image I drew), but by studying the original image part by part, I was able to get something decent.

Step Two: Pixel an Outline

I created a new 64×64 pixel image in Gimp, and prepared to embarrass myself. Finally, I ended up with the following:

Some things to note about this:

  • Although you don’t see it in the screenshot above, when working in Gimp I made sure to enable the grids so I had lines separating pixels.
  • There are some jagged lines. While I did heed the tutorial’s warning, I felt that there wasn’t much I could do about some of the jaggedness, particularly near the back of the wings. I hoped that they would come out later in the process.
  • Learning how to use the various Gimp tools to draw/erase/etc in a straight line is pretty helpful. Particularly, it is faster to use this method to draw a line rather than placing every pixel with the pencil tool. Even lines that are drawn at strange angles will give you pixels to start with, and you can just fine tune the resulting line with either the pencil or erase tool
  • Speaking of the erase tool, you’re obviously going to need to set it to “Hard Edge”.
  • One tip is to have a second view open to see what the image looks like in it’s actual size. After you’ve opened your Gimp window and have zoomed in on the image so you can work with the pixels, click “View -> New View”, and Gimp will give you another window that you can set to a different zoom (which is probably best to keep at the default zoom)

Step Three: Add Color

The next step was to add color. I bucket-filled the areas. This was actually pretty nice, since I have always been under the impression that if you bucket-fill a sprite it’s going to look terrible, and the only way to get something decent is to color each pixel individually. You’ll also see that I decided to add a propeller blade to the front for no particular reason.

These are just three colors that I randomly picked. Some day I might actually learn about color theory and all that, but I’ll save that lesson for some other day. Already, I’m pretty darn impressed. I would be happy with this! However, there is more that can be done.

Step Four: Shading/Lighting

The next part is what really makes the image “pop”.

I’m not sure if I got it “right”, but I did get… something. Notes on this step:

  • The basic idea, as explained in the tutorial, is to pretend that there is a source of light, choose the direction it’s coming from, and draw where the shadows should go. Also, lighten where the light hits directly. I sort of changed my mind up half-way through where the light was, so I might be kind of all over the place. Especially on the right side of the tail section. However, it should be pretty clear that the light is above the plane’s vertical axis, and to the left.
  • Here, the dodge/burn tool is your friend. The dodge will lighten, and the burn will darken the pixel you click. Remember to set the tool to “Hard Edge” or else it will affect multiple pixels!
  • Although it might be obvious to some, this wasn’t to me: if you have the default color for the pixel and you dodge (lighten) it, then decide you’d rather keep it at where it was, doing a burn (darken) will NOT get you back to your original color. You’ll need to undo, or just redraw the pixel
  • I reread the tutorial after I was done, and one tip was to do the shadows (darken) first. You’ll end up drawing more shadows this way, which sounds like a good thing. Think about it: with a single point of light, you will have more areas with less light (shadows) than you will being directly hit by the light. I’ll have to keep this in mind next time.

Step Five: Selective Outlining

As you can see, the pixels that I drew for the outline back in Step Two have been dulled down to the colors that are surrounding them. This makes the image less “hard” (or using Derek’s words, “less cartoony”).

  • I made use of the “Smudge” tool. As with the other tools, I made sure to set the “Hard Edge” option so that I would be affecting one pixel at a time. The way the “Smudge” tool works is you click and hold your mouse button on one area (i.e., a blueish pixel in the cockpit window ADJACENT to a black “outline” pixel in the cockpit window), and then drag the cursor INTO the black “outline” pixel. You can think of it as smudging your finger across the page, pushing some of the blue onto the black. Really, what this means is that you get some blend between the dark black and the light blue, without needing to manually pick the dark blue color. The cockpit glass is where it’s most noticeable, but I did it for the majority of the outline pixels.
  • Unlike the other tools, the Smudge tool requires a bit more finesse, since you have to “drag” color from the correct source pixel into the correct destination pixel. Obviously, this can be a pretty long process for all of the outline pixels. If I knew that there would be a large group of pixels in a row that would all have the same smudge source color, then I would smudge one of them. After, I would use the Color Picker tool to select the new color that was created, and use the pencil tool to draw that color onto other pixels that would do the same thing. This was especially effective for those long, straight lines of outline pixels.
  • One thing I could have concentrated on more was to do the selective outlining a bit lighter on the very outside edges of the sprite, as suggested. I played around a bit with the smudge settings, but could have gone even further by using the dodge tool to lighten up these pixels even more.

I Survived!

It’s by no means worthy of the video game hall of fame, but it’s better than stick figures. Some final thoughts on this entire process:

  • In total, it probably took me a bit over an hour for this one sprite. I imagine I can cut this time down by knowing the keyboard shorcuts for gimp, which I was only partially familiar with. Another was the fact that I did this using the trackpad on my laptop. A mouse on a desktop would probably be faster.
  • While Gimp has great toolage for messing around with a single image, I can imagine creating animated sprites would be difficult. On the one hand, Gimp has nothing built in to animate the sprite as you’re creating it. On the other hand, it would not be too hard to write a program that simply animates the sprite for you that you can stick into one corner of the screen while Gimp is open.

Comments/criticism welcome!

Strengths and Weaknesses

Posted by
Thursday, July 5th, 2012 11:00 pm

My first step in planning out this Ludum Dare is to analyze what I can do right now. The goal is that in the next 50 days, I can spend time between exploiting my strengths and working on my… less than ideals.

Major Strength: Programming

My biggest strength, IMO, is my programming ability. I’m constantly on the lookout for ways to reduce complexity in how I write my code. I’m not going to claim that I’m anywhere near where I want to be (the ideas of functional programming is something I’m pretty interested in learning, even if it just means bringing some good ideas over to my imperative code), but I believe I have enough experience in other programming pursuits to tie back into game development.

One thing I’ve enjoyed doing is writing code that doesn’t necessarily work, but succinctly describes what I want the program to do. In game parlance, I’m developing code that should only care about the logic of the game. Anything about sprite rendering, entity storage, etc, should be handled by some outside, magical framework that reads my mind, bakes me cookies, and does all of that boilerplate stuff for me. Then, I build that magical framework. Minus the cookies and telepathy.

1942 Clone Screenshot

It’s not much to look at, but it will do as a test case.

You can view the results as I go on my bitbucket page. Right now, there are two “games” in early development (a 1942 clone, and a physics-based platformer). They both are supported by the same Python framework, ffld (“Framework for Ludum Dare”) that I write during development. I’ll go more into detail of the framework in later posts. For now though, I will say this: while the name of the framework might seem to insinuate otherwise, the goal is not to cut corners. Instead, the goal is to allow for the modularity of common code for game essentials (e.g., physics, collision, graphics rendering, asset loading, game entity tracking) , leaving only for the custom logic that will make my game unique. Of course, to keep the scope creep down, I am adding some constraints; it will only support 2D games, and be based around pygame. At some point later, perhaps I’ll look into expanding to OpenGL, but pygame works will for my needs currently.

Hopefully, my development will be a large asset to rely upon. As far as strategy goes, this means that when coming up with a game idea, I will be better off sticking to an idea more interesting from an interaction point of view, as I have no worries with being able to throw together the strange code needed to cause it all to work right.

Major Weakness: Graphics

Pitfall: The Mayan Adventure Screenshot

Not by me. Not in a million years.

As of today, I can’t build a grass texture to save my life. This is my biggest fear: that no matter how cool or unique of a game I can build from a game logic standpoint, the graphics will just look childish. I’m heartened by viewing some past Ludum Dare winners who eeked by on pretty cheesy graphics. I’m pretty sure one of the reasons that I never did more game development in the past was because it was so exhausting trying to find graphic assets. Sure, you could find a cool sprite sheet here and there, but not enough to make a full game. You want another sprite, similar to the one you found online, for the next level? Not with these two left hands abusing my gimp window (I guess one of my other weaknesses is taking the time to develop relationships with people who could help in this regard).

And so, one of my large goals that I have tasked myself with achieving over the next 50 days is to become better at making graphics. This does not mean that I plan on becoming a turtle-necker. My goal here is not Pitfall: The Mayan Adventure. Realistically, my hope is to get into a situation where I can develop graphics that pass as… well, whatever they are supposed to look like. Maybe just one step above “programmer art”? I feel that with some work, I could probably make some grass textures that are more than just surface.fill(GREEN) if need be.

The Other Attributes:

Music/Sound

I don’t have much experience generating sound, but a quick look over the various toolkits shows that it doesn’t appear to be that difficult (some of it can be randomly generated very easily with tools such as bfxr and sfxr. In the coming weeks I hope to play some more with these tools. I doubt I would want to concentrate too much on this, but I realize that music and sound will contribute to the overall atmosphere of a game in a way that could be very time-effective. Even spending a single hour making a quick song, and another for adding sound effects, could be the difference between a hack and a game.

Planning and Research

Well, considering I have a gameplan of things to do 50 days before the event, I’d like to think that this is all pretty good. At some point I like to think that I’ll do a full mapping of my time during the LD weekend (When will I sleep? How long should I spend on design? How long can I develop the game? When do I call it done and spend the rest of the time polishing? How much liberty would I allow myself to deviate from such a schedule?) I also plan on reading some more post-mortems and other tips around the LD site. Of course, I could very well go into this thinking I’ll just let my first Ludum Dare hit me like a ton of bricks and learn for the next one. I feel, however, a certain pleasure in the humility of watching my best laid plans  get absolutely destroyed.

Writing

While I don’t have a lot of writing experience, I do like to think that if I take my time I can be a pretty decent writer. That being said, LD isn’t about taking your time. I don’t plan on using writing to much effect since it is pretty time-consuming, but that might change if I find myself with an idea that doesn’t need a lot of code to do. Perhaps in a future LD, when I feel a little more comfortable, I will try to make a story share the spotlight of one of my games.

 

[cache: storing page]