arrested (gaming) development: brace for impact!

please note in order to see the code and the videos, you’ll need to go to the full post. feedburner doesn’t appear to play nice with my embedded videos.

welcome to the fifth and last installment of the series. yes, i know it’s all a bit sudden, but when you see this week’s code you’ll see that there’s very little left to discuss. there will be a break between the next series of posts that form chapter three (galactic mail) of the game maker’s apprentice.

i’ll post the odd tech demo to show you what i’m up to, and as soon as i’ve made sufficient progress i’ll start posting again – so stay tuned!

last week we learnt how to deal with bullets and how to have a multitude of them on screen. this week we’re going to add the missing ingredient and enable collision detection. oh, and whilst we’re at it, we’ll also enable scoring!

first off, let’s look at the function that provides collision detection, which is lifted from linux format’s space invader and racing games.

def Intersect(s1_x, s1_y, s2_x, s2_y):
    if (s1_x > s2_x - 32) and (s1_x < s2_x + 32) and (s1_y > s2_y - 32) and (s1_y < s2_y + 32):
        return 1
    else:
        return 0

you can tell it's been lifted because i've not bothered to rewrite it to take into account the various shapes and sizes of the sprites (the offset is still 32 as the sprites were 32x32 pixels). all this function does is compare the position of the first sprite against the second sprite, so, after the offset (32 pixels) has been factored in, if the two overlap a collision has occurred.

so to see if any of our demons have collided with the dragon, here's what our code would look like.

    # iterate through demons
    for index, demon in enumerate(demons):
        :
        code to check if its time to remove demons from the list removed for brevity
        :

        if Intersect(demon.x, demon.y, dragon.x, dragon.y):
            quit = 1
            break

        :
        code to render the demons
        :

the baby dragon code pretty much does the same thing, except your score is incremented if a collision occurs.

the dragon's fireball has to test for collisions with both demons and baby dragons all within the same loop. furthermore if a collision occurs, it would be nice to make the former demon/baby dragon vanish, this one caught me out the first time around.

    # same for fireballs
    for index, fireball in enumerate(fireballs):
        if fireball.x > 640:
            del fireballs[index]

        for index2 in range(0, len(demons)):
            # NEW: 05/12
            if Intersect(fireball.x, fireball.y, demons[index2].x, demons[index2].y):
                del demons[index2]
                del fireballs[index]
                score += 100
                break

        for index2 in range(0, len(babies)):
            # NEW: 05/12
            if Intersect(fireball.x, fireball.y, babies[index2].x, babies[index2].y):
                del babies[index2]
                del fireballs[index]
                score -= 500
                break

        fireball.x += 10
        fireball.render()

as you can see from the code, you have to iterate through all the demons and baby dragons to see if any of them collided. you may have also noticed that i've switched from walking the list and instantiating each object. instead, i've use the method employed by linux format code, of going through the list and testing objects in place, referencing them by their subscript (index). this was done more for my amusement, rather than for the sake of efficiency. i'm pretty certain that sprite groups would simplify this operation through the use of group collision detection.

finally we get onto the topic of scoring. again, nothing major here. i amended the display.set_caption code so it became a formatted string and placed the score there. when a demon collides with the dragon, the last line of the program kicks in and displays the final screen to the console session that launched the game.

whilst this isn't how the game maker's apprentice displays the score, i lacked the "know how" to create a high score routine. i will have one for the next series of agd posts.

let's do one final comparison of the reference game maker and pygame versions of the game.

first is the reference video:

next is the pygame version:

unfortunately, i've just discovered that the utility i used to compress the videos before i uploaded them to youtube is too aggressive. therefore it's impossible to see the score changing in the title bar, so you'll just have to take my word for it that this video is different from previous pygame video.

whilst the pygame version is no where near as smooth or as functional as the game maker version, it's a pretty good facsmilie of it. it did take long to create, i'd hazard a guess that if each post equated to a day's work, and if we exclude the intro post, it took me four days to write something that could've been done in ten minutes in game maker.

i'm certain there's python coders out there who could write a mind blowing game in the time it took me to replicate the look and feel of the game maker game, but i'm not one of those guys. yet.

whilst working on this series of posts, i've come to appreciate how easy it is to write games in game maker. it takes away the management of trixsy things like controls, multiple sprites, collision detection, sound and scoring. instead you just get on with game design, be it difficulty level or level design. this means you've got a better chance of realising a product instead of giving up half way because of technical difficulties.

i hope you've enjoyed this series of posts as much as i've enjoyed writing them and i look forward to you joining me for the next series. until next time, keep it surreal!

prev (bullets) | about | next (???)


About this entry