Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

Controls.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004 Ivo Danihelka (ivo@danihelka.net)
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  */
00009 #include "Controls.h"
00010 
00011 #include "Unit.h"
00012 #include "PhaseLocker.h"
00013 
00014 #include "KeyStroke.h"
00015 #include "MouseStroke.h"
00016 
00017 //-----------------------------------------------------------------
00018 /**
00019  * Create list of drivers.
00020  * @param locker shared locker for anim
00021  */
00022 Controls::Controls(PhaseLocker *locker)
00023     : m_units(), m_moves()
00024 {
00025     m_locker = locker;
00026     m_active = m_units.begin();
00027     m_speedup = 0;
00028     m_switch = true;
00029     m_strokeSymbol = ControlSym::SYM_NONE;
00030 }
00031 //-----------------------------------------------------------------
00032 /**
00033  * Delete drivers.
00034  */
00035 Controls::~Controls()
00036 {
00037     t_units::iterator end = m_units.end();
00038     for (t_units::iterator i = m_units.begin(); i != end; ++i) {
00039         delete (*i);
00040     }
00041 }
00042 //-----------------------------------------------------------------
00043 /**
00044  * Add unit under our control.
00045  * @return model index
00046  */
00047     void
00048 Controls::addUnit(Unit *unit)
00049 {
00050     m_units.push_back(unit);
00051     //NOTE: insertion invalidates m_active
00052     t_units::iterator end = m_units.end();
00053     for (t_units::iterator i = m_units.begin(); i != end; ++i) {
00054         if ((*i)->startActive()) {
00055             setActive(i);
00056             return;
00057         }
00058     }
00059     setActive(m_units.begin());
00060 }
00061 //-----------------------------------------------------------------
00062 /**
00063  * Returns active unit or NULL.
00064  */
00065 const Unit *
00066 Controls::getActive()
00067 {
00068     Unit *result = NULL;
00069     if (m_active != m_units.end()) {
00070         result = *m_active;
00071     }
00072     return result;
00073 }
00074 //-----------------------------------------------------------------
00075 /**
00076  * Let drivers to drive.
00077  * Only one driver can drive at the same time.
00078  * @param input wrapped input
00079  * @return true when a fish has moved (switch does not count)
00080  */
00081     bool
00082 Controls::driving(const InputProvider *input)
00083 {
00084     bool moved = false;
00085     if (!useSwitch()) {
00086         if (!useStroke()) {
00087             moved = driveUnit(input);
00088         }
00089         else {
00090             moved = true;
00091         }
00092     }
00093     return moved;
00094 }
00095 //-----------------------------------------------------------------
00096 /**
00097  * Returns true when a switch was done.
00098  */
00099 bool
00100 Controls::useSwitch()
00101 {
00102     bool result = false;
00103     if (m_active != m_units.end()) {
00104         if (!(*m_active)->willMove()) {
00105             checkActive();
00106         }
00107 
00108         if (m_switch && m_active != m_units.end()) {
00109             m_locker->ensurePhases(3);
00110             (*m_active)->activate();
00111             result = true;
00112         }
00113     }
00114     m_switch = false;
00115     return result;
00116 }
00117 //-----------------------------------------------------------------
00118 /**
00119  * Use gathered stroke.
00120  * NOTE: returns true even for bad move (not used)
00121  * @return true for used stroke
00122  */
00123 bool
00124 Controls::useStroke()
00125 {
00126     bool result = false;
00127     if (m_strokeSymbol != ControlSym::SYM_NONE) {
00128        makeMove(m_strokeSymbol);
00129        m_strokeSymbol = ControlSym::SYM_NONE;
00130        result = true;
00131     }
00132     return result;
00133 }
00134 //-----------------------------------------------------------------
00135     bool
00136 Controls::driveUnit(const InputProvider *input)
00137 {
00138     char moved = ControlSym::SYM_NONE;
00139     if (m_active != m_units.end()) {
00140         moved = (*m_active)->driveBorrowed(input, m_arrows);
00141     }
00142 
00143     if (ControlSym::SYM_NONE == moved) {
00144         t_units::iterator end = m_units.end();
00145         for (t_units::iterator i = m_units.begin(); i != end; ++i) {
00146             moved = (*i)->drive(input);
00147             if (moved != ControlSym::SYM_NONE) {
00148                 setActive(i);
00149                 break;
00150             }
00151         }
00152     }
00153 
00154     if (moved != ControlSym::SYM_NONE) {
00155         m_moves.push_back(moved);
00156     }
00157     return (moved != ControlSym::SYM_NONE);
00158 }
00159 //-----------------------------------------------------------------
00160     void
00161 Controls::lockPhases()
00162 {
00163     if (m_active != m_units.end() && (*m_active)->isMoving()) {
00164         if ((*m_active)->isPushing()) {
00165             m_speedup = 0;
00166         }
00167         else if (!(*m_active)->isTurning()) {
00168             m_speedup++;
00169         }
00170 
00171         m_locker->ensurePhases(getNeededPhases(m_speedup));
00172     }
00173     else {
00174         m_speedup = 0;
00175     }
00176 }
00177 //-----------------------------------------------------------------
00178 int
00179 Controls::getNeededPhases(int speedup) const
00180 {
00181     static const int SPEED_WARP1 = 6;
00182     static const int SPEED_WARP2 = 10;
00183 
00184     int phases = 3;
00185     if (m_active != m_units.end()) {
00186         if ((*m_active)->isTurning()) {
00187             phases = (*m_active)->countAnimPhases("turn");
00188         }
00189         else if (speedup > SPEED_WARP2) {
00190             phases = (*m_active)->countAnimPhases("swam") / 6;
00191         }
00192         else if (speedup > SPEED_WARP1) {
00193             phases = (*m_active)->countAnimPhases("swam") / 3;
00194         }
00195         else {
00196             phases = (*m_active)->countAnimPhases("swam") / 2;
00197         }
00198     }
00199     return phases;
00200 }
00201 //-----------------------------------------------------------------
00202 /**
00203  * Check whether active unit can still drive,
00204  * otherwise make switch.
00205  */
00206 void
00207 Controls::checkActive()
00208 {
00209     if (m_active == m_units.end() || !(*m_active)->canDrive()) {
00210         switchActive();
00211     }
00212 }
00213 //-----------------------------------------------------------------
00214 /**
00215  * Switch active unit.
00216  * Activate next driveable unit.
00217  */
00218 void
00219 Controls::switchActive()
00220 {
00221     if (!m_units.empty()) {
00222         t_units::iterator start = m_active;
00223 
00224         do {
00225             if (m_active == m_units.end() || m_active + 1 == m_units.end()) {
00226                 m_active = m_units.begin();
00227             }
00228             else {
00229                 ++m_active;
00230             }
00231         } while (m_active != start && !(*m_active)->canDrive());
00232 
00233         if (start != m_active) {
00234             m_speedup = 0;
00235             m_switch = true;
00236         }
00237     }
00238 }
00239 //-----------------------------------------------------------------
00240 /**
00241  * Obtain first control symbol from keyboard events.
00242  */
00243 void
00244 Controls::controlEvent(const KeyStroke &stroke)
00245 {
00246     SDLKey key = stroke.getKey();
00247 
00248     if (m_strokeSymbol == ControlSym::SYM_NONE) {
00249         if (m_active != m_units.end()) {
00250             m_strokeSymbol = (*m_active)->mySymbolBorrowed(key, m_arrows);
00251         }
00252 
00253         if (m_strokeSymbol == ControlSym::SYM_NONE) {
00254             t_units::iterator end = m_units.end();
00255             for (t_units::iterator i = m_units.begin(); i != end; ++i) {
00256                 m_strokeSymbol = (*i)->mySymbol(key);
00257                 if (m_strokeSymbol != ControlSym::SYM_NONE) {
00258                     return;
00259                 }
00260             }
00261         }
00262     }
00263 }
00264 //-----------------------------------------------------------------
00265 /**
00266  * Activate fish under cursor.
00267  * @param occupant model to activate
00268  * @return true when fish was selected
00269  */
00270 bool
00271 Controls::activateSelected(const Cube *occupant)
00272 {
00273     t_units::iterator end = m_units.end();
00274     for (t_units::iterator i = m_units.begin(); i != end; ++i) {
00275         if ((*i)->equalsModel(occupant)) {
00276             m_active = i;
00277             m_switch = true;
00278             return true;
00279         }
00280     }
00281     return false;
00282 }
00283 //-----------------------------------------------------------------
00284 /**
00285  * Change active unit.
00286  * NOTE: change is without switch animation
00287  */
00288 void
00289 Controls::setActive(t_units::iterator active)
00290 {
00291     if (m_active != active) {
00292         m_speedup = 0;
00293         m_active = active;
00294     }
00295 }
00296 //-----------------------------------------------------------------
00297 /**
00298  * Make this move.
00299  * @return false for bad move
00300  */
00301 bool
00302 Controls::makeMove(char move)
00303 {
00304     t_units::iterator end = m_units.end();
00305     for (t_units::iterator i = m_units.begin(); i != end; ++i) {
00306         if ((*i)->driveOrder(move) == move) {
00307             setActive(i);
00308             m_moves.push_back(move);
00309             return true;
00310         }
00311     }
00312     return false;
00313 }
00314 //-----------------------------------------------------------------
00315 /**
00316  * Returns true when there is no unit which will be able to move.
00317  */
00318 bool
00319 Controls::cannotMove() const
00320 {
00321     t_units::const_iterator end = m_units.end();
00322     for (t_units::const_iterator i = m_units.begin(); i != end; ++i) {
00323         if ((*i)->willMove()) {
00324             return false;
00325         }
00326     }
00327     return true;
00328 }
00329 //-----------------------------------------------------------------
00330 /**
00331  * Returns true when active fish is powerful.
00332  */
00333 bool
00334 Controls::isPowerful() const
00335 {
00336     bool result = false;
00337     if (m_active != m_units.end()) {
00338         result = (*m_active)->isPowerful();
00339     }
00340     return result;
00341 }
00342 
00343 

Generated on Wed Jun 1 09:54:30 2005 for Fish Fillets - Next Generation by  doxygen 1.4.2