2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@sns.it>
3 (c) 2006 Maurizio Monge <maurizio.monge@kdemail.net>
5 This program 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 2 of the License, or
8 (at your option) any later version.
15 #include <boost/scoped_ptr.hpp>
18 #include "animation.h"
24 using namespace boost
;
26 #undef ANIMATION_DEBUG
28 //BEGIN ConcreteAnimation
30 ConcreteAnimation::ConcreteAnimation(const SpritePtr
& piece
)
33 //END ConcreteAnimation
35 //BEGIN MovementAnimation
37 MovementAnimation::MovementAnimation(const SpritePtr
& piece
,
38 const QPoint
& destination
, double speed
)
39 : ConcreteAnimation(piece
)
42 , m_destination(destination
)
45 #ifdef ANIMATION_DEBUG
46 cout
<< "creating animation " << this << " for piece " << piece
.get() << endl
;
50 MovementAnimation::~MovementAnimation() {
51 #ifdef ANIMATION_DEBUG
52 cout
<< "destroying animation " << this << " for piece " << m_piece
.get() << endl
;
53 if (m_piece
->movementAnimation().lock())
54 cout
<< " *********** BUG **************" << endl
;
56 // m_piece->setMovementAnimation(0);
59 void MovementAnimation::setTarget(const SpritePtr
& target
) {
63 void MovementAnimation::setSource(const SpritePtr
& source
) {
67 boost::shared_ptr
<Movement
>
68 MovementAnimation::createMovement(const QPoint
& from
, const QPoint
& to
) const {
69 return boost::shared_ptr
<Movement
>(new SigmoidalMovement
<LinearMovement
>(from
, to
));
72 void MovementAnimation::start() {
73 #ifdef ANIMATION_DEBUG
74 cout
<< "starting movement animation " << this
75 << " on piece " << m_piece
.get() << endl
;
79 if (shared_ptr
<Animation
> animation
= m_source
->movementAnimation().lock()) {
80 #ifdef ANIMATION_DEBUG
81 cout
<< "aborting movement animation " << animation
82 << " on piece " << m_source
.get() << endl
;
88 m_source
->setMovementAnimation(shared_ptr
<Animation
>());
89 m_target
->setMovementAnimation(shared_from_this());
92 m_movement
= createMovement(m_piece
->pos(), m_destination
);
94 // The total time of the animation is proportional to the square root
95 // of the distance and to the inverse of the speed factor.
96 double distance
= Point(m_destination
- m_piece
->pos()).norm();
98 Q_ASSERT(m_speed
> 0.0);
99 m_time
= 35 * sqrt(distance
) / m_speed
;
100 m_state
= m_time
> 0 ? Active
: Inactive
;
103 Animation::State
MovementAnimation::animationAdvance(int msec
) {
108 if (m_state
== Inactive
) abort();
114 // reparameterize the time variable in [0,1]
115 Q_ASSERT(m_time
> 0);
116 double t
= (msec
- m_start
) / m_time
;
119 #ifdef ANIMATION_DEBUG
120 cout
<< "active: t = " << t
<< endl
;
126 QPoint to
= m_movement
->pos(t
);
128 m_piece
->setRotation(m_movement
->rotation(t
));
135 #ifdef ANIMATION_DEBUG
136 cout
<< "advance (" << this << ") state = " << m_state
<< endl
;
141 void MovementAnimation::stop() {
142 #ifdef ANIMATION_DEBUG
143 cout
<< "stopping animation " << this
144 << " on piece " << m_piece
.get() << endl
;
146 m_piece
->moveTo(m_destination
);
147 m_piece
->setRotation(0);
152 void MovementAnimation::abort() {
153 #ifdef ANIMATION_DEBUG
154 cout
<< "aborting animation " << this
155 << " on piece " << m_piece
.get() << endl
;
158 m_target
->setMovementAnimation(shared_ptr
<MovementAnimation
>());
161 //END MovementAnimation
163 //BEGIN KnightMovementAnimation
165 KnightMovementAnimation::KnightMovementAnimation(const SpritePtr
& piece
, const QPoint
& destination
,
166 bool rotate
, double speed
)
167 : MovementAnimation(piece
, destination
, speed
)
171 boost::shared_ptr
<Movement
>
172 KnightMovementAnimation::createMovement(const QPoint
& from
, const QPoint
& to
) const {
173 return boost::shared_ptr
<Movement
>(new SigmoidalMovement
<LMovement
>(from
, to
, m_rotate
));
176 //END KnightMovementAnimation
178 //BEGIN OneShotAnimation
180 OneShotAnimation::OneShotAnimation(const SpritePtr
& piece
)
181 : ConcreteAnimation(piece
) { }
183 Animation::State
OneShotAnimation::animationAdvance(int) {
188 //END OneShotAnimation
190 //BEGIN InstantAnimation
192 InstantAnimation::InstantAnimation(const SpritePtr
& piece
, const QPoint
& destination
)
193 : OneShotAnimation(piece
)
194 , m_destination(destination
) { }
196 void InstantAnimation::shoot() {
197 m_piece
->moveTo(m_destination
);
199 if (shared_ptr
<Animation
> animation
= m_piece
->movementAnimation().lock()) {
201 m_piece
->setMovementAnimation(shared_ptr
<Animation
>());
205 //END InstantAnimation
207 //BEGIN CaptureAnimation
209 CaptureAnimation::CaptureAnimation(const SpritePtr
& piece
)
210 : OneShotAnimation(piece
) { }
212 void CaptureAnimation::shoot() {
215 if (shared_ptr
<Animation
> animation
= m_piece
->movementAnimation().lock()) {
217 m_piece
->setMovementAnimation(shared_ptr
<Animation
>());
222 //END CaptureAnimation
224 //BEGIN DropAnimation
226 DropAnimation::DropAnimation(const SpritePtr
& piece
)
227 : OneShotAnimation(piece
)
228 , m_valid_position(false) { }
230 DropAnimation::DropAnimation(const SpritePtr
& piece
, const QPoint
& pos
)
231 : OneShotAnimation(piece
)
232 , m_valid_position(true)
233 , m_position(pos
) { }
235 void DropAnimation::shoot() {
236 if (m_valid_position
)
237 m_piece
->moveTo(m_position
);
243 //BEGIN PromotionAnimation
245 PromotionAnimation::PromotionAnimation(const SpritePtr
& piece
,
246 const SpritePtr
& promoted
)
247 : OneShotAnimation(piece
)
248 , m_promoted(promoted
) { }
250 void PromotionAnimation::shoot() {
255 //END PromotionAnimation
257 //BEGIN CrossFadingAnimation
259 CrossFadingAnimation::CrossFadingAnimation(const SpritePtr
& piece
,
260 const SpritePtr
& promoted
)
262 addPreAnimation(shared_ptr
<FadeAnimation
>(new FadeAnimation(piece
, 255, 0)));
263 addPreAnimation(shared_ptr
<FadeAnimation
>(new FadeAnimation(promoted
, 0, 255)));
266 void CrossFadingAnimation::start() {
267 AnimationGroup::start();
270 //END CrossFadingAnimation
274 //BEGIN DelayAnimation
276 DelayAnimation::DelayAnimation(int secs
)
281 void DelayAnimation::start() {
285 Animation::State
DelayAnimation::animationAdvance(int msec
) {
294 if(msec
> m_start
+ m_msecs
)
302 void DelayAnimation::stop() {
306 void DelayAnimation::abort() {
314 //BEGIN FadeAnimation
316 FadeAnimation::FadeAnimation(const SpritePtr
& sprite
, const QPoint
& to
,
317 int fadeFrom
, int fadeTo
)
318 : ConcreteAnimation(sprite
)
319 , m_fadeFrom(fadeFrom
)
322 , m_state(Inactive
) { }
324 FadeAnimation::FadeAnimation(const SpritePtr
& sprite
, int fadeFrom
, int fadeTo
)
325 : ConcreteAnimation(sprite
)
326 , m_fadeFrom(fadeFrom
)
328 , m_to(Point::invalid())
329 , m_state(Inactive
) { }
331 void FadeAnimation::start() {
334 if (m_to
!= Point::invalid()) {
335 m_piece
->moveTo(m_to
);
338 m_piece
->setOpacity(m_fadeFrom
);
342 Animation::State
FadeAnimation::animationAdvance(int msec
) {
352 double t
= (msec
- m_start
) / 400.0;
358 int op
= static_cast<int>(m_fadeTo
* t
+ m_fadeFrom
* (1 - t
));
359 m_piece
->setOpacity(op
);
368 void FadeAnimation::stop() {
369 m_piece
->setOpacity(m_fadeTo
);
373 void FadeAnimation::abort() {
382 //BEGIN GrowAnimation
384 GrowAnimation::GrowAnimation(const SpritePtr
& sprite
)
385 : ConcreteAnimation(sprite
)
386 , m_state(Inactive
) { }
388 void GrowAnimation::start() {
392 m_piece
->setScale(0.0);
395 Animation::State
GrowAnimation::animationAdvance(int msec
) {
405 double t
= (msec
- m_start
) / 700.0;
412 m_piece
->setScale(t
);
421 void GrowAnimation::stop() {
422 m_piece
->setScale(1.0);
426 void GrowAnimation::abort() {
434 //BEGIN ExplodeAnimation
436 ExplodeAnimation::ExplodeAnimation(const SpritePtr
& sprite
, Random
& random
)
437 : ConcreteAnimation(sprite
)
439 , m_random(random
) { }
441 void ExplodeAnimation::start() {
445 m_piece
->setupExplosion(m_random
);
448 Animation::State
ExplodeAnimation::animationAdvance(int msec
) {
458 double t
= (msec
- m_start
) / 700.0;
465 m_piece
->setExplosionStep(sin(t
*M_PI
/2)*0.7);
466 //m_piece->setScale(1.0+t*0.2);
467 m_piece
->setOpacity(int(cos(t
*M_PI
/2)*255));
476 void ExplodeAnimation::stop() {
477 m_piece
->setExplosionStep(0.7);
478 //m_piece->setScale(1.2);
482 void ExplodeAnimation::abort() {
487 //END ExplodeAnimation
489 //BEGIN AnimationGroup
491 AnimationGroup::AnimationGroup(bool persistent
)
494 , m_persistent(persistent
)
495 , m_chain_abortions(!persistent
) {
498 void AnimationGroup::start() {
502 Animation::State
AnimationGroup::animationAdvance(int msec
) {
509 // advance pre-animations
510 for (Iterator i
= pre
.begin(); i
!= pre
.end(); ) {
511 State animation_state
= (*i
)->animationAdvance(msec
);
512 switch (animation_state
) {
515 if (m_chain_abortions
) {
516 for (Iterator j
= pre
.begin(); j
!= pre
.end(); ) {
525 // the animation ended or has been aborted,
526 // remove it from the list
530 // handle next animation
536 // if there are still pre-animations, we're done
541 // no pre-animations: handle post animations
542 for (Iterator i
= post
.begin(); i
!= post
.end(); ) {
543 State animation_state
= (*i
)->animationAdvance(msec
);
544 switch (animation_state
) {
547 if (m_chain_abortions
) {
552 // the animation ended or has been aborted,
553 // remove it from the list
557 // handle next animation
564 // go on animating if there are still animations left
565 // or the group is persistent
566 m_active
= m_persistent
|| !post
.empty();
567 return m_active
? Active
: Inactive
;
570 void AnimationGroup::addPreAnimation(AnimationPtr anim
) {
574 // cannot dynamically add pre-animations
575 // adding it as a post-animation, instead
576 addPostAnimation(anim
);
581 void AnimationGroup::addPostAnimation(AnimationPtr anim
) {
583 post
.push_back(anim
);
586 void AnimationGroup::stop() {
587 // stop all animations
588 for (Iterator i
= pre
.begin(); i
!= pre
.end(); ) {
592 for (Iterator i
= post
.begin(); i
!= post
.end(); ) {
603 //BEGIN TeleportAnimation
605 TeleportAnimation::TeleportAnimation(const SpritePtr
& sprite
,
606 const QPoint
& from
, const QPoint
& to
)
607 : AnimationGroup(1.0) {
609 SpritePtr
copy(sprite
->duplicate());
612 addPreAnimation(AnimationPtr(new FadeAnimation(copy
, from
, 255, 0)));
613 addPreAnimation(AnimationPtr(new FadeAnimation(sprite
, to
, 0, 255)));
616 TeleportAnimation::TeleportAnimation(const SpritePtr
& sprite
,
618 : AnimationGroup(1.0) {
620 SpritePtr
copy(sprite
->duplicate());
623 addPreAnimation(AnimationPtr(new FadeAnimation(copy
, copy
->pos(), 255, 0)));
624 addPreAnimation(AnimationPtr(new FadeAnimation(sprite
, to
, 0, 255)));
628 //END TeleportAnimation
630 //BEGIN DelayedAnimationSet
632 DelayedAnimationSet::DelayedAnimationSet(Random
& random
)
634 , m_state(Inactive
) { }
636 void DelayedAnimationSet::addAnimation(const shared_ptr
<Animation
>& animation
) {
637 if (animation
&& m_state
== Inactive
)
638 m_animations
.push_back(animation
);
641 void DelayedAnimationSet::start() {
642 const int n
= m_animations
.size();
647 // animation time is proportional to the
648 // number of animations
651 // one animation starts immediately
652 int immediate
= m_random
.rand(0, n
- 1)();
653 m_events
.push_back(Event(immediate
, m_start
));
655 // generate event times
656 Random::IntegerGenerator event_time
= m_random
.rand(m_start
, m_start
+ m_time
);
657 for (int i
= 0; i
< n
; i
++) {
658 if (i
== immediate
) continue;
659 m_events
.push_back(Event(i
, event_time()));
663 sort(m_events
.begin(), m_events
.end());
666 m_next_event
= m_events
.begin();
672 Animation::State
DelayedAnimationSet::animationAdvance(int msec
) {
677 if (m_state
== Inactive
) abort();
683 // if there are still events left
684 if (m_next_event
!= m_events
.end()) {
686 // if the event period is elapsed
687 if (msec
>= m_start
+ m_time
) {
688 // execute all remaining animations
689 while (m_next_event
!= m_events
.end())
690 execute((m_next_event
++)->index());
694 // if the event time has elapsed
695 while (m_next_event
!= m_events
.end() && msec
>= m_next_event
->time()) {
696 // run the corresponding animation
697 execute((m_next_event
++)->index());
702 // step all active animations
703 // continue animating until m_group is over
704 m_state
= m_group
.animationAdvance(msec
);
713 void DelayedAnimationSet::execute(int index
) {
714 // start animation adding it to m_group
715 m_group
.addPostAnimation(m_animations
[index
]);
717 // remove it from the animation vector
718 m_animations
[index
] = shared_ptr
<Animation
>();
721 void DelayedAnimationSet::stop() {
723 m_animations
.clear();
727 void DelayedAnimationSet::abort() {
729 m_animations
.clear();
732 //END DelayedAnimationSet