grid.cpp
来自「Source code (C++) of the Amoebax game fo」· C++ 代码 · 共 1,733 行 · 第 1/5 页
CPP
1,733 行
DeleteObject<Amoeba> ()); m_QueuedAmoebas.clear (); std::for_each (m_WaitingGhostAmoebas.begin (), m_WaitingGhostAmoebas.end (), DeleteObject<Amoeba> ()); m_WaitingGhostAmoebas.clear ();}////// \brief Adds a new step chain label.////// An step chain label is the text that appears on the grid/// when a chain is made to let know the user which step the/// chain was made in. The label will move a little to the top/// and then will disappear.////// \param stepChain The step in which the chain was made in. It starts/// from 1, not 0./// \param x The screen X position where the label should appear centered at./// \param y The screen Y position where the label should appear centered at.///voidGrid::addChainLabel (uint8_t stepChain, int16_t x, int16_t y){ m_ChainLabels.push_back (new ChainLabel (stepChain, x, y, y - getAmoebaSize ()));}////// \brief Adds a new amoebas pair.////// \param main The main amoeba of the pair./// \param satellite The satellite amoeba of the pair. This is the one that/// will rotate around \a main.///voidGrid::addNewPair (Amoeba *main, Amoeba *satellite){ // Just add the to the list of waiting amoebas. m_InactiveAmoebas.push_back (main); m_InactiveAmoebas.push_back (satellite); // Set up the initial amoebas. // We need to how 6 amoebas for the set up: The falling pair and // the two waiting pairs. if ( m_WaitingInitialAmoebas && 8 == m_InactiveAmoebas.size () ) { m_WaitingInitialAmoebas = false; getNextPair (); getNextPair (); setupFallingPair (); }}////// \brief Removes all dying amoebas.////// Once all dying amoebas are deleted checks for floating amoebas and if/// no floating amoeba is found then sets up the falling pair.///voidGrid::clearDyingAmoebas (void){ m_DieSound->play (); uint8_t amoebasErased = 0; for (std::vector<FallingAmoeba>::iterator currentAmoeba = m_DyingAmoebas.begin () ; currentAmoeba != m_DyingAmoebas.end () ; ++currentAmoeba ) { if ( Amoeba::ColourGhost != currentAmoeba->amoeba->getColour () ) { ++amoebasErased; } setAmoebaAt (currentAmoeba->x, currentAmoeba->y, 0); m_ActiveAmoebas.remove (currentAmoeba->amoeba); delete currentAmoeba->amoeba; } m_DyingAmoebas.clear (); // Activates all chain label. std::for_each (getChainLabels ().begin (), getChainLabels ().end (), std::mem_fun (&ChainLabel::activate)); // Increment the score based on the number of non-ghost amoebas erased // and the current step chain (starting from 0.) uint16_t score = ((2 * amoebasErased - 4) * 10) << getCurrentStepChain (); incrementScore (score); incrementCurrentStepChain (); // Compute the number of ghost amoebas the score generates, subtracts // the number of waiting amoebas and then set the remaining // ghost amoebas as ghost amoebas for the opponent. uint8_t newGhostAmoebas = static_cast<uint16_t>(std::ceil (score / static_cast<double>(70.0f))); uint8_t remainingGhostAmoebas = removeGhostAmoebas (newGhostAmoebas); setOpponentGhostAmoebas (remainingGhostAmoebas); findFloatingAmoebas (); // If there's no floating amoebas, set up the falling pair. if ( m_FloatingAmoebas.empty () ) { // If the positions above the grid of the 3rd column (from // the right) is occuped by an amoeba, then the grid is // considered filled. If any amobea is sitting over the grid in // any other column, this is not considered filled. if ( 0 != getAmoebaAt (3, k_FirstVisibleHeight - 1) ) { markAsFilled (); } else { scheduleFallingPair (); } }}////// \brief Finds floating amoebas.////// A floating amoeba is an amoeaba that just lost its supporting amoeba/// and hence "is floating" on the air and must start to fall.////// Checks each and every amoeba, except for those in the last line, to/// see if it's a floating amoeba and adds it to the m_FloatingAmoeba/// list if so.///voidGrid::findFloatingAmoebas (void){ // Now check which amoebas are "floating" and make them fall. m_FloatingAmoebasVerticalOffset = 0; for ( int16_t row = k_GridHeight - 2 ; row >= 0 ; --row ) { for ( int16_t column = 0 ; column < k_GridWidth ; ++column ) { Amoeba *amoeba = getAmoebaAt (column, row); if ( 0 != amoeba && 0 == getAmoebaAt (column, row + 1) ) { // This amoeba no longer occupes the current position. setAmoebaAt (column, row, 0); // Now is a falling amoeba. FallingAmoeba floatingAmoeba; floatingAmoeba.amoeba = amoeba; floatingAmoeba.x = column; floatingAmoeba.y = row; m_FloatingAmoebas.push_back (floatingAmoeba); // Set the state of the current and neighbour amoebas. amoeba->setState (Amoeba::StateNone); setAmoebaStateAt (column, row, true); } } }}////// \brief Gets the amoeba at a given grid's position.////// \param x The X position of the grid to get the amoeba from./// \param y The Y position of the grid to get the amoeba from./// \return The amoeba at position \p x and \p y or 0 if there's/// no amoeba at this position or the position is incorrect (i.e.,/// out of grid's limits.)///Amoeba *Grid::getAmoebaAt (int16_t x, int16_t y) const{ if ( 0 <= x && x < k_GridWidth && 0 <= y && y < k_GridHeight ) { return m_Grid[y * k_GridWidth + x]; } return 0;}////// \brief Gets the current satellite rotation degree.////// \return The current satellite rotation degree.///inline int16_tGrid::getCurrentRotationDegree (void) const{ return static_cast<int16_t> (m_CurrentRotationDegrees);}////// \brief Gets the main amoeba of the falling pair.////// \return The main falling amoeba of the falling pair.///Grid::FallingAmoebaGrid::getFallingMainAmoeba (void) const{ return m_FallingPair.main;}////// \brief Gets the satellite amoeba of the falling pair.////// \return The satellite falling amoeba of the falling pair.///Grid::FallingAmoebaGrid::getFallingSatelliteAmoeba (void) const{ return m_FallingPair.satellite;}////// \brief Gets the main amoeba that is going to fall after the next pair.////// Since this amoeba doesn't have a position, yet, we set it to/// bet at the center of the grid at the top position.////// \return The main amoeba that is going to fall after the next pair.///Grid::FallingAmoebaGrid::getFollowingFallingMainAmoeba (void) const{ FallingAmoeba followingMain; followingMain.x = k_GridWidth / 2; followingMain.y = -1; std::list<FallingPair>::const_iterator pair = m_Queue.begin (); ++pair; assert (m_Queue.end () != pair && "The pairs queue doesn't have two pairs" ); followingMain.amoeba = pair->main.amoeba; return followingMain;}////// \brief Gets the satellite amoeba that is going to fall after the next pair.////// Since this amoeba doesn't have a position, yet, we set it to/// bet at the center of the grid at the top position.////// \return The satellite amoeba that is going to fall after the next pair.///Grid::FallingAmoebaGrid::getFollowingFallingSatelliteAmoeba (void) const{ FallingAmoeba followingSatellite; followingSatellite.x = k_GridWidth / 2; followingSatellite.y = -1; std::list<FallingPair>::const_iterator pair = m_Queue.begin (); ++pair; assert (m_Queue.end () != pair && "The pairs queue doesn't have two pairs" ); followingSatellite.amoeba = pair->satellite.amoeba; return followingSatellite;}////// \brief Gets the main amoeba that is going to fall next.////// Since this amoeba doesn't have a position, yet, we set it to/// be at the center of the grid at the top position.////// \return The main amoeba that is going to fall next.///Grid::FallingAmoebaGrid::getNextFallingMainAmoeba (void) const{ FallingAmoeba nextMain; nextMain.x = k_GridWidth / 2; nextMain.y = -1; std::list<FallingPair>::const_iterator pair = m_Queue.begin (); assert (m_Queue.end () != pair && "The pairs queue is empty" ); nextMain.amoeba = pair->main.amoeba; return nextMain;}////// \brief Gets the main amoeba that is going to fall next.////// Since this amoeba doesn't have a position, yet, we set it to/// be at the center of the grid at the top position.////// \return The main amoeba that is going to fall next.///Grid::FallingAmoebaGrid::getNextFallingSatelliteAmoeba (void) const{ FallingAmoeba nextSatellite; nextSatellite.x = k_GridWidth / 2; nextSatellite.y = -2; std::list<FallingPair>::const_iterator pair = m_Queue.begin (); assert (m_Queue.end () != pair && "The pairs queue is empty" ); nextSatellite.amoeba = pair->satellite.amoeba; return nextSatellite;}////// \brief Gets the next pair from the inactive list and sets it to the queue.////// The next pair will be the last element in the queue, so it should/// be called when the first element of the queue becomes the falling pair.////// If the inactive amoebas list becomes empty, this function request/// to the pair generator a new pair.///voidGrid::getNextPair (void){ assert ( 0 != m_Generator && "Tried to get the next pair without a generator."); assert ( 2 <= m_InactiveAmoebas.size () && "Tried to get the next pair, but the inactive list is empty."); // Gets the next pair from the inactive list. Amoeba *main = m_InactiveAmoebas.front (); m_InactiveAmoebas.pop_front (); Amoeba *satellite = m_InactiveAmoebas.front (); m_InactiveAmoebas.pop_front (); // And set them to queued. m_QueuedAmoebas.push_back (main); m_QueuedAmoebas.push_back (satellite); // Sets they position to be the last pair on the queue. // Take into account the side where the queue is located at // to choose the offset to apply to this pair. uint16_t lastPairOffsetX = getAmoebaSize () / 2; if ( LayoutVertical == getLayout () ) { if ( Grid::QueueSideLeft == getQueueSide () ) { lastPairOffsetX = -lastPairOffsetX; } main->setX (getQueuePositionX () + lastPairOffsetX); main->setY (getQueuePositionY () + getAmoebaSize () * 3); satellite->setX (getQueuePositionX () + lastPairOffsetX); satellite->setY (getQueuePositionY () + getAmoebaSize () * 2); } else { if (Grid::QueueSideLeft == getQueueSide () ) { main->setX (getQueuePositionX () - getAmoebaSize () * 4); main->setY (getQueuePositionY () + lastPairOffsetX); satellite->setX (getQueuePositionX () - getAmoebaSize () * 3); satellite->setY (getQueuePositionY () + lastPairOffsetX); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?