简体   繁体   English

JavaScript 游戏中的 if 语句无法正常工作以允许碰撞检测

[英]if statement in JavaScript game not working as desired to allow for collision detection

I'm working through some basic steps in an HTML, CSS and JScript game to get very simple collision detection working between a CHARACTER and an ENEMY.我正在完成 HTML、CSS 和 JScript 游戏中的一些基本步骤,以便在角色和敌人之间进行非常简单的碰撞检测

I am looking for something that is simple enough to explain to children of age 8 - 11.我正在寻找足够简单的东西来向 8 - 11 岁的孩子解释。

If the character and the enemy collide then "game over".如果角色和敌人发生碰撞,则“游戏结束”。 I have tried various things, but require some help with the code and an explanation of getComputedStyle method and what Properties it gets, for me to effectively create the main if statement.我尝试了各种方法,但需要一些代码帮助和 getComputedStyle 方法的解释以及它获得的属性,以便我有效地创建主 if 语句。

This is the relevant if function:如果 function,这是相关的:

if(
        characterTop==enemyLeft //have tried characterRight==enemyLeft didn't work
    )
    {
        enemy.style.animation="none"; //remove the animation
        enemy.style.display="none";
        alert("Game Over");
        
    } 
},10);

And this is the setInterval function with the variables declared (which I use in the if function).这是声明变量的setInterval function (我在 if 函数中使用)。 I have created the var CharacterRight variable based on the varcharacterTop variable and enemyLeft, but it doesn't seem to work or I am not sure if I am going about it the right way.我已经基于 varcharacterTop 变量和enemyLeft 创建了 var CharacterRight 变量,但它似乎不起作用,或者我不确定我是否以正确的方式进行操作。

In the current set up something strange happens.在当前设置中发生了一些奇怪的事情。 If I leave the character and do not move it, after 5 bounces (of the enemy) the game is over, even though, as per the if function, characterTop is not changing at all.如果我离开角色并且不移动它,则(敌人)弹跳 5 次后游戏结束,即使按照 if function,characterTop 根本没有改变。 So what is happening there?那么那里发生了什么?

In an answer, please:请在回答中:

a) Suggest a proposed solution for collision detection based on my existing code a)根据我现有的代码提出碰撞检测的建议解决方案

b) Explanation of the GetComputedStyle and getProperties with documentation on it. b) GetComputedStyle 和 getProperties 的说明及其文档。 For instance, if characterTop doesn't change (if I don't move the character) how come it suddenly outputs "game over" which suggests characterTop is == enemyLeft.例如,如果 characterTop 没有改变(如果我不移动角色)它怎么会突然输出“游戏结束”,这表明 characterTop 是 ==enemyLeft。

c) Best practices for simple collision detection (for absolute beginner's learning concepts and propose the simplest possible solution, given the existing code) c) 简单碰撞检测的最佳实践(对于绝对初学者的学习概念,并根据现有代码提出最简单的解决方案)

var checkDead =setInterval(function(){
    var characterTop = parseInt(window.getComputedStyle(character).getPropertyValue("top"));
    var enemyLeft = parseInt(window.getComputedStyle(enemy).getPropertyValue("left"));
    //ADD VARIABLE TO FIND CHARACTER RIGHT -if it collides with enemy left, you are out
    //remove the condition that the enemy has to be in the first 30 pixels of the game (left side)
    var characterRight =parseInt(window.getComputedStyle(character).getPropertyValue("right"));

For completeness, here is the whole code:为了完整起见,这里是整个代码:

HTML HTML

<!DOCTYPE html>

<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
    
</head>
<body>
  <h1>Game</h1>
 
   
   
   <div id="game">
        <div id="sky"></div>
       <div id="ground"></div>
        <div id="enemy"></div>
       <div id="character"></div>
   </div>
   
<script src="script.js"></script>
</body>

</html>

CSS CSS

*{
    padding:0;
    margin:22;
}

#game{
    width:500px;
    height:500px;
    border:4px solid #171918;
}

#character{
    width:30px;
    height:120px;
    background-color:green;
    position:relative;
    top:320px;
    border-radius:20px;
    /*animation: jump 300ms */
    
}

/* new class called animate */
.animate{
    animation: jump 500ms;
}


#enemy{
    width:60px;
    height:60px;
    background-color:red;
    border-radius:14px;
    position:relative;
    top:320px;
    left:440px;
    animation: moveenemy 1s infinite linear;
    
}

@keyframes moveenemy{
    0%{left:440px;}
    50%{top:58px;}
    100%{left:0px; top:320x;}
}

@keyframes jump{
    0%{top:380px;}
    30%{top:50px;}
    50%{top:40px;}
    100%{top:380px;}
}





/* adding sky*/
#sky{
    width:500px;
    height:340px;
    background-color:skyblue;
    position:absolute;
    top:118px;
}

/* adding ground */
#ground{
    width:500px;
    height:170px;
    background-color:bisque;
    position:absolute;
    top:450px;
}

JavaScript JavaScript

var character = document.getElementById("character");
var enemy = document.getElementById("enemy");    
function jump(){
    if(character.classlist!="animate"){
    character.classList.add("animate");
    }
    setTimeout(function(){
        character.classList.remove("animate");
    },500);
    
}

//right movement

function right() {
  var leftVal =  parseInt(window.getComputedStyle(character).getPropertyValue("left"))
  character.style.left = (leftVal + 30) + "px";

}

//left movement
function left() {

  var leftVal =  parseInt(window.getComputedStyle(character).getPropertyValue("left"))
  character.style.left = (leftVal - 30) + "px";

}

var checkDead =setInterval(function(){
    var characterTop = parseInt(window.getComputedStyle(character).getPropertyValue("top"));
    var enemyLeft = parseInt(window.getComputedStyle(enemy).getPropertyValue("left"));
    //ADD VARIABLE TO FIND CHARACTER RIGHT -if it collides with enemy left, you are out
    //remove the condition that the enemy has to be in the first 30 pixels of the game (left side)
    var characterRight =parseInt(window.getComputedStyle(character).getPropertyValue("right"));
    
    console.log(characterRight);
    console.log(enemyLeft)
  
    if(
        characterTop==enemyLeft //have tried characterRight==enemyLeft didn't work
    )
    {
        enemy.style.animation="none"; //remove the animation
        enemy.style.display="none";
        alert("Game Over");
        
    } 
},10);


//left
addEventListener("keydown", function(e) {
    if(e.keyCode == 37) left()
})

//jump (up)
addEventListener("keydown", function(e) {
  if (e.keyCode === 38) {
    jump()
  }
})

//right
addEventListener("keydown", function(e) {
  if (e.keyCode === 39) {
    right()
  }
})

I've looked at this documentation, but it doesn't seem to refer to objects.我看过这个文档,但它似乎没有引用对象。 https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle

Taking the points raised in order:按顺序列出提出的要点:

a) Suggest a proposed solution for collision detection based on my existing code a)根据我现有的代码提出碰撞检测的建议解决方案

You cannot use getComputedStyle here (see point b).您不能在此处使用 getComputedStyle(参见 b 点)。 Below is code using getBoundingClientRect with collision detection (ie when the enemy and the character overlap at all)下面是使用带有碰撞检测的 getBoundingClientRect 的代码(即当敌人和角色完全重叠时)

b) Explanation of the GetComputedStyle and getProperties with documentation on it. b) GetComputedStyle 和 getProperties 的说明及其文档。 For instance, if characterTop doesn't change (if I don't move the character) how come it suddenly outputs "game over" which suggests characterTop is == enemyLeft.例如,如果 characterTop 没有改变(如果我不移动角色)它怎么会突然输出“游戏结束”,这表明 characterTop 是 ==enemyLeft。

getComputedStyle does just that, it runs through all the style settings and merges them so you get the current style for the element. getComputedStyle 就是这样做的,它遍历所有样式设置并将它们合并,以便您获得元素的当前样式。 See for example https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle参见例如https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle

The Window.getComputedStyle() method returns an object containing the values of all CSS properties of an element, after applying active stylesheets and resolving any basic computation those values may contain. Window.getComputedStyle() 方法返回一个 object 包含所有 CSS 元素的属性的值,在应用活动样式表并解析任何基本计算之后。

The problem we have in this case is that it's not the computed styles we are after, it is the actual, of this moment, position of an element which is being flown around the window by a CSS animation. The problem we have in this case is that it's not the computed styles we are after, it is the actual, of this moment, position of an element which is being flown around the window by a CSS animation. Therefore use getBoundingClientRect to get the actual current x and ys of the elements.因此使用 getBoundingClientRect 来获取元素的实际当前 x 和 ys。

The test in the original of the character's top against the enemy's left doesn't tell you anything.原作中角色顶部对敌人左侧的测试并没有告诉你任何事情。 But occasionally it's possible they might match and so you'd get a Game Over.但有时它们可能会匹配,所以你会得到一个游戏结束。

c) Best practices for simple collision detection (for beginner's learning concepts) c) 简单碰撞检测的最佳实践(针对初学者的学习概念)

I don't honestly think I can pontificate on this as I don't know how much geometry/algebra etc the students already have.老实说,我不认为我可以对此发表看法,因为我不知道学生已经掌握了多少几何/代数等。 The code used below detects whether the enemy is completely above the character or vice versa and if not whether one is completely to the left of the other.下面使用的代码检测敌人是否完全在角色上方,反之亦然,如果不是,则一个人是否完全在另一个人的左侧。 Otherwise they overlap.否则它们会重叠。

Here is complete code.这是完整的代码。 Unfortunately SO's snippet system did not seem to respond to the keydown events so I couldn't present it as a runnable snippet right here.不幸的是,SO 的代码片段系统似乎没有响应 keydown 事件,所以我无法在此处将其呈现为可运行的代码片段。

<!DOCTYPE html>

<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    *{
    padding:0;
    margin:22;
}

#game{
    width:500px;
    height:500px;
    border:4px solid #171918;
}

#character{
    width:30px;
    height:120px;
    background-color:green;
    position:relative;
    top:320px;
    border-radius:20px;
    /*animation: jump 300ms */
    
}

/* new class called animate */
.animate{
    animation: jump 500ms;
}


#enemy{
    width:60px;
    height:60px;
    background-color:red;
    border-radius:14px;
    position:relative;
    top:320px;
    left:440px;
    animation: moveenemy 1s infinite linear;    
}

@keyframes moveenemy{
    0%{left:440px;}
    50%{top:58px;}
    100%{left:0px; top:320x;}
}

@keyframes jump{
    0%{top:380px;}
    30%{top:50px;}
    50%{top:40px;}
    100%{top:380px;}
}





/* adding sky*/
#sky{
    width:500px;
    height:340px;
    background-color:skyblue;
    position:absolute;
    top:118px;
}

/* adding ground */
#ground{
    width:500px;
    height:170px;
    background-color:bisque;
    position:absolute;
    top:450px;
}
</style>    
</head>
<body>
  <h1>Game</h1>
 
   
   
   <div id="game">
        <div id="sky"></div>
       <div id="ground"></div>
        <div id="enemy"></div>
       <div id="character"></div>
   </div>
   
<script>
var character = document.getElementById("character");
var enemy = document.getElementById("enemy");    
function jump(){
    if(character.classlist!="animate"){
    character.classList.add("animate");
    }
    setTimeout(function(){
        character.classList.remove("animate");
    },500);
    
}

//right movement

function right() {
  var leftVal =  parseInt(window.getComputedStyle(character).getPropertyValue("left"))
  character.style.left = (leftVal + 30) + "px";

}

//left movement
function left() {

  var leftVal =  parseInt(window.getComputedStyle(character).getPropertyValue("left"))
  character.style.left = (leftVal - 30) + "px";

}

var checkDead = setInterval(function(){
       
    // Get the positions of the top, left and bottom, right of the enemy and the character    
    let enemyPos = enemy.getBoundingClientRect() // this will give us the left, right, top and bottom positions of the enemy
    let characterPos = character.getBoundingClientRect() // this will give us the left, right, top and bottom positions of the character

    // now let's see if there is any overlap between the enemy and the character

   // we are going to check whether one of them is to the left of the other.
   // For example if the left side of the enemy is bigger than the right side of the character then the enemy is to the right of the character
    if (enemyPos.left >= characterPos.right || characterPos.left >= enemyPos.right) {
       // Now we know they don't overlap as either the enemy is to the right of the character or vice versa so do nothing
    }
    
       // if we still don't know, we see whether the character is above the enemy or vice versa
    else if (enemyPos.bottom <= characterPos.top || characterPos.bottom <= enemyPos.top) {
       // Now we know they don't overlap as either the enemy is above the character or vice versa so do nothing
    }
      
      // neither of them is totally to the left or totally above the other so they must overlap somewhere- GOTCHA!
    else {
        enemy.style.animation="none"; //remove the animation
        enemy.style.display="none";
        alert("Game Over");
        clearInterval(checkDead); //I've added this but you may want to start again completely or....
    }        
  },10 );


//left
addEventListener("keydown", function(e) {
    if(e.keyCode == 37) left()
})

//jump (up)
addEventListener("keydown", function(e) {
  if (e.keyCode === 38) {
    jump()
  }
})

//right
addEventListener("keydown", function(e) {
  if (e.keyCode === 39) {
    right()
  }
})
</script>

</body>

</html>

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

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