3 Lunar Lander - a small tutorial on Perl SDL
7 This is a quick introduction to Perl and SDL (Simple DirectMedia
8 Layer, a cross-platform multimedia programming library). We'll write
9 a small game-- Lunar Lander-- in 100 lines of code, or less.
15 If you are using Debian or Ubuntu, it's probably easier to install
16 the module via apt-get:
18 apt-get install libsdl-perl
20 or for the bleeding edge with tons of bug fixes.
22 perl -MCPAN -e "install SDL"
24 If you are using other Linux distro, look for the corresponding
25 package. If you can't find it you'll have to compile it (and deal
26 with all the dependencies) yourself.
28 The point is that it is strongly recommend that you start with a
29 packaged module from your distribution. Avoid compiling SDL_Perl
34 We'll start with a text version of the game.
36 "What?", you may ask. "I thought it was a SDL tutorial".
38 Yes, it is -- thank you for reminding me. But we'll leave the SDL part for
39 later. We must build the game logic first!
41 One of the traps of game programming is focusing too much on the interface.
42 If we start with a simpler simulation, we can worry with the presentation
45 So, here's the initial code:
52 my $height = 1000; # m
53 my $velocity = 0; # m/s
54 my $gravity = 1; # m/s^2
58 while ( $height > 0 ) {
59 print "at $t s height = $height m, velocity = $velocity m/s\n";
61 $height = $height - $velocity;
62 $velocity = $velocity + $gravity;
66 if ( $velocity > 10 ) {
69 print "You landed on the surface safely! :-D\n";
72 Run the code and you'll see something like this:
74 at 0 s height = 1000 m, velocity = 0 m/s
75 at 1 s height = 1000 m, velocity = 1 m/s
76 at 2 s height = 999 m, velocity = 2 m/s
77 at 3 s height = 997 m, velocity = 3 m/s
78 at 4 s height = 994 m, velocity = 4 m/s
79 at 5 s height = 990 m, velocity = 5 m/s
81 at 43 s height = 97 m, velocity = 43 m/s
82 at 44 s height = 54 m, velocity = 44 m/s
83 at 45 s height = 10 m, velocity = 45 m/s
87 "What happened? How do I control the ship???"
89 =head2 CONTROLLING THE SHIP
91 The problem with our first spaceship is that it had no controls!
93 So, let's fix this problem, making the spaceship scriptable. (We
94 could write some code to handle keyboard and joysticks now, but
95 an scriptable spaceship will be easier to start. Remember, focus
98 So, create add this simple script to the end of your file:
101 at 41s, accelerate 10 m/s^2 up
107 The script is straightforward: it simply states a time when we
108 will push the spaceship up with a given acceleration. It accepts
109 free text: any two numbers you type will work.
111 We can parse the script using this regular expression:
113 my $script_re = qr/(\d+) \D+ (\d+)/x;
115 And we can build a hash of ( time => acceleration ) with:
117 my %up = map { $_ =~ $script_re } <DATA>;
119 So the middle section of the program will become:
121 my $script_re = qr/(\d+) \D+ (\d+)/x;
122 my %up = map { $_ =~ $script_re } <DATA>;
124 while ( $height > 0 ) {
125 print "at $t s height = $height m, velocity = $velocity m/s\n";
129 print "(accellerating $a m/s^2)\n";
130 $velocity = $velocity - $a;
133 $height = $height - $velocity;
134 $velocity = $velocity + $gravity;
140 Try to run the program, and the ship should land safely:
142 ./lunar.pl autopilot.txt
143 at 0 s height = 1000 m, velocity = 0 m/s
144 at 1 s height = 1000 m, velocity = 1 m/s
145 at 2 s height = 999 m, velocity = 2 m/s
146 at 3 s height = 997 m, velocity = 3 m/s
147 at 4 s height = 994 m, velocity = 4 m/s
148 at 5 s height = 990 m, velocity = 5 m/s
150 at 54 s height = 19 m, velocity = 4 m/s
151 at 55 s height = 15 m, velocity = 5 m/s
152 at 56 s height = 10 m, velocity = 6 m/s
153 at 57 s height = 4 m, velocity = 7 m/s
155 You landed on the surface safely! :-D
159 =head2 HOW ABOUT THE GRAPHICS?
161 Okay, okay... now that we have a working prototype, we can work on
162 the graphics. But, first of all, we'll need...
168 We won't use anything fancy here, just two images: a large one, for
169 the background, and a smaller one for the spaceship.
171 Create the images using the Gimp, or use the images provided by
172 this tutorial; Save these images in a subdirectory called "images":
173 ("C<images/background.jpg>" and "C<images/ship.png>").
177 First step: use the required libraries:
179 use SDL; #needed to get all constants
184 Second step: initialize C<SDL::App>:
186 my $app = SDL::App->new(
187 -title => "Lunar Lander",
193 Third step: load the images and create the necessary "rectangles":
195 my $background = SDL::Surface->new( -name => 'images/background.jpg', );
196 my $ship = SDL::Surface->new( -name => 'images/ship.png', );
198 my $background_rect = SDL::Rect->new(
199 -height => $background->height(),
200 -width => $background->width(),
203 my $ship_rect = SDL::Rect->new(
204 -height => $ship->height(),
205 -width => $ship->width(),
208 Fourth step: create a sub to draw the spaceship and background:
211 my ( $x, $y ) = @_; # spaceship position
213 # fix $y for screen resolution
214 $y = 450 * ( 1000 - $y ) / 1000;
217 $background->blit( $background_rect, $app, $background_rect );
220 my $ship_dest_rect = SDL::Rect->new(
221 -height => $ship->height(),
222 -width => $ship->width(),
227 $ship->blit( $ship_rect, $app, $ship_dest_rect );
229 $app->update($background_rect);
232 Note that this sub first combines all the bitmaps, using a blit
233 ("Block Image Transfer") operation -- which is quite fast, but does
234 not update the display.
236 The combined image is displayed in the last line. This process of
237 combining first, and displaying later, avoids that annoying fading
238 between cycles ("flickering").
240 Finally, add the following lines to the end of the main loop, so that
241 we call the C<draw()> function with the correct spaceship
244 while ( $height > 0 ) {
248 draw( 100, $height );
254 Run the program and watch the spaceship landing safely on the surface
257 =head1 COPYRIGHT & LICENSE
259 Copyright 2009 Nelson Ferraz, all rights reserved.
261 This program is free software; you can redistribute it and/or modify it
262 under the same terms as Perl itself.