⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mopoidball.cpp

📁 mopoid game symbian os application development
💻 CPP
字号:
/*
========================================================================
 Name        : MopoidBall.cpp
 Author      : 
 Copyright   :
 Description : Handles the ball of the Mopoid game.
 License     : 

========================================================================
*/
#include "MopoidBall.h"

// --- TBall
// -----------------------------------------------------------------------
TBall::TBall()
:
	iPos(0,0),
	iPosNew(0,0),
	iVx(0.0),
	iVy(0.0),
	iSettings(NULL)
{}


// -----------------------------------------------------------------------
void TBall::SetSettingsPointer(CMopoidSettings* aSettings)
	{
	iSettings = aSettings;
	}

// -----------------------------------------------------------------------
void TBall::ConvertToPos()
{
    iX = iXnew;
    iY = iYnew;
    iPos.SetXY((TInt)iX, (TInt)iY);
}

// -----------------------------------------------------------------------
TBool TBall::Move(TReal aStep)
{
    TBool collision = EFalse;
    iXnew = iX + (iVx * aStep);
    iYnew = iY + (iVy * aStep);

    // Check collision with walls
    if (iXnew + iSettings->iBallSizeHalf.iWidth > iSettings->iGameRect.iBr.iX)
    {
        // Reflect at right wall
        iXnew = iSettings->iGameRect.iBr.iX - iSettings->iBallSizeHalf.iWidth;
        BounceX();
        collision = ETrue;
    }
    else if (iXnew - iSettings->iBallSizeHalf.iWidth < iSettings->iGameRect.iTl.iX)
    {
        // Reflect at left wall
        iXnew = iSettings->iGameRect.iTl.iX + iSettings->iBallSizeHalf.iWidth;
        BounceX();
        collision = ETrue;
    }
    if (iYnew - iSettings->iBallSizeHalf.iHeight < iSettings->iGameRect.iTl.iY)
    {
        // Reflect at top
        iYnew = iSettings->iGameRect.iTl.iY + iSettings->iBallSizeHalf.iHeight;
        BounceY();
        collision = ETrue;
    }

    // Also store the new position in screen coordinates as TInt's, to
    // make calculations faster.
    iPosNew.SetXY((TInt)iXnew, (TInt)iYnew);

    return collision;
}

// -----------------------------------------------------------------------
TBool TBall::CheckPanelCollision(const TPanel& aPanel, TReal aStep)
{
    TBool collision = EFalse;
    if ( ((iYnew + iSettings->iBallSizeHalf.iHeight) >= aPanel.iPos.iY) && 
         ((iYnew - iSettings->iBallSizeHalf.iHeight) < aPanel.iPos.iY + iSettings->iPanelSizeHalf.iHeight) )
    {
        // We are far enough down so that a collision would be possible.
        // Check in more detail...
        // (ball going too far down will be handled elsewhere and has nothing
        // to do with panel collision!)
        if ((iXnew + iSettings->iBallSizeHalf.iWidth > aPanel.iX) &&
            (iXnew - iSettings->iBallSizeHalf.iWidth < aPanel.iX + iSettings->iPanelSize.iWidth))
        {
            // Collision with panel!
            collision = ETrue;
            // Reverse vertical direction
            BounceY();
            // Get absolute speed
            TReal originalSpeed;
            Math::Sqrt(originalSpeed, iVx*iVx + iVy*iVy);
            // Set new horizontal speed
            // - at front to reverse movement: if ball hits right side of panel, move right!
            iVx = -( (TReal)(aPanel.iX + iSettings->iPanelSizeHalf.iWidth) - iX ) / ((TReal)iSettings->iPanelSizeHalf.iWidth * iSettings->iPanelReflection);
            // Normalize new speed to previous speed
            TReal newSpeed;
            Math::Sqrt(newSpeed, iVx*iVx + iVy*iVy);
            TReal scale = originalSpeed / newSpeed;
            iVy *= scale;
            iVx *= scale;
            // Move again so that we're outside of the panel and won't bounce inside of it.
            ConvertToPos();
            Move(aStep);
            // Move ball up enough so that we won't collide again in the next turn
            iYnew = aPanel.iPos.iY - iSettings->iBallSizeHalf.iHeight;
        }
    }
    return collision;
}

// -----------------------------------------------------------------------
TBrick::TBrickType TBall::CheckBrickCollisionL(CMopoidGrid* aGrid, TReal aStep, TCollisionOffset aSide)
{
    TPoint checkPos(iPosNew);
    if (aSide == ELeft)
        checkPos.iX -= iSettings->iBallSizeHalf.iWidth;
    else if (aSide == ERight)
        checkPos.iX += iSettings->iBallSizeHalf.iWidth;

    // Check if the ball is in the area occupied by the grid.
    if (!aGrid->IsXYInGrid(checkPos))
        return TBrick::EBrickInactive;

    TBrick::TBrickType collisionWith = TBrick::EBrickInactive;

    // Get the position in the grid.
    TPoint gridPos = aGrid->ConvertXYToGrid(checkPos);
    TBool brickExists = aGrid->IsBrickAtPos(gridPos);

    if (brickExists)
    {
        // If we're in the field of a brick that exists - send a hit event to it.
        collisionWith = aGrid->GetBrickTypeAtPos(gridPos);
        aGrid->HitBrickAtPosL(gridPos);

        // Determine what side we hit
        // -> Calculate offset from the side of the brick
        TPoint brickUpperLeft = aGrid->ConvertGridToXY(gridPos);
        TInt offsetX = iPosNew.iX - brickUpperLeft.iX;
        TInt offsetY = iPosNew.iY - brickUpperLeft.iY;
        // Only bounce left/right on an open side
        TBool openSide = (iVx < 0) ? !aGrid->IsBrickAtPos(gridPos.iX + 1, gridPos.iY) : !aGrid->IsBrickAtPos(gridPos.iX - 1, gridPos.iY);
        if (openSide && ((offsetX < 3 && iVx > 0) || (offsetX > iSettings->iBrickSize.iWidth - 3 && iVx < 0)))
        {
            // Check top/bottom as well
            openSide = (iVy < 0) ? !aGrid->IsBrickAtPos(gridPos.iX, gridPos.iY + 1) : !aGrid->IsBrickAtPos(gridPos.iX, gridPos.iY - 1);
            if (openSide && ((offsetY < 2 && iVy > 0) || (offsetY > iSettings->iBrickSize.iHeight - 2 && iVy < 0)))
            {
                // Ball hit a corner - reverse its direction
                BounceXY();
            }
            else
            {
                // ball hit left or right side of a panel - bounce only in x-direction
                BounceX();
            }
        }
        else
        {
            // Ball hit top or bottom of a panel - bounce in y-direction
            BounceY();
        }
        // Move again
        ConvertToPos();
        Move(aStep);
    }
    return collisionWith;
}

// -----------------------------------------------------------------------
TBool TBall::CheckDeath(const TPanel& aPanel)
{
    if ((TInt)iYnew > (aPanel.iPos.iY + iSettings->iPanelSize.iHeight))
        // Ball is below the panel
        return ETrue;
    else
        // Ball is above the panel
        return EFalse;
}

// -----------------------------------------------------------------------
void TBall::BounceXY()
{
    BounceX();
    BounceY();
}

// -----------------------------------------------------------------------
void TBall::BounceX()
{
    iVx = -iVx;
    SpeedUpX();
}

// -----------------------------------------------------------------------
void TBall::BounceY()
{
    iVy = -iVy;
    SpeedUpY();
}

// -----------------------------------------------------------------------
void TBall::SpeedUpX()
{
    // Speed up the ball a tiny bit
    if (iVx < iSettings->iBallSpeedMaxX)
        iVx += (iSettings->iBallSpeedAccX * ((iVx > 0.0) ? 1.0 : -1.0) );
}

// -----------------------------------------------------------------------
void TBall::SpeedUpY()
{
    // Speed up the ball a tiny bit
    if (iVy < iSettings->iBallSpeedMaxY)
        iVy += (iSettings->iBallSpeedAccY * ((iVy > 0.0) ? 1.0 : -1.0) );
}

⌨️ 快捷键说明

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