tournamentstate.cpp

来自「Source code (C++) of the Amoebax game fo」· C++ 代码 · 共 629 行 · 第 1/2 页

CPP
629
字号
//// Cross-platform free Puyo-Puyo clone.// Copyright (C) 2006, 2007 Emma's Software//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.//#if defined (HAVE_CONFIG_H)#include <config.h>#endif // HAVE_CONFIG_H#include <cassert>#include <sstream>#include "AIPlayerFactory.h"#include "CongratulationsState.h"#include "File.h"#include "HumanPlayer.h"#include "System.h"#include "TournamentState.h"#include "TwoComputerPlayersState.h"#include "TwoPlayersState.h"#include "VersusState.h"#if defined (IS_GP2X_HOST) && !defined (__SYMBIAN32__)#include "TwoGP2XPlayersState.h"#endif // IS_GP2X_HOSTusing namespace Amoebax;static const int32_t k_BlinkTime = 400;static const uint8_t k_InvalidCharacterIndex = 255;static const uint8_t k_FaceSize = 128;static const uint8_t k_FacesPerRow = 7;static const uint16_t k_InitialHorizontalPosition = 1280 / 2 - k_FaceSize / 2;static const int32_t k_MatchStartTime = k_BlinkTime * 8;////// \brief Constructor.////// \param players The list of players going to compete in the tournament.///TournamentState::TournamentState (const std::vector<TournamentState::Player> &players):    IState (),    m_CurrentMatch (0),    m_Background (0),    m_BackgroundMusic (0),    m_CurrentMatchBlinkTime (k_BlinkTime),    m_CurrentMatchStartTime (k_MatchStartTime),    m_Faces (0),    m_HorizontalOffset (),    m_Matches (),    m_NumPlayers (players.size ()),    m_ShowCurrentOpponents (true),    m_SoundLose (Sound::fromFile (File::getSoundFilePath ("youlose.wav"))),    m_SoundWin (Sound::fromFile (File::getSoundFilePath ("youwin.wav"))),    m_VerticalPosition (){    loadGraphicResources ();    createMatchTree (players);}////// \brief Destructor.///TournamentState::~TournamentState (void){    deleteMatch (m_Matches.children.first);    deleteMatch (m_Matches.children.second);}voidTournamentState::activate (void){    if ( Music::isPaused () )    {        Music::resume ();    }    else if ( !Music::isPlaying () )    {        if ( 0 == m_BackgroundMusic.get () )        {            m_BackgroundMusic.reset (Music::fromFile                    (File::getMusicFilePath ("menu.ogg")));        }        m_BackgroundMusic->play ();    }}////// \brief Creates the tree of matches.////// Based on the number of players, this function creates a tree/// of matches and initializes it.  It also initializes the vertical/// positions and horizontal offsets of each level of the tree.////// \param players The vector of players that will play at the tournament.///voidTournamentState::createMatchTree (const std::vector<Player> &players){    assert ( (2 == players.size () || 4 == players.size ()) &&             "Currently only tournaments of 2 or 4 players are supported." );    // This is a sentinel player used to represent unused entries.    Player sentinelPlayer;    sentinelPlayer.characterIndex = k_InvalidCharacterIndex;    // The first "match" is the winner.    m_Matches.parent = 0;    m_Matches.opponents.first = sentinelPlayer;    m_Matches.opponents.second = sentinelPlayer;    m_Matches.children.second = 0;    Match *semifinal = new Match;    semifinal->parent = &m_Matches;    if ( 2 == players.size () )    {        m_HorizontalOffset.push_back (0);        m_HorizontalOffset.push_back (192);        m_VerticalPosition.push_back (288);        m_VerticalPosition.push_back (544);        semifinal->opponents.first = players[0];        semifinal->opponents.first.score = 0;        semifinal->opponents.second = players[1];        semifinal->opponents.second.score = 0;        semifinal->children.first = 0;        semifinal->children.second = 0;        m_Matches.children.first = semifinal;        m_CurrentMatch = semifinal;    }    else    {        m_HorizontalOffset.push_back (0);        m_HorizontalOffset.push_back (321);        m_HorizontalOffset.push_back (192);        m_VerticalPosition.push_back (160);        m_VerticalPosition.push_back (416);        m_VerticalPosition.push_back (672);        semifinal->opponents.first = sentinelPlayer;        semifinal->opponents.second = sentinelPlayer;        m_Matches.children.first = semifinal;        Match *leftMatch = new Match;        leftMatch->children.first = 0;        leftMatch->children.second = 0;        leftMatch->parent = semifinal;        leftMatch->opponents.first = players[0];        leftMatch->opponents.first.score = 0;        leftMatch->opponents.second = players[1];        leftMatch->opponents.second.score = 0;        Match *rightMatch = new Match;        rightMatch->children.first = 0;        rightMatch->children.second = 0;        rightMatch->parent = semifinal;        rightMatch->opponents.first = players[2];        rightMatch->opponents.first.score = 0;        rightMatch->opponents.second = players[3];        rightMatch->opponents.second.score = 0;        semifinal->children.first = leftMatch;        semifinal->children.second = rightMatch;        m_CurrentMatch = leftMatch;    }}////// \brief Recursively deletes a match and all its children.////// \param match The match to delete, and all its children.///voidTournamentState::deleteMatch (Match *match){    if ( 0 != match )    {        deleteMatch (match->children.first);        deleteMatch (match->children.second);        delete match;    }}voidTournamentState::endOfMatch (IPlayer::PlayerSide winner,                             uint32_t leftPlayerScore,                             uint32_t rightPlayerScore){    // Check if both players are computers, to play the correct sound later.    bool bothComputer = getCurrentMatch ()->opponents.first.isComputerPlayer &&                        getCurrentMatch ()->opponents.second.isComputerPlayer;    // Accumulate the scores.    getCurrentMatch ()->opponents.first.score += leftPlayerScore;    getCurrentMatch ()->opponents.second.score += rightPlayerScore;    Player winnerPlayer;    if ( IPlayer::LeftSide == winner )    {        winnerPlayer = getCurrentMatch ()->opponents.first;        getCurrentMatch ()->opponents.first.characterIndex =            k_InvalidCharacterIndex;    }    else    {        winnerPlayer = getCurrentMatch ()->opponents.second;        getCurrentMatch ()->opponents.second.characterIndex =            k_InvalidCharacterIndex;    }    if ( getCurrentMatch()->parent == &m_Matches )    {        setCurrentMatch (&m_Matches);        m_Matches.opponents.first = winnerPlayer;    }    else if ( getCurrentMatch () ==              getCurrentMatch ()->parent->children.first )    {        getCurrentMatch ()->parent->opponents.first = winnerPlayer;        if ( 0 != getCurrentMatch ()->parent->children.second )        {            setCurrentMatch (getCurrentMatch ()->parent->children.second);        }        else        {            setCurrentMatch (getCurrentMatch ()->parent);        }    }    else    {        getCurrentMatch ()->parent->opponents.second = winnerPlayer;        setCurrentMatch (getCurrentMatch ()->parent);    }    // Play the "winner" sound effect if the winner is human, otherwise    // play the "lose" sound effect.    if ( winnerPlayer.isComputerPlayer )    {        if ( bothComputer )        {            m_SoundWin->play ();        }        else        {            m_SoundLose->play ();        }    }    else    {        m_SoundWin->play ();    }}////// \brief Gets the best two players states based on the characters.////// \param leftCharacter The information about the left player's character./// \param rightCharacter The information about the right player's character./// \return The best two players state based on \p leftCharacter and///         \p rightCharacter fully initialized and ready to be set as///         active.///IState *TournamentState::getBestTwoPlayersState (const Player &leftCharacter,                                         const Player &rightCharacter){    IState *twoPlayersState = 0;    if ( leftCharacter.isComputerPlayer && rightCharacter.isComputerPlayer )    {        twoPlayersState =            new TwoComputerPlayersState (leftCharacter.computerPlayerLevel,                                         rightCharacter.computerPlayerLevel,                                         this);    }#if defined (IS_GP2X_HOST)&& !defined (__SYMBIAN32__)    else if ( !leftCharacter.isComputerPlayer &&              !rightCharacter.isComputerPlayer )    {        twoPlayersState =            new TwoGP2XPlayersState (                    AIPlayerFactory::getRandomBackgroundFileName (),                    leftCharacter.score, rightCharacter.score, this);    }#endif // IS_GP2X_HOST    else    {        IPlayer *leftPlayer = getMatchPlayer (leftCharacter, IPlayer::LeftSide);        IPlayer *rightPlayer = getMatchPlayer (rightCharacter, IPlayer::RightSide);        twoPlayersState =            new TwoPlayersState (leftPlayer, rightPlayer,                                 AIPlayerFactory::getRandomBackgroundFileName (),                                 leftCharacter.score, rightCharacter.score,                                 this);    }    return twoPlayersState;}////// \brief Gets the current match.////// \return The pointer to the current match.///

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?