removed "installing sdl" as it's already there
[sdlgit/SDL_perl.git] / lib / SDL / Tutorial / LunarLander.pm
CommitLineData
9000d229 1=head1 NAME
2
3Lunar Lander - a small tutorial on Perl SDL
4
5=head1 INTRODUCTION
6
b17615ea 7This is a quick introduction to Games, Perl, and SDL (Simple
8DirectMedia Layer, a cross-platform multimedia programming
9library). We'll write a small game -- Lunar Lander -- in 100
10lines of code, or less.
9000d229 11
9000d229 12
13=head2 FIRST VERSION
14
15We'll start with a text version of the game.
16
17"What?", you may ask. "I thought it was a SDL tutorial".
18
19Yes, it is -- thank you for reminding me. But we'll leave the SDL part for
20later. We must build the game logic first!
21
22One of the traps of game programming is focusing too much on the interface.
23If we start with a simpler simulation, we can worry with the presentation
24later.
25
26So, here's the initial code:
27
28 #!/usr/bin/perl
29
30 use strict;
31 use warnings;
32
33 my $height = 1000; # m
34 my $velocity = 0; # m/s
35 my $gravity = 1; # m/s^2
36
37 my $t = 0;
38
39 while ( $height > 0 ) {
40 print "at $t s height = $height m, velocity = $velocity m/s\n";
41
42 $height = $height - $velocity;
43 $velocity = $velocity + $gravity;
44 $t = $t + 1;
45 }
46
47 if ( $velocity > 10 ) {
48 print "CRASH!!!\n";
49 } else {
50 print "You landed on the surface safely! :-D\n";
51 }
52
53Run the code and you'll see something like this:
54
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
61 ...
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
65
66 CRASH!!!
67
68"What happened? How do I control the ship???"
69
70=head2 CONTROLLING THE SHIP
71
72The problem with our first spaceship is that it had no controls!
73
74So, let's fix this problem, making the spaceship scriptable. (We
75could write some code to handle keyboard and joysticks now, but
76an scriptable spaceship will be easier to start. Remember, focus
77on the game logic!)
78
79So, create add this simple script to the end of your file:
80
81 __DATA__
82 at 41s, accelerate 10 m/s^2 up
83 at 43s, 10 m/s^2
84 at 45s, 10
85 at 47s, 10
86 at 49s, 10
87
88The script is straightforward: it simply states a time when we
89will push the spaceship up with a given acceleration. It accepts
90free text: any two numbers you type will work.
91
92We can parse the script using this regular expression:
93
94 my $script_re = qr/(\d+) \D+ (\d+)/x;
95
96And we can build a hash of ( time => acceleration ) with:
97
98 my %up = map { $_ =~ $script_re } <DATA>;
99
100So the middle section of the program will become:
101
102 my $script_re = qr/(\d+) \D+ (\d+)/x;
103 my %up = map { $_ =~ $script_re } <DATA>;
104
105 while ( $height > 0 ) {
106 print "at $t s height = $height m, velocity = $velocity m/s\n";
107
108 if ( $up{$t} ) {
109 my $a = $up{$t};
110 print "(accellerating $a m/s^2)\n";
111 $velocity = $velocity - $a;
112 }
113
114 $height = $height - $velocity;
115 $velocity = $velocity + $gravity;
116 $t = $t + 1;
117 }
118
119That's it!
120
121Try to run the program, and the ship should land safely:
122
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
130 ...
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
135
136 You landed on the surface safely! :-D
137
138Cool, but...
139
140=head2 HOW ABOUT THE GRAPHICS?
141
142Okay, okay... now that we have a working prototype, we can work on
143the graphics. But, first of all, we'll need...
144
145=head3 THE GRAPHICS
146
147Yes, the graphics.
148
149We won't use anything fancy here, just two images: a large one, for
150the background, and a smaller one for the spaceship.
151
152Create the images using the Gimp, or use the images provided by
153this tutorial; Save these images in a subdirectory called "images":
154("C<images/background.jpg>" and "C<images/ship.png>").
155
156=head2 USING SDL
157
158First step: use the required libraries:
159
160 use SDL; #needed to get all constants
161 use SDL::App;
162 use SDL::Surface;
163 use SDL::Rect;
164
165Second step: initialize C<SDL::App>:
166
167 my $app = SDL::App->new(
168 -title => "Lunar Lander",
169 -width => 800,
170 -height => 600,
171 -depth => 32,
172 );
173
174Third step: load the images and create the necessary "rectangles":
175
176 my $background = SDL::Surface->new( -name => 'images/background.jpg', );
177 my $ship = SDL::Surface->new( -name => 'images/ship.png', );
178
179 my $background_rect = SDL::Rect->new(
180 -height => $background->height(),
181 -width => $background->width(),
182 );
183
184 my $ship_rect = SDL::Rect->new(
185 -height => $ship->height(),
186 -width => $ship->width(),
187 );
188
189Fourth step: create a sub to draw the spaceship and background:
190
191 sub draw {
192 my ( $x, $y ) = @_; # spaceship position
193
194 # fix $y for screen resolution
195 $y = 450 * ( 1000 - $y ) / 1000;
196
197 # background
198 $background->blit( $background_rect, $app, $background_rect );
199
200 # ship
201 my $ship_dest_rect = SDL::Rect->new(
202 -height => $ship->height(),
203 -width => $ship->width(),
204 -x => $x,
205 -y => $y,
206 );
207
208 $ship->blit( $ship_rect, $app, $ship_dest_rect );
209
210 $app->update($background_rect);
211 }
212
213Note that this sub first combines all the bitmaps, using a blit
214("Block Image Transfer") operation -- which is quite fast, but does
215not update the display.
216
217The combined image is displayed in the last line. This process of
218combining first, and displaying later, avoids that annoying fading
219between cycles ("flickering").
220
221Finally, add the following lines to the end of the main loop, so that
222we call the C<draw()> function with the correct spaceship
223coordinates:
224
225 while ( $height > 0 ) {
226
227 # ...
228
229 draw( 100, $height );
230 $app->delay(10);
231 }
232
233That's it!
234
235Run the program and watch the spaceship landing safely on the surface
236of the moon.
237
238=head1 COPYRIGHT & LICENSE
239
240Copyright 2009 Nelson Ferraz, all rights reserved.
241
242This program is free software; you can redistribute it and/or modify it
243under the same terms as Perl itself.
244