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 "variants/xchess/animator.h"
16 #include "variants/xchess/move.h"
17 #include "animation.h"
18 #include "graphicalposition.h"
19 #include "piecesprite.h"
21 #include "pointconverter.h"
24 using namespace boost
;
26 template <typename Variant
>
27 SimpleAnimator
<Variant
>::SimpleAnimator(PointConverter
* converter
,
28 const shared_ptr
<GPosition
>& position
)
29 : m_converter(converter
)
30 , m_position(position
) {
31 if(position
->getBoolSetting("animations", true)) {
32 m_anim_movement
= (bool)position
->getBoolSetting("animations.movement", true);
33 m_anim_explode
= (bool)position
->getBoolSetting("animations.explode", true);
34 m_anim_fade
= (bool)position
->getBoolSetting("animations.fading", true);
35 m_anim_rotate
= (bool)position
->getBoolSetting("animations.transform", true);
39 template <typename Variant
>
40 shared_ptr
<AnimationGroup
> SimpleAnimator
<Variant
>::warp(const Position
& final
) {
41 AnimationPtr
res(new AnimationGroup
);
43 for (Point i
= m_position
->first(); i
<= m_position
->last(); i
= m_position
->next(i
)) {
44 QPoint real
= m_converter
->toReal(i
);
46 // retrieve graphical element
47 GElement p
= m_position
->getElement(i
);
50 const Piece
* q
= final
.get(i
);
53 shared_ptr
<Animation
> a
;
55 // if the graphical element is valid
57 // assert that its sprite is valid as well
58 shared_ptr
<PieceSprite
> sprite
= p
.sprite();
61 // if the piece differs
62 if (!p
.piece().equals(q
)) {
63 shared_ptr
<PieceSprite
> sprite
= p
.sprite();
67 a
= shared_ptr
<Animation
>(new PromotionAnimation( sprite
,
68 m_position
->setPiece(i
, *q
, false, false) ));
72 m_position
->removeElement(i
);
73 a
= shared_ptr
<Animation
>(new CaptureAnimation(sprite
));
77 // if there is no graphical element, simply add it
79 a
= shared_ptr
<Animation
>(new DropAnimation( m_position
->setPiece(i
, *q
, false, false) ));
82 // add animation to the group
83 if (a
) res
->addPreAnimation(a
);
89 template <typename Variant
>
90 shared_ptr
<MovementAnimation
> SimpleAnimator
<Variant
>::createMovementAnimation(
91 const GElement
& element
,
92 const QPoint
& destination
) {
93 return shared_ptr
<MovementAnimation
>(new MovementAnimation(element
.sprite(),
98 template <typename Variant
>
99 shared_ptr
<Animation
> SimpleAnimator
<Variant
>::createCapture(const Point
& p
,
100 const GElement
& /*piece*/,
101 const GElement
& captured
,
102 const Position
& /*pos*/) {
104 return shared_ptr
<Animation
>();
105 else if(m_anim_explode
)
106 return shared_ptr
<Animation
>(new ExplodeAnimation(captured
.sprite(), m_random
));
108 return shared_ptr
<Animation
>(new FadeAnimation(captured
.sprite(),
109 m_converter
->toReal(p
), 255, 0));
111 return shared_ptr
<Animation
>(new CaptureAnimation(captured
.sprite()));
114 template <typename Variant
>
115 shared_ptr
<AnimationGroup
> SimpleAnimator
<Variant
>::forward(const Position
& final
,
117 Q_ASSERT(m_position
->consistent());
119 AnimationPtr
res(new AnimationGroup
);
121 GElement piece
= m_position
->getElement(move
.from
);
124 m_position
->removeElement(move
.from
);
125 Q_ASSERT(m_position
->consistent());
127 if (move
.to
.valid()) {
128 GElement captured
= m_position
->getElement(move
.to
);
130 m_position
->setElement(move
.to
, piece
);
131 Q_ASSERT(m_position
->consistent());
133 shared_ptr
<Animation
> mainAnimation
;
134 QPoint hotSpot
= piece
.sprite()->pos();
135 hotSpot
+= QPoint(piece
.sprite()->pixmap().width() / 2, piece
.sprite()->pixmap().height() / 2);
137 // do not animate forward
138 if (!m_anim_movement
) {
139 mainAnimation
= shared_ptr
<InstantAnimation
>(
140 new InstantAnimation(piece
.sprite(), m_converter
->toReal(move
.to
))
143 // the piece is already on the destination square:
144 // do a direct animation
145 else if (m_converter
->toLogical(hotSpot
) == move
.to
) {
146 mainAnimation
= shared_ptr
<MovementAnimation
>(
147 new MovementAnimation(piece
.sprite(), m_converter
->toReal(move
.to
))
151 // do an animation according to preferences
152 mainAnimation
= createMovementAnimation(piece
, m_converter
->toReal(move
.to
));
154 res
->addPreAnimation(mainAnimation
);
155 res
->addPostAnimation(createCapture(move
.to
, piece
, captured
, final
));
158 // if it is a one-click move, do nothing
159 // the warping animation will adjust everything
161 // add main animation
162 // the animation must be direct when the piece is already
163 // near the destination square
165 Q_ASSERT(m_position
->consistent());
167 finalizeForwardAnimation(res
, final
, move
);
169 AnimationPtr
warpingAnimation(new AnimationGroup
);
170 warpingAnimation
->addPreAnimation(res
);
171 warpingAnimation
->addPostAnimation(warp(final
));
173 return warpingAnimation
;
177 template <typename Variant
>
178 shared_ptr
<AnimationGroup
> SimpleAnimator
<Variant
>::back(const Position
& final
,
180 AnimationPtr
res(new AnimationGroup
);
181 const Piece
* captured
= final
.get(move
.to
);
182 GElement piece
= m_position
->getElement(move
.to
);
184 // the piece could have disappeared
187 Q_ASSERT(final
.get(move
.from
));
188 const Piece
* disappeared
= final
.get(move
.from
);
189 shared_ptr
<PieceSprite
> sprite
= m_position
->setPiece(move
.to
, *disappeared
, false, false);
190 res
->addPreAnimation(shared_ptr
<Animation
>(new DropAnimation(sprite
)));
191 piece
= m_position
->getElement(move
.to
);
194 m_position
->setElement(move
.from
, piece
);
197 // recreate captured piece sprite
198 QPoint real
= m_converter
->toReal(move
.to
);
200 res
->addPreAnimation( shared_ptr
<Animation
>(new FadeAnimation(
201 m_position
->setPiece(move
.to
, *captured
, false, false), real
, 0, 255 ) ));
203 res
->addPreAnimation( shared_ptr
<Animation
>(new DropAnimation(
204 m_position
->setPiece(move
.to
, *captured
, false, false) ) ));
207 m_position
->removeElement(move
.to
);
209 res
->addPreAnimation(
211 ? shared_ptr
<Animation
>(createMovementAnimation(piece
, m_converter
->toReal(move
.from
)))
212 : shared_ptr
<Animation
>(new InstantAnimation(piece
.sprite(), m_converter
->toReal(move
.from
)))
215 finalizeBackAnimation(res
, final
, move
);
217 AnimationPtr
warpingAnimation(new AnimationGroup
);
218 warpingAnimation
->addPreAnimation(res
);
219 warpingAnimation
->addPostAnimation(warp(final
));
221 return warpingAnimation
;