如何检查鼠标是否触摸了随机生成的Javascript对象?

问题描述 投票:0回答:1

我正在尝试创建一个游戏,其中对象(当前是圆形)在画布内随机生成,并且对象及其位置(以及其他信息)存储在数组中。

这些对象是随机生成的,我想要的是每当鼠标触摸它们时它们就会消失。目前,我通过在触发 onmousemove 时将对象的直径设置为 0 来实现此目的,但这不起作用;它只是偶尔移除物体。

任何人都可以为我指出如何实现这一点的正确方向吗?这是我的第一个 javascript 项目,我是一个刚刚学习的初学者。 :)

我得到的最好结果是尝试 1(靠近 startanimate 函数的底部),但它只是偶尔删除鼠标触摸的对象。

尝试 2 对我来说根本不起作用。我收到箭头函数定义错误的错误,并且圆圈根本不生成。

这是我的Javascript代码:

// get a refrence to the canvas and its context
var canvas = document.getElementById("canvas");
canvas.height = (window.innerHeight)*0.7;
canvas.width = (window.innerWidth)*0.7;
var ctx = canvas.getContext("2d");

// newly spawned objects start at Y=25
var spawnLineY = 25;

// spawn a new object every 500ms
var spawnRate = 100;

// when was the last object spawned
var lastSpawn = -1;

// this array holds all spawned object
var objects = [];

// save the starting time (used to calc elapsed time)
var startTime = Date.now();

var objcount = -1;

var mouseX = 0;

var mouseY = 0;

/* Attempt 2 which gives errors
function trackMouse (event) {
    //mouseX = event.clientX;
    //mouseY = event.clientY;
    objects.forEach ((object, i) => {
        if ((Math.abs(object.x - event.clientX) <= object.diameter/2) && (Math.abs(object.y - event.clientY) <= object.diameter/2)) {
            setTimeout (() => { objects.splice (i, 1) }, 0)
        }

    })
} */
    

// start animating
//animate();


function spawnRandomObject() {

    // select a random type for this new object
    var t;

    // About Math.random()
    // Math.random() generates a semi-random number between 0-1. 
    var temp = Math.random()
    if (temp < 0.25) {
        t = "green";
    } 
    else if (temp >= 0.25 && temp < 0.5) {
        t = "blue";
    }
    else if (temp >= 0.5 && temp < 0.75) {
        t = "purple";
    }
    else {
        t = "pink";
    }

    // create the new object
    var object = {
        // set this objects type
        type: t,
        // set spawn randomly on the canvas edge
        x: Math.random(),
        // set y to start on the line where objects are spawned
        y: Math.random(),

        xspeed: Math.random()*3.5 + 0.5,
        yspeed: Math.random()*3.5 +0.5,

        diameter: Math.ceil (Math.random()*29+1),
    }
    
    // set spawn coordinates so they spawn at the edges using previous x to randomly choose where along edges they spawn
    // 4 situtations
    if (object.x < 0.50){
        if (object.y < 0.5){
            object.x = -5; // along left edge and already moving to the right
        }
        else {
            object.x = canvas.width + 5; // along right edge
            object.xspeed = object.xspeed*-1; // should move towards left
        }
        object.y = Math.random() * (canvas.width - 300) + 15;
    }
    else {
        if (object.y >= 0.5){
            object.y = -5; // along top edge and already moving down
        }
        else {
            object.y = canvas.height + 5; // along bottom edge
            object.yspeed = object.yspeed*-1; // should move down
        }
        object.x = Math.random() * (canvas.width - 300) + 15;
    }

    // add the new object to the objects[] array
    objects.push(object);
}


function startanimate() {

    // get the elapsed time
    var time = Date.now();

    // see if its time to spawn a new object
    if (time > (lastSpawn + spawnRate)) {
        lastSpawn = time;
        spawnRandomObject();
        // spawnRate*=.95; to increase speed
    }

    // request another animation frame
    requestAnimationFrame(startanimate);

    // clear the canvas so all objects can be redrawn in new positions
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    /* draw the line where new objects are spawned
    ctx.beginPath();
    ctx.moveTo(0, spawnLineY); // starting position of line
    ctx.lineTo(canvas.width, spawnLineY); // ending position of line
    ctx.stroke();
    didnt need a line*/

    // move each object down the canvas
    for (var i = 0; i < objects.length; i++) {
        var object = objects[i];

        object.y += object.yspeed;
        object.x += object.xspeed;
        
        ctx.beginPath();
        ctx.arc(object.x, object.y, object.diameter, 0, Math.PI * 2);
        ctx.closePath();
        ctx.fillStyle = object.type;
        ctx.fill(); // need to fill to see the object

        /* ATTEMPT 1 but doesn't work properly, I believe because the forloop takes too long it get an accurate position
        if ((Math.abs(object.x - mouseX) <= object.diameter/2) && (Math.abs(object.y - mouseY) <= object.diameter/2)){
            console.log ("HELLO");
            object.diameter = 0;
        */
        }
    }

}

这是我在 HTML 中的内容:

<html>
  <head>
    <meta charset="UTF-8"> <! --- To establish proper website layout and properties--->
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- href is case sensitive -->
    <link rel="stylesheet" href="../CSS/fishgame.css">
  </head>

  
  <body>
    <canvas id="canvas" width="1000px" height="500px" onmousemove="trackMouse(event)"></canvas>

    <!-- must load javascript only after the html so animation can occur in the canvas-->
    <script src="../javascript/fishgame.js" onload="startanimate()"></script>
  </body>
</html>
javascript canvas javascript-objects mouseover mousemove
1个回答
0
投票

存在以下问题:

  • event.clientX
    event.clientY
    给出相对于 viewport 的坐标,而不是相对于画布的坐标。因此,您应该从这些坐标中减去画布元素的偏移量。

  • 您将

    diameter
    传递给
    arc
    函数,但该方法需要 radius,而不是 diameter。因此,你的圆圈是你预期的两倍大,因此“碰撞”检查是错误的。

  • 在绘制对象之前

    diameter 属性设置为 0 更有意义。

为了修复您的代码,我保留了名称

diameter

,但在 
radius 的意义上使用了它(您应该更改名称)。我混合使用了这两种方法,因为您肯定需要保持鼠标坐标更新,因此应该启用 trackMouse
。不过,碰撞检查不一定要在该函数中进行。在 
startanimate
 函数中做到这一点就足够了。

这是您的代码,仅包含这些更正。我删除了您的评论并将评论放在我编辑的位置,以便您可以看到更改的内容:

var canvas = document.getElementById("canvas"); canvas.height = (window.innerHeight)*0.7; canvas.width = (window.innerWidth)*0.7; var ctx = canvas.getContext("2d"); var spawnLineY = 25; var spawnRate = 100; var lastSpawn = -1; var objects = []; var startTime = Date.now(); var objcount = -1; var mouseX = 0; var mouseY = 0; // Enable this function: function trackMouse(event) { // Need to subtract the coordinates of the canvas mouseX = event.clientX - canvas.offsetLeft; mouseY = event.clientY - canvas.offsetTop; // No need to perform the "collision" check here: see startanimate function } function spawnRandomObject() { var t; var temp = Math.random() if (temp < 0.25) { t = "green"; } else if (temp >= 0.25 && temp < 0.5) { t = "blue"; } else if (temp >= 0.5 && temp < 0.75) { t = "purple"; } else { t = "pink"; } var object = { type: t, x: Math.random(), y: Math.random(), xspeed: Math.random()*3.5 + 0.5, yspeed: Math.random()*3.5 +0.5, diameter: Math.ceil (Math.random()*29+1), } if (object.x < 0.50){ if (object.y < 0.5){ object.x = -5; } else { object.x = canvas.width + 5; object.xspeed = object.xspeed*-1; } object.y = Math.random() * (canvas.width - 300) + 15; } else { if (object.y >= 0.5){ object.y = -5; } else { object.y = canvas.height + 5; object.yspeed = object.yspeed*-1; } object.x = Math.random() * (canvas.width - 300) + 15; } objects.push(object); } function startanimate() { var time = Date.now(); if (time > (lastSpawn + spawnRate)) { lastSpawn = time; spawnRandomObject(); } requestAnimationFrame(startanimate); ctx.clearRect(0, 0, canvas.width, canvas.height); for (var i = 0; i < objects.length; i++) { var object = objects[i]; // This should happen before the move. Don't divide by 2, as "diameter" is actually the radius if ((Math.abs(object.x - mouseX) <= object.diameter) && (Math.abs(object.y - mouseY) <= object.diameter)){ object.diameter = 0; } object.y += object.yspeed; object.x += object.xspeed; ctx.beginPath(); ctx.arc(object.x, object.y, object.diameter, 0, Math.PI * 2); ctx.closePath(); ctx.fillStyle = object.type; ctx.fill(); } } startanimate();
<canvas id="canvas" width="1000px" height="500px" onmousemove="trackMouse(event)"></canvas>

© www.soinside.com 2019 - 2024. All rights reserved.