首页 > 解决方案 > 在 JS 游戏中球碰撞导致 Game Over

问题描述

我正在尝试更新我的 Javascript 并制作一个简单的游戏来练习。基本上它涉及一个球员球方面,然后是几个在随机方向弹跳的环(全部在画布上动画),当球员球(由箭头键控制)与其中一个障碍物碰撞时,游戏结束。我的球员球和所有障碍物都可以正常工作,但是碰撞让我有点难过。我查看了很多其他示例,但似乎没有一个是在做同样的事情。也许有人可以看看并提供一些建议,这就是我一直在尝试的:

let canvas; 
let brush; 
let obstacles;
let player;

let myKeys = {
    // tracking the arrow keys
    up: false,
    down: false,
    left: false,
    right: false
};

// add a key press event listener to the body
let bodyElem = document.getElementById("body");
bodyElem.addEventListener("keydown", function(event){
    if(event.key === "ArrowUp"){
        myKeys.up = true;
    }

    if(event.key === "ArrowDown"){
        myKeys.down = true;
    }

    if(event.key === "ArrowLeft"){
        myKeys.left = true;
    }

    if(event.key === "ArrowRight"){
        myKeys.right = true;
    }
}
);

function Setup(){
    canvas = document.getElementById("drawingCanvas");
    brush = canvas.getContext("2d");
}
Setup();
function Clear(){
    brush.clearRect(0, 0, canvas.width, canvas.height);
}

function ToRadians(degrees){
    return degrees * Math.PI / 180;
}

function GetRandomInteger(a, b){ // returns random integer between 2 numbers, //swaps them if first is higher than 2nd
    if (a > b){
        small = b;
        large = a;
    }
    else{
        small = a;
        large = b;
    }
    
    let x = parseInt(Math.random() * (large - small + 1)) + small
    return x;
}

function GetRandomColor(){
    let red = GetRandomInteger(0,255);
    let green = GetRandomInteger(0, 255);
    let blue = GetRandomInteger(0, 255);
    let color = "rgb(" + red + ", " + green + ", " + blue + ")";
    return color;
}

class Circle {
    
    constructor(centerX, centerY, radius, dX, dY){
        this.centerX = centerX;
        this.centerY = centerY;
        this.rad = radius;
        this.color = GetRandomColor();
        this.name = "CIRCLE";

        this.dX = dX //movement in x direction
        this.dY = dY; // movement in y direction
    }

    Move(){
                let newX = this.x + this.dX;
        
                if(newX + this.radius >= canvas.width || newX - this.radius < 0){
                    this.dX = -this.dX;
                }
                else{
                    this.x = newX;
                }
        
                let newY = this.y + this.dY;
        
                if (newY + this.radius >= canvas.height || newY - this.radius < 0){
                    this.dY = -this.dY;
                }
                else{
                    this.y = newY;
                }
            }

    MoveUp(){
        if(this.centerY - this.dY - (this.rad - 1) >= 0){
            this.centerY -= this.dY;
        }
    }

    MoveDown(){
        if(this.centerY + this.dY + (this.rad - 1) < canvas.height){
            this.centerY += this.dY;
        }
    }

    MoveLeft(){
        if(this.centerX - this.dX - (this.rad - 1) >= 0){
            this.centerX -= this.dX;
        }
    }

    MoveRight(){
        if(this.centerX + this.dX + (this.rad - 1) < canvas.height){
            this.centerX += this.dX;
        }
    }

    MoveHorizontal(){
        if(this.centerX + this.rad - 1 >= canvas.width || this.centerX - this.rad + 1 < 0){
            this.dX = -this.dX;
        }
        this.centerX += this.dX;
    }

    MoveVertical(){
        if(this.centerY + this.rad >= canvas.height){
            this.dY = -this.dY;
        }
        if(this.centerY - this.rad + 1 < 0){
            this.dY = -this.dY;
        }
        this.centerY += this.dY;
    }

    Draw(isPlayer = false){
        // draws empty circle if enemy, filled circle if player
        brush.beginPath();
        brush.arc(this.centerX, this.centerY, this.rad, ToRadians(0), ToRadians(360));
        if(!isPlayer){
            // if not player object then draw a hollow circle
            brush.strokeStyle = this.color;
            brush.stroke();
        }
        else{
            brush.fillStyle = this.color;
            brush.fill();
        }
    }
}
let randomX=GetRandomInteger(0,canvas.width);

let halfX= canvas.width/2;
let playerStartY=canvas.height-10;

player = new Circle(halfX,playerStartY,25,halfX,playerStartY);

function CreateObstacles(n){
    //creates obstacles
     obstacles = [];
     for(let i = 0 ; i < n; i++){
        
         let speedX= GetRandomInteger(-10,10);
         let speedY= GetRandomInteger(-10,10);
         let enemy = new Circle(canvas.width/2, canvas.height/2, 25, speedX, speedY);
        
         obstacles.push(enemy);}
     
     }

function CreatePlayer(){
   // initializes player
     player = new Circle(halfX,playerStartY,25,10,10);
     player.Draw(isPlayer=true);

}
CreateObstacles(10);
function DrawAndMoveObstacles(){
   //loop through and draw obstacles
        for(let i = 0; i < obstacles.length; i++){

           obstacles[i].Draw();
            obstacles[i].MoveHorizontal();
            obstacles[i].MoveVertical();
            
} }
// setInterval(DrawAndMoveObstacles,300);
CreatePlayer();



function Distance(x1,y1,x2,y2){
    //distance between two circles
    let dis = Math.sqrt((x2-x1)**2 + (y2-y1)**2);
    return dis;
}

circle1= new Circle(player.x,player.y,25,player.dX,player.dY);
circle2= new Circle(obstacles.x,obstacles.y,25,
        obstacles.dX,obstacles.dY);

function Overlaps(circle1, circle2){
   //here is where I'm having issues...not sure how to fix

   let distance = Distance(circle1.x,circle1.y,circle2.x,circle2.y);
   if(distance < 50){
         
   }
   return true;
    }
 

console.log(Overlaps(player,obstacles));

function CheckCollission(){
    //loop through and see if things collide
     for(let i = 0; i < obstacles.length; i++){
         if (Overlaps(player,obstacles) == true){
            
         }
     }
}

function DrawGameScreen(){
    //putting everything together
    Clear();
    DrawAndMoveObstacles();
    
    player.Draw(true);
    if(myKeys.up===true){
        player.MoveUp();
        player.Draw(true);
        myKeys.up=false;
        player.Draw(true);
        }
    if(myKeys.down===true){
       player.MoveDown();
       player.Draw(true);
       myKeys.down=false;
    player.Draw(true);
   } if(myKeys.left===true){
       player.MoveLeft();
       player.Draw(true);
       myKeys.left=false;
        player.Draw(true);
   } if(myKeys.right===true){
       player.MoveRight();
       player.Draw(true);
       myKeys.right=false;
       player.Draw(true);
   }
   
}
console.log(Distance(player,obstacles));

setInterval(DrawGameScreen,400); //testing it

我一直在使用在 setInterval (Gamescreen, 400) 上运行的 GameScreen 函数对其进行测试,该函数将所有功能合二为一,以使棋子移动。

感谢您对新学习者的耐心等待

标签: javascriptfunctioncanvas

解决方案


您的代码存在许多问题,首先您在 Overlaps 中引用了 circle.x 和 circle.y

let distance = Distance(circle1.x,circle1.y,circle2.x,circle2.y);

这应该是您的 Circle 类中定义的 centerX 和 centerY

所以你的重叠应该修改为:

 function Overlaps(circle1, circle2){
   let distance = 
   Distance(circle1.centerX,circle1.centerY,circle2.centerX,circle2.centerY);
       if(distance < 50){
             console.log(distance); // show distance when collision found
             return true;
           }
           return false;
        }

线

console.log(Distance(player,obstacles));

在控制台中给出一个 Nan 错误,障碍物是一个数组而不是一个圆圈,所以只需删除那条线

接下来确保您正在检查 DrawGameScreen 中的碰撞,因此请更改

 function DrawGameScreen(){
            //putting everything together
            Clear();
            DrawAndMoveObstacles();

function DrawGameScreen(){
       //putting everything together
       Clear();
       DrawAndMoveObstacles();
       CheckCollission();

最后,circle1 和 circle2 的全局定义从未使用过,所以只需删除这些行

circle1= new Circle(player.x,player.y,25,player.dX,player.dY);
circle2= new Circle(obstacles.x,obstacles.y,25,
        obstacles.dX,obstacles.dY); 

推荐阅读