Initial porting to the new component API.
[tagua/yd.git] / src / hlvariant / animator.h
blobb2a62b2b42b045fd4bb5019e3a703241af73fec0
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 <core/namedsprite.h>
15 #include "animation.h"
16 #include "variantdata.h"
17 #include "common.h"
19 class NamedSprite;
20 class Point;
21 class AnimationFactory;
23 namespace HLVariant {
25 /**
26 * A generic animator.
27 * Can be used as a base class for other specialized animators.
29 template <typename _Variant>
30 class BaseAnimator {
31 public:
32 typedef _Variant Variant;
33 protected:
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;
38 API m_cinterface;
39 public:
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> {
52 public:
53 typedef _Variant Variant;
54 private:
55 typedef BaseAnimator<Variant> Base;
56 protected:
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);
65 public:
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);
74 // IMPLEMENTATION
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++) {
83 Point p(i, 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)),
90 Animate::Instant);
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)),
102 Animate::Instant);
107 return res;
110 template <typename Variant>
111 AnimationGroupPtr BaseAnimator<Variant>::forward(const GameState& final, const Move&) {
112 return warp(final);
116 template <typename Variant>
117 AnimationGroupPtr BaseAnimator<Variant>::back(const GameState& final, const Move&) {
118 return warp(final);
121 template <typename Variant>
122 AnimationGroupPtr SimpleAnimator<Variant>::warp(const GameState& final) {
123 AnimationFactory res(m_cinterface->inner());
125 res.setGroup(Base::warp(final));
127 return res;
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;
133 int mtype = 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);
147 if (piece)
148 res.addPreAnimation(*movement(piece, move.from(), move.to()));
149 else
150 ERROR("Bug!!!");
152 if (captured)
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));
164 else
165 ERROR("Bug!!!");
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));
185 return res;
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));
200 if (!piece) {
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);
215 piece = 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));
240 return res;
246 #endif // HLVARIANT__ANIMATOR_H