Changed my email in the copyright statements.
[tagua/yd.git] / src / hlvariant / dropanimator.h
blobd8de977aeaf87e8fcb5d0008bc5d7cc2fe6fa580
1 /*
2 Copyright (c) 2007 Paolo Capriotti <p.capriotti@gmail.com>
3 (c) 2007 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 */
12 #ifndef HLVARIANT__DROPANIMATOR_H
13 #define HLVARIANT__DROPANIMATOR_H
15 #include "animationfactory.h"
16 #include "namedsprite.h"
17 #include "common.h"
19 namespace HLVariant {
21 template <typename Base>
22 class DropAnimatorMixin : public Base {
23 typedef typename Base::Variant Variant;
24 using Base::m_cinterface;
25 protected:
26 typedef typename Base::API API;
27 typedef typename Base::GameState GameState;
28 typedef typename Base::Piece Piece;
29 typedef typename Base::Move Move;
31 virtual void updatePool(const GameState& final);
32 public:
33 DropAnimatorMixin(API cinterface);
35 virtual AnimationGroupPtr warp(const GameState& final);
36 virtual AnimationGroupPtr forward(const GameState& final, const Move& move);
37 virtual AnimationGroupPtr back(const GameState& final, const Move& move);
40 // IMPLEMENTATION
42 template <typename Base>
43 DropAnimatorMixin<Base>::DropAnimatorMixin(API cinterface)
44 : Base(cinterface) { }
47 template <typename Base>
48 void DropAnimatorMixin<Base>::updatePool(const GameState& final) {
49 for(int color = 0; color < 2; color++) {
50 typename Piece::Color c = static_cast<typename Piece::Color>(color);
51 const typename GameState::Pool pool = final.pools().pool(c);
52 const int n = pool.size();
54 for (int index = 0; index < n; ) {
55 // precondition: pool and graphical pool match up to index
57 // no more sprites on the graphical pool
58 if (index >= m_cinterface->poolSize(color)) {
59 // add extra sprites
60 for (int i = index; i < n; i++)
61 m_cinterface->insertPoolPiece(color, i, pool.get(i));
63 // done
64 break;
67 NamedSprite sprite = m_cinterface->getPoolSprite(color, index);
68 int i;
70 // find a matching piece on the pool
71 for (i = index; i < n; i++) {
72 if (pool.get(i).name() == sprite.name())
73 break;
76 if (i < n) {
77 // matching piece found on the pool
78 // insert all pieces before this one on the graphical pool
79 for (int j = index; j < i; j++)
80 m_cinterface->insertPoolPiece(color, j, pool.get(j));
81 index = i + 1;
83 else {
84 // no such piece found: remove it from the graphical pool
85 m_cinterface->removePoolSprite(color, index);
89 // remove extra pieces from the graphical pool
90 while (m_cinterface->poolSize(color) > n)
91 m_cinterface->removePoolSprite(color, n);
95 template <typename Base>
96 AnimationGroupPtr DropAnimatorMixin<Base>::warp(const GameState& final) {
97 updatePool(final);
98 return Base::warp(final);
101 template <typename Base>
102 AnimationGroupPtr DropAnimatorMixin<Base>::forward(const GameState& final, const Move& move) {
103 AnimationFactory res(m_cinterface->inner());
105 if (move.drop() != Piece()) {
106 NamedSprite captured = m_cinterface->takeSprite(move.to());
108 std::pair<int, int> dropped = m_cinterface->droppedPoolPiece();
109 if (dropped.first != -1 && dropped.second != -1
110 && m_cinterface->position()->pools().pool(
111 static_cast<typename Piece::Color>(dropped.first)
112 ).get(
113 static_cast<typename Piece::Type>(dropped.second)
114 ) == move.drop()) {
115 NamedSprite drop = m_cinterface->takePoolSprite(dropped.first, dropped.second);
116 m_cinterface->setSprite(move.to(), drop);
117 res.addPreAnimation(Animate::move(drop, move.to()));
119 else {
120 NamedSprite drop = m_cinterface->setPiece(move.to(), move.drop(), false);
121 drop.sprite()->raise();
122 res.addPreAnimation(Animate::appear(drop));
126 if (captured)
127 res.addPostAnimation(Animate::destroy(captured));
128 res.group()->addPostAnimation(warp(final));
130 else {
131 res.setGroup(Base::forward(final, move));
134 return res;
137 template <typename Base>
138 AnimationGroupPtr DropAnimatorMixin<Base>::back(const GameState& final, const Move& move) {
139 AnimationFactory res(m_cinterface->inner());
141 if(move.drop() != Piece()) {
142 NamedSprite drop = m_cinterface->takeSprite(move.to());
143 res.addPostAnimation(Animate::disappear(drop));
145 res.group()->addPostAnimation(warp(final));
147 else {
148 res.setGroup(Base::back(final, move));
151 return res;
156 #endif // HLVARIANT__DROPANIMATOR_H