fredag 24 juli 2009

What's next?

In pondering which kind of game I wanted to make I uncovered and discarded many options before finally settling on this puzzle game idea. However, the roads left unexplored might still be pretty interesting, especially considering that the puzzle game won out mostly by account of its simplicity. Anyway, some other ideas I was toying around with were:

* A massively-multiplayer online role-playing game exploring race relations in contemporary european society. Graphics engine based on a octree ray-trace rendering architecture proposed by John Carmack.


* A shooter game based on Herman Melville's Moby Dick, but set 200 years in the future. The game would let the players assume the role of either a cybernetically enhanced captain Ahab or a cybernetically enhanced whale.

* An adventure game similar to Metroid / Prince of Persia / Cave Story in which the protagonist is a tomb-raiding Indiana Jones ripoff. The graphics would be simple and unassuming - 2D sprites in a style reminiscent of old NES games - but the actual game content would be all the more ambitious.

"Indiana Jones platform adventure" is not a really goundbreaking concept - it's been done before, more than once, in fact- but that's not something that really deters me. The idea for making this game came from:

1.) reading Jordan Mercher's journal from the development of the original Prince of Persia

2.) skimming through this transcript of meetings between George Lucas, Steven Spielberg and the scriptwriter for the first Indiana Jones movie, wherein they discuss the story in the first Indy movie

Anyway, I've been thinking about doing a Cave Story game for a long time now, but it never got anywhere but really vague ideas and some notes scribbled down and filed away indefinitely. However, right now I feel like I have a pretty clear vision of what I want this game to be and how to make it.

What this game is supposed to be - narrative hooks

Some time ago I got Castlevania: Portrait of Ruin for my Nintendo DS. The game was fun for a while, but after putting maybe five or six hours into it I never touched it again. Why? The reason was, I think, that all I had been doing was killing monsters. There was no suspense, no feeling like there's a mystery you want to solve, or some unknown territory you want to explore. There was no compelling reason for me to go back, because all I expected to find was new monsters.

In the Metroid games you're always wondering what's in those areas you can't access yet - the game gives the player a lot of tantalizing secrets, questions that the player is just dying to find out the answer to. I remember reading the Harry Potter books and observing something similar - there's a structure in wherein the reader is presented with lots of mysteries, some of which will be unravelled in the short term ("Who's making the crying sounds in the girls' bathroom?") and some of which pretty much span the whole book ("Who's the bad guy helping Voldemort from within Hogwarth's?"). When an answer to a smaller mystery is revealed the reader is relieved, but still she finds herself wanting more because there are even greater puzzles to be solved.

If I remember correctly there is also some overlap between the unravelling of an old mystery and introduction of a new the one. This keeps the reader "trapped", so to speak - you want to find out what was behind the crying noises in the bathroom, but when you've almost arrived at the conclusion you get hooked by some other unanswered question ("Was that a snake?"), which is even more compelling than the last one. When this story structure gets completely out of hand you get something like Lost, which is completely addictive at first, but brutally disappointing when you eventually realize the writers seem no more hip to what's happening than you are.

Setpieces & Puzzles

I also want this game to have a lot of setpieces, puzzles and other things that deviate from the standard mode of play. For example, one thing that I pretty much stole entirely from the Lucas/Spielberg conversation is the collapsing roof:

Our hero enters a narrow tunnel. Afer a few steps he notices the skeleton of a previous adventurer - terribly mishappen, as if it had been squashed flat somehow. As he progresses he sees more and more of these skeletons and suddenly there's a creaking sound coming from the roof - it's slowly collapsing, about to crush him! If the player starts running back at this point he will just be able to squeeze out of the collapsing tunnel, Millenium Falcon style. The solution to this puzzle could be for the player to carry with her a block of stone to stop the crushing floor (there has to be previous puzzle involving these stones, or the player might not think of using them, or they need to be right there, which makes it too obvious). Alternatively this could be some kind of pushing puzzle where the player realizes that he might be able to push a statue (or something similar) down from a floor above, and then use it to keep the roof up. Maybe some kind of ramp has to be constructed first, or the statue might land on too low ground to fit in the tunnel, etc.

A good precursor to the crushing roof puzzle might be one where you have to jump off of a stone block to be able to reach a high ledge. Later, you might even have to construct a small staircase since you're carrying a stone block and can't jump as high.

Clearly, there's a lot of places you could go with puzzles like this and it will add variety to gameplay which would otherwise get pretty repetitive.

What would be really great is if we could make it have lots of adventure / puzzle game elements, like Monkey Island or Grim Fandango but in a platform game. Why not?

A love interest and a nemesis? Story elements

Maybe we can squeeze in a romantic subplot as well, as long as it's not about the main character setting out to rescue his girlfriend (that plot was old even when they did it in Kung Fu). This depends on what kind of an atmosphere we want - Metroid thrived on the fact that you are the only human on planet Zebes, which gives it a very different feeling of vulnerability and isolation than games where there are NPCs you can interact with. Tombs could be a perfect setting for creating that kind of feeling, but I'm not sure that's what we want.

For a more serial adventure feel, we need a good villain. Prince of Persia had some kind of shadow version of yourself who would steal health potions and otherwise annoy you. I think this could be a great device for seriously pissing the player off - they see a really nice power-up, laid out right in front of them, and this other guy just pops out and snatches it from them. They would really hate that guy's guts!

Maybe this can be expanded into some kind of larger story context, which gives the player extra motivation for progressing in the game. She could hook up with some underground civilisation (hello Cave Story) and there's this internal conflict between the good underground people and the bad underground people and of course you side with the good guys and the antagonist sides with the bad guys. Anyway, we could make the player be part of something larger than just exploring tombs.

Technical requirements

Powerful scripting language, maybe even a DSL. A powerful editor with script support.

Note to self: I should read Swords & Circuitry

torsdag 23 juli 2009

Done with the basics

I have completed a very rudimentary but pretty much fully functional (as far as game mechanics are concerned) version of the game! The player can move the rows of squares, and lining up three or more squares result in them disappearing. Still not even a hint of graphics or keyboard control though!

Had a bit of trouble with the function for finding lines to clear, but I managed to sort it out eventually - I was a little bit too tired to really think/care about what I was doing, which is like the height of false economy ("save a penny, spend a pound"). The code could be prettier, but never mind that, I can always clean it up later.

Architecturally I'm still pretty pleased with the program and hopefully I will manage to keep it that way - these things tend to deteriorate as time goes by ;)

Right now I think it's plausible to keep the current game pretty much as is and then build a View and a Controller on top of it, making the game the Model in a Model-View-Controller architecture. I kind of had this in mind from the beginning, and for some reason I built my "blocks falling down"-routine so that blocks would only fall down one square per update. I told myself this would be a requirement for building it as an MVC - now I can't really give a good motivation why.

Anyway, I've been playing around with this text-only version a little bit - trying to match up colours is kind of fun, but sitting here bored at work with nothing to do my perspective might be a bit warped ;)

Still haven't decided how to actually give the player a challenge - there will clearly be more blocks appearing on the playing field in some way or other, but where will they come from and when? What could trigger this terrifying torrent of trapezoids?

EDIT: Something just struck me - the game doesn't have a name yet! I encourage all visitors to this blog to leave your suggestions, and they will be subject to the most vicious sport of all - the name-a-game contest!

EDIT 2: Just checked the number of lines of code: 203 in total, which isn't too bad, especially considering half of that is probably whitespace and stuff I've commented out but never bothered to delete. So there you have it, something resembling a game in less than 200 lines of code! That's the power of Python ;)

onsdag 22 juli 2009

More work done

Okay, not really close to a playable version yet, but feels like it's almost halfway there ;)

In my previous post is all the code so far, almost all of it written today... it's evolved into quite a program, I do say!

Some explanation of what it does: The program below lets you play around a little bit with the mechanics in the game - the user can move rows of blocks either to the left or right, and if this results in any "gaps" in the stack of blocks it will collapse appropriately.

As the observant reader might have already noticed, there are no graphics modules loaded - the game is, as of now, played only in the Python shell. Moving the rows of blocks is accomplished by typing which row you want to move, and wheter you want to move it left ("l") or right ("r"). As you can see it's still pretty spartan at this point.

Anyway, next thing to implement is the function for determining if a row of blocks should be cleared or not - arranging blocks in the same colour in rows of three makes the blocks disappear and adds to the player's score. Creating "chain reactions" this way - clearing blocks in a way that result in more blocks being cleared - gives the player bonus points. Getting these "chain reactions" will be the main challenge of the game, and creating clever block setups will hopefully be as fun and rewarding as getting a huge combo in Tetris Attack, another game I've ripped off been inspired by ;)
source:
import random

def fall_down(playing_field):

    anything_fell_down = False

    #Make a temporary copy for checking for empty spaces
    #(modifying the list we use to check for empty spaces will result in errors)
    tmp_list = playing_field[:]
    
    for i, row in enumerate(playing_field):
        for j, square in enumerate(row):
            #Check that we're not at the bottom
            if i < len(playing_field) - 1:
                #If we're not at the bottom, make stuff fall down
                if tmp_list[i + 1][j] == 0:
                    playing_field[i + 1][j] = playing_field[i][j]
                    playing_field[i][j] = 0
                    anything_fell_down = True

    return anything_fell_down


def fall_down2(playing_field):
    anything_fell_down = False

    for i in range(len(playing_field[0])):
        #Keep track of where the lowest hole is
        last_hole = 0
        for j in range(len(playing_field)):

            #Look for holes
            if j < len(playing_field) - 1:
                if playing_field[j][i] != 0 and playing_field[j + 1][i] == 0:
                    #print "hole at ", i, j + 1
                    anything_fell_down = True
                    last_hole = j + 1
       
        #Make what's above the hole fall down one notch             
        if last_hole > 0:
            for m in range(last_hole):
                playing_field[last_hole - m][i] = playing_field[last_hole - m - 1][i]
                #print "moved [", last_hole - m - 1, "][", i, "] to [", last_hole - m , "][", i, "]"
            #The first row in the column should always be "0" if stuff fell down, so set it:
            playing_field[0][i] = 0

    return anything_fell_down

                    
def move(direction, row, playing_field):
    if direction > 0:
        playing_field[row] = playing_field[row][-1:] + playing_field[row][:-1]
    else:
        playing_field[row] = playing_field[row][1:] + playing_field[row][0:1]


def find_lines(playing_field):

    #Find horizontal lines
    for row in playing_field:
        for i in range(len(row)):
            counter = 0
            while i + counter < len(row) and row[i] != 0 and row[i] == row[i + counter]:
                print "compare ", row[i], " to ", row[i + counter]
                counter += 1
            print counter


#initalize playing field
playing_field = []
dimensions = (8, 6)

for i in range(dimensions[0]):
    playing_field.append([None] * dimensions[1])


#populate playing field
for row in playing_field:
    for index, square in enumerate(row):
        if random.random() > 0.5:
            row[index] = random.randint(1, 4)
        else:
            row[index] = 0

print playing_field

print "\n"
for row in playing_field:
    print row

##fall_down2(playing_field)
##
##print "\n"
##for row in playing_field:
##    print row

##print "\n"
##for row in playing_field:
##    print row


while fall_down2(playing_field):
    print "stuff is falling"

print "\n"
for row in playing_field:
    print row

print "\nLet's play!"
print "Type which line you want to move and in which direction (in that order). Use 'l' and 'r' for moving left / right respectively"
print "Example: '5 l' moves line five to the left"

while(True):

    
    input_string = raw_input().split()

    direction = 0
    row = input_string[0]
    
    if input_string[1] == "l":
        direction = -1
    else:
        direction = 1

    move(direction, int(row), playing_field)

    print "\n"
    for row in playing_field:
        print row

    find_lines(playing_field)
    


tisdag 21 juli 2009

Grundkoncept

Okay, I've decided to make a puzzle game with coloured blocks (pretty original, right?).

The player has a game board with stacks of blocks, and can move a row in the stack either to the left or right. If three(?) blocks of the same colour make a row (horizontally or vertically... what about diagonally?) they disappear, and points are added to the player's score. If this in turn leads to more blocks disappearing as the stack collapses (gravity!) you get extra points - the player's goal is to create chain reactions akin to the ones in Puyo Puyo.

There also needs to be an element of danger - if the player is too slow, taking her jolly time, she must be punished. Maybe a new row of blocks will appear if the player failed to remove any blocks in her previous move? Also, as is the standard in these games, you get a "game over" if the screen fills up with blocks.

That's the basic concept - here's how I'm thinking the flow of program should look like:
1.) The player moves a row of blocks
2.) Check if there are blocks with no blocks under them, i.e. they're "hovering"
2.1.) If hovering blocks are found, make them fall down
3.) Check if there are any rows of three of blocks of the same colour
3.1.) If rows like that are found, remove those blocks and go back to 2.), else go back to 1.)

Okej, jag har bestämt mig för att göra ett pusselspel med färgade block (originellt, eller hur?). Spelaren har en spelplan med massor av block, och kan flytta alla block i en rad ett steg i sidled. Om tre(?) block i samma färg ligger i rad (vågrätt eller lodrätt, men inte i sidled?) så försvinner de och spelaren får poäng. Om detta sedan leder till att fler block försvinner genom att högen med block kollapsar får man extra mycket poäng - målet är alltså att skapa kedjereaktioner (precis som i Puyo Puyo).

På något sätt måste också spelaren straffas om hon är för långsam - kanske en ny rad av block dyker upp varje gång man flyttat block utan att lyckas ta bort några? Spelet är slut när spelplanen är helt fylld av block.

Det är det grundläggande konceptet. Så här hade jag tänkt att programflödet skulle se ut:

1.) Spelaren flyttar en rad block
2.) Kolla om det finns block som inte har några block under sig ("hänger i luften")
2.1) Om det finns sådana, låt dem ramla ner
3.) Kolla om det finns några rader av tre block i samma färg
3.1) Om det finns några rader, ta bort blocken och gå tillbaka till 2.)