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 <core/namedsprite.h>
15 #include "animation.h"
16 #include "variantdata.h"
21 class AnimationFactory
;
27 * Can be used as a base class for other specialized animators.
29 template <typename _Variant
>
32 typedef _Variant Variant
;
34 typedef typename UnwrappedGraphicalAPIPtr
<Variant
>::type API
;
35 typedef typename VariantData
<Variant
>::GameState GameState
;
36 typedef typename VariantData
<Variant
>::Move Move
;
37 typedef typename VariantData
<Variant
>::Piece Piece
;
40 BaseAnimator(API cinterface
)
41 : m_cinterface(cinterface
) { }
42 virtual ~BaseAnimator() { }
44 virtual AnimationGroupPtr
warp(const GameState
& final
);
45 virtual AnimationGroupPtr
forward(const GameState
& final
, const Move
& move
);
46 virtual AnimationGroupPtr
back(const GameState
& final
, const Move
& move
);
50 template <typename _Variant
>
51 class SimpleAnimator
: BaseAnimator
<_Variant
> {
53 typedef _Variant Variant
;
55 typedef BaseAnimator
<Variant
> Base
;
57 typedef typename
Base::API API
;
58 typedef typename
Base::GameState GameState
;
59 typedef typename
Base::Move Move
;
60 typedef typename
Base::Piece Piece
;
62 using Base::m_cinterface
;
64 virtual SchemePtr
movement(const NamedSprite
& sprite
, const Point
& from
, const Point
& to
);
66 SimpleAnimator(API cinterface
)
67 : Base(cinterface
) { }
69 virtual AnimationGroupPtr
warp(const GameState
& final
);
70 virtual AnimationGroupPtr
forward(const GameState
& final
, const Move
& move
);
71 virtual AnimationGroupPtr
back(const GameState
& final
, const Move
& move
);
76 template <typename Variant
>
77 AnimationGroupPtr BaseAnimator
<Variant
>::warp(const GameState
& final
) {
78 const GameState
* current
= m_cinterface
->position();
79 AnimationFactory
res(m_cinterface
->inner());
81 for (int i
= 0; i
< current
->board().size().x
; i
++) {
82 for (int j
= 0; j
< current
->board().size().y
; j
++) {
85 NamedSprite sprite
= m_cinterface
->getSprite(p
);
86 Piece piece
= final
.board().get(p
);
88 if (!sprite
&& piece
!= Piece()) {
89 res
.addPreAnimation(Animate::appear(m_cinterface
->setPiece(p
, piece
, false)),
93 else if (sprite
&& piece
== Piece()) {
94 m_cinterface
->takeSprite(p
);
95 res
.addPreAnimation(Animate::disappear(sprite
), Animate::Instant
);
98 // sprite and piece differ
99 else if (sprite
&& piece
!= Piece() && piece
.name() != sprite
.name()) {
100 m_cinterface
->takeSprite(p
);
101 res
.addPreAnimation(Animate::morph(sprite
, m_cinterface
->setPiece(p
, piece
, false)),
110 template <typename Variant
>
111 AnimationGroupPtr BaseAnimator
<Variant
>::forward(const GameState
& final
, const Move
&) {
116 template <typename Variant
>
117 AnimationGroupPtr BaseAnimator
<Variant
>::back(const GameState
& final
, const Move
&) {
121 template <typename Variant
>
122 AnimationGroupPtr SimpleAnimator
<Variant
>::warp(const GameState
& final
) {
123 AnimationFactory
res(m_cinterface
->inner());
125 res
.setGroup(Base::warp(final
));
130 template <typename Variant
>
131 SchemePtr SimpleAnimator
<Variant
>::movement(const NamedSprite
& sprite
, const Point
& from
, const Point
& to
) {
132 bool knight
= m_cinterface
->position()->board().get(from
).type() == Piece::KNIGHT
;
134 ? Animate::move::LShaped
| Animate::move::Rotating
135 : Animate::move::Straight
;
136 return SchemePtr(new Animate::move(sprite
, to
, mtype
));
139 template <typename Variant
>
140 AnimationGroupPtr SimpleAnimator
<Variant
>::forward(const GameState
& final
, const Move
& move
) {
141 AnimationFactory
res(m_cinterface
->inner());
143 NamedSprite piece
= m_cinterface
->takeSprite(move
.from());
144 NamedSprite captured
= m_cinterface
->takeSprite(move
.captureSquare());
145 m_cinterface
->setSprite(move
.to(), piece
);
148 res
.addPreAnimation(*movement(piece
, move
.from(), move
.to()));
153 res
.addPostAnimation(Animate::destroy(captured
));
155 if (move
.promoteTo() != -1) {
156 Piece promoted
= final
.board().get(move
.to());
158 if (promoted
!= Piece()) {
159 NamedSprite old_sprite
= m_cinterface
->getSprite(move
.to());
160 NamedSprite new_sprite
= m_cinterface
->setPiece(move
.to(), promoted
, /*false,*/ false);
162 res
.addPostAnimation(Animate::morph(old_sprite
, new_sprite
));
167 else if (move
.kingSideCastling()) {
168 Point rookSquare
= move
.to() + Point(1,0);
169 Point rookDestination
= move
.from() + Point(1,0);
171 NamedSprite rook
= m_cinterface
->takeSprite(rookSquare
);
172 m_cinterface
->setSprite(rookDestination
, rook
);
173 res
.addPreAnimation(Animate::move(rook
, rookDestination
));
175 else if (move
.queenSideCastling()) {
176 Point rookSquare
= move
.to() + Point(-2,0);
177 Point rookDestination
= move
.from() + Point(-1,0);
179 NamedSprite rook
= m_cinterface
->takeSprite(rookSquare
);
180 m_cinterface
->setSprite(rookDestination
, rook
);
181 res
.addPreAnimation(Animate::move(rook
, rookDestination
));
184 res
.group()->addPostAnimation(warp(final
));
188 template <typename Variant
>
189 AnimationGroupPtr SimpleAnimator
<Variant
>::back(const GameState
& final
, const Move
& move
) {
190 AnimationFactory
res(m_cinterface
->inner());
192 NamedSprite piece
= m_cinterface
->takeSprite(move
.to());
193 NamedSprite captured
;
194 Piece captured_piece
= final
.board().get(move
.captureSquare());
195 if (captured_piece
!= Piece()) {
196 captured
= m_cinterface
->setPiece(move
.captureSquare(), captured_piece
, false);
197 res
.addPreAnimation(Animate::appear(captured
));
201 piece
= m_cinterface
->createPiece(move
.to(), final
.board().get(move
.from()), false);
202 res
.addPreAnimation(Animate::appear(piece
));
205 m_cinterface
->setSprite(move
.from(), piece
);
207 if (move
.promoteTo() != -1) {
208 Piece pawn_piece
= final
.board().get(move
.from());
209 if (pawn_piece
!= Piece()) {
210 NamedSprite pawn
= m_cinterface
->createPiece(move
.to(), pawn_piece
, false);
211 res
.addPreAnimation(Animate::morph(piece
, pawn
));
213 // replace piece with pawn
214 m_cinterface
->setSprite(move
.from(), pawn
);
218 else if (move
.kingSideCastling()) {
219 Point rookSquare
= move
.to() + Point(1,0);
220 Point rookDestination
= move
.from() + Point(1,0);
222 NamedSprite rook
= m_cinterface
->takeSprite(rookDestination
);
223 m_cinterface
->setSprite(rookSquare
, rook
);
225 res
.addPreAnimation(Animate::move(rook
, rookSquare
));
227 else if (move
.queenSideCastling()) {
228 Point rookSquare
= move
.to() + Point(-2,0);
229 Point rookDestination
= move
.from() + Point(-1,0);
231 NamedSprite rook
= m_cinterface
->takeSprite(rookDestination
);
232 m_cinterface
->setSprite(rookSquare
, rook
);
234 res
.addPreAnimation(Animate::move(rook
, rookSquare
));
237 res
.addPreAnimation(*movement(piece
, move
.to(), move
.from()));
238 res
.group()->addPostAnimation(warp(final
));
246 #endif // HLVARIANT__ANIMATOR_H