3 Lunar Lander - a small tutorial on Perl SDL
7 This is a quick introduction to Games, Perl, and SDL (Simple
8 DirectMedia Layer, a cross-platform multimedia programming
9 library). We'll write a small game -- Lunar Lander -- in 100
10 lines of code, or less.
15 We'll start with a text version of the game.
17 "What?", you may ask. "I thought it was a SDL tutorial".
19 Yes, it is -- thank you for reminding me. But we'll leave the SDL part for
20 later. We must build the game logic first!
22 One of the traps of game programming is focusing too much on the interface.
23 If we start with a simpler simulation, we can worry with the presentation
26 So, here's the initial code:
33 my $height = 1000; # m
34 my $velocity = 0; # m/s
35 my $gravity = 1; # m/s^2
39 while ( $height > 0 ) {
40 print "at $t s height = $height m, velocity = $velocity m/s\n";
42 $height = $height - $velocity;
43 $velocity = $velocity + $gravity;
47 if ( $velocity > 10 ) {
50 print "You landed on the surface safely! :-D\n";
53 Run the code and you'll see something like this:
55 at 0 s height = 1000 m, velocity = 0 m/s
56 at 1 s height = 1000 m, velocity = 1 m/s
57 at 2 s height = 999 m, velocity = 2 m/s
58 at 3 s height = 997 m, velocity = 3 m/s
59 at 4 s height = 994 m, velocity = 4 m/s
60 at 5 s height = 990 m, velocity = 5 m/s
62 at 43 s height = 97 m, velocity = 43 m/s
63 at 44 s height = 54 m, velocity = 44 m/s
64 at 45 s height = 10 m, velocity = 45 m/s
68 "What happened? How do I control the ship???"
70 =head2 CONTROLLING THE SHIP
72 The problem with our first spaceship is that it had no controls!
74 So, let's fix this problem, making the spaceship scriptable. (We
75 could write some code to handle keyboard and joysticks now, but
76 an scriptable spaceship will be easier to start. Remember, focus
79 So, create add this simple script to the end of your file:
82 at 41s, accelerate 10 m/s^2 up
88 The script is straightforward: it simply states a time when we
89 will push the spaceship up with a given acceleration. It accepts
90 free text: any two numbers you type will work.
92 We can parse the script using this regular expression:
94 my $script_re = qr/(\d+) \D+ (\d+)/x;
96 And we can build a hash of ( time => acceleration ) with:
98 my %up = map { $_ =~ $script_re } <DATA>;
100 So the middle section of the program will become:
102 my $script_re = qr/(\d+) \D+ (\d+)/x;
103 my %up = map { $_ =~ $script_re } <DATA>;
105 while ( $height > 0 ) {
106 print "at $t s height = $height m, velocity = $velocity m/s\n";
110 print "(accellerating $a m/s^2)\n";
111 $velocity = $velocity - $a;
114 $height = $height - $velocity;
115 $velocity = $velocity + $gravity;
121 Try to run the program, and the ship should land safely:
123 ./lunar.pl autopilot.txt
124 at 0 s height = 1000 m, velocity = 0 m/s
125 at 1 s height = 1000 m, velocity = 1 m/s
126 at 2 s height = 999 m, velocity = 2 m/s
127 at 3 s height = 997 m, velocity = 3 m/s
128 at 4 s height = 994 m, velocity = 4 m/s
129 at 5 s height = 990 m, velocity = 5 m/s
131 at 54 s height = 19 m, velocity = 4 m/s
132 at 55 s height = 15 m, velocity = 5 m/s
133 at 56 s height = 10 m, velocity = 6 m/s
134 at 57 s height = 4 m, velocity = 7 m/s
136 You landed on the surface safely! :-D
140 =head2 HOW ABOUT THE GRAPHICS?
142 Okay, okay... now that we have a working prototype, we can work on
143 the graphics. But, first of all, we'll need...
149 We won't use anything fancy here, just two images: a large one, for
150 the background, and a smaller one for the spaceship.
152 Create the images using the Gimp, or use the images provided by
153 this tutorial; Save these images in a subdirectory called "images":
154 ("C<images/background.jpg>" and "C<images/ship.png>").
158 First step: use the required libraries:
160 use SDL; #needed to get all constants
165 Second step: initialize C<SDL::App>:
167 my $app = SDL::App->new(
168 -title => "Lunar Lander",
174 Third step: load the images and create the necessary "rectangles":
176 my $background = SDL::Surface->new( -name => 'images/background.jpg', );
177 my $ship = SDL::Surface->new( -name => 'images/ship.png', );
179 my $background_rect = SDL::Rect->new(
180 -height => $background->height(),
181 -width => $background->width(),
184 my $ship_rect = SDL::Rect->new(
185 -height => $ship->height(),
186 -width => $ship->width(),
189 Fourth step: create a sub to draw the spaceship and background:
192 my ( $x, $y ) = @_; # spaceship position
194 # fix $y for screen resolution
195 $y = 450 * ( 1000 - $y ) / 1000;
198 $background->blit( $background_rect, $app, $background_rect );
201 my $ship_dest_rect = SDL::Rect->new(
202 -height => $ship->height(),
203 -width => $ship->width(),
208 $ship->blit( $ship_rect, $app, $ship_dest_rect );
210 $app->update($background_rect);
213 Note that this sub first combines all the bitmaps, using a blit
214 ("Block Image Transfer") operation -- which is quite fast, but does
215 not update the display.
217 The combined image is displayed in the last line. This process of
218 combining first, and displaying later, avoids that annoying fading
219 between cycles ("flickering").
221 Finally, add the following lines to the end of the main loop, so that
222 we call the C<draw()> function with the correct spaceship
225 while ( $height > 0 ) {
229 draw( 100, $height );
235 Run the program and watch the spaceship landing safely on the surface
238 =head1 COPYRIGHT & LICENSE
240 Copyright 2009 Nelson Ferraz, all rights reserved.
242 This program is free software; you can redistribute it and/or modify it
243 under the same terms as Perl itself.