(译)LearnOpenGL实际案例Breakout(五):小球

来源:互联网 发布:我只是数据全文下载 编辑:程序博客网 时间:2024/06/06 06:55

英文原文

现在我们有一个砖块的关卡和一个可移动的玩家挡板。和经典Breakout唯一缺失的是小球。目标是让小球碰撞所有的砖块直到每一个可破坏的砖块被破坏,但是这有一个条件是小球不能触碰屏幕的底部边缘。 
撇开一般的游戏组件对象,一个小球有一个半径和一个标识出小球是卡在挡板上还是可以自由移动的额外的bool值。当游戏开始,小球最初被卡在玩家挡板上直到玩家按下任意键开始游戏。 
因为小球是有一些额外特性的游戏基础物体,让场景常见一个BallObject类作为GameObject的子集:

class BallObject : public GameObject{public:    // Ball state       GLfloat   Radius;    GLboolean Stuck;    BallObject();    BallObject(glm::vec2 pos, GLfloat radius, glm::vec2 velocity, Texture2D sprite);    glm::vec2 Move(GLfloat dt, GLuint window_width);    void      Reset(glm::vec2 position, glm::vec2 velocity);};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

BallObject的构造函数初始化它子集的值,也初始化它底层的GameObject。这个BallObject类有一个Move方法来让小球基于它的速度来移动以及检查它是否到达场景的任意一条边以及是否反弹小球的速度:

glm::vec2 BallObject::Move(GLfloat dt, GLuint window_width){    // If not stuck to player board    if (!this->Stuck)    {        // Move the ball        this->Position += this->Velocity * dt;        // Check if outside window bounds; if so, reverse velocity and restore at correct position        if (this->Position.x <= 0.0f)        {            this->Velocity.x = -this->Velocity.x;            this->Position.x = 0.0f;        }        else if (this->Position.x + this->Size.x >= window_width)        {            this->Velocity.x = -this->Velocity.x;            this->Position.x = window_width - this->Size.x;        }        if (this->Position.y <= 0.0f)        {            this->Velocity.y = -this->Velocity.y;            this->Position.y = 0.0f;        }    }    return this->Position;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

除了反弹小球的速度之外我们还想要沿着边移动小球。小球仅仅在它没有被卡住的时候移动。 
你能在这找到小球对象的代码: 
BallObject: header, code 
首先让我们添加小球到游戏中。和玩家挡板相似,我们创建一个BallObject并且定义两个我们用来初始化小球的常量。作为小球的贴图,我们将会在LearnOpenGL Breakout游戏中使用一个来让场景变得完美:小球贴图。

// Initial velocity of the Ballconst glm::vec2 INITIAL_BALL_VELOCITY(100.0f, -350.0f);// Radius of the ball objectconst GLfloat BALL_RADIUS = 12.5f;BallObject     *Ball;void Game::Init(){    [...]    glm::vec2 ballPos = playerPos + glm::vec2(PLAYER_SIZE.x / 2 - BALL_RADIUS, -BALL_RADIUS * 2);    Ball = new BallObject(ballPos, BALL_RADIUS, INITIAL_BALL_VELOCITY,        ResourceManager::GetTexture("face"));}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

我们必须在每一帧通过在game代码的Update方法中调用它的Move方法更新小球的位置:

void Game::Update(GLfloat dt){    Ball->Move(dt, this->Width);}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

更多的,因为小球被初始化为固定在挡板上,我们必须让玩家能够从它的固定位置移除。我们选中空格键来从挡板释放小球。这意味着我们必须改变ProcessInput方法:

void Game::ProcessInput(GLfloat dt){    if (this->State == GAME_ACTIVE)    {        GLfloat velocity = PLAYER_VELOCITY * dt;        // Move playerboard        if (this->Keys[GLFW_KEY_A])        {            if (Player->Position.x >= 0)            {                Player->Position.x -= velocity;                if (Ball->Stuck)                    Ball->Position.x -= velocity;            }        }        if (this->Keys[GLFW_KEY_D])        {            if (Player->Position.x <= this->Width - Player->Size.x)            {                Player->Position.x += velocity;                if (Ball->Stuck)                    Ball->Position.x += velocity;            }        }        if (this->Keys[GLFW_KEY_SPACE])            Ball->Stuck = false;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

在这里,如果用户按下空格条,小球的附着参数变为false。当小球被固定住的时候我们仍然沿着挡板的位置更新ProcessInput方法来移动小球的位置。 
最后,很显然我们需要渲染小球:

void Game::Render(){    if (this->State == GAME_ACTIVE)    {        [...]        Ball->Draw(*Renderer);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

最终小球跟着挡板并且当我们按下空格条的时候自由漫步。小球仍然恰当的在左,右和顶部边缘反弹,但是它还没有碰撞任何一个砖块。 
原文此处有个视频,但是我不会再CSDN博客插入mp4视频,有会的请告诉一声,谢谢。 
转载请注明出处:http://blog.csdn.net/ylbs110/article/details/52722652 
我们想要创建一个或多个方法来检查小球对象是否碰撞到关卡中的任何一个砖块,并且销毁这个砖块。这在下一节教程中称为碰撞检测方法。

0 0
原创粉丝点击