2017-02-19 4 views
-1

最近、私は次のチュートリアルで簡単なゲームを作ることができたので、ポンのゲームを始めました。ポンボールの衝突の問題

私はポンは私が思ったほどシンプルではないと思う。すべての

まず、ここのコードです:

#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をクリックしてください。 基本的には、ポンでは、プレイヤーのパドルを越えてポンボールを獲得しようとし、フィールドのあなたの側を守る必要があります。 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がパドルと衝突することをどのように検出する必要がありますか?

答えて

2

Collision detectionゲームでは一般的にそんなに簡単な作業ではありません。しかし、パドルとボールのサイズを無視できる最も単純なポンでは、ボールの軌道とパドルを交差させるだけで十分です。つまり、前のフレームのボールの位置から現在のボールの位置まで、パドルの一方の端から別の端まで2つの線分を取ることができます。また、交差する場合はボールをバウンスすることもできます。

+0

これは私の非常にばかげて聞こえますが、2本の線が交差する場合はどのように計算しますか?そしてボールが実際のパドルからかなり離れて飛び跳ねるという問題を私は得られないでしょうか?非常に興味深い! – Zedtho

+0

[Here](http://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/)がその一例です。ボールがバウンスするためには、ボールを交差点に置くことができ(クリッピングを排除する)、速度ベクトルを反映/拡大縮小することができます。しかし、少なくとも幾つかの基本的な幾何学/線形代数はgamedevのために不可欠です。数学に精通していない人のために[良い本がいくつかあります](https://www.amazon.com/exec/obidos/ASIN/1482250926)。 – w1ck3dg0ph3r

+0

ありがとう!私はあなたのポストを見たときにもその結論に至りましたが、その計算方法はわかりませんでした。 – Zedtho