1

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

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

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

这是相关的 if 函数:

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 函数(我在 if 函数中使用)。我已经基于 varcharacterTop 变量和enemyLeft 创建了 var CharacterRight 变量,但它似乎不起作用,或者我不确定我是否以正确的方式进行操作。

在当前设置中发生了一些奇怪的事情。如果我离开角色并且不移动它,则(敌人)弹跳 5 次后游戏结束,即使根据 if 函数,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

4

1 回答 1

2

按顺序列出提出的要点:

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

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

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

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

Window.getComputedStyle() 方法在应用活动样式表并解析这些值可能包含的任何基本计算之后,返回一个包含元素所有 CSS 属性值的对象。

在这种情况下,我们遇到的问题是,我们所追求的不是计算出来的样式,而是当前通过 CSS 动画在窗口周围飞行的元素的实际位置。因此使用 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>
于 2021-02-05T13:39:12.043 回答