簡體   English   中英

實現碰撞檢測以在 javascript“接球”游戲中計分

[英]Implement collision detection for scoring on a javascript "catch" game

我正在使用畫布開發一個非常簡單的 JS 游戲,但我真的很難為得分點實現碰撞檢測。

該游戲是一個接球游戲,因此,每當玩家控制的屏幕底部的方塊擊中一個落球時,得分計數應更新 1。 我在網上尋找了許多不同的方法來做到這一點,但到目前為止還沒有運氣。

該游戲具有三個不同的對象,Ball、Player 和 Score,每個對象都有自己的繪制和更新功能。 我最近一直在嘗試通過將碰撞檢測放入分數的更新函數中來實現碰撞檢測,但無濟於事。

你會怎么做呢?

這是代碼:

 const canvas = document.querySelector('canvas') const c = canvas.getContext('2d') canvas.width = 500 canvas.height = 800 //Variables //keyboard events let leftPressed = false let rightPressed = false //ball let moveSpeed = 5 let balls = [] //player let player let pWidth = 60 let pHeight = 20 let color = 'black' //score let score let x = canvas.width / 1.5 let y = 30 let points = 0 //Event listeners //move document.addEventListener("keydown", keyDownHandler, false); function keyDownHandler(e) { if (e.key == "Right" || e.key == "ArrowRight") { rightPressed = true; } else if (e.key == "Left" || e.key == "ArrowLeft") { leftPressed = true; } } //stop document.addEventListener("keyup", keyUpHandler, false); function keyUpHandler(e) { if (e.key == "Right" || e.key == "ArrowRight") { rightPressed = false; } else if (e.key == "Left" || e.key == "ArrowLeft") { leftPressed = false; } } //Objects function Ball(x, y, dy, radius, color) { this.x = x this.y = y this.dy = dy this.radius = radius this.color = color this.draw = function() { c.beginPath() c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false) c.strokeStyle = 'black' c.stroke() c.fillStyle = this.color c.fill() c.closePath() } this.update = function() { this.y += dy this.draw() } } function Player(x, y, pWidth, pHeight, color) { this.x = x this.y = y this.pWidth = pWidth this.pHeight = pHeight this.color = color this.draw = function() { c.fillStyle = this.color c.fillRect(this.x, this.y, this.pWidth, this.pHeight) } this.update = function() { //move player if (leftPressed && this.x > 0) { this.x -= moveSpeed } else if (rightPressed && this.x < canvas.width - pWidth) { this.x += moveSpeed } this.draw() } } function Score(x, y, points) { this.x = x this.y = y this.points = 0 this.draw = function() { c.font = '30px Helvetica' c.fillStyle = '#000' c.fillText(points, this.x, this.y) } this.update = function() { if (balls.x >= player.x && balls.x + balls.radius <= player.x + player.pWidth) { this.points += 1 } this.draw() } } // Initialize function init() { //Initialize balls for (i = 0; i < 40; i++) { let x = Math.random() * canvas.width let y = Math.random() * canvas.height let dy = 3 let radius = 15 let color = 'purple' balls.push(new Ball(x, y, dy, radius, color)) } //Initialize player player = new Player((canvas.width / 2) - (pWidth / 2), canvas.height - pHeight, pWidth, pHeight, color) //Initialize score score = new Score(x, y, 'Score: ' + points) } // Animate function animate() { requestAnimationFrame(animate) c.clearRect(0, 0, canvas.width, canvas.height) for (i = 0; i < balls.length; i++) { balls[i].update() } player.update() score.update() } init() animate()

您可能希望在可以訪問所有可碰撞對象的主循環中的某個位置進行碰撞檢測。 假設只有球和玩家發生碰撞,那么 in the loop with balls 是一個很好的選擇。 根據您想要的碰撞類型,創建一個接受球對象並將其與玩家進行比較的函數。 最簡單的命中檢測是基於每個對象的大小/半徑的簡單距離,但存在其他更高級的方法。

 // Animate function animate() { requestAnimationFrame(animate); c.clearRect(0, 0, canvas.width, canvas.height); for (i = 0; i < balls.length; i++) { balls[i].update(); if (detectHit(ball[i], player)) { // hit was detected, do stuff } } player.update(); score.update(); } function detectHit(ball, player) { const ballRadius = ball.radius; const ballCenter = {x: ball.x, y: ball.y}; const playerRadius = Math.min(player.pWidth, player.pHeight); const playerCenter = { x: player.x + player.pWidth / 2, y: player.y + player.pHeight / 2 }; // distance = sqr((x1 - x2)^2 + (y1 - y2)^2) const distanceSqrd = (ballCenter.x - playerCenter.x) ** 2 + (ballCenter.y - playerCenter.y) ** 2; const radiusDistanceSqrd = (ballRadius + playerRadius) ** 2; /* Instead of getting the square root, save a complex calculation by comparing the squared distances directly */ return distanceSqrd <= radiusDistanceSqrd; } const balls = [ { x: 10, y: 10, radius: 5 }, { x: 50, y: 10, radius: 5 }, ]; const player = { x: 20, y: 10, pWidth: 15, pHeight: 15, }; balls.forEach(ball => console.log('Hit detected: ', detectHit(ball, player)));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM