Функция столкновения кирпичного выключателя - PullRequest
0 голосов
/ 10 апреля 2020

Я пытаюсь создать функцию, которая распознает, попадает ли мяч в кирпич в моей игре, и регулирует скорость мяча по оси x или y в зависимости от того, где он попадает в кирпич.

Я собираюсь столкнуться Функция проверить, какая ближайшая сторона кирпича в зависимости от местоположения шара. Если мяч попадает в левую или правую часть кирпича, он меняет скорость по оси x, а если он попадает в верх или низ, он меняет скорость по оси y.

В настоящее время он проверяет только левую или правую сторону. , но вот где моя проблема.

Ниже приведен файл, содержащий функцию:

let collision = false;
let bottomOfBall = ball.position.y + ball.height;
let topOfBall = ball.position.y;
let leftSideBall = ball.position.x;
let rightSideBall = ball.position.x + ball.width;
let topOfObject = gameObject.position.y;
let bottomOfObject = gameObject.position.y + gameObject.height;
let leftSideObject = gameObject.position.x
let rightSideObject = gameObject.position.x + gameObject.width;

let ballXMidPoint = rightSideBall - (rightSideBall - leftSideBall / 2);
let ballYMidPoint = bottomOfBall - (bottomOfBall - topOfBall / 2);
let ballXRadius = ball.width / 2;
let vertex = 0;

let nearestBrickSide;

if (topOfObject >= bottomOfBall && leftSideBall >= rightSideObject) {

    let x = (leftSideBall - rightSideObject)^2;
    let y = (topOfObject - bottomOfBall)^2;
    let z1 = Math.sqrt((x- .01) + y);
    let z2 = Math.sqrt(x + (y + .01));
    if (z1 < z2) nearestBrickSide = topOfObject;
    else if (z1 > z2) nearestBrickSide = rightSideObject;
    else nearestBrickSide = vertex;
}  
else if (topOfObject >= bottomOfBall && leftSideObject >= rightSideBall) {
    let x = (leftSideObject - rightSideBall)^2;
    let y = (topOfObject - bottomOfBall)^2;
    let z1 = Math.sqrt((x+ .01) + y);
    let z2 = Math.sqrt(x + (y + .01));
    if (z1 < z2) nearestBrickSide = topOfObject;
    else if (z1 > z2) nearestBrickSide = leftSideObject;
    else nearestBrickSide = vertex;
}
else if (topOfBall >= bottomOfObject && leftSideBall >= rightSideObject) {
    let x = (leftSideBall - rightSideObject)^2;
    let y = (topOfBall - bottomOfObject)^2;
    let z1 = Math.sqrt(x + (y - .01));
    let z2 = Math.sqrt((x - .01) + y);
    if (z1 < z2) nearestBrickSide = rightSideObject;
    else if (z1 > z2) nearestBrickSide = bottomOfObject;
    else nearestBrickSide = vertex;
}   
else if (topOfBall >= bottomOfObject && leftSideObject >= rightSideBall) {
    let x = (leftSideObject - rightSideBall)^2;
    let y = (topOfBall - bottomOfObject)^2;
    let z1 = Math.sqrt(x + (y - .01));
    let z2 = Math.sqrt((x + .01) + y);
    if (z1 < z2) nearestBrickSide = leftSideObject;
    else if (z1 > z2) nearestBrickSide = bottomOfObject;
    else nearestBrickSide = vertex;
} 
else if (topOfBall >= bottomOfObject && rightSideBall >= leftSideObject && leftSideBall <= rightSideObject) {
    nearestBrickSide = bottomOfObject;
}
else if (topOfObject >= bottomOfBall && rightSideBall >= leftSideObject && leftSideBall <= rightSideObject) {
    nearestBrickSide = topOfObject;
}
else if (leftSideObject >= rightSideBall && bottomOfBall >= topOfObject && topOfBall <= bottomOfObject) {
    nearestBrickSide = leftSideObject;
}
else if (leftSideBall >= rightSideObject && bottomOfBall >= topOfObject && topOfBall <= bottomOfObject) {
    nearestBrickSide = rightSideObject;
}

if (collision === false) {

if (nearestBrickSide === rightSideObject && ballXMidPoint - rightSideObject < ballXRadius) {
    collision = true;
    return true;
} 
else if (nearestBrickSide === leftSideObject && rightSideObject - ballXMidPoint < ballXRadius) {
    collision = true;
    return true;
}
else return false;
} else return false;
}

Функция кажется слишком широкой, потому что когда я играю в игру, мяч будет переключайте направление х много раз, даже если оно не обязательно близко к кирпичу. Я попытался добавить ограничения в оператор if в конце функции, чтобы функция возвращала true только тогда, когда ballXMidPoint - rightSideObject <= ballXRadius || rightSideObject - ballXMidPoint <ballXRadius. Но это не очень помогает. Я все еще получаю дрожащий шар. </p>

Как мне исправить функцию? Кроме того, как я могу сделать так, чтобы функция не повторялась так быстро? (т.е. я думаю, что с каждым обновлением шар все еще может соответствовать истинным требованиям для функции, и это заставляет шар снова и снова переключать направления. Я устанавливаю переменную, называемую коллизией, так что, когда функция возвращает истину, коллизия true. в моей игре. js, я установил функцию timeOut для сброса столкновения на false после 100 мс. Таким образом, мяч может попадать в кирпич только каждые 100 мс. Есть ли лучший способ настроить эту задержку?

Решено

Мне удалось заставить функцию столкновения работать должным образом, изменив несколько вещей.

1: Я изменил условие, оценивающее функцию на true .

if (nearestBrickSide === rightSideObject &&
        leftSideBall - rightSideObject < ballRadius &&
        bottomOfBall >= topOfObject &&
        topOfBall <= bottomOfObject &&
        ball.speed.x <= 0 ) 
        { return true }
         else if (nearestBrickSide === leftSideObject &&
        leftSideObject - rightSideBall < ballRadius && 
        bottomOfBall >= topOfObject && 
        topOfBall <= bottomOfObject &&
        ball.speed.x >= 0)
        { return true }

Я изменил свой кирпич. js файл

if (!this.game.ball.collision){


    if(detectYCollision(this.game.ball, this )) {

        this.game.ball.collision = true;
        this.game.ball.speed.y = - this.game.ball.speed.y;
        if (this.hitBrick) this.markedForDeletion = true;
        this.hitBrick = true;

    } 

    if(detectXCollision(this.game.ball, this )) {

        this.game.ball.collision = true;
        this.game.ball.speed.x = - this.game.ball.speed.x;
        if (this.hitBrick) this.markedForDeletion = true;
        this.hitBrick = true;

    }                                                                                                                  
} 

//Prevents multiple hits to same brick if ball has not left brick bounds
 if (this.game.ball.collision) {

    if (this.game.ball.position.x > this.position.x + this.width + this.game.ball.width / 2 ||
        this.game.ball.position.x < this.position.x ||
        this.game.ball.position.y > this.position.y + this.height + this.game.ball.height / 2 ||
        this.game.ball.position.y < this.position.y) {
            this.game.ball.collision = false;
        }  

    }  
...