xF4B
xF4B

Reputation: 86

Canvas Rectangle & Ball Collision Not working

I'm making a html5 canvas game and I have a problem with the collision. The problem is when the ball collides with any platform, the ball gravity should be -1 and go up as the same velocity as the platforms but it only works with the last platform and the left one. How can I fix it? Thanks!

HTML:

<html>
    <head>
        <title>Falldown</title>
    </head>
    <body>
      <canvas id="canvas" width = "380" height= "640"></canvas>  
      <script src="beta.js"></script>
    </body>
</html>

JS Code:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var isMenu = true;
var isPlaying = false;
var testing = true;
var pressingLeft = false;
var pressingRight = false;

var Platforms = [];

var difficulty = 1;

var gravity = 1;

var Player = {
    color: "red",
    radius: 7.5,
    stepY: 1.5,
    x: 175,
    y: 75
};

function RectCircleColliding(circle, rect) {
    var distX = Math.abs(circle.x - rect.x - rect.width / 2);
    var distY = Math.abs(circle.y - rect.y - 20 / 2);

    if (distX > (rect.width / 2 + circle.radius)) return false;
    if (distY > (20 / 2 + circle.radius)) return false;

    if (distX <= (rect.width / 2)) return true;
    if (distY <= (20 / 2)) return true;

    var dx = distX - rect.width / 2;
    var dy = distY - 20 / 2;
    return (dx * dx + dy * dy <= (circle.radius * circle.radius)); 
}

function drawBackground() {
    ctx.fillStyle = "black";
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    if (isMenu && !isPlaying) {
        createText("60px monospace", "white", "FallDown", 45, 130);
        createText("34px Arial", "white", "PLAY", 130, 260);
        createText("34px Arial", "white", "LEADERBOARD", 50, 340);
        createText("34px Arial", "white", "SETTINGS", 90, 420);
    } else {
        if (testing) {
            Platforms = [];
            for (var i = 0; i < 13; i++) {
                Platforms.push({
                    "x": 10,
                    "y": 160 + (i * 70),
                    "width": (Math.random() * canvas.width) - 60
                });
            }
            testing = false;
        }

        for (var i in Platforms) {
            ctx.fillStyle = "#00ffff";
            ctx.fillRect(10, Platforms[i].y, Platforms[i].width, 20);

            var totalTest = Platforms[i].width + 60;
            ctx.fillRect(totalTest + 30, Platforms[i].y, canvas.width - totalTest, 20);

            Platforms[i].y -= 1;

            if (RectCircleColliding(Player, Platforms[i])) {
                gravity = -1;
            } else {
                gravity = 1;
            }
        }

        detectBorderCollision();
        detectPlayerCollision();
        drawPlayer();
        drawBorder();

        if (Platforms.length === 7) Platforms = [];
    }
}

function detectBorderCollision() {
    if (Player.x > 370 - Player.radius) {
        Player.x = 370 - Player.radius;
    } else if (Player.x < 3.8 + Player.radius * 2) {
        Player.x = 3.8 + Player.radius * 2
    }
}

function detectPlayerCollision() {

}

function drawPlayer() {
    ctx.beginPath();
    ctx.fillStyle = Player.color;
    ctx.arc(Player.x, Player.y, Player.radius, 0, 2 * Math.PI);
    ctx.fill();
    ctx.closePath();

    Player.y += gravity;

    if (pressingRight) {
        Player.x += 2;
    } else if (pressingLeft) {
        Player.x -= 2;
    }

    /*
ctx.fillStyle = "#00ffff";
        ctx.fillRect(10, 160, 300, 20);
    */
}

function drawBorder() {
    ctx.beginPath();
    ctx.strokeStyle = "#00ffff";
    ctx.lineWidth = 10;
    ctx.moveTo(5, 0);
    ctx.lineTo(5, 640);

    ctx.moveTo(375, 0);
    ctx.lineTo(375, 640);
    ctx.stroke();
    ctx.closePath();
}

function createText(font, color, value, posX, posY) {
    ctx.font = font;
    ctx.fillStyle = color;
    ctx.fillText(value, posX, posY)
}

function isInside(realX, realY, x1, x2, y1, y2) {
    return (realX > x1 && realX < x2) && (realY > y1 && realY < y2)
}

function drawGame() {
    drawBackground();
}

function startDrawing() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drawGame();
    requestAnimationFrame(startDrawing);
}

function Init() {
    requestAnimationFrame(startDrawing);

    canvas.addEventListener("click", function(evt) {
        var rect = canvas.getBoundingClientRect();
        var mouseX = evt.clientX - rect.left;
        var mouseY = evt.clientY - rect.top;

        if (isMenu && !isPlaying) {
            if (isInside(mouseX, mouseY, 115, 230, 220, 270)) {
                isPlaying = true;
                isMenu = false;
            } else if (isInside(mouseX, mouseY, 35, 320, 300, 345)) {
                console.log("Leaderboard");
            } else if (isInside(mouseX, mouseY, 75, 270, 380, 430)) {
                console.log("Settings");
            }
        }

    });

    window.addEventListener("keydown", function(evt) {
        if (!isMenu && isPlaying) {
            if (evt.keyCode === 39) { // right
                pressingRight = true;
            } else if (evt.keyCode === 37) { // left
                pressingLeft = true;
            }
        }
    });

    window.addEventListener("keyup", function(evt) {
        if (!isMenu && isPlaying) {
            if (evt.keyCode === 39) { // right
                pressingRight = false;
            } else if (evt.keyCode === 37) { // left
                pressingLeft = false;
            }
        }
    });
}

Init();

Upvotes: 0

Views: 143

Answers (1)

MikeM
MikeM

Reputation: 13641

There are so many magic numbers in your code that debugging it is difficult and tedious. Replace all the number literals with identifiers which describe what the values represent.

The following amendment to part of the drawBackground function causes all the collisions with left hand platforms to work, but not perfectly.

var hasCollided;

for (var i in Platforms) {
    ctx.fillStyle = "#00ffff";
    ctx.fillRect(10, Platforms[i].y, Platforms[i].width, 20);

    var totalTest = Platforms[i].width + 60;
    ctx.fillRect(totalTest + 30, Platforms[i].y, canvas.width - totalTest, 20);

    Platforms[i].y -= 1;

    if (!hasCollided) { 
        if (RectCircleColliding(Player, Platforms[i])) {
            gravity = -1;
            hasCollided = true;
        } else {
            gravity = 1;
        }
    }
}

Upvotes: 1

Related Questions