Я делаю простую игру, используя HTML5 canvas и простой JavaScript. Совсем недавно я пытался добавить функцию для стрельбы пулями, которая затем разрушала бы препятствия, но я столкнулся с проблемой. Всякий раз, когда вы стреляете в пулю, она не двигается, пока не выстрелит другая. Даже когда он начинает двигаться и сталкивается с одним из препятствий, ничего не происходит. Я сделал некоторые проблемы, и я не могу понять, что до конца. Любая помощь и / или предложения будут с благодарностью.

Код обработки столкновений:

for(var i = 0; i {amp}lt; this.bullets.length - 1; i  ) { // -1 is present because whenever I remove it I get an error. I have a feeling this may be related to the order of how everything updates, will be fixed this.bullets[i].x  = this.bullets[i].speed; if(this.bullets[i].x {amp}gt; cvs.width) { this.bullets.splice(i, 1); } for(var j = 0; j {amp}lt; obstacles.length - 1; j  ) { // Same here if(rectanglesColliding(this.bullets[i], obstacles[j])) { console.log("Collision"); } } } 

Полный объект игрока:

 var player = { score: 0, x: 50, y: 150, radius: 10, jumping: false, bullets: [], velocityX: 0, velocityY: 1, angle: 90, update: function() { this.draw(); this.score  ; if(this.y   this.radius   2 {amp}gt; cvs.height - 50 {amp}amp;{amp}amp; this.jumping === false || this.y - this.radius   2 {amp}lt; 0   50 {amp}amp;{amp}amp; this.jumping === true) { this.velocityY = 0; } else if(this.jumping === false){ this.velocityY = 4; } else { this.velocityY = -4; } obstacles.forEach((obstacle) ={amp}gt; { if(colliding(this, obstacle)) { gameEnded = true; } }); this.x  = this.velocityX; this.y  = this.velocityY; for(var i = 0; i {amp}lt; this.bullets.length - 1; i  ) { // -1 is present because whenever I remove it I get an error. I have a feeling this may be related to the order of how everything updates, will be fixed this.bullets[i].x  = this.bullets[i].speed; if(this.bullets[i].x {amp}gt; cvs.width) { this.bullets.splice(i, 1); } for(var j = 0; j {amp}lt; obstacles.length - 1; j  ) { // Same here if(rectanglesColliding(this.bullets[i], obstacles[j])) { console.log("Collision"); } } } }, draw: function() { this.bullets.forEach((bullet) ={amp}gt; { ctx.fillStyle = 'green'; ctx.fillRect(bullet.x, bullet.y, 7, 2); }); ctx.fillStyle = 'blue'; ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); ctx.fill(); } }; 

Функция обнаружения столкновения:

 function rectanglesColliding(rect1, rect2) { if(rect1.x {amp}lt; rect2.x   rect2.width {amp}amp;{amp}amp; rect1.x   rect1.width {amp}gt; rect2.x {amp}amp;{amp}amp; // Found on Mozilla.com: https://developer.mozilla.org/en-US/docs/Games/Techniques/2D_collision_detection rect1.y {amp}lt; rect2.y   rect2.height {amp}amp;{amp}amp; rect1.y   rect1.height {amp}gt; rect2.y) return true; else return false; } 

Функция съемки:

 function shoot() { player.bullets.push({ x: player.x   10, y: player.y, speed: 6 }); } 

Цель игры: выжить как можно дольше, избегая препятствий.

Управление: Space: Go up W: Shoot Bullet

Полный фрагмент кода:

 var cvs = document.getElementById('canvas'); var ctx = cvs.getContext("2d"); var gameEnded = false; var player = { score: 0, x: 50, y: 150, radius: 10, jumping: false, bullets: [], velocityX: 0, velocityY: 1, angle: 90, update: function() { this.draw(); this.score  ; if(this.y   this.radius   2 {amp}gt; cvs.height - 50 {amp}amp;{amp}amp; this.jumping === false || this.y - this.radius   2 {amp}lt; 0   50 {amp}amp;{amp}amp; this.jumping === true) { this.velocityY = 0; } else if(this.jumping === false){ this.velocityY = 4; } else { this.velocityY = -4; } obstacles.forEach((obstacle) ={amp}gt; { if(colliding(this, obstacle)) { gameEnded = true; } }); this.x  = this.velocityX; this.y  = this.velocityY; for(var i = 0; i {amp}lt; this.bullets.length - 1; i  ) { this.bullets[i].x  = this.bullets[i].speed; if(this.bullets[i].x {amp}gt; cvs.width) { this.bullets.splice(i, 1); } for(var j = 0; j {amp}lt; obstacles.length - 1; j  ) { if(rectanglesColliding(this.bullets[i], obstacles[j])) { console.log("Collision"); // obstacles.splice(i, 1); } } } }, draw: function() { this.bullets.forEach((bullet) ={amp}gt; { ctx.fillStyle = 'green'; ctx.fillRect(bullet.x, bullet.y, 7, 2); }); ctx.fillStyle = 'blue'; ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); ctx.fill(); } }; var obstacles = [{ x: 150, y: 60, width: 10, height: 20 }]; document.addEventListener('keydown', (event) ={amp}gt; { if(event.key === ' ') { player.jumping = true; } if(event.key === 'w') { shoot(); } }); document.addEventListener('keyup', (event) ={amp}gt; { if(event.key === ' ') { player.jumping = false; } }); function randomIntFromRange(min, max) { return Math.floor(Math.random() * (max - min   1)   min); } function getWidth() { return Math.max( document.body.scrollWidth, document.documentElement.scrollWidth, document.body.offsetWidth, document.documentElement.offsetWidth, document.documentElement.clientWidth ); } function getHeight() { return Math.max( document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.documentElement.clientHeight ); } function colliding(circle, rect) { var distX = Math.abs(circle.x - rect.x - rect.width / 2); var distY = Math.abs(circle.y - rect.y - rect.height / 2); if(distX {amp}gt; (rect.width / 2   circle.radius)) return false; if(distY {amp}gt; (rect.height / 2   circle.radius)) return false; if(distX {amp}lt;= (rect.width / 2)) return true; if(distY {amp}lt;= (rect.height / 2)) return true; } function rectanglesColliding(rect1, rect2) { if(rect1.x {amp}lt; rect2.x   rect2.width {amp}amp;{amp}amp; rect1.x   rect1.width {amp}gt; rect2.x {amp}amp;{amp}amp; rect1.y {amp}lt; rect2.y   rect2.height {amp}amp;{amp}amp; rect1.y   rect1.height {amp}gt; rect2.y) { return true; } } function distance(x1, y1, x2, y2) { const xDist = x2 - x1; const yDist = y2 - y1; return Math.sqrt(Math.pow(xDist, 2)   Math.pow(yDist, 2)); } function shoot() { player.bullets.push({ x: player.x   10, y: player.y, speed: 6 }); } function generateObstacle() { var obstacle = { x: obstacles[0].x   randomIntFromRange(cvs.width - 100, cvs.width   70), y: 0   randomIntFromRange(20, 550), width: randomIntFromRange(25, 35), height: randomIntFromRange(10, 25) }; for(var i = 0; i {amp}lt; obstacles.length; i  ) { if(distance(obstacle.x, obstacle.y, obstacles[i].x, obstacles[i].y) {amp}lt; 65) { obstacle = { x: obstacles[0].x   randomIntFromRange(cvs.width - 100, cvs.width   70), y: 0   randomIntFromRange(20, 550), width: randomIntFromRange(25, 35), height: randomIntFromRange(10, 25) }; i = -1; } } obstacles.push({ x: obstacle.x, y: obstacle.y, width: obstacle.width, height: obstacle.height }); } function removeBadObstacles() { for(var i = 0; i {amp}lt; obstacles.length; i  ) { if(obstacles[i].x {amp}lt; 0) { obstacles.splice(i, 1); } } } function updateObstacles() { if(obstacles[obstacles.length - 1].x {amp}lt; cvs.width   5) { generateObstacle(); generateObstacle(); } obstacles.forEach((obstacle) ={amp}gt; { obstacle.x -= 10; ctx.fillStyle = 'red'; ctx.fillRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height); }); } function init() { cvs.width = getWidth(); cvs.height = getHeight(); update(); } function update() { if(gameEnded) { ctx.font = '50px Verdana'; return ctx.fillText('Game Over', 110, cvs.height / 2); } requestAnimationFrame(update); removeBadObstacles(); ctx.fillStyle = 'black'; ctx.fillRect(0, 0, cvs.width, cvs.height); updateObstacles(); player.update(); ctx.font = '30px Impact'; ctx.fillText("Score: "   player.score, 20, 40); } init(); 
 {amp}lt;!DOCTYPE html{amp}gt; {amp}lt;html{amp}gt; {amp}lt;head{amp}gt; {amp}lt;title{amp}gt;Game{amp}lt;/title{amp}gt; {amp}lt;/head{amp}gt; {amp}lt;body{amp}gt; {amp}lt;canvas id="canvas"{amp}gt;{amp}lt;/canvas{amp}gt; {amp}lt;script type="text/javascript" src="./JS/main.js"{amp}gt;{amp}lt;/script{amp}gt; {amp}lt;/body{amp}gt; {amp}lt;/html{amp}gt; 

  • при итерации по массиву последний элемент имеет length-1 (что означает, что вы должны использовать {amp}lt; length , а не {amp}lt; length-1 )
  • удаляемый код должен представлять собой obstacles.splice(j, 1); ( i индекс для пули)
  • Вы не назначаете размер пули (и вы также можете использовать этот размер при рисовании)
 var cvs = document.getElementById('canvas'); var ctx = cvs.getContext("2d"); var gameEnded = false; var player = { score: 0, x: 50, y: 150, radius: 10, jumping: false, bullets: [], velocityX: 0, velocityY: 1, angle: 90, update: function() { this.draw(); this.score  ; if(this.y   this.radius   2 {amp}gt; cvs.height - 50 {amp}amp;{amp}amp; this.jumping === false || this.y - this.radius   2 {amp}lt; 0   50 {amp}amp;{amp}amp; this.jumping === true) { this.velocityY = 0; } else if(this.jumping === false){ this.velocityY = 4; } else { this.velocityY = -4; } obstacles.forEach((obstacle) ={amp}gt; { if(colliding(this, obstacle)) { gameEnded = true; } }); this.x  = this.velocityX; this.y  = this.velocityY; for(var i = 0; i {amp}lt; this.bullets.length; i  ) {//{amp}lt;============== this.bullets[i].x  = this.bullets[i].speed; if(this.bullets[i].x {amp}gt; cvs.width) { this.bullets.splice(i, 1); } for(var j = 0; j {amp}lt; obstacles.length; j  ) {//{amp}lt;============== if(rectanglesColliding(this.bullets[i], obstacles[j])) { console.log("Collision"); obstacles.splice(j, 1);//{amp}lt;============== } } } }, draw: function() { this.bullets.forEach((bullet) ={amp}gt; { ctx.fillStyle = 'green'; ctx.fillRect(bullet.x, bullet.y, 7, 2); }); ctx.fillStyle = 'blue'; ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); ctx.fill(); } }; var obstacles = [{ x: 150, y: 60, width: 10, height: 20 }]; document.addEventListener('keydown', (event) ={amp}gt; { if(event.key === ' ') { player.jumping = true; } if(event.key === 'w') { shoot(); } }); document.addEventListener('keyup', (event) ={amp}gt; { if(event.key === ' ') { player.jumping = false; } }); function randomIntFromRange(min, max) { return Math.floor(Math.random() * (max - min   1)   min); } function getWidth() { return Math.max( document.body.scrollWidth, document.documentElement.scrollWidth, document.body.offsetWidth, document.documentElement.offsetWidth, document.documentElement.clientWidth ); } function getHeight() { return Math.max( document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.documentElement.clientHeight ); } function colliding(circle, rect) { var distX = Math.abs(circle.x - rect.x - rect.width / 2); var distY = Math.abs(circle.y - rect.y - rect.height / 2); if(distX {amp}gt; (rect.width / 2   circle.radius)) return false; if(distY {amp}gt; (rect.height / 2   circle.radius)) return false; if(distX {amp}lt;= (rect.width / 2)) return true; if(distY {amp}lt;= (rect.height / 2)) return true; } function rectanglesColliding(rect1, rect2) { if(rect1.x {amp}lt; rect2.x   rect2.width {amp}amp;{amp}amp; rect1.x   rect1.width {amp}gt; rect2.x {amp}amp;{amp}amp; rect1.y {amp}lt; rect2.y   rect2.height {amp}amp;{amp}amp; rect1.y   rect1.height {amp}gt; rect2.y) { return true; } } function distance(x1, y1, x2, y2) { const xDist = x2 - x1; const yDist = y2 - y1; return Math.sqrt(Math.pow(xDist, 2)   Math.pow(yDist, 2)); } function shoot() { player.bullets.push({ x: player.x   10, y: player.y, speed: 6, width: 7, height: 6 }); //{amp}lt;==================== } function generateObstacle() { var obstacle = { x: obstacles[0].x   randomIntFromRange(cvs.width - 100, cvs.width   70), y: 0   randomIntFromRange(20, 550), width: randomIntFromRange(25, 35), height: randomIntFromRange(10, 25) }; for(var i = 0; i {amp}lt; obstacles.length; i  ) { if(distance(obstacle.x, obstacle.y, obstacles[i].x, obstacles[i].y) {amp}lt; 65) { obstacle = { x: obstacles[0].x   randomIntFromRange(cvs.width - 100, cvs.width   70), y: 0   randomIntFromRange(20, 550), width: randomIntFromRange(25, 35), height: randomIntFromRange(10, 25) }; i = -1; } } obstacles.push({ x: obstacle.x, y: obstacle.y, width: obstacle.width, height: obstacle.height }); } function removeBadObstacles() { for(var i = 0; i {amp}lt; obstacles.length; i  ) { if(obstacles[i].x {amp}lt; 0) { obstacles.splice(i, 1); } } } function updateObstacles() { if(obstacles[obstacles.length - 1].x {amp}lt; cvs.width   5) { generateObstacle(); generateObstacle(); } obstacles.forEach((obstacle) ={amp}gt; { obstacle.x -= 10; ctx.fillStyle = 'red'; ctx.fillRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height); }); } function init() { cvs.width = getWidth(); cvs.height = getHeight(); update(); } function update() { if(gameEnded) { ctx.font = '50px Verdana'; return ctx.fillText('Game Over', 110, cvs.height / 2); } requestAnimationFrame(update); removeBadObstacles(); ctx.fillStyle = 'black'; ctx.fillRect(0, 0, cvs.width, cvs.height); updateObstacles(); player.update(); ctx.font = '30px Impact'; ctx.fillText("Score: "   player.score, 20, 40); } init(); 
 {amp}lt;!DOCTYPE html{amp}gt; {amp}lt;html{amp}gt; {amp}lt;head{amp}gt; {amp}lt;title{amp}gt;Game{amp}lt;/title{amp}gt; {amp}lt;/head{amp}gt; {amp}lt;body{amp}gt; {amp}lt;canvas id="canvas"{amp}gt;{amp}lt;/canvas{amp}gt; {amp}lt;script type="text/javascript" src="./JS/main.js"{amp}gt;{amp}lt;/script{amp}gt; {amp}lt;/body{amp}gt; {amp}lt;/html{amp}gt;