C++ 乒乓球碰撞问题

C++ 乒乓球碰撞问题,c++,visual-c++,C++,Visual C++,最近,我开始制作乒乓球游戏,因为我正在学习的教程告诉我,我现在可以制作简单的游戏了 我想乒乓球并不像我想的那么简单 首先,代码如下: #include "MainWindow.h" #include "Game.h" #include <ctime> #include <iostream> #include <cstdlib> using namespace std; Game::Game(MainWindow& wnd) :

最近,我开始制作乒乓球游戏,因为我正在学习的教程告诉我,我现在可以制作简单的游戏了

我想乒乓球并不像我想的那么简单

首先,代码如下:

#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.
}
如果您不熟悉乒乓球游戏,请单击。 基本上,在乒乓球比赛中,你试着让乒乓球越过球员的球拍,并且需要防守你这边的场地。你“防守”的方式是将你的球拍移向乒乓球的方向,乒乓球会向你的对手随机发射回来

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

BallX=BallX+BallVX; 巴利=巴利+巴利维

这意味着它可以跳过桨叶的撞击框,而不会与桨叶发生碰撞。这种方法无论如何都是错误的,因为通过加速到不同的方向来改变乒乓球的方向也会使乒乓球更快

我应该补充一点,gfx.PutPixel()函数是教程给我的,它的工作原理如下:gfx.PutPixel(XCoordinate,YCoordinate,Red Value,Green Value,Blue Value),就我所知,Draw函数不会引起任何问题,所以您可能应该跳过它们

我的问题是:
我应该如何检测庞巴球是否会与球拍相撞?

在游戏中,一般来说,这不是一项简单的任务。但对于乒乓球的一个最简单的例子,你们可以忽略球拍和球的大小,只要把球的轨迹和球拍相交就足够了。换言之,您可以选取两条线段:第一条是从前一帧中球的位置到当前球的位置,第二条是从球拍的一端到另一端,如果它们相交,则弹起球。

我听起来非常愚蠢,但我如何计算这两条线是否相交?我不觉得球会反弹到离实际划桨相当远的地方吗?不过很有趣!这是一个例子。对于球反弹,可以将球放置在交点(消除剪裁)处,并反射/缩放速度向量。不过,gamedev至少需要一些基本的几何/线性代数。谢谢你不懂数学。非常感谢!当我看到你的帖子时,我也得出了这个结论,但我不知道如何计算。
#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;

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