New game: Space Invaders

It’s been a while since I published RetroRacer, but a lot of new things happened in Steroids too! So many things that I backported the old games to the new engine; I’ll be testing them each time to see if I’m introducing any breaking changes. But! back to Space Invaders.

Image

(brave ship fighting off alien hordes)

 

The game is now available at https://github.com/tadzik/steroids. Below I’ll outline some of the new features in the engine itself.

Animations

It is now possible to load animations from spritesheets (example here), and tell Steroids to animate them over time.

self.load_spritesheet(‘invader’, ‘assets/invader.png’, 72, 32, 7);

my $invader = self.add_sprite(‘invader’, $x, $y);

self.add_animation($invader, Any, 200, True);

In order: load a spritesheet of seven 72×32 images, put it on screen an animate all its frames (Any), changing a frame every 200 miliseconds, and play it in a loop (True). The ships will rotate and look nice :)

Gamepad support

method update($dt) {
    my $pad = self.gamepads[0];
    my $analog = $pad.analog_percentage($pad.analog_left_x);

    if self.is_pressed(“Left”) or $pad.dpad_position(“Left”) {
        $!player.x -= 15;
    } elsif self.is_pressed(“Right”) or $pad.dpad_position(“Right”) {
        $!player.x += 15;
    } elsif $analog.abs > 0.1 {
        $!player.x += Int(15 * $analog);
    }

    …

}

    

New steroids features gamepad support! At this point the only supported one is the Xbox controller (I accidentally used the old SDL joystick API instead of a new, shiny gamecontroller API), so it’s all a little bit experimental. But, as you can see, it works pretty well and is quite useful indeed!

Game states

class Main is Steroids::State {

    …

}

 

class Menu is Steroids::State {

    …

}

 

given Steroids::Game.new {
    .add_state(‘menu’, { Menu.new });
    .add_state(‘main’, { Main.new });
    .change_state(‘menu’);
    .start;
}

What’s going on here? We have to separate game states (one for the menu and one for the actual game), and we can switch between them at any point using the change_state() method. For example, somewhere in Menu’s code:

method keypressed($k) {
    if $k eq ‘S’ {
        self.reset_state(‘main’);
        self.change_state(‘main’);
    }

    …

}

The states themselves are passed in as code references for the sake of the reset_state() method shown above. You can think of them as factories. The reset above is necessary, so each time you start a new game, it actually starts anew instead of continuing the old one (which is probably either lost or won by that time).

I probably forgot about something, so if anything is unclear just write it in the comment section. Go try out Space Invaders, and don’t forget about the soundtrack!

I’ll be talking about Steroids next weekend at this year’s Polish Perl Workshop; make sure to stop to find out about the latest developments and future plans.

Advertisements

New Perl6 game: RetroRacer

(I’m really sorry for the name; I couldn’t think of anything better :))

Image

 

This game, apart from (obviously) being a showcase for a new Steroids iteration, is all about switching lanes on a high traffic road in a fast car. Yay!

It’s really no rocket science compared to ThroughTheWindow from the last post – even code even looks similar. One obvious improvement (beside finally using proper PNGs instead of silly BMPs – timotimo++!) is a built-in collision detection:

my $s self.add_sprite(‘othercar’$_0);

# …

$s.when({ $_.collides_with($!player}, {

    # …

});

No more cheating with collisions like I did with ThroughTheWindow. The existing solution uses the entire image sprite as a hitbox; I’m hoping to make it customizable one day (it’s a simple thing really, code-wise).

All in all, the game isn’t all that much more sophisticated than the last one; I was really just looking for a good excuse to write a new game (and add some new stuff to Steroids), and I sort of came up with a nice theme to follow: ThroughTheWindow used just one key (spacebar), so the next step was to use two (thus RetroRacer) uses left and right arrow keys. What will the next game use? 3 keys? 4 keys? Is it an arithmetical or geometrical series? Oh my, I can’t wait to find out myself.

Now go and grab it at https://github.com/tadzik/RetroRacer, and don’t forget about the soundtrack!

 


Perl 6 on steroids: Through The Window

Image

 

I got into programming because I wanted to write games. I played games as a kid (wolfenstein 3d, putt-putt, I don’t remember the rest of the names), and I thought “when I grow up, I’m going to write games!”

I never really did; at some point I realized I’ve written more compilers than games: whatever happened to the childhood dream? So I thought I’ll write some, to try and learn something new.

With two friends from work I went to javascript game programming conference – it was the only game conf I’ve ever heard of, so I thought “javascript or not, let’s see how gamedev geeks party”. The universal “let’s create idiotic games and make a lot of money on ads and In-App-Purchases” attitude of the startup crowd discouraged me a little bit, but I tried to ignore that bit and focus on the technical content. I never liked javascript, I didn’t really want to use it for any kind of programming, and frankly, working in Perl and Python I grew tired of dynamic typing altogether, but I thought “hmm, maybe if I created a superset of JS that has nice type annotations, that the compiler checks and then drops, emitting vanilla JS, that wouldn’t be so bad to write code in”. I consulted a friend of mine, and, as it usually happens, it turned out that such thing already exists: it’s called Typescript, and Microsoft created it long ago. Oh well, let’s give it a try.

Why am I writing about all this? Where does Perl 6 come in? Thing is, when I started programming in Typescript, I got annoyed. It’s severly underdocumented, undersupported, development is not pleasant, because you get some errors from the compiler and then different errors from a browser, but the worst thing is: it was slow! It was so slow it was unbearable, and I thought “ah, screw it. I’ll be better off with Perl 6”.

I chose Perl 6 for performance reasons! Ain’t that something to tell my grandkids about.

Of course, creating games in Perl 6 is not so trivial: I’ll have to write the engine/framework/whatever myself. Time to roll the sleeves up and get to work.

I got quite motivated by http://lessmilk.com. This guy creates a new game every week to learn game development. Cool thing! He was describing phaser.js in one of his articles, so I created Steroids, and modelled it after Phaser.

Why steroids? Well, at some point I ported my C Asteroids to Perl 6, as a proof of concept, to see if it can indeed handle 60fps games (it can), and the “steroids” bit somewhat got stuck in my mind. Also, being on steroids gives you much more flexibility than, say, being on the rails. Don’t worry, nothing bad about being on Steroids: Just ask Duke Nukem, he got by just fine.

So, Perl 6 on Steroids was born. I started writing a running-jumping game, and abstracting the commonly used bits to a module as I went on. Why a running-jumping game? Well, you asked for it: it’s time for another backstory:

Ever wrote in a backseat of the car as a kid, looking out the window? Did you imagine a person running along the car, jumping over obstacles? I did, and from what I’ve heard I am not the only one. Thus, “Through the Window” was born: a game where a man runs along the horizon, jumping over trees and cows, being the first showcase for Steroids, and a reason for it to exist.

The post is getting lenghty enough, and there’s much to announce still, so I’ll run through the 80 lines of code really quickly to show you what Steroids gives you. You can read the entire source code here

class Game is Steroids::Game

You create a class that inherits from Steroids::Game. You need to define at least two methods for it to make any sense: create() and update(). The former initializes the game, and the latter is called 60 times per second to update the game state.

Some of the things you may want to do in the create() method:

self.load_bitmap(‘background’, ‘assets/background.bmp’);

self.add_sprite(‘background’, 0, 0);

Pretty self-explanatory. Steroids handles loading bitmaps from disk for you, and putting them in a scene.

self.load_bitmap(‘runner’, ‘assets/runner.bmp’);

$!runner = self.add_sprite(‘runner’, 50, GROUNDLEVEL);

$!runner.y -= $!runner.h;

$!runner.gravity = 1;
$!runner.when({ $_.y > GROUNDLEVEL – $_.h }, {
$!runner.y = GROUNDLEVEL – $!runner.h;
    $!runner.velocity[1] = 0;
})

;

Plenty of things here: we add a runner to the scene. We move him up a little bit, so he’s actually standing on the ground, rather than having his head on the ground level, we give him a gravity (so he’s falling down all the time), and we add an event, so when he hits the ground with his feet we stop him, so he doesn’t fall any further down. This should probably be handled by a collision detection at some point, but I didn’t get around to write collision detection yet.
 
That’s the interesting part from create(), now let’s look at update() really quickly.
 
method update {
        if @!obstacles
        and @!obstacles[0].x < ($!runner.x + $!runner.w) < (@!obstacles[0].x + @!obstacles[0].w)
        and $!runner.y + $!runner.h > @!obstacles[0].y {
            say “===========================================”;
            say ” Game over! You traveled $!distance pixels “;
            say “===========================================”;
            say “”;
            self.quit;
        }
Here’s our half-assed collision detection: if the front foot of the runner is inside the first obstacle (so, the leftmost), then the game is over.
 
How do the obstacles get there in the first place?
 if $!distance > $!last-obstacle + 40 and rand > 0.9 {
     my $s = self.add_sprite(<cow tree>.pick, self.width, GROUNDLEVEL);
     $s.y -= $s.h;
     $s.velocity[0] = -12;
     @!obstacles.push: $s;
     $s.when({ $_.x < 0 – $_.w }, {
     self.remove_sprite($_);
         @!obstacles.shift;
     });
     $!last-obstacle = $!distance;
}
If enough time has passed since we put an obstacle on the road (we don’t want the road to be impossible to travel), we add either a tree or a cow on the ground, as far on the right as we can. We make it slowly move to the left, add it to the list of obstacles, and add an event so when it reaches the left edge of the screen we remove it from the scene.
This part features a hack: @!obstacles.shift removes the first element of the list, and it just so happens that the object disappearing from the scene will always be the first one on the list: we don’t need to look through @!obstacles to find which one it is.
 
if self.is_pressed(“Space”) and $!runner.y == GROUNDLEVEL – $!runner.h {
     $!runner.velocity[1] = -22;
}
Pretty obvious: if Space is pressed while the runner is on the ground, he bounces upwards.
 
That’s just about all that it’s there to describe. Go play around with it, and remember about the soundtrack (in the README) – it’s a very important part of the game :)
 
(I was informed that the build process can be a bit more complicated on OSX; the entire Steroids development team is working hard to fix it, but if you have a good and ready solution, please send me a pull request).
 
But wait, there’s more! To celebrate the best game I’ve ever written, I’m announcing a contest: The task is to write a game using Steroids (with as many patches to it as you want). Let’s see how much can we squeeze out of those 120 lines of code to create something fun. One week from now, next sunday, I’m going to pick a winner and reward the author with a game that I like, and the author doesn’t yet have. Have an inappropriate amount of fun!