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"
32 Animation
* animation_new()
34 Animation
* animation
= (Animation
*)calloc(1, sizeof(Animation
));
35 assert(animation
!= NULL
);
39 Animation
* animation_append(Animation
* animation
, AnimationPart
* part
)
41 if (part
->end
> animation
->duration
) {
42 animation
->duration
= part
->end
;
45 if (animation
->head
== NULL
) {
46 /* insert into empty list */
49 animation
->head
= part
;
50 animation
->tail
= part
;
52 /* insert into non-empty list */
53 part
->prev
= animation
->tail
;
55 animation
->tail
->next
= part
;
56 animation
->tail
= part
;
62 void animation_free(Animation
* animation
)
67 part
= animation
->head
;
68 while (part
!= NULL
) {
70 animation_part_free(part
);
77 AnimationState
* animation_state_new(Animation
* animation
)
79 AnimationState
* state
= (AnimationState
*)calloc(1, sizeof(AnimationState
));
80 assert(state
!= NULL
);
82 state
->animation
= animation
;
83 state
->started
= SDL_GetTicks();
84 state
->ending
= state
->started
+ animation
->duration
;
89 void animation_state_run(AnimationState
* state
, int interruptible
)
96 while (animation_state_update(state
)) {
98 while (SDL_PollEvent(&e
)) {
99 if (e
.type
== SDL_KEYDOWN
|| e
.type
== SDL_MOUSEBUTTONDOWN
|| e
.type
== SDL_QUIT
) {
104 p
= state
->animation
->head
;
106 animation_part_display(p
, state
);
113 int animation_state_update(AnimationState
* state
)
115 assert(state
!= NULL
);
117 state
->current
= SDL_GetTicks();
119 return state
->current
< state
->ending
;
122 void animation_state_free(AnimationState
* state
)
127 AnimationPart
* animation_part_new_from_surface(Uint32 start
, Uint32 end
,
128 unsigned int effects
, int x
, int y
, int zindex
, unsigned int gravity
,
129 SDL_Surface
* surface
, unsigned char free_surface
, int pos
, int count
)
131 AnimationPart
* part
= (AnimationPart
*)calloc(1, sizeof(AnimationPart
));
132 assert(part
!= NULL
);
136 part
->effects
= effects
;
140 part
->zindex
= zindex
;
142 part
->gravity
= gravity
;
144 part
->surface
= surface
;
145 part
->free_surface
= free_surface
;
152 AnimationPart
* animation_part_new_text(Uint32 start
, Uint32 end
,
153 unsigned int effects
, int x
, int y
, int zindex
, unsigned int gravity
,
154 font_id id
, const char* text
, Uint8 r
, Uint8 g
, Uint8 b
)
156 return animation_part_new_from_surface(
164 font_render_surface(id
, text
, r
, g
, b
),
171 void animation_part_display(AnimationPart
* part
, AnimationState
* state
)
173 Uint32 start
= state
->started
+ part
->start
;
174 Uint32 end
= state
->started
+ part
->end
;
177 SDL_Surface
* surface
;
179 if (state
->current
< start
|| state
->current
> end
) {
180 /* this part has had it's time (or is yet to have it ;) */
184 surface
= part
->surface
;
185 p
= (float)(state
->current
- start
)/(float)(end
- start
);
187 if (part
->effects
& ANIMATION_ZOOM_2X
) {
188 surface
= rotozoom_surface(surface
, 0.0, p
+1);
191 switch (part
->gravity
) {
192 case GRAVITY_CENTER_UPPERHALF
:
193 x
= (WIDTH
- surface
->w
)/2 + part
->x
;
194 y
= HEIGHT
/2 - surface
->h
+ part
->y
;
196 case GRAVITY_CENTER_BOTTOMHALF
:
197 x
= (WIDTH
- surface
->w
)/2 + part
->x
;
198 y
= HEIGHT
/2 + part
->y
;
200 case GRAVITY_CENTER_SCREEN
:
201 x
= (WIDTH
- surface
->w
)/2 + part
->x
;
202 y
= (HEIGHT
- surface
->h
)/2 + part
->y
;
204 case GRAVITY_TOPLEFT
:
205 /* fall-through to default */
212 if (part
->effects
& ANIMATION_FROM_BOTTOM
) {
213 y
= y
* p
+ (HEIGHT
-part
->surface
->h
) * (1-p
);
216 if (part
->effects
& ANIMATION_SLIDE_LEFT
) {
220 if (part
->effects
& ANIMATION_SLIDE_RIGHT
) {
221 x
= (WIDTH
-surface
->w
) * (1.-p
) + x
* pe
;
224 blit_surface_simple(surface
, x
, y
);
226 /* FIXME: fade in and out should be handled by blitting w/ alpha value */
227 if (part
->effects
& ANIMATION_FADE_IN
) {
228 if (p
< ANIMATION_FADE_PART
) {
229 rectangle_alpha(x
, y
, surface
->w
, surface
->h
, 0, 0, 0,
230 255*(1-(1./ANIMATION_FADE_PART
)*p
));
234 if (part
->effects
& ANIMATION_FADE_OUT
) {
235 if (p
> (1-ANIMATION_FADE_PART
)) {
236 rectangle_alpha(x
, y
, surface
->w
, surface
->h
, 0, 0, 0,
237 255*((1./ANIMATION_FADE_PART
)*(p
-(1-ANIMATION_FADE_PART
))));
241 if (part
->effects
& ANIMATION_ZOOM_2X
) {
242 SDL_FreeSurface(surface
);
246 void animation_part_free(AnimationPart
* part
)
248 /* free surface if necessary */
249 if (part
->free_surface
) {
250 SDL_FreeSurface(part
->surface
);
257 Animation
* create_intro()
259 Animation
* intro
= animation_new();
261 /* Just some weird demo of how the animations work */
262 animation_append(intro
, animation_part_new_text(100, 4000, ANIMATION_FADE_IN
| ANIMATION_FADE_OUT
| ANIMATION_SLIDE_LEFT
, 0, 0, 0, GRAVITY_CENTER_UPPERHALF
, FONT_MEDIUM
, "Deine Eltern sind", 255, 255, 255));
263 animation_append(intro
, animation_part_new_text(1000, 4500, ANIMATION_FADE_IN
| ANIMATION_FADE_OUT
| ANIMATION_SLIDE_RIGHT
, 0, 0, 0, GRAVITY_CENTER_BOTTOMHALF
, FONT_MEDIUM
, "auf einem Tennixturnier", 255, 255, 255));
264 animation_append(intro
, animation_part_new_from_surface(2000, 5500, ANIMATION_FADE_IN
| ANIMATION_FADE_OUT
| ANIMATION_FROM_BOTTOM
| ANIMATION_ZOOM_2X
, 0, 0, 0, GRAVITY_CENTER_SCREEN
, get_surface(GR_TENNIXLOGO
), 0, 0, 1));