File: LunarLander.pod

package info (click to toggle)
libsdl-perl 2.548-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,972 kB
  • sloc: perl: 13,985; ansic: 583; makefile: 35
file content (310 lines) | stat: -rw-r--r-- 6,698 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310

=head1 NAME

SDL::Tutorial::LunarLander - a small tutorial on Perl SDL

=head2 CATEGORY

Tutorials

=head1 INTRODUCTION

This is a quick introduction to Games, Perl, and  SDL (Simple 
DirectMedia Layer, a cross-platform multimedia programming 
library). We'll write a small game -- Lunar Lander -- in 100 
lines of code, or less.

=head3 CREATING A DEMO

You can see the final version of the demo code by doing:



   perl -MSDL::Tutorial::LunarLander=lander.pl -e1



this will create all three files used in the tutorial.


=head2 FIRST VERSION

We'll start with a text version of the game.

"What?", you may ask. "I thought it was a SDL tutorial".

Yes, it is -- thank you for reminding me. But we'll leave the SDL part for
later. We must build the game logic first!

One of the traps of game programming is focusing too much on the interface.
If we start with a simpler simulation, we can worry with the presentation
later.

So, here's the initial code:



    #!/usr/bin/perl

    use strict;
    use warnings;

    my $height   = 1000; # m
    my $velocity = 0;    # m/s
    my $gravity  = 1;    # m/s^2

    my $t = 0;

    while ( $height > 0 ) {
        print "at $t s height = $height m, velocity = $velocity m/s\n";

        $height   = $height - $velocity;
        $velocity = $velocity + $gravity;
        $t        = $t + 1;
    }

    if ( $velocity > 10 ) {
        print "CRASH!!!\n";
    } else {
        print "You landed on the surface safely! :-D\n";
    }



Run the code and you'll see something like this:



    at 0 s height = 1000 m, velocity = 0 m/s
    at 1 s height = 1000 m, velocity = 1 m/s
    at 2 s height = 999 m, velocity = 2 m/s
    at 3 s height = 997 m, velocity = 3 m/s
    at 4 s height = 994 m, velocity = 4 m/s
    at 5 s height = 990 m, velocity = 5 m/s
    ...
    at 43 s height = 97 m, velocity = 43 m/s
    at 44 s height = 54 m, velocity = 44 m/s
    at 45 s height = 10 m, velocity = 45 m/s

    CRASH!!!



"What happened? How do I control the ship???"

=head2 CONTROLLING THE SHIP

The problem with our first spaceship is that it had no controls!

So, let's fix this problem, making the spaceship scriptable. (We 
could write some code to handle keyboard and joysticks now, but 
an scriptable spaceship will be easier to start. Remember, focus
on the game logic!)

So, create add this simple script to the end of your file:



    __DATA__
    at 41s, accelerate 10 m/s^2 up
    at 43s, 10 m/s^2
    at 45s, 10
    at 47s, 10
    at 49s, 10



The script is straightforward: it simply states a time when we
will push the spaceship up with a given acceleration. It accepts
free text: any two numbers you type will work.

We can parse the script using this regular expression:



    my $script_re = qr/(\d+) \D+ (\d+)/x;



And we can build a hash of ( time => acceleration ) with:



    my %up = map { $_ =~ $script_re } <DATA>;



So the middle section of the program will become:



    my $script_re = qr/(\d+) \D+ (\d+)/x;
    my %up = map { $_ =~ $script_re } <DATA>;

    while ( $height > 0 ) {
        print "at $t s height = $height m, velocity = $velocity m/s\n";

        if ( $up{$t} ) {
            my $a = $up{$t};
            print "(accelerating $a m/s^2)\n";
            $velocity = $velocity - $a;
        }

        $height   = $height - $velocity;
        $velocity = $velocity + $gravity;
        $t        = $t + 1;
    }



That's it!

Try to run the program, and the ship should land safely:



    ./lunar.pl autopilot.txt 
    at 0 s height = 1000 m, velocity = 0 m/s
    at 1 s height = 1000 m, velocity = 1 m/s
    at 2 s height = 999 m, velocity = 2 m/s
    at 3 s height = 997 m, velocity = 3 m/s
    at 4 s height = 994 m, velocity = 4 m/s
    at 5 s height = 990 m, velocity = 5 m/s
    ...
    at 54 s height = 19 m, velocity = 4 m/s
    at 55 s height = 15 m, velocity = 5 m/s
    at 56 s height = 10 m, velocity = 6 m/s
    at 57 s height = 4 m, velocity = 7 m/s

    You landed on the surface safely! :-D



Cool, but...

=head2 HOW ABOUT THE GRAPHICS?

Okay, okay... now that we have a working prototype, we can work on
the graphics. But, first of all, we'll need...

=head3 THE GRAPHICS

Yes, the graphics.

We won't use anything fancy here, just two images: a large one, for
the background, and a smaller one for the spaceship.

Create the images using the Gimp, or use the images provided by
this tutorial; Save these images in a subdirectory called "images":
("C<images/background.jpg>" and "C<images/ship.png>").

=head2 USING SDL

First step: use the required libraries:



	use SDL; #needed to get all constants
	use SDL::Video;
	use SDLx::App;
	use SDL::Surface;
	use SDL::Rect;
	use SDL::Image;



Second step: initialize C<SDLx::App>:



    my $app = SDLx::App->new(
        title  => "Lunar Lander",
        width  => 800,
        height => 600,
        depth  => 32,
    );



Third step: load the images and create the necessary "rectangles":



	my $background = SDL::Image::load('images/background.jpg');
	my $ship       = SDL::Image::load('images/ship.jpg');

	my $background_rect = SDL::Rect->new(0,0,
	    $background->w,
	    $background->h,
	);

	my $ship_rect = SDL::Rect->new(0,0,
	    $ship->w,
	    $ship->h,
	);



Fourth step: create a sub to draw the spaceship and background:



	sub draw {
	    my ( $x, $y ) = @_; # spaceship position

	    # fix $y for screen resolution
	    $y = 450 * ( 1000 - $y ) / 1000;

	    # background
	    SDL::Video::blit_surface($background, $background_rect, $app, $background_rect );

	    # ship
	    my $ship_dest_rect = SDL::Rect->new(
		$x, $y, $ship->w, $ship->h,
	    );

	    SDL::Video::blit_surface($ship, $ship_rect, $app, $ship_dest_rect );

	    SDL::Video::update_rects($app, $background_rect);
	}



Note that this sub first combines all the bitmaps, using a blit
("Block Image Transfer") operation -- which is quite fast, but does
not update the display.

The combined image is displayed in the last line. This process of
combining first, and displaying later, avoids that annoying fading
between cycles ("flickering").

Finally, add the following lines to the end of the main loop, so that
we call the C<draw()> function with the correct spaceship
coordinates:



    while ( $height > 0 ) {

        # ...

        draw( 100, $height );
        $app->delay(10);
    }



That's it!

Run the program and watch the spaceship landing safely on the surface
of the moon.

=head1 COPYRIGHT & LICENSE

Copyright 2009 Nelson Ferraz, all rights reserved.

Updated and maintained by the SDL Perl project. See L<SDL/AUTHORS>.

This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.