繁体   English   中英

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

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

我正在完成 HTML、CSS 和 JScript 游戏中的一些基本步骤,以便在角色和敌人之间进行非常简单的碰撞检测

我正在寻找足够简单的东西来向 8 - 11 岁的孩子解释。

如果角色和敌人发生碰撞,则“游戏结束”。 我尝试了各种方法,但需要一些代码帮助和 getComputedStyle 方法的解释以及它获得的属性,以便我有效地创建主 if 语句。

如果 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);

这是声明变量的setInterval function (我在 if 函数中使用)。 我已经基于 varcharacterTop 变量和enemyLeft 创建了 var CharacterRight 变量,但它似乎不起作用,或者我不确定我是否以正确的方式进行操作。

在当前设置中发生了一些奇怪的事情。 如果我离开角色并且不移动它,则(敌人)弹跳 5 次后游戏结束,即使按照 if function,characterTop 根本没有改变。 那么那里发生了什么?

请在回答中:

a)根据我现有的代码提出碰撞检测的建议解决方案

b) GetComputedStyle 和 getProperties 的说明及其文档。 例如,如果 characterTop 没有改变(如果我不移动角色)它怎么会突然输出“游戏结束”,这表明 characterTop 是 ==enemyLeft。

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"));

为了完整起见,这里是整个代码:

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

*{
    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

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()
  }
})

我看过这个文档,但它似乎没有引用对象。 https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle

按顺序列出提出的要点:

a)根据我现有的代码提出碰撞检测的建议解决方案

您不能在此处使用 getComputedStyle(参见 b 点)。 下面是使用带有碰撞检测的 getBoundingClientRect 的代码(即当敌人和角色完全重叠时)

b) GetComputedStyle 和 getProperties 的说明及其文档。 例如,如果 characterTop 没有改变(如果我不移动角色)它怎么会突然输出“游戏结束”,这表明 characterTop 是 ==enemyLeft。

getComputedStyle 就是这样做的,它遍历所有样式设置并将它们合并,以便您获得元素的当前样式。 参见例如https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle

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. 因此使用 getBoundingClientRect 来获取元素的实际当前 x 和 ys。

原作中角色顶部对敌人左侧的测试并没有告诉你任何事情。 但有时它们可能会匹配,所以你会得到一个游戏结束。

c) 简单碰撞检测的最佳实践(针对初学者的学习概念)

老实说,我不认为我可以对此发表看法,因为我不知道学生已经掌握了多少几何/代数等。 下面使用的代码检测敌人是否完全在角色上方,反之亦然,如果不是,则一个人是否完全在另一个人的左侧。 否则它们会重叠。

这是完整的代码。 不幸的是,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