简体   繁体   English

边界矩形碰撞 - 球跳过桨的错误一侧

[英]Bounding rectangle collisions - ball jumps through wrong side of paddle

I'm making a Pong game, and I've come across a problem. 我正在制作Pong游戏,我遇到了一个问题。 When the ball (a rectangle) collides with the racket (or the bat) below or above the racket, I get a strange bug where the ball moves into the rectangle and goes left-right-left-right reaching high speeds(because I added acceleration) and jumps out at the opposite side. 当球(一个矩形)与球拍下方或上方的球拍(或球棒)碰撞时,我得到一个奇怪的错误,球进入矩形并左右 - 左 - 右达到高速(因为我添加了)加速)并在对面跳出来。 I know why this bug is happening: 我知道为什么会发生这个错误:

if (ballrec.Intersects(player1rec)
        && ball.x <= 20
        && ball.y + 20 >= player.y
        && ball.y <= player.y + 100) //checks the front rebound-here's the bug
{
    ball.vx *= -1; //changes x-direction
    if (ball.vx < 0)
        ball.vx -= 1; //increases x-velocity
    effect.Play();
    if (R.Next(4) == 0)
    {
        if (ball.vy < 0) ball.vy--;
        else ball.vy++; //increases y-velocity on a special occasion
    }
}
else
{
    if (ballrec.Intersects(player1rec))
    {
        ball.vy *= -1;
        effect.Play();
    }
}

ball.vy=velocity y-axis: I multiply it with -1 to change the direction ball.vy = velocity y-axis:我将它乘以-1以改变方向

effect=sound 效果声音=

The bug: To make the ball rebound at any given location on the front of the racket, it says that the ball's lower side (that +20) mustn't be higher than the racket's upper side and the ball's upper side mustn't be lower than the racket's lower side. 错误:为了让球在球拍正面的任何位置反弹,它表示球的下侧(+20)不得高于球拍的上侧,并且球的上侧不得为低于球拍的下侧。 However because of the x coordinates (ball.x<=20, 20=the width of the racket), the front rebound effect consumes the top and the bottom side of the racket, and then the rebound there can't work. 但是由于x坐标(ball.x <= 20,20 =球拍的宽度),前反弹效果消耗球拍的顶部和底部,然后反弹就无法工作。

When I try to solve it, my best non-complicated solution (because next year I'm starting middle school (14-18 in my country) and don't know a lot of fancy maths), I don't get a good solution (check below). 当我试图解决它时,我最好的非复杂的解决方案(因为明年我开始上中学(在我的国家14-18)并且不知道很多花哨的数学),我没有得到好的解决方案(见下文)。

My solution (which I'm not happy with): I lower the area required for the front rebound to ball.y>=player.y and ball.y+20<=player.y+100(the length) and the up and down rebound work, but if the ball hits a corner of the racket, the same bug appears only in this case the ball moves up-down-up-down. 我的解决方案(我不满意):我将前方篮板所需的区域降低到ball.y> = player.y和ball.y + 20 <= player.y + 100(长度)和向上但是如果球击中球拍的一个角落,那么同样的错误只会出现在这种情况下,球会向上 - 向下 - 上下移动。

My question: How to fix the bug? 我的问题:如何解决这个问题? Thank you for your time! 感谢您的时间! Hope that wasn't too long! 希望不会太久!

Current solution (not perfect): 目前的解决方案(不完美):

if (ballrec.Intersects(player1rec)
        && ball.x <= 20
        && ball.y >= player.y
        && ball.y + 20 <= player.y + 100)
{
    ball.vx *= -1;
    if (ball.vx < 0)
        ball.vx -= 1;
    effect.Play();
    if (R.Next(4) == 0)
    {
        if (ball.vy < 0) ball.vy--;
        else ball.vy++;
    }
}
else
{
    if (ballrec.Intersects(player1rec))
    {
        ball.vy *= -1;
        effect.Play();
    }
}

Solution 1: Check speed Vector 解决方案1:检查速度矢量

One solution would be to take the direction of the Speep vector ( ball.vx ) into account. 一种解决方案是考虑Speep向量( ball.vx )的方向。 Just allow the player1 to flip the balls x speed if the speed is negative (eg moving towards the left screen and vice versa for the second player) If this is a simple pong game, this would be perfectly fine: 如果速度为负,只允许player1翻转球x速度(例如向第二个玩家移向左侧屏幕,反之亦然)如果这是一个简单的乒乓球比赛,这将是完美的:

// Player 1
if (ballrec.Intersects(player1rec)
    && ball.x <= 20
    && ball.y >= player.y
    && ball.y + 20 <= player.y + 100
    && ball.vx <= 0 ) //<--- Here
{
// .....
}

// Player 2
if (ballrec.Intersects(player2rec)
    // ....
    && ball.vx >= 0 ) //<--- Here
{
// .....
}

Solution 2: Save the collision state of the Ball 解决方案2:保存Ball的碰撞状态

Another solution is to save the current collision state (colliding or not colliding and only flip the speed when this status switches from not colliding to colliding): 另一个解决方案是保存当前的碰撞状态(碰撞或不碰撞,只有在此状态从不碰撞切换到碰撞时才翻转速度):

public class Ball
{
    public bool colliding = false;
}

//In Update of Ball/Game
bool player1Collision = ballrec.Intersects(player1rec)
    && ball.x <= 20
    && ball.y >= player.y
    && ball.y + 20 <= player.y + 100;
if( player1Collision && !ball.colliding )
{
    // Set state here, so reduce issues when there is a chance that different players can overlap
    ball.colliding = true;
    // .....
}

// Same for player 2,3,4,5 .....

//Update state for next frame
ball.colliding = player1Collision || player2Collision /* .... */;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM