GameScript: Move initialization out of constructor.
[gemrb.git] / gemrb / core / Animation.cpp
blob147974ff91e320ee8a370717f6cd5f9a7a39db40
1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "win32def.h"
22 #include "Animation.h"
23 #include "Interface.h"
24 #include "Video.h"
25 #include "Map.h"
26 #include "Game.h"
28 #ifndef WIN32
29 #include <sys/time.h>
30 #else
31 #include <windows.h>
32 #endif
34 Animation::Animation(int count)
36 frames = (Sprite2D **) calloc(count, sizeof(Sprite2D *));
37 indicesCount = count;
38 if (count) {
39 pos = rand() % count;
41 else {
42 pos = 0;
44 starttime = 0;
45 x = 0;
46 y = 0;
47 Flags = A_ANI_ACTIVE;
48 fps = 15;
49 endReached = false;
50 //behaviour flags
51 playReversed = false;
52 gameAnimation = false;
55 Animation::~Animation(void)
57 Video *video = core->GetVideoDriver();
59 for (unsigned int i = 0; i < indicesCount; i++) {
60 video->FreeSprite( frames[i] );
62 free(frames);
65 void Animation::SetPos(unsigned int index)
67 if (index<indicesCount) {
68 pos=index;
70 starttime = 0;
71 endReached = false;
74 /* when adding NULL, it means we already added a frame of index */
75 void Animation::AddFrame(Sprite2D* frame, unsigned int index)
77 if (index>=indicesCount) {
78 printf("You tried to write past a buffer in animation, BAD!\n");
79 abort();
81 core->GetVideoDriver()->FreeSprite(frames[index]);
82 frames[index]=frame;
84 int x = -frame->XPos;
85 int y = -frame->YPos;
86 int w = frame->Width;
87 int h = frame->Height;
88 if (x < animArea.x) {
89 animArea.w += (animArea.x - x);
90 animArea.x = x;
92 if (y < animArea.y) {
93 animArea.h += (animArea.y - y);
94 animArea.y = y;
96 if (x+w > animArea.x+animArea.w) {
97 animArea.w = x+w-animArea.x;
99 if (y+h > animArea.y+animArea.h) {
100 animArea.h = y+h-animArea.y;
104 unsigned int Animation::GetCurrentFrame() const
106 if (playReversed)
107 return indicesCount-pos-1;
108 return pos;
111 Sprite2D* Animation::LastFrame(void)
113 if (!Flags&A_ANI_ACTIVE) {
114 printf("Frame fetched while animation is inactive!\n");
115 return NULL;
117 if (gameAnimation) {
118 starttime = core->GetGame()->Ticks;
119 } else {
120 GetTime( starttime );
122 Sprite2D* ret;
123 if (playReversed)
124 ret = frames[indicesCount-pos-1];
125 else
126 ret = frames[pos];
127 return ret;
130 Sprite2D* Animation::NextFrame(void)
132 if (!Flags&A_ANI_ACTIVE) {
133 printf("Frame fetched while animation is inactive!\n");
134 return NULL;
136 if (starttime == 0) {
137 if (gameAnimation) {
138 starttime = core->GetGame()->Ticks;
139 } else {
140 GetTime( starttime );
143 Sprite2D* ret;
144 if (playReversed)
145 ret = frames[indicesCount-pos-1];
146 else
147 ret = frames[pos];
149 if (endReached && (Flags&A_ANI_PLAYONCE) )
150 return ret;
152 unsigned long time;
153 if (gameAnimation) {
154 time = core->GetGame()->Ticks;
155 } else {
156 GetTime(time);
159 //it could be that we skip more than one frame in case of slow rendering
160 //large, composite animations (dragons, multi-part area anims) require synchronisation
161 if (( time - starttime ) >= ( unsigned long ) ( 1000 / fps )) {
162 int inc = (time-starttime)*fps/1000;
163 pos += inc;
164 starttime += inc*1000/fps;
166 if (pos >= indicesCount ) {
167 if (indicesCount) {
168 if (Flags&A_ANI_PLAYONCE) {
169 pos = indicesCount-1;
170 endReached = true;
171 } else {
172 pos = pos%indicesCount;
173 endReached = false; //looping, there is no end
175 } else {
176 pos = 0;
177 endReached = true;
179 starttime = 0;
181 return ret;
184 Sprite2D* Animation::GetSyncedNextFrame(Animation* master)
186 if (!Flags&A_ANI_ACTIVE) {
187 printf("Frame fetched while animation is inactive!\n");
188 return NULL;
190 Sprite2D* ret;
191 if (playReversed)
192 ret = frames[indicesCount-pos-1];
193 else
194 ret = frames[pos];
196 starttime = master->starttime;
197 pos = master->pos;
198 endReached = master->endReached;
200 return ret;
204 void Animation::release(void)
206 delete this;
208 /** Gets the i-th frame */
209 Sprite2D* Animation::GetFrame(unsigned int i)
211 if (i >= indicesCount) {
212 return NULL;
214 return frames[i];
217 void Animation::MirrorAnimation()
219 Video *video = core->GetVideoDriver();
221 for (size_t i = 0; i < indicesCount; i++) {
222 Sprite2D * tmp = frames[i];
223 frames[i] = video->MirrorSpriteHorizontal( tmp, true );
224 video->FreeSprite(tmp);
227 // flip animArea horizontally as well
228 animArea.x = -animArea.w - animArea.x;
231 void Animation::MirrorAnimationVert()
233 Video *video = core->GetVideoDriver();
235 for (size_t i = 0; i < indicesCount; i++) {
236 Sprite2D * tmp = frames[i];
237 frames[i] = video->MirrorSpriteVertical( tmp, true );
238 video->FreeSprite(tmp);
241 // flip animArea vertically as well
242 // animArea.y = -animArea.h - animArea.y;
245 void Animation::AddAnimArea(Animation* slave)
247 int x = slave->animArea.x;
248 int y = slave->animArea.y;
249 int w = slave->animArea.w;
250 int h = slave->animArea.h;
251 if (x < animArea.x) {
252 animArea.w += (animArea.x - x);
253 animArea.x = x;
255 if (y < animArea.y) {
256 animArea.h += (animArea.y - y);
257 animArea.y = y;
259 if (x+w > animArea.x+animArea.w) {
260 animArea.w = x+w-animArea.x;
262 if (y+h > animArea.y+animArea.h) {
263 animArea.h = y+h-animArea.y;