2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@gmail.com>
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.
11 #ifndef HLVARIANT__ANIMATOR_H
12 #define HLVARIANT__ANIMATOR_H
14 #include "animation.h"
17 #include "variantdata.h"
18 #include "namedsprite.h"
19 #include "animationfactory.h"
24 class AnimationFactory
;
30 * Can be used as a base class for other specialized animators.
32 template <typename _Variant
>
35 typedef _Variant Variant
;
37 typedef typename UnwrappedGraphicalAPIPtr
<Variant
>::type API
;
38 typedef typename VariantData
<Variant
>::GameState GameState
;
39 typedef typename VariantData
<Variant
>::Move Move
;
40 typedef typename VariantData
<Variant
>::Piece Piece
;
43 BaseAnimator(API cinterface
)
44 : m_cinterface(cinterface
) { }
45 virtual ~BaseAnimator() { }
47 virtual AnimationGroupPtr
warp(const GameState
& final
);
48 virtual AnimationGroupPtr
forward(const GameState
& final
, const Move
& move
);
49 virtual AnimationGroupPtr
back(const GameState
& final
, const Move
& move
);
53 template <typename _Variant
>
54 class SimpleAnimator
: BaseAnimator
<_Variant
> {
56 typedef _Variant Variant
;
58 typedef BaseAnimator
<Variant
> Base
;
60 typedef typename
Base::API API
;
61 typedef typename
Base::GameState GameState
;
62 typedef typename
Base::Move Move
;
63 typedef typename
Base::Piece Piece
;
65 using Base::m_cinterface
;
67 virtual SchemePtr
movement(const NamedSprite
& sprite
, const Point
& from
, const Point
& to
);
69 SimpleAnimator(API cinterface
)
70 : Base(cinterface
) { }
72 virtual AnimationGroupPtr
warp(const GameState
& final
);
73 virtual AnimationGroupPtr
forward(const GameState
& final
, const Move
& move
);
74 virtual AnimationGroupPtr
back(const GameState
& final
, const Move
& move
);
79 template <typename Variant
>
80 AnimationGroupPtr BaseAnimator
<Variant
>::warp(const GameState
& final
) {
81 const GameState
* current
= m_cinterface
->position();
82 AnimationFactory
res(m_cinterface
->inner());
84 for (int i
= 0; i
< current
->board().size().x
; i
++) {
85 for (int j
= 0; j
< current
->board().size().y
; j
++) {
88 NamedSprite sprite
= m_cinterface
->getSprite(p
);
89 Piece piece
= final
.board().get(p
);
91 if (!sprite
&& piece
!= Piece()) {
92 res
.addPreAnimation(Animate::appear(m_cinterface
->setPiece(p
, piece
, false)),
96 else if (sprite
&& piece
== Piece()) {
97 m_cinterface
->takeSprite(p
);
98 res
.addPreAnimation(Animate::disappear(sprite
), Animate::Instant
);
101 // sprite and piece differ
102 else if (sprite
&& piece
!= Piece() && piece
.name() != sprite
.name()) {
103 m_cinterface
->takeSprite(p
);
104 res
.addPreAnimation(Animate::morph(sprite
, m_cinterface
->setPiece(p
, piece
, false)),
113 template <typename Variant
>
114 AnimationGroupPtr BaseAnimator
<Variant
>::forward(const GameState
& final
, const Move
&) {
119 template <typename Variant
>
120 AnimationGroupPtr BaseAnimator
<Variant
>::back(const GameState
& final
, const Move
&) {
124 template <typename Variant
>
125 AnimationGroupPtr SimpleAnimator
<Variant
>::warp(const GameState
& final
) {
126 AnimationFactory
res(m_cinterface
->inner());
128 res
.setGroup(Base::warp(final
));
133 template <typename Variant
>
134 SchemePtr SimpleAnimator
<Variant
>::movement(const NamedSprite
& sprite
, const Point
& from
, const Point
& to
) {
135 bool knight
= m_cinterface
->position()->board().get(from
).type() == Piece::KNIGHT
;
137 ? Animate::move::LShaped
| Animate::move::Rotating
138 : Animate::move::Straight
;
139 return SchemePtr(new Animate::move(sprite
, to
, mtype
));
142 template <typename Variant
>
143 AnimationGroupPtr SimpleAnimator
<Variant
>::forward(const GameState
& final
, const Move
& move
) {
144 AnimationFactory
res(m_cinterface
->inner());
146 NamedSprite piece
= m_cinterface
->takeSprite(move
.from());
147 NamedSprite captured
= m_cinterface
->takeSprite(move
.captureSquare());
148 m_cinterface
->setSprite(move
.to(), piece
);
151 res
.addPreAnimation(*movement(piece
, move
.from(), move
.to()));
153 kError() << "Scheduling movement animation for a null piece";
156 res
.addPostAnimation(Animate::destroy(captured
));
158 if (move
.promoteTo() != -1) {
159 Piece promoted
= final
.board().get(move
.to());
161 if (promoted
!= Piece()) {
162 QPoint real
= m_cinterface
->converter()->toReal(move
.to());
163 NamedSprite old_sprite
= m_cinterface
->getSprite(move
.to());
164 NamedSprite new_sprite
= m_cinterface
->setPiece(move
.to(), promoted
, /*false,*/ false);
166 res
.addPostAnimation(Animate::morph(old_sprite
, new_sprite
));
169 kError() << "Scheduling morph animation for a null piece";
171 else if (move
.kingSideCastling()) {
172 Point rookSquare
= move
.to() + Point(1,0);
173 Point rookDestination
= move
.from() + Point(1,0);
175 NamedSprite rook
= m_cinterface
->takeSprite(rookSquare
);
176 m_cinterface
->setSprite(rookDestination
, rook
);
177 res
.addPreAnimation(Animate::move(rook
, rookDestination
));
179 else if (move
.queenSideCastling()) {
180 Point rookSquare
= move
.to() + Point(-2,0);
181 Point rookDestination
= move
.from() + Point(-1,0);
183 NamedSprite rook
= m_cinterface
->takeSprite(rookSquare
);
184 m_cinterface
->setSprite(rookDestination
, rook
);
185 res
.addPreAnimation(Animate::move(rook
, rookDestination
));
188 res
.group()->addPostAnimation(warp(final
));
192 template <typename Variant
>
193 AnimationGroupPtr SimpleAnimator
<Variant
>::back(const GameState
& final
, const Move
& move
) {
194 AnimationFactory
res(m_cinterface
->inner());
196 NamedSprite piece
= m_cinterface
->takeSprite(move
.to());
197 NamedSprite captured
;
198 Piece captured_piece
= final
.board().get(move
.captureSquare());
199 if (captured_piece
!= Piece()) {
200 captured
= m_cinterface
->setPiece(move
.captureSquare(), captured_piece
, false);
201 res
.addPreAnimation(Animate::appear(captured
));
205 piece
= m_cinterface
->createPiece(move
.to(), final
.board().get(move
.from()), false);
206 res
.addPreAnimation(Animate::appear(piece
));
209 m_cinterface
->setSprite(move
.from(), piece
);
211 if (move
.promoteTo() != -1) {
212 Piece pawn_piece
= final
.board().get(move
.from());
213 if (pawn_piece
!= Piece()) {
214 NamedSprite pawn
= m_cinterface
->createPiece(move
.to(), pawn_piece
, false);
215 res
.addPreAnimation(Animate::morph(piece
, pawn
));
217 // replace piece with pawn
218 m_cinterface
->setSprite(move
.from(), pawn
);
222 else if (move
.kingSideCastling()) {
223 Point rookSquare
= move
.to() + Point(1,0);
224 Point rookDestination
= move
.from() + Point(1,0);
226 NamedSprite rook
= m_cinterface
->takeSprite(rookDestination
);
227 m_cinterface
->setSprite(rookSquare
, rook
);
229 res
.addPreAnimation(Animate::move(rook
, rookSquare
));
231 else if (move
.queenSideCastling()) {
232 Point rookSquare
= move
.to() + Point(-2,0);
233 Point rookDestination
= move
.from() + Point(-1,0);
235 NamedSprite rook
= m_cinterface
->takeSprite(rookDestination
);
236 m_cinterface
->setSprite(rookSquare
, rook
);
238 res
.addPreAnimation(Animate::move(rook
, rookSquare
));
241 res
.addPreAnimation(*movement(piece
, move
.to(), move
.from()));
242 res
.group()->addPostAnimation(warp(final
));
250 #endif // HLVARIANT__ANIMATOR_H