5 * Copyright (C) 2003, 2007, 2008, 2009 Thomas Perl <thp@thpinfo.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
30 #include "animation.h"
34 Animation
* animation_new()
36 Animation
* animation
= (Animation
*)calloc(1, sizeof(Animation
));
37 assert(animation
!= NULL
);
41 Animation
* animation_append(Animation
* animation
, AnimationPart
* part
)
43 if (part
->end
> animation
->duration
) {
44 animation
->duration
= part
->end
;
47 if (animation
->head
== NULL
) {
48 /* insert into empty list */
51 animation
->head
= part
;
52 animation
->tail
= part
;
54 /* insert into non-empty list */
55 part
->prev
= animation
->tail
;
57 animation
->tail
->next
= part
;
58 animation
->tail
= part
;
64 void animation_free(Animation
* animation
)
69 part
= animation
->head
;
70 while (part
!= NULL
) {
72 animation_part_free(part
);
79 AnimationState
* animation_state_new(Animation
* animation
)
81 AnimationState
* state
= (AnimationState
*)calloc(1, sizeof(AnimationState
));
82 assert(state
!= NULL
);
84 state
->animation
= animation
;
85 state
->started
= SDL_GetTicks();
86 state
->ending
= state
->started
+ animation
->duration
;
91 void animation_state_run(AnimationState
* state
, int interruptible
)
98 while (animation_state_update(state
)) {
100 while (SDL_PollEvent(&e
)) {
101 if (e
.type
== SDL_KEYDOWN
|| e
.type
== SDL_QUIT
) {
106 p
= state
->animation
->head
;
108 animation_part_display(p
, state
);
115 int animation_state_update(AnimationState
* state
)
117 assert(state
!= NULL
);
119 state
->current
= SDL_GetTicks();
121 return state
->current
< state
->ending
;
124 void animation_state_free(AnimationState
* state
)
129 AnimationPart
* animation_part_new_from_surface(Uint32 start
, Uint32 end
,
130 unsigned int effects
, int x
, int y
, int zindex
, unsigned int gravity
,
131 SDL_Surface
* surface
, unsigned char free_surface
, int pos
, int count
)
133 AnimationPart
* part
= (AnimationPart
*)calloc(1, sizeof(AnimationPart
));
134 assert(part
!= NULL
);
138 part
->effects
= effects
;
142 part
->zindex
= zindex
;
144 part
->gravity
= gravity
;
146 part
->surface
= surface
;
147 part
->free_surface
= free_surface
;
154 AnimationPart
* animation_part_new_text(Uint32 start
, Uint32 end
,
155 unsigned int effects
, int x
, int y
, int zindex
, unsigned int gravity
,
156 font_id id
, const char* text
, Uint8 r
, Uint8 g
, Uint8 b
)
158 return animation_part_new_from_surface(
166 font_render_surface(id
, text
, r
, g
, b
),
173 void animation_part_display(AnimationPart
* part
, AnimationState
* state
)
175 Uint32 start
= state
->started
+ part
->start
;
176 Uint32 end
= state
->started
+ part
->end
;
179 SDL_Surface
* surface
;
181 if (state
->current
< start
|| state
->current
> end
) {
182 /* this part has had it's time (or is yet to have it ;) */
186 surface
= part
->surface
;
187 p
= (float)(state
->current
- start
)/(float)(end
- start
);
189 if (part
->effects
& ANIMATION_ZOOM_2X
) {
190 surface
= rotozoom_surface(surface
, 0.0, p
+1);
193 switch (part
->gravity
) {
194 case GRAVITY_CENTER_UPPERHALF
:
195 x
= (WIDTH
- surface
->w
)/2 + part
->x
;
196 y
= HEIGHT
/2 - surface
->h
+ part
->y
;
198 case GRAVITY_CENTER_BOTTOMHALF
:
199 x
= (WIDTH
- surface
->w
)/2 + part
->x
;
200 y
= HEIGHT
/2 + part
->y
;
202 case GRAVITY_CENTER_SCREEN
:
203 x
= (WIDTH
- surface
->w
)/2 + part
->x
;
204 y
= (HEIGHT
- surface
->h
)/2 + part
->y
;
207 x
= (WIDTH
- surface
->w
)/2 + part
->x
;
210 case GRAVITY_TOPLEFT
:
211 /* fall-through to default */
218 if (part
->effects
& ANIMATION_FROM_BOTTOM
) {
219 y
= y
* p
+ (HEIGHT
-part
->surface
->h
) * (1-p
);
222 if (part
->effects
& ANIMATION_SLIDE_LEFT
) {
226 if (part
->effects
& ANIMATION_SLIDE_RIGHT
) {
227 x
= (WIDTH
-surface
->w
) * (1.-p
) + x
* p
;
230 blit_surface_simple(surface
, x
, y
);
232 /* FIXME: fade in and out should be handled by blitting w/ alpha value */
233 if (part
->effects
& ANIMATION_FADE_IN
) {
234 if (p
< ANIMATION_FADE_PART
) {
235 rectangle_alpha(x
, y
, surface
->w
, surface
->h
, 0, 0, 0,
236 255*(1-(1./ANIMATION_FADE_PART
)*p
));
240 if (part
->effects
& ANIMATION_FADE_OUT
) {
241 if (p
> (1-ANIMATION_FADE_PART
)) {
242 rectangle_alpha(x
, y
, surface
->w
, surface
->h
, 0, 0, 0,
243 255*((1./ANIMATION_FADE_PART
)*(p
-(1-ANIMATION_FADE_PART
))));
247 if (part
->effects
& ANIMATION_ZOOM_2X
) {
248 SDL_FreeSurface(surface
);
252 void animation_part_free(AnimationPart
* part
)
254 /* free surface if necessary */
255 if (part
->free_surface
) {
256 SDL_FreeSurface(part
->surface
);
263 Animation
* create_intro()
265 Animation
* intro
= animation_new();
267 /* Just some weird demo of how the animations work */
268 animation_append(intro
, animation_part_new_text(100, 4000, ANIMATION_FADE_IN
| ANIMATION_FADE_OUT
, 0, 0, 0, GRAVITY_CENTER_SCREEN
, FONT_MEDIUM
, "thpinfo.com presents", 255, 255, 255));
269 animation_append(intro
, animation_part_new_from_surface(4000, 8000, ANIMATION_FADE_IN
| ANIMATION_FADE_OUT
| ANIMATION_ZOOM_2X
, 0, 0, 0, GRAVITY_CENTER_SCREEN
, get_surface(GR_TENNIXLOGO
), 0, 0, 1));
274 Animation
* create_credits()
277 Animation
* credits
= animation_new();
278 while (credits_text
[pos
] != NULL
) {
279 animation_append(credits
,
280 animation_part_new_text(100+pos
*CREDITS_OFFSET
,
281 100+pos
*CREDITS_OFFSET
+ CREDITS_DURATION
,
282 ANIMATION_FADE_IN
| ANIMATION_FADE_OUT
| ANIMATION_FROM_BOTTOM
,