• Main Page
  • Classes
  • Files
  • File List
  • File Members

code/include/Player.h

Go to the documentation of this file.
00001 /*
00002  * TetriCycle
00003  * Copyright (C) 2009, 2010 Cale Scholl
00004  *
00005  * This file is part of TetriCycle.
00006  *
00007  * TetriCycle is free software: you can redistribute it and/or modify
00008  * it under the terms of the GNU Lesser General Public License as published
00009  * by the Free Software Foundation, either version 3 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * TetriCycle is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with TetriCycle.  If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00021 /** @file Player.h
00022  * @brief Defines the Player class.
00023  * @author Cale Scholl / calvinss4
00024  */
00025 
00026 #pragma once
00027 #ifndef __PLAYER_H__
00028 #define __PLAYER_H__
00029 
00030 #include <cstring> // for memset
00031 
00032 #include "TetrisPiece.h"
00033 #include "PowerupUtils.h"
00034 #include "Color.h"
00035 #include "Powerup.h"
00036 #include "Profile.h"
00037 #include "defines.h"
00038 #include "defines_Player.h"
00039 
00040 extern ColorGradient g_cubeGradients[COLOR_ID_MAX];
00041 
00042 enum
00043 {
00044   ROTATE_NORMAL,
00045   ROTATE_REVERSE,
00046   ROTATE_PIECE,
00047   ROTATE_SIZE
00048 };
00049 
00050 enum
00051 {
00052   GUIDE_OFF,
00053   GUIDE_SHADOW,
00054   GUIDE_LINE,
00055   GUIDE_SIZE
00056 };
00057 
00058 /// This class represents a player.
00059 class Player
00060 {
00061   /// Player data used when a powerup is in effect.
00062   /** If the data is non-zero then it overrides the normal data. */
00063   struct PlayerPowerupData
00064   {
00065     PlayerPowerupData() : playfieldScale(0),
00066                           isBigHand(false),
00067                           isReverse(false),
00068                           mirrorCtr(0) { }
00069 
00070     float playfieldScale;
00071     bool isBigHand;
00072     bool isReverse;
00073     u8 mirrorCtr;
00074   };
00075 
00076   /// Player data that needs to be reset every game should go here.
00077   struct PlayerGameData
00078   {
00079     PlayerGameData() : grabbedPowerup(NULL),
00080                        score(0),
00081                        lines(0),
00082                        pieces(-1),
00083                        frame(0),
00084                        level(0),
00085                        speed(START_SPEED),
00086                        cycleIdx(0),
00087                        leftRightCtr(0),
00088                        downCtr(0),
00089                        isDead(false),
00090                        isGrabHeld(false),
00091                        isLeftRightHeld(false),
00092                        isDownHeld(false)
00093     {
00094       memset(powerupQueue, 0, sizeof(powerupQueue));
00095       memset(powerupEffects, 0, sizeof(powerupEffects));
00096     }
00097 
00098     TetrisPieceBlock playfield[MAX_PLAYFIELD_WIDTH][MAX_PLAYFIELD_HEIGHT];
00099     Powerup *powerupQueue[MAX_ACQUIRED_POWERUPS]; ///< powerups gained by this player
00100     Powerup *powerupEffects[MAX_POWERUP_EFFECTS]; ///< powerups used on this player
00101     PlayerPowerupData powerupData;
00102     Powerup *grabbedPowerup;
00103     u16 score;
00104     u16 lines;
00105     u16 pieces;
00106     u8 frame;
00107     u8 level;
00108     u8 speed;
00109     u8 cycleIdx;
00110     u8 leftRightCtr;
00111     u8 downCtr;
00112     bool isDead;
00113     bool isGrabHeld;
00114     bool isLeftRightHeld;
00115     bool isDownHeld;
00116   };
00117   
00118 public:
00119   Player() : powerups(g_totalPowerups),
00120              cubeAngle(DEFAULT_CUBE_ANGLE), 
00121              playfieldDX(DEFAULT_PLAYFIELD_DX),
00122              playfieldDY(DEFAULT_PLAYFIELD_DY),
00123              powerupsSize(g_totalPowerups),
00124              playfieldWidth(DEFAULT_PLAYFIELD_WIDTH), 
00125              playfieldHeight(DEFAULT_PLAYFIELD_HEIGHT), 
00126              playfieldScale(DEFAULT_PLAYFIELD_SCALE),
00127              rotation(ROTATE_NORMAL),
00128              guide(GUIDE_SHADOW),
00129              isShakeEnabled(false),
00130              isPreviewEnabled(true), 
00131              isHandicapEnabled(false)
00132   {
00133     for (int i = 0; i < g_totalPowerups; ++i)
00134       powerups[i] = (PowerupId)i;
00135   }
00136 
00137   PlayerGameData gameData;    ///< the player game data
00138   Profile profile;            ///< the player profile
00139   vector<PowerupId> powerups; ///< powerups that are enabled for this player
00140   TetrisPiece currPiece;      ///< the currently falling tetris piece
00141   TetrisPiece nextPiece;      ///< the next tetris piece
00142   float cubeAngle;
00143   s16 playfieldDX;
00144   s16 playfieldDY;
00145   u8 powerupsSize; ///< the actual size of the powerups array
00146   u8 playfieldWidth;
00147   u8 playfieldHeight;
00148   u8 playfieldScale;
00149   u8 id;
00150   u8 rotation;
00151   u8 guide;
00152   bool isShakeEnabled;
00153   bool isPreviewEnabled;
00154   bool isHandicapEnabled;
00155 
00156   /// Rotate the TetriCycle base to the right.
00157   void IncrementCycle() 
00158   { 
00159     gameData.cycleIdx = ++gameData.cycleIdx % playfieldWidth;
00160   }
00161 
00162   /// Rotate the TetriCycle base to the left.
00163   void DecrementCycle() 
00164   { 
00165     gameData.cycleIdx = (gameData.cycleIdx > 0) ? gameData.cycleIdx - 1 : playfieldWidth - 1;
00166   }
00167 
00168   /// Reset all state associated with this player.
00169   void Reset();
00170 
00171   /// Get an open slot for storing an acquired powerup.
00172   /** @return The index of the first open slot, if one exists; else, -1. */
00173   int GetPowerupQueueSlot()
00174   {
00175     for (int i = 0; i < MAX_ACQUIRED_POWERUPS; ++i)
00176     {
00177       if (!gameData.powerupQueue[i])
00178       {
00179         return i;
00180       }
00181     }
00182 
00183     return -1;
00184   }
00185 
00186   /// Adds the acquired powerup to the powerup queue.
00187   void QueuePowerup(Powerup *powerup, int slot)
00188   {
00189     gameData.powerupQueue[slot] = powerup;
00190   }
00191 
00192   /// Removes an acquired powerup from the powerup queue.
00193   void RemovePowerup(int slot)
00194   {
00195     gameData.powerupQueue[slot] = NULL;
00196   }
00197 
00198   /// Get an open slot for storing a powerup effect.
00199   /** @return The index of the first open slot, if one exists; else, -1. */
00200   int GetEffectQueueSlot()
00201   {
00202     for (int i = 0; i < MAX_POWERUP_EFFECTS; ++i)
00203     {
00204       if (!gameData.powerupEffects[i])
00205       {
00206         return i;
00207       }
00208     }
00209 
00210     return -1;
00211   }
00212 
00213   /// Adds a powerup to the powerup effect queue.
00214   /** @return True if the powerup was successfully used on this player; else, false. */
00215   bool QueueEffect(Powerup *powerup)
00216   {
00217     for (int i = 0; i < MAX_POWERUP_EFFECTS; ++i)
00218     {
00219       if (!gameData.powerupEffects[i])
00220       {
00221         gameData.powerupEffects[i] = powerup;
00222         return true;
00223       }
00224     }
00225 
00226     return false;
00227   }
00228 
00229   /// Queue a powerup effect at the specified slot.
00230   void QueueEffect(Powerup *powerup, int slot)
00231   {
00232     gameData.powerupEffects[slot] = powerup;
00233   }
00234 
00235   /// Removes a powerup from the powerup effect queue.
00236   /** @return True if the powerup was successfully removed; else, false. */
00237   bool RemoveEffect(Powerup *powerup)
00238   {
00239     for (int i = 0; i < MAX_POWERUP_EFFECTS; ++i)
00240     {
00241       if (gameData.powerupEffects[i] == powerup)
00242       {
00243         gameData.powerupEffects[i] = NULL;
00244         return true;
00245       }
00246     }
00247 
00248     return false;
00249   }
00250 
00251   /// Updates the player state.
00252   void Update()
00253   {
00254     Powerup *powerup;
00255     for (int i = 0; i < MAX_POWERUP_EFFECTS; ++i)
00256     {
00257       powerup = gameData.powerupEffects[i];
00258       if (powerup)
00259         powerup->Update();
00260     }
00261   }
00262 
00263   /// Draw the playfield (all the static tetris pieces).
00264   void DrawPlayfield();
00265 
00266   /// Draws a tetris piece.
00267   void DrawPiece(TetrisPiece* cp = NULL, u8 alpha = 255);
00268 
00269   /// Draw where the current piece will end up if dropped.
00270   void DrawPieceShadow();
00271 
00272   /// Draw the next piece.
00273   void DrawNextPiece()
00274   {
00275     if (isPreviewEnabled)
00276       DrawPiece(&nextPiece, 145);
00277   }
00278 
00279   /// Draw the base of the TetriCycle.
00280   void DrawBase();
00281 
00282   /// Rotate the current piece.
00283   void RotateCurrentPiece(int rot)
00284   {
00285     int oldRot = currPiece.GetRotation();
00286     currPiece.SetRotation(rot);
00287 
00288     // If the new rotation can't be placed, revert to the old one.
00289     if (!_CanPlacePiece())
00290       currPiece.SetRotation(oldRot);
00291   }
00292 
00293   /// Move the playfield.
00294   bool MovePlayfield(int type);
00295 
00296   /// Moves the tetris piece in the given direction.
00297   bool MovePiece(int type, TetrisPiece *cp = NULL);
00298 
00299   /// Move the current piece down automatically.
00300   void DoMovement();
00301 
00302   /// Draw each tetris piece block as a cube.
00303   void DrawBlockAsCube(float x, float y, ColorId colorIdx, u8 alpha = 255, GuiImageData *imgData = NULL, bool isGuideDot = false);
00304 
00305 private:
00306   float _GetScale() { return !gameData.powerupData.playfieldScale ? (float)playfieldScale : gameData.powerupData.playfieldScale; } ///< Get the scale factor used for drawing this player's TetriCycle.
00307   void _SetBaseColor(GXColor &c) { g_cubeGradients[COLOR_ID_BASE].SetColor(c); }
00308   void _GetWinner();
00309   void _DisplayWinner(int winner);
00310   void _IncreaseLevelAllBut(int plyrIdx);
00311 
00312   /// Increases the player's level.
00313   /** This increases the speed of the falling piece. */
00314   void _IncreaseLevel()
00315   {
00316     if (gameData.level < MAX_LEVEL)
00317     {
00318       gameData.level++;
00319       gameData.speed = START_SPEED - 3 * gameData.level;
00320     }
00321   }
00322 
00323   /// Assigns the next piece to the current piece.
00324   void _SpawnNextPiece()
00325   {
00326     currPiece.InitPiece(nextPiece.GetPieceId(), playfieldWidth);
00327     currPiece.SetPowerupId(nextPiece.GetPowerupId());
00328 
00329     nextPiece.InitPiece(TetrisPiece::GetNextId(), playfieldWidth);
00330     nextPiece.SetPowerupId(PowerupUtils::GetNextId(*this));
00331   }
00332 
00333   /// Returns true if the piece can be placed on the playfield.
00334   bool _CanPlacePiece(TetrisPiece *cp = NULL);
00335 
00336   /// Removes all the completed lines.
00337   bool _RemoveLines();
00338 
00339   /// Removes the line at the given row.
00340   void _RemoveLine(int line);
00341 };
00342 
00343 #endif // __PLAYER_H__

Generated on Wed Oct 20 2010 17:06:58 for TetriCycle by  doxygen 1.7.1