The Professional Steve

Tutorials, developer resources and inspiration.

Snake Log 9: Some Bugs Squashed

Yesterday I fixed two bugs (the scrolling issue, and the edible block appearing on the snake) and did a fair bit of work on another (when you hit different arrow keys too fast the game restarts). The intermittent freezing issue seemed to disappear and then reappear throughout the day yesterday. I did a fair amount of refactoring of that code so it’s possible that the freezing issue is gone. There’s no way to tell without more testing.

I hope to have the arrow key issue and the disappearing snake issue solved today.

Snake Log 8: It’s online

In my last post about this game I said I was going to do some bug squashing, but immediately afterward I decided to tackle a few other things. One of the things I was encouraged to do when I was asked to make this game (as part of a job application) was to use the Underscore.js JavaScript library, possibly by using the RequireJS Javascript file and module loader. It was also suggested that I might make this game a Node.js app (Node.js is a web application framework) hosted on Heroku, a web application hosting service.

Well I’ve done most of that. The game is now a Node.js app and it’s online. The link is professional-snake.herokuapp.com. It’s using requireJS to load the Underscore.js library but I’m not using all that many Underscore.js functions. I plan to use more as I refactor the code and finally get around to squashing these bugs.

Snake Log 7: It’s playable!

Here’s the screenshot!

snake_shot_4

snake_shot_4

We’ve got a snake that grows in length and speeds up a little bit every time it eats a block. If it hits a wall or eats it’s own tail the game restarts. Booyah! Built a working game in a week!

That said there are a few bugs that need fixing: the game freezes intermittently when you hit a wall, the edible block sometimes appears on top of the snake and often too close, if you hit different arrow keys too fast the game restarts, if the browser window loses focus for too long the snake disappears, and the whole page scrolls slightly up and down when you hit the up and down arrow keys.

I hope to get these fixed today and tomorrow so I can get back to adding new features.

Python Lists of Dictionaries And Dictionaries Of Lists: Part 2

In our last post we started talking about creating more complicated data structures by starting to write a simple game. Here’s where we left off:

inventory = {"helmut":"sauce pan", "sword":"wooden stick", "armor":"winter coat",
             "items":["healing potion", "small rubber duck", "smart phone", "potato"]}

for inventory_item in inventory:
    if inventory_item != "items":
        print "Your " + inventory_item + " is a " + inventory[inventory_item]
    else:
        print "items in your backpack:"
        for item in inventory[inventory_item]:
            print "    " + item

Now let me add a little more to our project:

player_data = {"inventory":{"helmut":"sauce pan",
                            "sword":"wooden stick",
                            "armor":"winter coat",
                            "items":["healing potion",
                                     "small rubber duck",
                                     "smart phone",
                                     "potato"]}}

print "What is your name?"
player_data["name"] = raw_input()

print "You are " + player_data["name"] + " the adventurer."

print ""

for inventory_item in player_data["inventory"]:
    if inventory_item != "items":
        print "Your " + inventory_item + " is a " + player_data["inventory"][inventory_item]
    else:
        print "items in your backpack:"
        for item in player_data["inventory"][inventory_item]:
            print "    " + item

And here’s some output:

What is your name?
Mr.Potato Man
You are Mr.Potato Man the adventurer.

Your armor is a winter coat
Your helmut is a sauce pan
Your sword is a wooden stick
items in your backpack:
    healing potion
    small rubber duck
    smart phone
    potato

Before I get too far with explanations I should note that I’ve indented our player_data data structure just for readability, python doesn’t require us to indent the dictionary this way.

The additions I’ve made to the code are more of the same. It’s still just a nested data structure, but a little bigger. player_data is a dictionary that, at first, only has one key: “inventory”. The value associated with that key is the old inventory data structure we’ve been building.

Then after we ask the player their name we add another key and value to our dictionary. The new key is “name” and the new value is whatever the player wants to enter as their name.

Now let’s add a list of monsters. After all, what’s an adventure game without monsters for our player to fight?

import random

game_data = {"player":{"inventory":{"helmut":"sauce pan",
                                    "sword":"wooden stick",
                                    "armor":"winter coat",
                                    "items":["healing potion",
                                             "small rubber duck",
                                             "smart phone",
                                             "potato"]}},
             "monsters":[{"name":"Croco-Duck",
                          "attack":"Croco-Quacking"},
                         {"name":"Techno-Fish",
                          "attack":"Disco-Dancing"},
                         {"name":"Television News Anchor",
                          "attack":"Top-Notch Journalism"}]}

print "What is your name?"
game_data["player"]["name"] = raw_input()

print "You are " + game_data["player"]["name"] + " the adventurer."

print ""

for inventory_item in game_data["player"]["inventory"]:
    if inventory_item != "items":
        inventory_item_description = game_data["player"]["inventory"][inventory_item]
        print "Your " + inventory_item + " is a " + inventory_item_description
    else:
        print "items in your backpack:"
        items = game_data["player"]["inventory"][inventory_item]
        for item in items:
            print "    " + item

print ""

monster = random.choice(game_data["monsters"])
print "You've encountered a " + monster["name"] + "!"
print "The " + monster["name"] + " attacks you with " + monster["attack"] + "!!"

And here’s some example output from our program:

What is your name?
Elbows McGee
You are Elbows McGee the adventurer.

Your armor is a winter coat
Your helmut is a sauce pan
Your sword is a wooden stick
items in your backpack:
    healing potion
    small rubber duck
    smart phone
    potato

You've encountered a Techno-Fish!
The Techno-Fish attacks you with Disco-Dancing!!

So, what have we added?

Well, we went another level deep. The data structure has been renamed to game_data. The top level is a dictionary with two keys: “player” and “monsters”. The value for “player” is the same dictionary we’ve been using, and the value for “monsters” is a list of dictionaries, each of which contain “name” and “attack” keys. The values for these, of course, are the names and attacks for each monster.

The rest of the code is almost exactly like before, but where we used to have player-data we now have game_data[“player”].

Also, check out these lines:

        inventory_item_description = game_data["player"]["inventory"][inventory_item]
        print "Your " + inventory_item + " is a " + inventory_item_description

And these lines:

        items = game_data["player"]["inventory"][inventory_item]
        for item in items:
            print "    " + item

All I’m doing here is creating new variables to make the code more readable. Using the names inventory_item_description and items makes the code more descriptive than:

        print "Your " + inventory_item + " is a " + game_data["player"]["inventory"][inventory_item]

And:

        for item in game_data["player"]["inventory"][inventory_item]:
            print "    " + item

There’s a bit of personal preference here. You could argue that those variables are unnecessary but I think they make the code easier to read.

The only other truly new addition to this code is this line at the top:

import random

And this bit at the bottom:

monster = random.choice(game_data["monsters"])
print "You've encountered a " + monster["name"] + "!"
print "The " + monster["name"] + " attacks you with " + monster["attack"] + "!!"

All you need to know for now about the top line is that import random gives us more stuff we can use for our programs. Ideally you should never write code that someone, somewhere else, has already written. Why do unecessary work? If we want a random monster encounter in our game we could write new code to do that or we could simply use functions (more on functions later) that others have already written. By importing random we get a whole bunch of functions for generating random stuff or choosing things randomly.

The line:

monster = random.choice(game_data["monsters"])

does just that. We give the function random.choice our monster list and it will give us a random monster from that list.

Whew! I know that was a lot to take in, but now I hope you’re beginning to see just how useful data structures can be.

Tutorial Site: W3 Schools

If you’ve googled around trying to learn how to do something in HTML, CSS, or JavaScript, you’ve probably found W3Schools, but if you haven’t and you need to learn web development. This is the place to learn. w3schools.com has tutorials on HTML5, CSS3, JQuery, AJAX, JSON, SQL, and on and on and on and on… They are super great and easy to understand. I still use them all the time as reference.

Snake Log 6

We have a snake tail! Here’s a screen shot:

snake_shot_3

snake_shot_3

Problem is, the tail grows with ever corner turned. I don’t have that quite figured out but once I do I’ll need to make the snake’s tail grow, just a little, every time the snake eats a block.

After that there are a few bugs that need attention, and I also really need to refactor some of this code. Then I’ll need to add some more features, like restarting the game when you click on the screen, pausing with the spacebar, and so on.

I don’t really know how long the tail thing will take so let’s just say my goal is to have that and a few other bugs squashed by the end of today.

Snake Log 5

There might be something wrong with the code that chooses where to make the next block appear. The block seems to appear too close to the snake. At the moment I have one number for minimum distance from both the walls and the snake. The thing to do is to separate those into two numbers and do a bit of fiddling.

However I think my time would be best spent actually making this snake longer than a square. I have the basic idea for the algorithm in my head. I just need to implement it. I hope to have it done by tomorrow. Then I’ll tackle the new-block-location algorithm.

Python Lists of Dictionaries And Dictionaries Of Lists: Part 1

You may have heard the term Data Structures and, like me when I first heard it, been intimidated and confused. It’s really not a big deal. Data structures are structures of data. A list is a data structure. So is a dictionary. But I tend not to use the fancy term data structure when I’m talking about simple lists and dictionaries. It’s when you start combining them that things get interesting enough to justify the term.

In one of my last posts I started writing code that might help you make a game. Let’s keep going with that.

gear = {"helmut":"sauce pan", "sword":"wooden stick", "armor":"winter coat"}

Yup, that’s our standard dictionary. The keys are “helmut”, “sword”, and “armor”. The values associated with these keys are “sauce pan”, “sword”, and “winter coat” respectively.

print gear["helmut"]

gets you

sauce pan

and

print gear["armor"]

gets you

winter coat

And so on. This should all be old news if you’ve been reading my Python posts.

So what about this?

inventory = {"helmut":"sauce pan", "sword":"wooden stick", "armor":"winter coat",
             "items":["healing potion", "small rubber duck", "smart phone", "potato"]}

Have a look at that last key in this dictionary, “items”. Before this, the only values I’ve showed you for a key in a dictionary have been strings, but a dictionary value can be anything, even another dictionary or a list. In this case, the value for the key “items” in the dictionary inventory is the list [“healing potion”, “small rubber duck”, “smart phone”, “potato”].

So what happens when you try to loop over this list?

inventory = {"helmut":"sauce pan", "sword":"wooden stick", "armor":"winter coat",
             "items":["healing potion", "small rubber duck", "smart phone", "potato"]}

for item in inventory:
    print "Your " + item + " is a " + inventory[item]

Well, you get this output:

Your armor is a winter coat
Your helmut is a sauce pan
Your sword is a wooden stick
Traceback (most recent call last):
  File "list_loops.py", line 5, in 
    print "Your " + item + " is a " + inventory[item]
TypeError: cannot concatenate 'str' and 'list' objects

Basically, our loop can’t handle this more complicated data structure, but it’s no thing. We’re programmers. We have the technology. We can give our program special instructions to handle the item list:

inventory = {"helmut":"sauce pan", "sword":"wooden stick", "armor":"winter coat",
             "items":["healing potion", "small rubber duck", "smart phone", "potato"]}

for inventory_item in inventory:
    if inventory_item != "items":
        print "Your " + inventory_item + " is a " + inventory[inventory_item]
    else:
        print "items in your backpack:"
        for item in inventory[inventory_item]:
            print "    " + item

And here’s our output:

Your armor is a winter coat
Your helmut is a sauce pan
Your sword is a wooden stick
items in your backpack:
    healing potion
    small rubber duck
    smart phone
    potato

All we did was to add a special instruction to the loop. Now, if one of the items in the inventory dictionary we’ll start another loop inside the loop that prints out all the items in the items list.

Of course it can get a lot more complicated that this, but let’s leave that to part 2.

Start Learning MongoDB In The Browser

Here’s another one of these “code right in the browser sites.” try.mongodb.org. This time it’s for MongoDB, one of these fancy noSQL databases. Having some experience with SQL, I can testify that mongoDB looks like a pretty sweet alternative. It’s key-value just like a dictionary in Python or a hash in Perl. For most uses I have a for a database, namely small web projects, this seems so much simpler that dealing with complicated SQL queries. I’m keen to add it to the Nine Men’s Morris project.

Snake Log 4

Not a whole lot of visible progress to report from yesterday. I sunk a lot of the time I did have available yesterday into dividing the game board into quadrants. One of the requirements of the game is that the block the snake eats appear randomly some specified distance from the walls and the snake’s head. Pursuant to that I went about doing lots of calculating trying to figure out how to do it.

I realized late last night it would just be better to randomly generate a spot, then measure the block’s distance from the walls and the snake, then keep regenerating a spot if the conditions aren’t met. That will take me soooo much less time to code, and really, the browser should be fast enough to do a few simple calculations for a few loops.

That bit of coding shouldn’t take me too long. After that I should quickly be able to increase the snake’s speed for each block it eats and then get started on creating the snake’s tail by tonight.

Follow

Get every new post delivered to your Inbox.

Join 188 other followers