PageRenderTime 15ms CodeModel.GetById 7ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/pods/SDL/Tutorial/LunarLander.pod

http://github.com/PerlGameDev/SDL
Unknown | 310 lines | 175 code | 135 blank | 0 comment | 0 complexity | 6d2a6e24b243e1c525a80d4139da9f53 MD5 | raw file
  1
  2=head1 NAME
  3
  4SDL::Tutorial::LunarLander - a small tutorial on Perl SDL
  5
  6=head2 CATEGORY
  7
  8Tutorials
  9
 10=head1 INTRODUCTION
 11
 12This is a quick introduction to Games, Perl, and  SDL (Simple 
 13DirectMedia Layer, a cross-platform multimedia programming 
 14library). We'll write a small game -- Lunar Lander -- in 100 
 15lines of code, or less.
 16
 17=head3 CREATING A DEMO
 18
 19You can see the final version of the demo code by doing:
 20
 21
 22
 23   perl -MSDL::Tutorial::LunarLander=lander.pl -e1
 24
 25
 26
 27this will create all three files used in the tutorial.
 28
 29
 30=head2 FIRST VERSION
 31
 32We'll start with a text version of the game.
 33
 34"What?", you may ask. "I thought it was a SDL tutorial".
 35
 36Yes, it is -- thank you for reminding me. But we'll leave the SDL part for
 37later. We must build the game logic first!
 38
 39One of the traps of game programming is focusing too much on the interface.
 40If we start with a simpler simulation, we can worry with the presentation
 41later.
 42
 43So, here's the initial code:
 44
 45
 46
 47    #!/usr/bin/perl
 48
 49    use strict;
 50    use warnings;
 51
 52    my $height   = 1000; # m
 53    my $velocity = 0;    # m/s
 54    my $gravity  = 1;    # m/s^2
 55
 56    my $t = 0;
 57
 58    while ( $height > 0 ) {
 59        print "at $t s height = $height m, velocity = $velocity m/s\n";
 60
 61        $height   = $height - $velocity;
 62        $velocity = $velocity + $gravity;
 63        $t        = $t + 1;
 64    }
 65
 66    if ( $velocity > 10 ) {
 67        print "CRASH!!!\n";
 68    } else {
 69        print "You landed on the surface safely! :-D\n";
 70    }
 71
 72
 73
 74Run the code and you'll see something like this:
 75
 76
 77
 78    at 0 s height = 1000 m, velocity = 0 m/s
 79    at 1 s height = 1000 m, velocity = 1 m/s
 80    at 2 s height = 999 m, velocity = 2 m/s
 81    at 3 s height = 997 m, velocity = 3 m/s
 82    at 4 s height = 994 m, velocity = 4 m/s
 83    at 5 s height = 990 m, velocity = 5 m/s
 84    ...
 85    at 43 s height = 97 m, velocity = 43 m/s
 86    at 44 s height = 54 m, velocity = 44 m/s
 87    at 45 s height = 10 m, velocity = 45 m/s
 88
 89    CRASH!!!
 90
 91
 92
 93"What happened? How do I control the ship???"
 94
 95=head2 CONTROLLING THE SHIP
 96
 97The problem with our first spaceship is that it had no controls!
 98
 99So, let's fix this problem, making the spaceship scriptable. (We 
100could write some code to handle keyboard and joysticks now, but 
101an scriptable spaceship will be easier to start. Remember, focus
102on the game logic!)
103
104So, create add this simple script to the end of your file:
105
106
107
108    __DATA__
109    at 41s, accelerate 10 m/s^2 up
110    at 43s, 10 m/s^2
111    at 45s, 10
112    at 47s, 10
113    at 49s, 10
114
115
116
117The script is straightforward: it simply states a time when we
118will push the spaceship up with a given acceleration. It accepts
119free text: any two numbers you type will work.
120
121We can parse the script using this regular expression:
122
123
124
125    my $script_re = qr/(\d+) \D+ (\d+)/x;
126
127
128
129And we can build a hash of ( time => acceleration ) with:
130
131
132
133    my %up = map { $_ =~ $script_re } <DATA>;
134
135
136
137So the middle section of the program will become:
138
139
140
141    my $script_re = qr/(\d+) \D+ (\d+)/x;
142    my %up = map { $_ =~ $script_re } <DATA>;
143
144    while ( $height > 0 ) {
145        print "at $t s height = $height m, velocity = $velocity m/s\n";
146
147        if ( $up{$t} ) {
148            my $a = $up{$t};
149            print "(accelerating $a m/s^2)\n";
150            $velocity = $velocity - $a;
151        }
152
153        $height   = $height - $velocity;
154        $velocity = $velocity + $gravity;
155        $t        = $t + 1;
156    }
157
158
159
160That's it!
161
162Try to run the program, and the ship should land safely:
163
164
165
166    ./lunar.pl autopilot.txt 
167    at 0 s height = 1000 m, velocity = 0 m/s
168    at 1 s height = 1000 m, velocity = 1 m/s
169    at 2 s height = 999 m, velocity = 2 m/s
170    at 3 s height = 997 m, velocity = 3 m/s
171    at 4 s height = 994 m, velocity = 4 m/s
172    at 5 s height = 990 m, velocity = 5 m/s
173    ...
174    at 54 s height = 19 m, velocity = 4 m/s
175    at 55 s height = 15 m, velocity = 5 m/s
176    at 56 s height = 10 m, velocity = 6 m/s
177    at 57 s height = 4 m, velocity = 7 m/s
178
179    You landed on the surface safely! :-D
180
181
182
183Cool, but...
184
185=head2 HOW ABOUT THE GRAPHICS?
186
187Okay, okay... now that we have a working prototype, we can work on
188the graphics. But, first of all, we'll need...
189
190=head3 THE GRAPHICS
191
192Yes, the graphics.
193
194We won't use anything fancy here, just two images: a large one, for
195the background, and a smaller one for the spaceship.
196
197Create the images using the Gimp, or use the images provided by
198this tutorial; Save these images in a subdirectory called "images":
199("C<images/background.jpg>" and "C<images/ship.png>").
200
201=head2 USING SDL
202
203First step: use the required libraries:
204
205
206
207	use SDL; #needed to get all constants
208	use SDL::Video;
209	use SDLx::App;
210	use SDL::Surface;
211	use SDL::Rect;
212	use SDL::Image;
213
214
215
216Second step: initialize C<SDLx::App>:
217
218
219
220    my $app = SDLx::App->new(
221        title  => "Lunar Lander",
222        width  => 800,
223        height => 600,
224        depth  => 32,
225    );
226
227
228
229Third step: load the images and create the necessary "rectangles":
230
231
232
233	my $background = SDL::Image::load('images/background.jpg');
234	my $ship       = SDL::Image::load('images/ship.jpg');
235
236	my $background_rect = SDL::Rect->new(0,0,
237	    $background->w,
238	    $background->h,
239	);
240
241	my $ship_rect = SDL::Rect->new(0,0,
242	    $ship->w,
243	    $ship->h,
244	);
245
246
247
248Fourth step: create a sub to draw the spaceship and background:
249
250
251
252	sub draw {
253	    my ( $x, $y ) = @_; # spaceship position
254
255	    # fix $y for screen resolution
256	    $y = 450 * ( 1000 - $y ) / 1000;
257
258	    # background
259	    SDL::Video::blit_surface($background, $background_rect, $app, $background_rect );
260
261	    # ship
262	    my $ship_dest_rect = SDL::Rect->new(
263		$x, $y, $ship->w, $ship->h,
264	    );
265
266	    SDL::Video::blit_surface($ship, $ship_rect, $app, $ship_dest_rect );
267
268	    SDL::Video::update_rects($app, $background_rect);
269	}
270
271
272
273Note that this sub first combines all the bitmaps, using a blit
274("Block Image Transfer") operation -- which is quite fast, but does
275not update the display.
276
277The combined image is displayed in the last line. This process of
278combining first, and displaying later, avoids that annoying fading
279between cycles ("flickering").
280
281Finally, add the following lines to the end of the main loop, so that
282we call the C<draw()> function with the correct spaceship
283coordinates:
284
285
286
287    while ( $height > 0 ) {
288
289        # ...
290
291        draw( 100, $height );
292        $app->delay(10);
293    }
294
295
296
297That's it!
298
299Run the program and watch the spaceship landing safely on the surface
300of the moon.
301
302=head1 COPYRIGHT & LICENSE
303
304Copyright 2009 Nelson Ferraz, all rights reserved.
305
306Updated and maintained by the SDL Perl project. See L<SDL/AUTHORS>.
307
308This program is free software; you can redistribute it and/or modify it
309under the same terms as Perl itself.
310