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

code/source/tcyc_input.cpp

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 tcyc_input.cpp
00022  * @author Cale Scholl / calvinss4
00023  */
00024 
00025 #include "tcyc_input.h"
00026 
00027 #include "main.h"          // for TCYC_GetTargetPlayer, TCYC_GetTargetPowerupSlot
00028 #include "tcyc_menu.h"     // for TCYC_MenuPause
00029 #include "Player.h"        // for Player
00030 #include "Options.h"       // for Options
00031 #include "libwiigui/gui.h" // for GuiTrigger
00032 #include "PowerupUtils.h"  // for PowerupUtils
00033 
00034 extern Player *g_players;       ///< the player instances
00035 extern int g_tcycMenu;          ///< the current menu state
00036 extern Options *g_options;      ///< the global options
00037 extern GuiTrigger userInput[4]; ///< user input
00038 extern bool g_isClassicMode;    ///< classic mode
00039 
00040 // helper routines
00041 static void _HandlePowerups(int plyrIdx);
00042 static void _HandleLeftRight(int plyrIdx, bool isEditMode = false);
00043 static void _HandleDown(int plyrIdx);
00044 
00045 void TCYC_ProcessInput()
00046 {
00047   // Allow any player to pause the game.
00048   if (PausePressedAnyPlayer())
00049   {
00050     TCYC_MenuPause("Pause");
00051     if (g_tcycMenu != TCYC_MENU_NONE)
00052       return;
00053 
00054     // This is necessary so that powerups don't expire as soon as we unpause 
00055     // the game.
00056     PowerupUtils::ResetPowerupStartTimes();
00057   }
00058 
00059   for (int i = 0; i < g_options->players; ++i)
00060   {
00061     Player &player = g_players[i];
00062     TetrisPiece &piece = player.currPiece;
00063 
00064     if (player.gameData.isDead)
00065       continue;
00066 
00067     // POWERUPS:
00068     _HandlePowerups(i);
00069 
00070     // ROTATE PIECE:
00071     int rot = piece.GetRotation();
00072 
00073     if (ROTATE_PRESSED(i))
00074     {
00075       ++rot;
00076       if (rot > 3)
00077         rot = 0;
00078       player.RotateCurrentPiece(rot);
00079     }
00080     else if (ROTATE2_PRESSED(i))
00081     {
00082       --rot;
00083       if (rot < 0)
00084         rot = 3;
00085       player.RotateCurrentPiece(rot);
00086     }
00087 
00088     // LEFT, RIGHT:
00089     _HandleLeftRight(i);
00090 
00091     // DOWN:
00092     _HandleDown(i);
00093 
00094     // DROP:
00095     bool isAccelPressed = ACCEL_Z_PRESSED(i) && piece.IsAccelEnabled();
00096 
00097     if (DROP_PRESSED(i) || (player.isShakeEnabled && isAccelPressed))
00098     {
00099       while (player.MovePiece(DOWN));
00100       player.DoMovement();
00101     }
00102   }
00103 }
00104 
00105 void TCYC_ProcessEditModeInput()
00106 {
00107   for (int i = 0; i < g_options->players; ++i)
00108   {
00109     _HandleLeftRight(i, true);
00110   }
00111 }
00112 
00113 bool PausePressedAnyPlayer()
00114 {
00115   for (int i = 0; i < g_options->players; ++i)
00116   {
00117     if (PAUSE_PRESSED(i))
00118       return true;
00119   }
00120 
00121   return false;
00122 }
00123 
00124 void _HandlePowerups(int plyrIdx)
00125 {
00126   Player &player = g_players[plyrIdx];
00127 
00128   // Get the target powerup slot.
00129   int targetSlot = -1;
00130   if (userInput[plyrIdx].wpad->ir.valid)
00131   {
00132     targetSlot = TCYC_GetTargetPowerupSlot(plyrIdx, 
00133                                            userInput[plyrIdx].wpad->ir.x, 
00134                                            userInput[plyrIdx].wpad->ir.y);
00135   }
00136 
00137   if (GRAB_HELD(plyrIdx))
00138   {
00139     if (!player.gameData.isGrabHeld)
00140     {
00141       player.gameData.isGrabHeld = true;
00142       if (targetSlot >= 0)
00143       {
00144         // The player grabbed a powerup this frame.
00145         player.gameData.grabbedPowerup = player.gameData.powerupQueue[targetSlot];
00146         player.gameData.powerupQueue[targetSlot] = NULL;
00147 
00148         // If we're in this player's powerup zone and grab was pressed this 
00149         // frame, then ignore all other button presses.
00150         WPAD_Data(plyrIdx)->btns_d = 0;
00151       }
00152     }
00153   }
00154   else
00155   {
00156     player.gameData.isGrabHeld = false;
00157     if (player.gameData.grabbedPowerup)
00158     {
00159       // The player dropped a powerup. If we're in this player's powerup 
00160       // zone then try to put the powerup back.
00161       if (targetSlot >= 0)
00162       {
00163         int emptySlot = player.GetPowerupQueueSlot();
00164         if (emptySlot >= 0)
00165         {
00166           player.QueuePowerup(player.gameData.grabbedPowerup, emptySlot);
00167         }
00168         else
00169         {
00170           // play a buzz sound for negative reinforcement
00171           PowerupUtils::GetInvalidTargetSound()->Play();
00172         }
00173       }
00174       // Otherwise try to use the powerup on the target player.
00175       else
00176       {
00177         int targetPlayer = -1;
00178         if (userInput[plyrIdx].wpad->ir.valid)
00179           targetPlayer = TCYC_GetTargetPlayer(userInput[plyrIdx].wpad->ir.x);
00180 
00181         bool success = false;
00182         if (targetPlayer >= 0)
00183         {
00184           // handle the mirror powerup
00185           if (g_players[targetPlayer].gameData.powerupData.mirrorCtr)
00186             targetPlayer = plyrIdx;
00187 
00188           success = player.gameData.grabbedPowerup->Initiate(targetPlayer);
00189         }
00190 
00191         if (!success)
00192         {
00193           // If we couldn't use the powerup then try to put it back.
00194           int emptySlot = player.GetPowerupQueueSlot();
00195           if (emptySlot >= 0)
00196             player.QueuePowerup(player.gameData.grabbedPowerup, emptySlot);
00197 
00198           // play a buzz sound for negative reinforcement
00199           PowerupUtils::GetInvalidTargetSound()->Play();
00200         }
00201       }
00202 
00203       player.gameData.grabbedPowerup = NULL;
00204     }
00205   }
00206 }
00207 
00208 void _HandleLeftRight(int plyrIdx, bool isEditMode)
00209 {
00210   Player &player = g_players[plyrIdx];
00211 
00212   // When the analog stick is held in a given direction, only register a 
00213   // press for that direction every 'leftRightTimeout' frames.
00214   static const int leftRightTimeout = 5;
00215 
00216   bool isLeftPressed  = LEFT_PRESSED(plyrIdx);
00217   bool isRightPressed = RIGHT_PRESSED(plyrIdx);
00218 
00219   if (player.gameData.powerupData.isReverse)
00220     SWAP(isLeftPressed, isRightPressed);
00221 
00222   if (!isLeftPressed && !isRightPressed)
00223   {
00224     player.gameData.isLeftRightHeld = false;
00225     player.gameData.leftRightCtr = 0;
00226   }
00227   else if (!player.gameData.isLeftRightHeld 
00228            || player.gameData.leftRightCtr > leftRightTimeout)
00229   {
00230     player.gameData.isLeftRightHeld = true;
00231 
00232     if (player.gameData.leftRightCtr > leftRightTimeout)
00233       player.gameData.leftRightCtr = 0;
00234 
00235     if (isLeftPressed) 
00236     {
00237       if (!isEditMode)
00238       {
00239         if (player.rotation != ROTATE_PIECE && !g_isClassicMode)
00240         {
00241           if (player.MovePlayfield(LEFT))
00242             player.IncrementCycle();
00243         }
00244         else
00245         {
00246           player.MovePiece(LEFT);
00247         }
00248       }
00249       else
00250       {
00251         player.IncrementCycle();
00252       }
00253     }
00254 
00255     if (isRightPressed)
00256     {
00257       if (!isEditMode)
00258       {
00259         if (player.rotation != ROTATE_PIECE && !g_isClassicMode)
00260         {
00261           if (player.MovePlayfield(RIGHT))
00262             player.DecrementCycle();
00263         }
00264         else
00265         {
00266           player.MovePiece(RIGHT);
00267         }
00268       }
00269       else
00270       {
00271         player.DecrementCycle();
00272       }
00273     }
00274   }
00275   else
00276   {
00277     player.gameData.leftRightCtr++;
00278   }
00279 }
00280 
00281 void _HandleDown(int plyrIdx)
00282 {
00283   Player &player = g_players[plyrIdx];
00284 
00285   // When the analog stick is held in the down direction, only register a 
00286   // press for that direction every 'downTimeout' frames.
00287   static const int downTimeout = 1; // ==> every other frame
00288 
00289   bool isDownPressed = DOWN_PRESSED(plyrIdx);
00290 
00291   if (!isDownPressed)
00292   {
00293     player.gameData.isDownHeld = false;
00294     player.gameData.downCtr = 0;
00295   }
00296   else if (!player.gameData.isDownHeld 
00297            || player.gameData.downCtr > downTimeout)
00298   {
00299     player.gameData.isDownHeld = true;
00300 
00301     if (player.gameData.downCtr > downTimeout)
00302       player.gameData.downCtr = 0;
00303 
00304     player.DoMovement();
00305   }
00306   else
00307   {
00308     player.gameData.downCtr++;
00309   }
00310 
00311   // Move the piece down every 'speed' frames.
00312   if (player.gameData.frame 
00313       && player.gameData.frame % player.gameData.speed == 0)
00314   {
00315     player.DoMovement();
00316   }
00317 }

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