1 // Copyright 2008 Brian Caine && Justin Overfelt
3 // This file is part of Potpourri.
5 // Potpourri is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
10 // Potpourri is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTIBILITY of FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with Potpourri. If not, see <http://www.gnu.org/licenses/>.
25 #include <SDL/SDL_rotozoom.h>
29 #define PI 3.141592653589793
31 using namespace fragrant
;
33 Sprite
* Sprite::makeSprite(std::vector
<SDL_Surface
*> dframes
,
36 Sprite
* the_sprite
= new Sprite(dframes
, dparams
);
42 std::cerr
<< "Sprite::makeSprite(): Error making sprite" << std::endl
;
52 std::map
<int, std::vector
<SDL_Surface
*> >::iterator biter
;
53 std::vector
<SDL_Surface
*>::iterator niter
;
55 for (biter
= angle_frames
.begin(); biter
!= angle_frames
.end(); biter
++)
56 for (niter
= biter
->second
.begin(); niter
!= biter
->second
.end(); niter
++)
58 SDL_FreeSurface(*niter
);
62 void Sprite::draw(SDL_Surface
* dest
)
66 int cur_ticks
= SDL_GetTicks();
67 ticks_left
-= (cur_ticks
- last_tick
);
69 last_tick
= cur_ticks
;
71 while (ticks_left
<= 0)
74 if (cur_frame
== frames
.size() && sequence
.repeat
)
77 ticks_left
= sequence
.frames
.at(cur_frame
).duration
+ ticks_left
;
81 std::map
<int, std::vector
<SDL_Surface
*> >::iterator iter
;
83 std::vector
<SDL_Surface
*> cocked_frames
;
85 for (iter
= angle_frames
.begin(); iter
!= angle_frames
.end(); iter
++)
87 if ((sequence
.angle
+ ANGLE_SNAP
> iter
->first
) &&
88 (sequence
.angle
- ANGLE_SNAP
< iter
->first
))
89 cocked_frames
= iter
->second
;
92 if (!cocked_frames
.size())
94 makeNewAngleFrame(sequence
.angle
);
95 cocked_frames
= angle_frames
[sequence
.angle
];
100 SDL_Surface
* surface
= cocked_frames
.at(cur_frame
);
102 SDL_Rect pos
= {sequence
.position
.at(0) + angle_offset
.at(0),
103 sequence
.position
.at(1) + angle_offset
.at(1),
104 surface
->w
, surface
->h
};
105 SDL_BlitSurface(surface
, 0, dest
, &pos
);
110 int Sprite::getCurrentFrame()
115 int Sprite::getAngle()
117 return sequence
.angle
;
120 void Sprite::setAngle(int new_angle
)
122 sequence
.angle
= new_angle
;
123 sequence
.angle
%= 360;
128 std::vector
<int> Sprite::getPosition()
130 return sequence
.position
;
133 void Sprite::setPosition(std::vector
<int> new_position
)
135 if (new_position
.size() < 2)
137 std::cerr
<< "Sprite::setPosition(): Not enough parameters for "
138 << "new position" << std::endl
;
142 if (new_position
.size() > 2)
144 std::cerr
<< "Sprite::setPosition(): Too many parameters for new "
145 << "position" << std::endl
;
148 sequence
.position
= new_position
;
153 Sprite::Sprite(std::vector
<SDL_Surface
*> dframes
, SpriteParams dparams
)
157 if (!dframes
.size() || !dparams
.frames
.size())
160 std::vector
<Frame
>::iterator iter
;
161 for (iter
= dparams
.frames
.begin(); iter
!= dparams
.frames
.end(); iter
++)
162 if (iter
->frame
>= dframes
.size())
165 if ((dparams
.position
.size() < 2) || (dparams
.focal_point
.size() < 2))
168 if (dparams
.position
.size() > 2)
169 std::cerr
<< "Sprite::makeSprite(): Warning, More position "
170 << "parameters then needed..." << std::endl
;
172 if (dparams
.focal_point
.size() > 2)
173 std::cerr
<< "Sprite::makeSprite(): Warning, More focal point "
174 << "parameters then needed..." << std::endl
;
176 if (dparams
.angle
> 360)
178 std::cerr
<< "Sprite::makeSprite(): Warning, Angle is greater than 360, "
179 << "wrapping around..." << std::endl
;
180 dparams
.angle
%= 360;
184 std::vector
<SDL_Surface
*>::iterator inc
;
185 bool frame_size
= true;
187 w
= dframes
.at(0) -> w
;
188 h
= dframes
.at(0) -> h
;
190 for (inc
= dframes
.begin(); inc
!= dframes
.end(); inc
++)
191 frame_size
= ((*inc
)-> w
== w
) && ((*inc
) -> h
== h
) && (frame_size
);
195 std::cerr
<< "Sprite::makeSprite(): Warning, not all frames are the same size"
199 was_made
= was_made
&& frame_size
;
215 bool Sprite::makeAngleFrames()
219 for (cur
= 0; cur
< CIRCLE
; cur
+= ANGLE_CACHE
)
220 makeNewAngleFrame(cur
);
225 void Sprite::makeNewAngleFrame(int angle
)
229 std::vector
<SDL_Surface
*> new_frames
;
231 std::vector
<SDL_Surface
*>::iterator iter
;
233 for (iter
= frames
.begin(); iter
!= frames
.end(); iter
++)
235 temp
= rotozoomSurface(*iter
, static_cast<double>(angle
), 1, 1);
236 SDL_SetAlpha(temp
, SDL_SRCALPHA
, SDL_ALPHA_OPAQUE
);
237 new_frames
.push_back(temp
);
240 angle_frames
[angle
] = new_frames
;
245 void Sprite::calcAngleOffset()
248 SDL_Surface
* temp_surf
= 0;
250 std::map
<int, std::vector
<SDL_Surface
*> >::iterator iter
;
251 for (iter
= angle_frames
.begin(); iter
!= angle_frames
.end(); iter
++)
252 if ((sequence
.angle
+ ANGLE_SNAP
> iter
->first
) &&
253 (sequence
.angle
- ANGLE_SNAP
< iter
->first
))
256 temp_surf
= iter
->second
.at(0);
262 float c_1
[2], c_2
[2], c_3
[2];
263 float center_1
[2], center_2
[2];
264 float size_1
[2], size_2
[2];
265 float focus_1
[2], focus_2
[2], focus_3
[2], focus_4
[2];
266 float radius_1
, radius_2
, theta_1
, theta_2
, theta_3
;
268 size_1
[0] = frames
.at(cur_frame
)->w
;
269 size_1
[1] = frames
.at(cur_frame
)->h
;
271 size_2
[0] = temp_surf
->w
;
272 size_2
[1] = temp_surf
->h
;
274 focus_1
[0] = sequence
.focal_point
.at(0);
275 focus_1
[1] = sequence
.focal_point
.at(1);
280 center_1
[0] = size_1
[0] / 2;
281 center_1
[1] = size_1
[1] / 2;
283 center_2
[0] = size_2
[0] / 2;
284 center_2
[1] = size_2
[1] / 2;
287 static_cast<double>(pow(center_1
[0], 2) + pow(center_1
[1], 2)));
288 theta_1
= acos(-center_1
[0] / radius_1
) * (180/PI
);
290 c_2
[0] = radius_1
* cos((theta_1
+ rot
) * (PI
/180));
291 c_2
[1] = radius_1
* sin((theta_1
+ rot
) * (PI
/180));
293 c_3
[0] = c_2
[0] + center_2
[0];
294 c_3
[1] = center_2
[1] - c_2
[1];
297 static_cast<double>(pow(focus_1
[0], 2) + pow(focus_1
[1], 2)));
299 theta_2
= -acos(focus_1
[0] / radius_2
) * (180/PI
);
303 theta_3
= theta_2
+ rot
;
305 focus_2
[0] = radius_2
* cos(theta_3
* (PI
/180));
306 focus_2
[1] = radius_2
* sin(theta_3
* (PI
/180));
308 focus_3
[0] = c_3
[0] + focus_2
[0];
309 focus_3
[1] = c_3
[1] - focus_2
[1];
311 focus_4
[0] = focus_1
[0] - focus_3
[0];
312 focus_4
[1] = focus_1
[0] - focus_3
[1];
314 angle_offset
.clear();
315 angle_offset
.push_back(static_cast<int>(focus_4
[0]));
316 angle_offset
.push_back(static_cast<int>(focus_4
[1]));
321 bool Sprite::was_made
= false;