push 3d4e9e0832507dc01d09c79a6b95c4d44c86028c
[tagua/yd.git] / src / hlvariant / animator.h
blob218e0dc605f860a2078418ae9ccd9c31684cc0d6
1 /*
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.
9 */
11 #ifndef HLVARIANT__ANIMATOR_H
12 #define HLVARIANT__ANIMATOR_H
14 #include "animation.h"
15 #include <KDebug>
16 #include "fwd.h"
17 #include "variantdata.h"
18 #include "namedsprite.h"
19 #include "animationfactory.h"
20 #include "common.h"
22 class NamedSprite;
23 class Point;
24 class AnimationFactory;
26 namespace HLVariant {
28 /**
29 * A generic animator.
30 * Can be used as a base class for other specialized animators.
32 template <typename _Variant>
33 class BaseAnimator {
34 public:
35 typedef _Variant Variant;
36 protected:
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;
41 API m_cinterface;
42 public:
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> {
55 public:
56 typedef _Variant Variant;
57 private:
58 typedef BaseAnimator<Variant> Base;
59 protected:
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);
68 public:
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);
77 // IMPLEMENTATION
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++) {
86 Point p(i, 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)),
93 Animate::Instant);
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)),
105 Animate::Instant);
110 return res;
113 template <typename Variant>
114 AnimationGroupPtr BaseAnimator<Variant>::forward(const GameState& final, const Move&) {
115 return warp(final);
119 template <typename Variant>
120 AnimationGroupPtr BaseAnimator<Variant>::back(const GameState& final, const Move&) {
121 return warp(final);
124 template <typename Variant>
125 AnimationGroupPtr SimpleAnimator<Variant>::warp(const GameState& final) {
126 AnimationFactory res(m_cinterface->inner());
128 res.setGroup(Base::warp(final));
130 return res;
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;
136 int mtype = 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);
150 if (piece)
151 res.addPreAnimation(*movement(piece, move.from(), move.to()));
152 else
153 kError() << "Scheduling movement animation for a null piece";
155 if (captured)
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));
168 else
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));
189 return res;
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));
204 if (!piece) {
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);
219 piece = 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));
244 return res;
250 #endif // HLVARIANT__ANIMATOR_H