zoukankan      html  css  js  c++  java
  • 使用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

    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试试吧~~~~~

  • 相关阅读:
    服务器状态码
    QuerySet中添加Extra进行SQL查询
    django配置一个网站建设
    MySQL数据库查询中的特殊命令
    125. Valid Palindrome
    121. Best Time to Buy and Sell Stock
    117. Populating Next Right Pointers in Each Node II
    98. Validate Binary Search Tree
    91. Decode Ways
    90. Subsets II
  • 原文地址:https://www.cnblogs.com/tomboy/p/2571014.html
Copyright © 2011-2022 走看看