JavaScript 游戏中的 if 语句无法正常工作以允许碰撞检测 [英] if statement in JavaScript game not working as desired to allow for collision detection

查看:42
本文介绍了JavaScript 游戏中的 if 语句无法正常工作以允许碰撞检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我正在寻找一些简单到可以向 8 - 11 岁儿童解释的内容.

如果角色和敌人发生碰撞,则游戏结束".我尝试了各种方法,但需要一些代码帮助以及 getComputedStyle 方法及其获取的属性的说明,以便我有效地创建主 if 语句.

这是相关的 if 函数:

if(characterTop==enemyLeft//尝试过 characterRight==enemyLeft 没有用){敌人.style.animation =无";//移除动画敌人.style.display =无";警报(游戏结束");}},10);

这是带有声明的变量的 setInterval 函数(我在 if 函数中使用).我已经根据 varcharacterTop 变量和敌人Left 创建了 var CharacterRight 变量,但它似乎不起作用,或者我不确定我是否以正确的方式进行操作.

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

在回答中,请:

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

b) 解释 GetComputedStyle 和 getProperties 及其相关文档.例如,如果 characterTop 没有改变(如果我不移动角色)它怎么会突然输出game over"?这表明 characterTop 是 ==敌对左.

c) 简单碰撞检测的最佳实践(对于绝对初学者的学习概念并提出最简单的可能解决方案,给定现有代码)

var checkDead =setInterval(function(){var characterTop = parseInt(window.getComputedStyle(character).getPropertyValue("top"));var敌人Left = parseInt(window.getComputedStyle(enemy).getPropertyValue(left"));//ADD VARIABLE TO FIND CHARACTER RIGHT - 如果它与左边的敌人相撞,你就出局了//去除敌人必须在游戏前30像素(左侧)的条件var characterRight =parseInt(window.getComputedStyle(character).getPropertyValue("right"));

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

HTML

<html lang="en"><头><元字符集=UTF-8"><title>文档</title><link rel="样式表";href="style.css"><身体><h1>游戏</h1><div id="游戏"><div id=天空"></div><div id="ground"></div><div id=敌人"></div><div id="字符"></div>

<script src="script.js"></script></html>

CSS

<代码>*{填充:0;边距:22;}#游戏{宽度:500px;高度:500px;边框:4px 实心 #171918;}#特点{宽度:30px;高度:120px;背景颜色:绿色;位置:相对;顶部:320px;边框半径:20px;/*动画:跳跃300ms */}/* 名为 animate 的新类 */.animate{动画:跳跃500ms;}#敌人{宽度:60px;高度:60px;背景颜色:红色;边框半径:14px;位置:相对;顶部:320px;左:440px;动画:moveenemy 1s 无限线性;}@keyframes moveenemy{0%{left:440px;}50%{top:58px;}100%{left:0px;顶部:320x;}}@关键帧跳转{0%{顶部:380px;}30%{top:50px;}50%{top:40px;}100%{top:380px;}}/* 添加天空*/#天空{宽度:500px;高度:340px;背景颜色:天蓝色;位置:绝对;顶部:118px;}/* 添加地面 */#地面{宽度:500px;高度:170px;背景色:素色;位置:绝对;顶部:450px;}

JavaScript

var character = document.getElementById("character");var敌人 = document.getElementById(敌人");函数跳转(){if(character.classlist!=动画"){character.classList.add(动画");}设置超时(功能(){character.classList.remove(动画");},500);}//向右移动功能右(){var leftVal = parseInt(window.getComputedStyle(character).getPropertyValue("left"))character.style.left = (leftVal + 30) + "px";}//左移函数左(){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敌人Left = parseInt(window.getComputedStyle(enemy).getPropertyValue(left"));//ADD VARIABLE TO FIND CHARACTER RIGHT - 如果它与左边的敌人相撞,你就出局了//去除敌人必须在游戏前30像素(左侧)的条件var characterRight =parseInt(window.getComputedStyle(character).getPropertyValue("right"));console.log(characterRight);console.log(enemyLeft)如果(characterTop==enemyLeft//尝试过 characterRight==enemyLeft 没有用){敌人.style.animation =无";//移除动画敌人.style.display =无";警报(游戏结束");}},10);//剩下addEventListener("keydown", function(e) {if(e.keyCode == 37) left()})//跳起来)addEventListener("keydown", function(e) {if (e.keyCode === 38) {跳()}})//对addEventListener("keydown", function(e) {if (e.keyCode === 39) {对()}})

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

解决方案

把提出的观点按顺序:

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

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

b) 解释 GetComputedStyle 和 getProperties 及其相关文档.例如,如果 characterTop 没有改变(如果我不移动角色)它怎么会突然输出游戏结束"?这表明 characterTop 是 ==敌对左.

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

<块引用>

Window.getComputedStyle() 方法返回一个包含应用 active 后元素的所有 CSS 属性的值样式表并解决这些值可能的任何基本计算包含.

在这种情况下,我们遇到的问题不是我们要计算的样式,而是当前通过 CSS 动画在窗口周围飞行的元素的实际位置.因此使用 getBoundingClientRect 来获取元素的实际当前 x 和 y.

原始角色顶部对着敌人左侧的测试没有告诉您任何信息.但有时它们可​​能会匹配,所以你会得到游戏结束.

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

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

这是完整的代码.不幸的是,SO 的代码段系统似乎没有响应 keydown 事件,所以我无法在此处将其显示为可运行的代码段.

<html lang="en"><头><元字符集=UTF-8"><title>文档</title><风格>*{填充:0;边距:22;}#游戏{宽度:500px;高度:500px;边框:4px 实心 #171918;}#特点{宽度:30px;高度:120px;背景颜色:绿色;位置:相对;顶部:320px;边框半径:20px;/*动画:跳跃300ms */}/* 名为 animate 的新类 */.animate{动画:跳跃500ms;}#敌人{宽度:60px;高度:60px;背景颜色:红色;边框半径:14px;位置:相对;顶部:320px;左:440px;动画:moveenemy 1s 无限线性;}@keyframes moveenemy{0%{left:440px;}50%{top:58px;}100%{left:0px;顶部:320x;}}@关键帧跳转{0%{顶部:380px;}30%{top:50px;}50%{top:40px;}100%{top:380px;}}/* 添加天空*/#天空{宽度:500px;高度:340px;背景颜色:天蓝色;位置:绝对;顶部:118px;}/* 添加地面 */#地面{宽度:500px;高度:170px;背景色:素色;位置:绝对;顶部:450px;}</风格><身体><h1>游戏</h1><div id="游戏"><div id=天空"></div><div id="ground"></div><div id=敌人"></div><div id="字符"></div>

<脚本>var character = document.getElementById("character");var敌人 = document.getElementById(敌人");函数跳转(){if(character.classlist!=动画"){character.classList.add(动画");}设置超时(功能(){character.classList.remove(动画");},500);}//向右移动功能右(){var leftVal = parseInt(window.getComputedStyle(character).getPropertyValue("left"))character.style.left = (leftVal + 30) + "px";}//左移函数左(){var leftVal = parseInt(window.getComputedStyle(character).getPropertyValue("left"))character.style.left = (leftVal - 30) + "px";}var checkDead = setInterval(function(){//获取敌人和角色的上、左、下、右位置让敌人Pos =敌人.getBoundingClientRect()//这会给我们敌人的左、右、上、下位置let characterPos = character.getBoundingClientRect()//这将为我们提供字符的左、右、上、下位置//现在让我们看看敌人和角色之间是否有重叠//我们将检查其中一个是否在另一个的左侧.//例如,如果敌人的左侧比角色的右侧大,那么敌人就在角色的右侧if (enemyPos.left >= characterPos.right || characterPos.left >=敌人Pos.right) {//现在我们知道它们不会重叠,因为敌人在角色的右侧,反之亦然,所以什么都不做}//如果我们仍然不知道,我们看看角色是否在敌人上方,反之亦然else if (enemyPos.bottom <= characterPos.top || characterPos.bottom <=enemyPos.top) {//现在我们知道它们不会重叠,因为敌人在角色上方,反之亦然,所以什么都不做}//它们都不完全在左边或完全在另一个之上,所以它们必须在某处重叠 - GOTCHA!别的 {敌人.style.animation =无";//移除动画敌人.style.display =无";警报(游戏结束");clearInterval(checkDead);//我已经添加了这个,但你可能想完全重新开始或者....}},10);//剩下addEventListener("keydown", function(e) {if(e.keyCode == 37) left()})//跳起来)addEventListener("keydown", function(e) {if (e.keyCode === 38) {跳()}})//对addEventListener("keydown", function(e) {if (e.keyCode === 39) {对()}})</html>

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.

I am looking for something that is simple enough to explain to children of age 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.

This is the relevant 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);

And this is the setInterval function with the variables declared (which I use in the if function). 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.

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. So what is happening there?

In an answer, please:

a) Suggest a proposed solution for collision detection based on my existing code

b) Explanation of the GetComputedStyle and getProperties with documentation on it. 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.

c) Best practices for simple collision detection (for absolute beginner's learning concepts and propose the simplest possible solution, given the existing code)

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

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

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

解决方案

Taking the points raised in order:

a) Suggest a proposed solution for collision detection based on my existing code

You cannot use getComputedStyle here (see point b). Below is code using getBoundingClientRect with collision detection (i.e. when the enemy and the character overlap at all)

b) Explanation of the GetComputedStyle and getProperties with documentation on it. 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.

getComputedStyle does just that, it runs through all the style settings and merges them so you get the current style for the element. See for example 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.

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.

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)

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.

<!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>

这篇关于JavaScript 游戏中的 if 语句无法正常工作以允许碰撞检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆