使用C++与SFML编写一个简单的撞球游戏Part7——弹球的碰撞检测

这一Part,我们会让球动起来!!!在VisibleGameObject.h的public部分
//获取精灵对象的宽
virtual float GetWidth() const;
//获取精灵对象的高
virtual float GetHeight() const;
//获取精灵对象的矩形区域
virtual sf::Rect<float> GetBoundingRect() const;
VisibleGameObject.cpp
float VisibleGameObject::GetHeight() const
{
    return _sprite.getLocalBounds().height;
}

float VisibleGameObject::GetWidth() const
{
    return _sprite.getLocalBounds().width;
}

sf::Rect<float> VisibleGameObject::GetBoundingRect() const
{
    return _sprite.getGlobalBounds();
}

接下来回到Game类补充一个函数,Game.h的public部分

const static GameObjectManager& GetGameObjectManager();

Game.cpp中的实现

const GameObjectManager& Game::GetGameObjectManager()
{
    return Game::_gameObjectManager;
}

最后就是我们的压轴嘉宾——GameBall类,代码有点长,GameBall.h

#pragma once
#include "visiblegameobject.h"

//继承自VisibleGameObject
class GameBall :
    public VisibleGameObject
{
public:
    GameBall();
    virtual ~GameBall();
    void Update(float);  //更新弹球属性状态

private:
    float _velocity;  //速度
    float _angle;  //移动的方向
    float _elapsedTimeSinceStart;  //游戏总时间

    float LinearVelocityX(float angle); //水平线速度
    float LinearVelocityY(float angle);  //垂直线速度

};

GameBall.cpp
使用C++与SFML编写一个简单的撞球游戏Part7——弹球的碰撞检测使用C++与SFML编写一个简单的撞球游戏Part7——弹球的碰撞检测View Code

#include "StdAfx.h"
#include "GameBall.h"
#include "Game.h"

GameBall::GameBall() :
    _velocity(230.0f),
    _elapsedTimeSinceStart(0.0f)
{
    //assert方法作用:括号里面的表达式必须返回true,若返回false则会出现系统错误
    Load("images/ball.png");
    assert(IsLoaded());

    GetSprite().setOrigin(15,15);

    //设置弹球的移动方向为1到360之间的随机值
    _angle = std::rand() % 360 + 1; 
    //_angle = (float)(sf::Randomizer::Random(0,360);
}


GameBall::~GameBall()
{
}


void GameBall::Update(float elapsedTime)
{
    _elapsedTimeSinceStart += elapsedTime;

    // 设置弹球在开始游戏3秒后才开始更新
    if(_elapsedTimeSinceStart < 3.0f)
        return;

    //弹球每帧的移动距离
    float moveAmount = _velocity * elapsedTime;

    //水平位移
    float moveByX = LinearVelocityX(_angle) * moveAmount;
    //垂直位移
    float moveByY = LinearVelocityY(_angle) * moveAmount;


    //当弹球碰撞到屏幕两边时的处理
    if(GetPosition().x + moveByX <= 0 + GetWidth()/2 
        || GetPosition().x + GetHeight()/2 + moveByX >= Game::SCREEN_WIDTH)
    {
        //调整方向以及更改水平位移使其反弹
        _angle = 360.0f - _angle;
        if(_angle > 260.0f && _angle < 280.0f)
            _angle += 20.0f;
        if(_angle > 80.0f && _angle < 100.0f)
            _angle += 20.0f;
        moveByX = -moveByX;
    }


    //获取玩家弹板
    PlayerPaddle* player1 = dynamic_cast<PlayerPaddle*>(Game::GetGameObjectManager().Get("Paddle1"));
    if(player1 != NULL)
    {
        //存储玩家弹板的矩形区域
        sf::Rect<float> p1BB = player1->GetBoundingRect();

        //检测玩家弹板的矩形区域与弹球的矩形区域是否有重叠
        //有则表示发生了碰撞,然后处理相关反弹的细节
        if(p1BB.intersects(GetBoundingRect()))
        { 
            _angle =  360.0f - (_angle - 180.0f);
            if(_angle > 360.0f)
                _angle -= 360.0f;



            moveByY = -moveByY;

            // 确保弹球不会跑到弹板的矩形区域内
            if(GetBoundingRect().width > player1->GetBoundingRect().top)
            {
                SetPosition(GetPosition().x,player1->GetBoundingRect().top - GetWidth()/2 -1 );
            }


            float playerVelocity = player1->GetVelocity();

            //当弹板向左移动时
            if(playerVelocity < 0)
            {
                //使弹球角度减少
                _angle -= 20.0f;
                if(_angle < 0 )
                    _angle = 360.0f - _angle;
            }
            else if(playerVelocity > 0)
            {
                _angle += 20.0f;
                if(_angle > 360.0f)
                    _angle = _angle - 360.0f;
            }
            //每次碰撞弹板都使弹球速度增加
            _velocity += 5.0f;
        }

        //当弹球碰撞到屏幕上方则令其反弹
        if(GetPosition().y - GetHeight()/2 <= 0)
        {
            _angle =  180 - _angle;
            moveByY = -moveByY;
        }


        //当弹球落到比弹板低的地方则重置弹球
        if(GetPosition().y + GetHeight()/2 + moveByY >= Game::SCREEN_HEIGHT)
        {
            GetSprite().setPosition(Game::SCREEN_WIDTH/2, Game::SCREEN_HEIGHT/2);
            _angle = std::rand() % 360 + 1;
            _velocity = 220.0f;
            _elapsedTimeSinceStart = 0.0f;
        }

        //弹球的移动函数
        GetSprite().move(moveByX,moveByY);
    }
}

float GameBall::LinearVelocityX(float angle)
{
    angle -= 90;
    if (angle < 0)
        angle = 360 + angle;
    return (float)std::cos( angle * ( 3.1415926 / 180.0f ));
}

float GameBall::LinearVelocityY(float angle)
{
    angle -= 90;
    if (angle < 0)
        angle = 360 + angle;
    return (float)std::sin( angle * ( 3.1415926 / 180.0f ));
}

至此如无意外你将得到像下图那样游戏,赶快按F5试试吧~~~~~

使用C++与SFML编写一个简单的撞球游戏Part7——弹球的碰撞检测
原文链接: https://www.cnblogs.com/tomboy/archive/2012/06/30/2571014.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/54072

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 上午5:19
下一篇 2023年2月9日 上午5:19

相关推荐