乒乓球碰撞问题



最近,我已经开始制作乒乓球游戏,因为我关注的教程告诉我我现在可以制作简单的游戏。

我猜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游戏,请单击此处。基本上,在乒乓球比赛中,您尝试使乒乓球越过球员桨,需要捍卫自己的领域。您可以通过以乒乓球方式移动桨来"捍卫",从而将其朝对手朝随机方向发射。

我现在面临的问题是,我无法使Pongball的Hitbox击中播放器的Hitbox。这是因为乒乓球通过将"加速器"添加到坐标中来移动。

ballx = ballx ballvx; bally = bally ballvy;

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

我应该补充说gfx.putpixel()函数是由教程给我的,它的工作原理:gfx.putpixel(xCoortion,ycoorcord,ycoorcord,ycoorcord,ycoordication,ycoorcord,red value,green value,blue value);,据我所知,绘制功能并没有引起任何问题,因此您可能应该跳过它们。

我对你们的问题是:我应该如何检测到乒乓球会与桨碰相撞?

游戏中的碰撞检测并不是一项琐碎的任务。但是对于乒乓球中最简单的情况,您可以无视桨和球的大小,足以与桨相交球轨迹。换句话说,您可以采用两个线段:首先从上帧的球位置到当前的球位置,第二个从桨的一端到另一端,然后在球上弹跳。

最新更新