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