first merge
[sdlgit/SDL_perl.git] / test / testgfxroto.sdlpl
1 #!/usr/bin/env perl
2 #
3 # testgfxroto.pl
4 #
5 # Copyright (C) 2005 David J. Goehrig <dgoehrig@cpan.org>
6 #
7 # ------------------------------------------------------------------------------
8 #
9 # This library is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU Lesser General Public
11 # License as published by the Free Software Foundation; either
12 # version 2.1 of the License, or (at your option) any later version.
13
14 # This library is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 # Lesser General Public License for more details.
18
19 # You should have received a copy of the GNU Lesser General Public
20 # License along with this library; if not, write to the Free Software
21 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 #
23 # ------------------------------------------------------------------------------
24 #
25 # Please feel free to send questions, suggestions or improvements to:
26 #
27 #       David J. Goehrig
28 #       dgoehrig@cpan.org
29 #
30
31 use strict;
32 use Getopt::Long;
33 use Data::Dumper;
34 use MIME::Base64 qw(decode_base64);
35
36 use SDL;
37 use SDL::App;
38 use SDL::Event;
39 use SDL::Surface;
40 use SDL::Color;
41 use SDL::Rect;
42 use SDL::Config;
43
44 use vars qw/ $app $app_rect $background $event $sprite $sprite_rect $videoflags /;
45
46 ## Test for SDL_gfx support
47
48 die "Your system was not configured with SDL_gfx support!\n"
49         unless SDL::Config->has('SDL_gfx');
50
51
52 ## User tweakable settings (via cmd-line)
53 my %settings = (
54         'numsprites'            => 10,
55         'screen_width'  => 200,
56         'screen_height' => 200,
57         'video_bpp'              => 8,
58         'fast'                                  => 0,
59         'hw'                                            => 0,
60         'flip'                                  => 1,
61         'fullscreen'            => 0,
62         'bpp'                                    => undef,
63 );
64
65 ## Process commandline arguments
66
67 sub get_cmd_args
68 {
69         GetOptions("width:i"    => \$settings{screen_width},
70                          "height:i" => \$settings{screen_height},
71                          "bpp:i"                => \$settings{bpp},
72                          "fast!"         => \$settings{fast},
73                          "hw!"           => \$settings{hw},
74                          "flip!"                => \$settings{flip},
75                          "fullscreen!" => \$settings{fullscreen},
76                          "numsprites=i" => \$settings{numsprites},
77                         );
78 }
79
80 ## Initialize application options
81
82 sub set_app_args
83 {
84         $settings{bpp} ||= 8;           # default to 8 bits per pix
85
86         $videoflags |= SDL_HWACCEL               if $settings{hw};      
87         $videoflags |= SDL_DOUBLEBUF     if $settings{flip};    
88         $videoflags |= SDL_FULLSCREEN   if $settings{fullscreen}; 
89 }
90
91 ## Setup 
92
93 sub     init_game_context
94 {
95         $app = new SDL::App (
96                                          -width => $settings{screen_width}, 
97                                          -height=> $settings{screen_height}, 
98                                          -title => "testsprite",
99                                          -flags => $videoflags,
100                         );
101
102         $app_rect= new SDL::Rect(
103                                  -height => $settings{screen_height}, 
104                                  -width => $settings{screen_width},
105                                 );
106
107         $background = $SDL::Color::black;
108
109         $sprite = new SDL::Surface -name =>"/tmp/spiral.png"; 
110
111         $sprite->display_format();
112
113         SDL::SetColorKey($$sprite, SDL_SRCCOLORKEY, SDL::SurfacePixel($$sprite,0,0));
114
115         $sprite_rect = new SDL::Rect(-x          => 0, 
116                                                  -y              => 0,
117                                                  -width => $sprite->width,
118                                                  -height=> $sprite->height,
119                                                 );
120         
121         $event = new SDL::Event();
122 }
123
124 ## Prints diagnostics
125
126 sub instruments
127 {
128         if ( ($app->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
129                 printf("Screen is in video memory\n");
130         } else {
131                 printf("Screen is in system memory\n");
132         }
133
134         if ( ($app->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF ) {
135                 printf("Screen has double-buffering enabled\n");
136         }
137
138         if ( ($sprite->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
139                 printf("Sprite is in video memory\n");
140         } else {
141                 printf("Sprite is in system memory\n");
142         }
143         
144         # Run a sample blit to trigger blit (if posssible)
145         # acceleration before the check just after 
146         put_sprite_rotated($sprite,
147                         $settings{screen_width}/2, $settings{screen_height}/2,
148                         0,0,0);
149         
150         if ( ($sprite->flags & SDL_HWACCEL) == SDL_HWACCEL ) {
151                 printf("Sprite blit uses hardware acceleration\n");
152         }
153         if ( ($sprite->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
154                 printf("Sprite blit uses RLE acceleration\n");
155         }
156         
157 }
158
159
160
161
162 # this can      get silly in terms of
163 # memory usage, and maybe key lookup.
164 # it would be better to 'tie' the hash
165 # to an object which can
166 # better manage memory usage.
167
168 my %rotate_cache =();
169
170 sub generate_sprite_rotated
171 {
172         my ($surface, $angle, $zoom, $smooth) = @_;
173
174         $angle %= 360;
175         my $key = "$surface$angle$zoom$smooth";
176
177         if ( $rotate_cache{$key} )
178         {
179                 return $rotate_cache{$key};
180         }
181         else
182         {
183                  my $sur = SDL::GFXRotoZoom($surface, $angle, $zoom, $smooth);
184
185                  $rotate_cache{$key}= SDL::DisplayFormat($sur);
186         }
187         return $rotate_cache{$key};
188 }
189
190 sub put_sprite_rotated
191 {
192         my ($surface, $x, $y, $angle, $zoom, $smooth) = @_;
193
194         my $roto = generate_sprite_rotated($$surface, $angle, $zoom, $smooth);
195
196         die "Failed to create rotozoom surface" unless $roto;
197
198         my ($w,$h) = (SDL::SurfaceW($roto),SDL::SurfaceH($roto));;       
199         
200
201         my $dest_rect = new SDL::Rect
202                                 -x => $x - ($w/2),
203                                 -y => $y - ($h/2),
204                                 -width  => $w,
205                                 -height => $h;
206
207         
208         SDL::BlitSurface($roto, 0, $$app, $$dest_rect); 
209 }
210
211
212 sub game_loop
213 {
214         my $ox=$settings{screen_width}>>1;;
215         my $oy=$settings{screen_height}>>1;
216         my $sectors = 12;
217         my $angleDelta = 360/$sectors;;
218         my $zoom        = 1;
219         my $smooth =1;
220
221         my $angle        =0;
222         my $radius      =128;
223
224  FRAME:
225         while (1) 
226         {
227                 # process event queue
228                 $event->pump;
229                 if ($event->poll)
230                 {
231                         my $etype=$event->type();                       
232                         
233                         # handle quit events
234                         last FRAME if ($etype == SDL_QUIT() );
235                         last FRAME if (SDL::GetKeyState(SDLK_ESCAPE));
236                 }
237
238                 # needed for HW surface locking
239                 #$app->lock() if $app->lockp(); 
240                 #$app->unlock();
241                 $app->flip if $settings{flip};
242
243                 ################################################
244                 # do some drawing 
245                 
246                 $app->fill($app_rect, $background);
247
248                 $angle += 16;
249
250                 put_sprite_rotated($sprite, 
251                         $settings{screen_width}/2, $settings{screen_height}/2,
252                         $angle, $zoom, $smooth);
253                         
254         }
255         print "Cache entries: " . scalar(keys %rotate_cache) . "\n";
256 }
257
258
259
260 ## Main program loop
261
262 write_spiral();
263 get_cmd_args();
264 set_app_args();
265 init_game_context();
266 instruments();
267 game_loop();
268 exit(0);
269
270 sub write_spiral {
271         my $png = decode_base64 <<EOF;
272 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
392 EOF
393         open FP, "> /tmp/spiral.png";
394         print FP $png;
395         close FP;
396 }