我正在尝试创建一个游戏,其中对象(当前是圆形)在画布内随机生成,并且对象及其位置(以及其他信息)存储在数组中。
这些对象是随机生成的,我想要的是每当鼠标触摸它们时它们就会消失。目前,我通过在触发 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>
存在以下问题:
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>