Commit | Line | Data |
b3ef54ec |
1 | <div class="pod"> |
2 | <!-- INDEX START --> |
3 | <h3 id="TOP">Index</h3> |
4 | |
60f74f6f |
5 | <ul><li><a href="#NAME">NAME</a> |
6 | <ul><li><a href="#CATEGORY">CATEGORY</a></li> |
7 | </ul> |
8 | </li> |
b3ef54ec |
9 | <li><a href="#INTRODUCTION">INTRODUCTION</a> |
10 | <ul> |
11 | <li> |
12 | <ul><li><a href="#CREATING_A_DEMO">CREATING A DEMO</a></li> |
13 | </ul> |
14 | </li> |
15 | <li><a href="#FIRST_VERSION">FIRST VERSION</a></li> |
16 | <li><a href="#CONTROLLING_THE_SHIP">CONTROLLING THE SHIP</a></li> |
17 | <li><a href="#HOW_ABOUT_THE_GRAPHICS">HOW ABOUT THE GRAPHICS?</a> |
18 | <ul><li><a href="#THE_GRAPHICS">THE GRAPHICS</a></li> |
19 | </ul> |
20 | </li> |
21 | <li><a href="#USING_SDL">USING SDL</a></li> |
22 | </ul> |
23 | </li> |
24 | <li><a href="#COPYRIGHT_amp_LICENSE">COPYRIGHT & LICENSE</a> |
25 | </li> |
26 | </ul><hr /> |
27 | <!-- INDEX END --> |
28 | |
29 | <h1 id="NAME">NAME</h1><p><a href="#TOP" class="toplink">Top</a></p> |
30 | <div id="NAME_CONTENT"> |
56d4907c |
31 | <p>SDL::Tutorial::LunarLander - a small tutorial on Perl SDL</p> |
b3ef54ec |
32 | |
33 | </div> |
60f74f6f |
34 | <h2 id="CATEGORY">CATEGORY</h2> |
35 | <div id="CATEGORY_CONTENT"> |
36 | <p>Tutorials</p> |
37 | |
38 | </div> |
b3ef54ec |
39 | <h1 id="INTRODUCTION">INTRODUCTION</h1><p><a href="#TOP" class="toplink">Top</a></p> |
40 | <div id="INTRODUCTION_CONTENT"> |
41 | <p>This is a quick introduction to Games, Perl, and SDL (Simple |
42 | DirectMedia Layer, a cross-platform multimedia programming |
43 | library). We'll write a small game -- Lunar Lander -- in 100 |
44 | lines of code, or less.</p> |
45 | |
46 | </div> |
47 | <h3 id="CREATING_A_DEMO">CREATING A DEMO</h3> |
48 | <div id="CREATING_A_DEMO_CONTENT"> |
49 | <p>You can see the final version of the demo code by doing:</p> |
56d4907c |
50 | <pre> |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | perl -MSDL::Tutorial::LunarLander=lander.pl -e1 |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
b3ef54ec |
63 | |
64 | </pre> |
56d4907c |
65 | <p>this will create all three files used in the tutorial.</p> |
b3ef54ec |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | </div> |
72 | <h2 id="FIRST_VERSION">FIRST VERSION</h2> |
73 | <div id="FIRST_VERSION_CONTENT"> |
74 | <p>We'll start with a text version of the game.</p> |
75 | <p>"What?", you may ask. "I thought it was a SDL tutorial".</p> |
76 | <p>Yes, it is -- thank you for reminding me. But we'll leave the SDL part for |
77 | later. We must build the game logic first!</p> |
78 | <p>One of the traps of game programming is focusing too much on the interface. |
79 | If we start with a simpler simulation, we can worry with the presentation |
80 | later.</p> |
81 | <p>So, here's the initial code:</p> |
56d4907c |
82 | <pre> |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | #!/usr/bin/perl |
b3ef54ec |
89 | |
90 | use strict; |
91 | use warnings; |
92 | |
93 | my $height = 1000; # m |
94 | my $velocity = 0; # m/s |
95 | my $gravity = 1; # m/s^2 |
96 | |
97 | my $t = 0; |
98 | |
99 | while ( $height > 0 ) { |
100 | print "at $t s height = $height m, velocity = $velocity m/s\n"; |
101 | |
102 | $height = $height - $velocity; |
103 | $velocity = $velocity + $gravity; |
104 | $t = $t + 1; |
105 | } |
106 | |
107 | if ( $velocity > 10 ) { |
108 | print "CRASH!!!\n"; |
109 | } else { |
110 | print "You landed on the surface safely! :-D\n"; |
111 | } |
112 | |
56d4907c |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | |
b3ef54ec |
119 | </pre> |
b3ef54ec |
120 | <p>Run the code and you'll see something like this:</p> |
56d4907c |
121 | <pre> |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | at 0 s height = 1000 m, velocity = 0 m/s |
b3ef54ec |
128 | at 1 s height = 1000 m, velocity = 1 m/s |
129 | at 2 s height = 999 m, velocity = 2 m/s |
130 | at 3 s height = 997 m, velocity = 3 m/s |
131 | at 4 s height = 994 m, velocity = 4 m/s |
132 | at 5 s height = 990 m, velocity = 5 m/s |
133 | ... |
134 | at 43 s height = 97 m, velocity = 43 m/s |
135 | at 44 s height = 54 m, velocity = 44 m/s |
136 | at 45 s height = 10 m, velocity = 45 m/s |
137 | |
138 | CRASH!!! |
139 | |
56d4907c |
140 | |
141 | |
142 | |
143 | |
144 | |
145 | |
b3ef54ec |
146 | </pre> |
b3ef54ec |
147 | <p>"What happened? How do I control the ship???"</p> |
148 | |
149 | </div> |
150 | <h2 id="CONTROLLING_THE_SHIP">CONTROLLING THE SHIP</h2> |
151 | <div id="CONTROLLING_THE_SHIP_CONTENT"> |
152 | <p>The problem with our first spaceship is that it had no controls!</p> |
153 | <p>So, let's fix this problem, making the spaceship scriptable. (We |
154 | could write some code to handle keyboard and joysticks now, but |
155 | an scriptable spaceship will be easier to start. Remember, focus |
156 | on the game logic!)</p> |
157 | <p>So, create add this simple script to the end of your file:</p> |
56d4907c |
158 | <pre> |
159 | |
160 | |
161 | |
162 | |
163 | |
164 | __DATA__ |
b3ef54ec |
165 | at 41s, accelerate 10 m/s^2 up |
166 | at 43s, 10 m/s^2 |
167 | at 45s, 10 |
168 | at 47s, 10 |
169 | at 49s, 10 |
170 | |
56d4907c |
171 | |
172 | |
173 | |
174 | |
175 | |
176 | |
b3ef54ec |
177 | </pre> |
b3ef54ec |
178 | <p>The script is straightforward: it simply states a time when we |
179 | will push the spaceship up with a given acceleration. It accepts |
180 | free text: any two numbers you type will work.</p> |
181 | <p>We can parse the script using this regular expression:</p> |
56d4907c |
182 | <pre> |
183 | |
184 | |
185 | |
186 | |
187 | |
188 | my $script_re = qr/(\d+) \D+ (\d+)/x; |
189 | |
190 | |
191 | |
192 | |
193 | |
194 | |
b3ef54ec |
195 | |
196 | </pre> |
b3ef54ec |
197 | <p>And we can build a hash of ( time => acceleration ) with:</p> |
56d4907c |
198 | <pre> |
199 | |
200 | |
201 | |
202 | |
203 | |
204 | my %up = map { $_ =~ $script_re } <DATA>; |
205 | |
206 | |
207 | |
208 | |
209 | |
210 | |
b3ef54ec |
211 | |
212 | </pre> |
b3ef54ec |
213 | <p>So the middle section of the program will become:</p> |
56d4907c |
214 | <pre> |
215 | |
216 | |
217 | |
218 | |
219 | |
220 | my $script_re = qr/(\d+) \D+ (\d+)/x; |
b3ef54ec |
221 | my %up = map { $_ =~ $script_re } <DATA>; |
222 | |
223 | while ( $height > 0 ) { |
224 | print "at $t s height = $height m, velocity = $velocity m/s\n"; |
225 | |
226 | if ( $up{$t} ) { |
227 | my $a = $up{$t}; |
228 | print "(accellerating $a m/s^2)\n"; |
229 | $velocity = $velocity - $a; |
230 | } |
231 | |
232 | $height = $height - $velocity; |
233 | $velocity = $velocity + $gravity; |
234 | $t = $t + 1; |
235 | } |
236 | |
56d4907c |
237 | |
238 | |
239 | |
240 | |
241 | |
242 | |
b3ef54ec |
243 | </pre> |
b3ef54ec |
244 | <p>That's it!</p> |
245 | <p>Try to run the program, and the ship should land safely:</p> |
56d4907c |
246 | <pre> |
247 | |
248 | |
249 | |
250 | |
251 | |
252 | ./lunar.pl autopilot.txt |
b3ef54ec |
253 | at 0 s height = 1000 m, velocity = 0 m/s |
254 | at 1 s height = 1000 m, velocity = 1 m/s |
255 | at 2 s height = 999 m, velocity = 2 m/s |
256 | at 3 s height = 997 m, velocity = 3 m/s |
257 | at 4 s height = 994 m, velocity = 4 m/s |
258 | at 5 s height = 990 m, velocity = 5 m/s |
259 | ... |
260 | at 54 s height = 19 m, velocity = 4 m/s |
261 | at 55 s height = 15 m, velocity = 5 m/s |
262 | at 56 s height = 10 m, velocity = 6 m/s |
263 | at 57 s height = 4 m, velocity = 7 m/s |
264 | |
265 | You landed on the surface safely! :-D |
266 | |
56d4907c |
267 | |
268 | |
269 | |
270 | |
271 | |
272 | |
b3ef54ec |
273 | </pre> |
b3ef54ec |
274 | <p>Cool, but...</p> |
275 | |
276 | </div> |
277 | <h2 id="HOW_ABOUT_THE_GRAPHICS">HOW ABOUT THE GRAPHICS?</h2> |
278 | <div id="HOW_ABOUT_THE_GRAPHICS_CONTENT"> |
279 | <p>Okay, okay... now that we have a working prototype, we can work on |
280 | the graphics. But, first of all, we'll need...</p> |
281 | |
282 | </div> |
283 | <h3 id="THE_GRAPHICS">THE GRAPHICS</h3> |
284 | <div id="THE_GRAPHICS_CONTENT"> |
285 | <p>Yes, the graphics.</p> |
286 | <p>We won't use anything fancy here, just two images: a large one, for |
287 | the background, and a smaller one for the spaceship.</p> |
288 | <p>Create the images using the Gimp, or use the images provided by |
289 | this tutorial; Save these images in a subdirectory called "images": |
290 | ("<code>images/background.jpg</code>" and "<code>images/ship.png</code>").</p> |
291 | |
292 | </div> |
293 | <h2 id="USING_SDL">USING SDL</h2> |
294 | <div id="USING_SDL_CONTENT"> |
295 | <p>First step: use the required libraries:</p> |
56d4907c |
296 | <pre> |
297 | |
298 | |
299 | |
300 | |
301 | |
302 | use SDL; #needed to get all constants |
1f5d8082 |
303 | use SDL::Video; |
ca0a3441 |
304 | use SDLx::App; |
1f5d8082 |
305 | use SDL::Surface; |
306 | use SDL::Rect; |
307 | use SDL::Image; |
b3ef54ec |
308 | |
56d4907c |
309 | |
310 | |
311 | |
312 | |
313 | |
314 | |
b3ef54ec |
315 | </pre> |
ca0a3441 |
316 | <p>Second step: initialize <code>SDLx::App</code>:</p> |
56d4907c |
317 | <pre> |
318 | |
319 | |
320 | |
321 | |
322 | |
ca0a3441 |
323 | my $app = SDLx::App->new( |
505f308d |
324 | title => "Lunar Lander", |
325 | width => 800, |
326 | height => 600, |
327 | depth => 32, |
b3ef54ec |
328 | ); |
329 | |
56d4907c |
330 | |
331 | |
332 | |
333 | |
334 | |
335 | |
b3ef54ec |
336 | </pre> |
b3ef54ec |
337 | <p>Third step: load the images and create the necessary "rectangles":</p> |
56d4907c |
338 | <pre> |
339 | |
340 | |
341 | |
342 | |
343 | |
344 | my $background = SDL::Image::load('images/background.jpg'); |
1f5d8082 |
345 | my $ship = SDL::Image::load('images/ship.jpg'); |
b3ef54ec |
346 | |
1f5d8082 |
347 | my $background_rect = SDL::Rect->new(0,0, |
348 | $background->w, |
349 | $background->h, |
350 | ); |
b3ef54ec |
351 | |
1f5d8082 |
352 | my $ship_rect = SDL::Rect->new(0,0, |
353 | $ship->w, |
354 | $ship->h, |
355 | ); |
b3ef54ec |
356 | |
56d4907c |
357 | |
358 | |
359 | |
360 | |
361 | |
362 | |
b3ef54ec |
363 | </pre> |
b3ef54ec |
364 | <p>Fourth step: create a sub to draw the spaceship and background:</p> |
56d4907c |
365 | <pre> |
366 | |
367 | |
368 | |
369 | |
370 | |
371 | sub draw { |
1f5d8082 |
372 | my ( $x, $y ) = @_; # spaceship position |
b3ef54ec |
373 | |
1f5d8082 |
374 | # fix $y for screen resolution |
375 | $y = 450 * ( 1000 - $y ) / 1000; |
b3ef54ec |
376 | |
1f5d8082 |
377 | # background |
378 | SDL::Video::blit_surface($background, $background_rect, $app, $background_rect ); |
b3ef54ec |
379 | |
1f5d8082 |
380 | # ship |
381 | my $ship_dest_rect = SDL::Rect->new( |
382 | $x, $y, $ship->w, $ship->h, |
383 | ); |
b3ef54ec |
384 | |
1f5d8082 |
385 | SDL::Video::blit_surface($ship, $ship_rect, $app, $ship_dest_rect ); |
b3ef54ec |
386 | |
1f5d8082 |
387 | SDL::Video::update_rects($app, $background_rect); |
388 | } |
b3ef54ec |
389 | |
56d4907c |
390 | |
391 | |
392 | |
393 | |
394 | |
395 | |
b3ef54ec |
396 | </pre> |
b3ef54ec |
397 | <p>Note that this sub first combines all the bitmaps, using a blit |
398 | ("Block Image Transfer") operation -- which is quite fast, but does |
399 | not update the display.</p> |
400 | <p>The combined image is displayed in the last line. This process of |
401 | combining first, and displaying later, avoids that annoying fading |
402 | between cycles ("flickering").</p> |
403 | <p>Finally, add the following lines to the end of the main loop, so that |
404 | we call the <code>draw()</code> function with the correct spaceship |
405 | coordinates:</p> |
56d4907c |
406 | <pre> |
407 | |
408 | |
409 | |
410 | |
411 | |
412 | while ( $height > 0 ) { |
b3ef54ec |
413 | |
414 | # ... |
415 | |
416 | draw( 100, $height ); |
417 | $app->delay(10); |
418 | } |
419 | |
56d4907c |
420 | |
421 | |
422 | |
423 | |
424 | |
425 | |
b3ef54ec |
426 | </pre> |
b3ef54ec |
427 | <p>That's it!</p> |
428 | <p>Run the program and watch the spaceship landing safely on the surface |
429 | of the moon.</p> |
430 | |
431 | </div> |
432 | <h1 id="COPYRIGHT_amp_LICENSE">COPYRIGHT & LICENSE</h1><p><a href="#TOP" class="toplink">Top</a></p> |
433 | <div id="COPYRIGHT_amp_LICENSE_CONTENT"> |
434 | <p>Copyright 2009 Nelson Ferraz, all rights reserved.</p> |
1dbe1697 |
435 | <p>Updated and maintained by the SDL Perl project. See <a href="/SDL.html#AUTHORS">/SDL.html#AUTHORS</a>.</p> |
b3ef54ec |
436 | <p>This program is free software; you can redistribute it and/or modify it |
437 | under the same terms as Perl itself.</p> |
438 | |
439 | </div> |
440 | </div> |