12 # int type = {projection type enum}
13 # float boundingradius
14 # int width = width of largest frame
15 # int height = height of largest frame
18 # int synctype = {ST_SYNC=0, ST_RAND=1}
22 # int type = {SPR_SINGLE=0, SPR_GROUP=1}
23 # if type == SPR_GROUP:
24 # int numframes_thisgroup
25 # for 1..numframes_thisgroup:
27 # for 1..numframes_thisgroup:
33 # width*height*4 bytes of image data, RGBA
35 my $magick = Image::Magick->new();
46 my ($spritestruct, $filename) = @_;
47 open my $fh, '>', $filename;
50 syswrite $fh, pack 'V', 32;
51 syswrite $fh, pack 'V', $spritestruct->{type};
53 my $radius_x = abs(abs($spritestruct->{x0}) > abs($spritestruct->{x1}) ? $spritestruct->{x0} : $spritestruct->{x1});
54 my $radius_y = abs(abs($spritestruct->{y0}) > abs($spritestruct->{y1}) ? $spritestruct->{y0} : $spritestruct->{y1});
56 syswrite $fh, pack 'f', sqrt($radius_x * $radius_x + $radius_y * $radius_y);
57 syswrite $fh, pack 'V', $spritestruct->{x1} - $spritestruct->{x0};
58 syswrite $fh, pack 'V', $spritestruct->{y1} - $spritestruct->{y0};
59 syswrite $fh, pack 'V', scalar @{$spritestruct->{groups}};
60 syswrite $fh, pack 'f', $spritestruct->{beamlength};
61 syswrite $fh, pack 'V', $spritestruct->{synctype};
63 for my $g(@{$spritestruct->{groups}})
69 syswrite $fh, pack 'V', 0;
74 syswrite $fh, pack 'V', 1;
75 syswrite $fh, pack 'V', scalar @$f;
76 syswrite $fh, pack 'f', $_->{interval} for @$f;
80 syswrite $fh, pack 'V', $_->{orgx} - $_->{width};
81 syswrite $fh, pack 'V', $_->{orgy};
82 syswrite $fh, pack 'V', $_->{width};
83 syswrite $fh, pack 'V', $_->{height};
84 syswrite $fh, $_->{data};
91 my ($type, $beamlength, $synctype) = @_;
94 beamlength => $beamlength,
95 synctype => $synctype,
117 sub spriteframe($$$$$)
119 my ($spritestruct, $imagefile, $orgx, $orgy, $interval) = @_;
120 checkmagick $magick->Read($imagefile);
121 my ($width, $height) = $magick->Get('columns', 'rows');
122 my $data = $magick->ImageToBlob(depth => 8, magick => 'RGBA');
124 die "Size mismatch for $imagefile: @{[length $data]} is not @{[4 * $width * $height]}"
125 if length $data != 4 * $width * $height;
126 my $g = ($spritestruct->{groups}->[-1]);
127 push @{$g->{frames}}, my $s = {};
128 $s->{width} = $width;
131 $s->{width} = $width;
132 $s->{height} = $height;
134 $s->{interval} = $interval;
138 my $x1 = $width - $orgx;
139 my $y1 = $height - $orgy;
141 $spritestruct->{x0} = $x0 if $width > $spritestruct->{x0};
142 $spritestruct->{y0} = $y0 if $width > $spritestruct->{y0};
143 $spritestruct->{x1} = $x1 if $width > $spritestruct->{x1};
144 $spritestruct->{y1} = $y1 if $width > $spritestruct->{y1};
149 my ($spritestruct) = @_;
150 push @{$spritestruct->{groups}}, my $g = {};
158 [-proj projectiontype]
162 -sprite filename.tga orgx orgy interval
163 [-sprite filename.tga orgx orgy interval [...]]
165 -sprite filename.tga orgx orgy interval
166 [-sprite filename.tga orgx orgy interval [...]] [...]]
170 my $proj = 2; # SPR_VP_PARALLEL
194 $outfile = shift @ARGV;
196 elsif($s eq '-group')
200 elsif($s eq '-sprite')
208 unshift @ARGV, '-sprite';
213 usage() unless defined $outfile;
215 my $spritestruct = spritestruct($proj, $beam, $synctype);
216 print "created sprite with projection $proj, beam length $beam, sync type $synctype\n";
218 spritegroup($spritestruct);
219 print " created sprite group\n";
228 my ($filename, $orgx, $orgy, $interval) = splice @ARGV, 0, 4;
229 usage() if not defined $interval;
230 spriteframe($spritestruct, $filename, $orgx, $orgy, $interval);
231 print " created sprite frame $filename, origin at $orgx|$orgy, interval $interval\n";
233 elsif($s eq '-group')
235 spritegroup($spritestruct);
236 print " created sprite group\n";
240 my ($orgx, $orgy, $interval) = splice @ARGV, 0, 3;
241 usage() if not defined $interval;
242 spriteframe($spritestruct, $s, $orgx, $orgy, $interval);
243 print " created sprite frame $s, origin at $orgx|$orgy, interval $interval\n";
247 writesprite($spritestruct, $outfile);
248 print "written to $outfile\n";