I fixed up the main SConstruct.
[potpourri.git] / src / Sprite.cpp
blob358aa871ed3a853af7b1bd60971832bf9fabed5c
1 // Copyright 2008 Brian Caine
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/>.
18 // NOTES:
20 // See Sprite.h
22 #include <iostream>
23 #include <cmath>
25 #include <SDL/SDL_rotozoom.h>
27 #include "Sprite.h"
29 #define PI 3.141592653589793
31 using namespace fragrant;
33 Sprite* Sprite::makeSprite(std::vector<SDL_Surface*> dframes,
34 SpriteParams dparams)
36 Sprite* the_sprite = new Sprite(dframes, dparams);
38 if (!was_made)
40 delete the_sprite;
41 the_sprite = 0;
42 std::cerr << "Sprite::makeSprite(): Error making sprite" << std::endl;
45 was_made = false;
47 return the_sprite;
50 Sprite::~Sprite()
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)
64 // timing stuff
66 int cur_ticks = SDL_GetTicks();
67 ticks_left -= (cur_ticks - last_tick);
69 last_tick = cur_ticks;
71 while (ticks_left <= 0)
73 cur_frame++;
74 if (cur_frame == frames.size() && sequence.repeat)
75 cur_frame = 0;
77 ticks_left = sequence.frames.at(cur_frame).duration + ticks_left;
80 // rotation stuff
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];
98 // actual rendering
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);
107 return;
110 Sprite::Sprite(std::vector<SDL_Surface*> dframes, SpriteParams dparams)
112 was_made = true;
114 if (!dframes.size() || !dparams.frames.size())
115 was_made = false;
117 std::vector<Frame>::iterator iter;
118 for (iter = dparams.frames.begin(); iter != dparams.frames.end(); iter++)
119 if (iter->frame >= dframes.size())
120 was_made = false;
122 if ((dparams.position.size() < 2) || (dparams.focal_point.size() < 2))
123 was_made = false;
125 if (dparams.position.size() > 2)
126 std::cerr << "Sprite::makeSprite(): Warning, More position "
127 << "parameters then needed..." << std::endl;
129 if (dparams.focal_point.size() > 2)
130 std::cerr << "Sprite::makeSprite(): Warning, More focal point "
131 << "parameters then needed..." << std::endl;
133 if (dparams.angle > 360)
135 std::cerr << "Sprite::makeSprite(): Warning, Angle is greater than 360, "
136 << "wrapping around..." << std::endl;
137 dparams.angle %= 360;
140 if (was_made)
142 sequence = dparams;
143 frames = dframes;
145 cur_frame = 0;
146 last_tick = -1;
147 ticks_left = -1;
149 makeAngleFrames();
150 calcAngleOffset();
154 bool Sprite::makeAngleFrames()
156 int cur;
158 for (cur = 0; cur < CIRCLE; cur += ANGLE_CACHE)
159 makeNewAngleFrame(cur);
161 return true;
164 void Sprite::makeNewAngleFrame(int angle)
166 SDL_Surface* temp;
168 std::vector<SDL_Surface*> new_frames;
170 std::vector<SDL_Surface*>::iterator iter;
172 for (iter = frames.begin(); iter != frames.end(); iter++)
174 temp = rotozoomSurface(*iter, static_cast<double>(angle), 1, 1);
175 new_frames.push_back(temp);
178 angle_frames[angle] = new_frames;
180 return;
183 void Sprite::calcAngleOffset()
185 std::vector<int> new_offset;
187 int rot = -1;
188 SDL_Surface* temp_surf = 0;
190 std::map<int, std::vector<SDL_Surface*> >::iterator iter;
191 for (iter = angle_frames.begin(); iter != angle_frames.end(); iter++)
192 if ((sequence.angle + ANGLE_SNAP > iter->first) &&
193 (sequence.angle - ANGLE_SNAP < iter->first))
195 rot = iter->first;
196 temp_surf = iter->second.at(0);
199 if (!temp_surf)
200 return;
202 float x_1, y_1, x_2, y_2, radius, theta_1, theta_2;
203 float w_1, h_1, w_2, h_2;
205 x_1 = sequence.focal_point.at(0);
206 y_1 = sequence.focal_point.at(1);
208 w_1 = frames.at(0)->w;
209 h_1 = frames.at(0)->h;
211 radius = static_cast<int>(sqrt(
212 pow((static_cast<double>(x_1), static_cast<double>(w_1) / 2), 2) +
213 pow((static_cast<double>(y_1), static_cast<double>(h_1) / 2), 2) ));
215 theta_1 = (180 / PI) * acos(static_cast<double>(x_1) /
216 static_cast<double>(radius));
217 theta_2 = theta_1 + rot;
219 x_2 = radius * cos(theta_2 * (PI / 180)) + (w_1 / 2);
220 y_2 = radius * sin(theta_2 * (PI / 180)) + (h_1 / 2);
222 w_2 = temp_surf->w;
223 h_2 = temp_surf->h;
225 new_offset.push_back(static_cast<int>(
226 (x_2 - x_1) + ((w_1 / 2) - (w_2 / 2))));
227 new_offset.push_back(static_cast<int>(
228 (y_2, - y_1) + ((h_1 / 2) - (h_2 / 2))));
230 angle_offset = new_offset;
232 return;
235 bool Sprite::was_made = false;