乒乓球碰撞问题

时间:2017-02-19 18:30:18

标签: c++ visual-c++

最近,我开始制作Pong游戏,因为我正在关注的教程告诉我,我现在可以制作简单的游戏了。

我猜Pong并不像我想的那么简单。

首先,这是代码:

#include "MainWindow.h"
#include "Game.h"
#include <ctime>
#include <iostream>
#include <cstdlib>
using namespace std;




Game::Game(MainWindow& wnd)
    :
    wnd(wnd),
    gfx(wnd)
{
}

void Game::Go()
{
    gfx.BeginFrame();
    UpdateModel();
    ComposeFrame();
    gfx.EndFrame();
}

void Game::UpdateModel()
{
    ///Moves player paddles
    MovePaddle();
    ///Checks if player paddles are inside the given parameters.
    LeftPlayerY = WallInsideBorder(LeftPlayerY);
    RightPlayerY = WallInsideBorder(RightPlayerY);
    PongBallPhysics();
    IsGoal();

}

void Game::ComposeFrame()
{

    DrawBall(BallX, BallY, BallRed, BallGreen, BallBlue);
    DrawWall(LeftPlayerX, LeftPlayerY);
    DrawWall(RightPlayerX, RightPlayerY);
    DrawThePixelatedWall();
    DrawScoreboard();

}

///Draws the Pongball
void Game::DrawBall(int BallX, int BallY, int BallRed, int BallGreen, int BallBlue)
{
    ///Middle layer of pixels
    gfx.PutPixel(BallX, BallY, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX + 1, BallY, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX + 2, BallY, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX + 3, BallY, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX - 1, BallY, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX - 2, BallY, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX - 3, BallY, BallRed, BallGreen, BallBlue);
    ///Layer of Pixels above middle layer
    gfx.PutPixel(BallX - 3, BallY - 1, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX - 2, BallY - 1, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX - 1, BallY - 1, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX, BallY - 1, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX + 1, BallY - 1, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX + 2, BallY - 1, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX + 3, BallY - 1, BallRed, BallGreen, BallBlue);
    ///Layer of Pixels beneath top layer
    gfx.PutPixel(BallX - 2, BallY - 2, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX - 1, BallY - 2, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX, BallY - 2, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX + 1, BallY - 2, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX + 2, BallY - 2, BallRed, BallGreen, BallBlue);
    ///Top Layer
    gfx.PutPixel(BallX - 1, BallY - 3, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX, BallY - 3, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX + 1, BallY - 3, BallRed, BallGreen, BallBlue);
    ///Layer beneath middle layer
    gfx.PutPixel(BallX - 3, BallY + 1, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX - 2, BallY + 1, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX - 1, BallY + 1, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX, BallY + 1, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX + 1, BallY + 1, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX + 2, BallY + 1, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX + 3, BallY + 1, BallRed, BallGreen, BallBlue);
    ///Layer above bottom layer
    gfx.PutPixel(BallX - 2, BallY + 2, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX - 1, BallY + 2, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX, BallY + 2, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX + 1, BallY + 2, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX + 2, BallY + 2, BallRed, BallGreen, BallBlue);
    ///Bottom layer
    gfx.PutPixel(BallX - 1, BallY + 3, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX, BallY + 3, BallRed, BallGreen, BallBlue);
    gfx.PutPixel(BallX + 1, BallY + 3, BallRed, BallGreen, BallBlue);



}
///Draws the walls for the players (100 pixels tall)
void Game::DrawWall(int XCoordinate, int YCoordinate)
{
    if (XCoordinate == LeftPlayerX)
    {
        for (int i = -50; i <= 50; ++i)
        {
            gfx.PutPixel(XCoordinate, YCoordinate + i, 255, 255, 255);
            gfx.PutPixel(XCoordinate - 1, YCoordinate + i, 255, 255, 255);
            gfx.PutPixel(XCoordinate - 2, YCoordinate + i, 255, 255, 255);
            gfx.PutPixel(XCoordinate - 3, YCoordinate + i, 255, 255, 255);
        }
    }

    if (XCoordinate == RightPlayerX)
    {
        for (int i = -50; i <= 50; ++i)
        {
            gfx.PutPixel(XCoordinate, YCoordinate + i, 255, 255, 255);
            gfx.PutPixel(XCoordinate + 1, YCoordinate + i, 255, 255, 255);
            gfx.PutPixel(XCoordinate + 2, YCoordinate + i, 255, 255, 255);
            gfx.PutPixel(XCoordinate + 3, YCoordinate + i, 255, 255, 255);
        }
    }
}
///Draws the boundary between the player fields
void Game::DrawThePixelatedWall()
{
    for (int i = 0; i <= 597; i = i + 3)
    {
        gfx.PutPixel(399, i, 255, 255, 255);
    }
}
///Draws the scoreboard.
void Game::DrawScoreboard()
{
    switch (LeftPlayerScore) {
    case 0:
        for (int i = 6; i <= 50; ++i)
        {
            gfx.PutPixel(320 + 6, i, 255, 255, 255);
            gfx.PutPixel(320 + 5, i, 255, 255, 255);
            gfx.PutPixel(320 - 5, i, 255, 255, 255);
            gfx.PutPixel(320 - 6, i, 255, 255, 255);
            gfx.PutPixel(320 + 7, i, 255, 255, 255);
            gfx.PutPixel(320 - 7, i, 255, 255, 255);
        }
        for (int i = -4; i <= 6; ++i)
        {
            gfx.PutPixel(320 + i, 6, 255, 255, 255);
            gfx.PutPixel(320 + i, 7, 255, 255, 255);
            gfx.PutPixel(320 + i, 8, 255, 255, 255);
            gfx.PutPixel(320 + i, 50, 255, 255, 255);
            gfx.PutPixel(320 + i, 49, 255, 255, 255);
            gfx.PutPixel(320 + i, 48, 255, 255, 255);
        }


        break;

    case 1:
        for (int i = 6; i <= 50; ++i)
        {
            gfx.PutPixel(320, i, 255, 255, 255);
            gfx.PutPixel(320 + 1, i, 255, 255, 255);
            gfx.PutPixel(320 - 1, i, 255, 255, 255);
        }
        break;

    case 2:
        break;

    case 3:
        break;

    case 4:
        break;

    case 5:
        break;

    case 6:
        break;

    case 7:
        break;

    case 8:
        for (int i = 6; i <= 50; ++i)
        {
            gfx.PutPixel(320 + 6, i, 255, 255, 255);
            gfx.PutPixel(320 + 5, i, 255, 255, 255);
            gfx.PutPixel(320 - 5, i, 255, 255, 255);
            gfx.PutPixel(320 - 6, i, 255, 255, 255);
            gfx.PutPixel(320 + 7, i, 255, 255, 255);
            gfx.PutPixel(320 - 7, i, 255, 255, 255);
        }
        for (int i = -4; i <= 6; ++i)
        {
            gfx.PutPixel(320 + i, 6, 255, 255, 255);
            gfx.PutPixel(320 + i, 7, 255, 255, 255);
            gfx.PutPixel(320 + i, 8, 255, 255, 255);
            gfx.PutPixel(320 + i, 50, 255, 255, 255);
            gfx.PutPixel(320 + i, 49, 255, 255, 255);
            gfx.PutPixel(320 + i, 48, 255, 255, 255);
            gfx.PutPixel(320 + i, 27, 255, 255, 255);
            gfx.PutPixel(320 + i, 28, 255, 255, 255);
        }

        break;

    case 9:
        break;

    case 10:
        break;

    }
    switch (RightPlayerScore) {
    case 0:
        for (int i = 6; i <= 50; ++i)
        {
            gfx.PutPixel(478 + 6, i, 255, 255, 255);
            gfx.PutPixel(478 + 5, i, 255, 255, 255);
            gfx.PutPixel(478 - 5, i, 255, 255, 255);
            gfx.PutPixel(478 - 6, i, 255, 255, 255);
            gfx.PutPixel(478 + 7, i, 255, 255, 255);
            gfx.PutPixel(478 - 7, i, 255, 255, 255);
        }
        for (int i = -4; i <= 6; ++i)
        {
            gfx.PutPixel(478 + i, 6, 255, 255, 255);
            gfx.PutPixel(478 + i, 7, 255, 255, 255);
            gfx.PutPixel(478 + i, 8, 255, 255, 255);
            gfx.PutPixel(478 + i, 50, 255, 255, 255);
            gfx.PutPixel(478 + i, 49, 255, 255, 255);
            gfx.PutPixel(478 + i, 48, 255, 255, 255);
        }
        break;

    case 1:
        for (int i = 6; i <= 50; ++i)
        {
            gfx.PutPixel(478, i, 255, 255, 255);
            gfx.PutPixel(478 + 1, i, 255, 255, 255);
            gfx.PutPixel(478 - 1, i, 255, 255, 255);
        }
        break;

    case 2:
        break;

    case 3:
        break;

    case 4:
        break;

    case 5:
        break;

    case 6:
        break;

    case 7:
        break;

    case 8:
        break;

    case 9:
        break;

    case 10:
        break;

    }
}
///Checks if Walls are inside
int Game::WallInsideBorder(int YCoordinate)
{
    if (YCoordinate + 50 >= gfx.ScreenHeight)
    {
        return gfx.ScreenHeight - 51;
    }
    if (YCoordinate - 50 < 0)
    {
        return 51;
    }
    return YCoordinate;
}
///Pong Ball physics :D
void Game::PongBallPhysics()
{
    BallX = BallX + BallVX;
    BallY = BallY + BallVY;
    ///Sets initial VX and VY
    if (FirstTime)
    {
        srand(time(NULL));
        BallY = rand() % 599;
        BallVX = rand() % 4 + 1;
        srand(time(NULL));
        BallVY = rand() % 4 + 1;
        FirstTime = false;
    }
    /// Touching top or bottom?
    if (BallY - 3 < 0)
    {
        DoBounceCalculation();
        BallY = 3;
    }
    if (BallY + 3 > 599)
    {
        DoBounceCalculation();
        BallY = 595;
    }
    ///Touching a wall?
    /// ERROR, BallVX goes PAST LeftPlayerX/RightPlayerX!
    IsTouchingWall();

}
///Makes the angle be the same as when it hit the wall/boundary.Looked at and is working
void Game::DoBounceCalculation()
{
    BallVY = -BallVY;
} 
///Swaps two variables, looked at and should be working
void Game::Swap(int &x, int &y)
{
    int SwapVariable = x;
    x = y;
    y = SwapVariable;
}
///Checks if ball is in opponent's goal, looked at and is working
void Game::IsGoal()
{
    if (BallX - 3 <= 0)
    {
        RightPlayerScore++;
        BallX = 399;
        FirstTime = true;
    }
    if (BallX + 3 >= gfx.ScreenWidth)
    {
        LeftPlayerScore++;
        BallX = 399;
        FirstTime = true;
    }
}
///Moves player walls, looked at and is working
void Game::MovePaddle()
{
    if (wnd.kbd.KeyIsPressed(0x57))
    {
        LeftPlayerY = LeftPlayerY - 3;
    }
    if (wnd.kbd.KeyIsPressed(0x53))
    {
        LeftPlayerY = LeftPlayerY + 3;
    }
    if (wnd.kbd.KeyIsPressed(0x49))
    {
        RightPlayerY = RightPlayerY - 3;
    }
    if (wnd.kbd.KeyIsPressed(0x4B))
    {
        RightPlayerY = RightPlayerY + 3;
    }
}
///Checks if Ball is touching Player paddles and changes velocity accordingly, this is bwoke man, check it
void Game::IsTouchingWall()
{
    // if-statement that checks if the ball is gonna hit the paddle in the next frame.
    // The problem is, that VX or VY skip the pixels between (when they're set to anything higher than 1)
    // So that they jump other the paddle.
}

如果你感兴趣的话,这是头文件。

#pragma once

#include "Keyboard.h"
#include "Mouse.h"
#include "Graphics.h"

class Game
{
public:
    Game(class MainWindow& wnd);
    Game(const Game&) = delete;
    Game& operator=(const Game&) = delete;
    void Go();
private:
    void ComposeFrame();
    void UpdateModel();
    /********************************/
    /*  User Functions              */
    void DrawBall(int BallX, int BallY, int BallRed, int BallGreen, int BallBlue);
    void DrawWall(int XCoordinate, int YCoordinate);
    void DrawThePixelatedWall();
    void DrawScoreboard();
    int WallInsideBorder(int YCoordinate);
    void PongBallPhysics();
    void DoBounceCalculation();
    void Swap(int& x, int& y);
    void IsGoal();
    void MovePaddle();
    void IsTouchingWall();

    /********************************/
private:
    MainWindow& wnd;
    Graphics gfx;
    /********************************/
    /*  User Variables              */
    int BallVX = 0;
    int BallVY = 0;
    int BallX = 399;
    int BallY = 0;
    int BallRed = 255;
    int BallGreen = 255;
    int BallBlue = 255;
    const int LeftPlayerX = 100;
    int LeftPlayerY = 299;
    const int RightPlayerX = 700;
    int RightPlayerY = 299;
    int LeftPlayerScore = 0;
    int RightPlayerScore = 0;
    bool FirstTime = true;

    /********************************/
};

如果您不熟悉Pong游戏,请单击here。 基本上,在Pong,你试图让Pongball超越球员的桨,并需要保护你的球场。你可以通过Pongball的方式移动你的桨来“防守”,它会以随机的方向将它发射回你的对手。

我现在面临的问题是,我不能让Pongball的击球手击中球员的命中箱。这是因为Pongball通过在坐标上添加“加速器”来移动。

  

BallX = BallX + BallVX;    BallY = BallY + BallVY;

这意味着它可以跳过拨片的击打盒,而不是与拨片碰撞。这种方法无论如何都是错误的,因为通过加速到不同的方向来改变Pongball的方向也使得Pongball也更快。

我应该补充说教程中给出了gfx.PutPixel()函数,它的工作原理如下:gfx.PutPixel(XCoordinate,YCoordinate,Red Value,Green Value,Blue Value); ,据我所知,Draw功能不会引起任何问题,所以你应该跳过它们。

我向你们提出的问题是: 我应该如何发现Pongball会与桨撞击?

1 个答案:

答案 0 :(得分:2)

一般来说,游戏中的Collision detection并不是一项微不足道的任务。但是对于乒乓球中最简单的情况,你可以忽略桨和球的大小,将球的轨迹与桨相交就足够了。换句话说,你可以采取两个线段:首先从前一帧中球的位置到当前球的位置,第二个从球的一端到另一个球,如果它们相交则反弹球。