繁体   English   中英

如何运行单个对象JavaScript的多个实例

[英]How to run multiple instances of a single object JavaScript

当前正在尝试对圆的弹性碰撞进行物理模拟。 我遇到了一个问题,即我不知道如何在两个圈子同时交互的情况下运行模拟。 我还没有希望在圈子之间建立互动,只是让它们同时运行。 任何帮助深表感谢。 这是我的第一篇文章,因此如果格式化不正确,我深表歉意。

 var width = 400; var height = 400; var canvas = ctx = false; var frameRate = 1 / 60; // Seconds var frameDelay = frameRate * 1000; // ms var loopTimer = false; var ball = { position: { x: width / 2, y: height / 2 }, velocity: { x: 0, y: 0 }, radius: 15, // 1px = 1cm restitution: -1 }; var mouse = { x: 0, y: 0, isDown: false }; function getMousePosition(event) { mouse.x = event.pageX - canvas.offsetLeft; mouse.y = event.pageY - canvas.offsetTop; } var mouseDown = function(event) { if (event.which == 1) { getMousePosition(event); mouse.isDown = true; ball.position.x = mouse.x; ball.position.y = mouse.y; } } var mouseUp = function(event) { if (event.which == 1) { mouse.isDown = false; ball.velocity.y = (ball.position.y - mouse.y) / 10; ball.velocity.x = (ball.position.x - mouse.x) / 10; } } var setup = function() { canvas = document.getElementById("canvas"); ctx = canvas.getContext("2d"); canvas.onmousemove = getMousePosition; canvas.onmousedown = mouseDown; canvas.onmouseup = mouseUp; ctx.fillStyle = 'blue'; ctx.strokeStyle = '#000000'; loopTimer = setInterval(loop, frameDelay); } var loop = function() { if (!mouse.isDown) { ball.position.x += ball.velocity.x * frameRate * 100; ball.position.y += ball.velocity.y * frameRate * 100; } if (ball.position.y > height - ball.radius) { ball.velocity.y *= ball.restitution; ball.position.y = height - ball.radius; } if (ball.position.x > width - ball.radius) { ball.velocity.x *= ball.restitution; ball.position.x = width - ball.radius; } if (ball.position.x < ball.radius) { ball.velocity.x *= ball.restitution; ball.position.x = ball.radius; } if (ball.position.y < ball.radius) { ball.velocity.y *= ball.restitution; ball.position.y = ball.radius; } ctx.clearRect(0, 0, width, height); ctx.save(); ctx.translate(ball.position.x, ball.position.y); ctx.beginPath(); ctx.arc(0, 0, ball.radius, 0, Math.PI * 2, true); ctx.fill(); ctx.closePath(); ctx.restore(); if (mouse.isDown) { ctx.beginPath(); ctx.moveTo(ball.position.x, ball.position.y); ctx.lineTo(mouse.x, mouse.y); ctx.stroke(); ctx.closePath(); } } setup(); 
 #canvas { border: solid 1px #ccc; } 
 <canvas id="canvas"></canvas> 

这是我的方法:

我没有使球成为一种静态对象,而是构造了一个构造函数( 更多有关此内容 )。

然后,我制作了一个球阵列来存储所有球。

为了使拖动成为可能,我将一个单独的球存储在newBall变量中,该球不会被“物理”移动。 该球不可见,或者是当前正在拖动的球。

mouseDown()newBall位于光标下方。 mouseUp()它获取速度并添加到动画balls数组中。 还创建了一个新的newBall

loop()我两次遍历动画balls数组。 一次是物理学,一次是绘画。 (通常,您会使用带有不同tickRates的两种不同方法来使动画更加平滑,因为物理计算不需要每秒进行60次。

 var width = 400; var height = 400; var canvas = ctx = false; var frameRate = 1 / 60; // Seconds var frameDelay = frameRate * 1000; // ms var loopTimer = false; function ball() { this.position = { x: width / 2, y: height / 2 }; this.velocity = { x: 0, y: 0 }; this.radius = 15; // 1px = 1cm this.restitution = -1 }; var balls = []; var newBall = new ball(); var mouse = { x: 0, y: 0, isDown: false }; function getMousePosition(event) { mouse.x = event.pageX - canvas.offsetLeft; mouse.y = event.pageY - canvas.offsetTop; } var mouseDown = function(event) { if (event.which == 1) { getMousePosition(event); mouse.isDown = true; newBall.position.x = mouse.x; newBall.position.y = mouse.y; } } var mouseUp = function(event) { if (event.which == 1) { mouse.isDown = false; newBall.velocity.y = (newBall.position.y - mouse.y) / 10; newBall.velocity.x = (newBall.position.x - mouse.x) / 10; balls.push(newBall); newBall = new ball(); } } var setup = function() { canvas = document.getElementById("canvas"); ctx = canvas.getContext("2d"); canvas.onmousemove = getMousePosition; canvas.onmousedown = mouseDown; canvas.onmouseup = mouseUp; ctx.fillStyle = 'blue'; ctx.strokeStyle = '#000000'; loopTimer = setInterval(loop, frameDelay); } var loop = function() { for (var ball of balls) { ball.position.x += ball.velocity.x * frameRate * 100; ball.position.y += ball.velocity.y * frameRate * 100; if (ball.position.y > height - ball.radius) { ball.velocity.y *= ball.restitution; ball.position.y = height - ball.radius; } if (ball.position.x > width - ball.radius) { ball.velocity.x *= ball.restitution; ball.position.x = width - ball.radius; } if (ball.position.x < ball.radius) { ball.velocity.x *= ball.restitution; ball.position.x = ball.radius; } if (ball.position.y < ball.radius) { ball.velocity.y *= ball.restitution; ball.position.y = ball.radius; } } ctx.clearRect(0, 0, width, height); for (var ball of balls) { ctx.save(); ctx.translate(ball.position.x, ball.position.y); ctx.beginPath(); ctx.arc(0, 0, ball.radius, 0, Math.PI * 2, true); ctx.fill(); ctx.closePath(); ctx.restore(); } ctx.save(); ctx.translate(newBall.position.x, newBall.position.y); ctx.beginPath(); ctx.arc(0, 0, newBall.radius, 0, Math.PI * 2, true); ctx.fill(); ctx.closePath(); ctx.restore(); if (mouse.isDown) { ctx.beginPath(); ctx.moveTo(newBall.position.x, newBall.position.y); ctx.lineTo(mouse.x, mouse.y); ctx.stroke(); ctx.closePath(); } } setup(); 
 #canvas { border: solid 1px #ccc; } 
 <canvas id="canvas"></canvas> 

现在变得更加复杂:

我添加了tickDelaytickTimer以在tickTimer中使用它们

ball构造器现在有两种方法:

show()在画布上绘制球

tick()进行物理处理( dt = deltaTime:自上次滴答以来的时间)

如果未按下鼠标,则newBall现在为null

setup()根据<canvas>元素的实际大小初始化widthheight

tick()在球中循环并调用.tick() tickDelay以毫秒为单位,因此除以1000

drawFrame()是您以前的loop()并完成绘图工作

 var width = 400; var height = 400; var canvas = ctx = false; var frameRate = 1 / 60; // Seconds var frameDelay = frameRate * 1000; // ms var tickDelay = frameDelay * 2; //ticks 2 times slower than frames var frameTimer; var tickTimer; function ball() { this.position = { x: width / 2, y: height / 2 }; this.velocity = { x: 0, y: 0 }; this.radius = 15; // 1px = 1cm this.restitution = -.99; this.show = function() { ctx.save(); ctx.translate(this.position.x, this.position.y); ctx.beginPath(); ctx.arc(0, 0, this.radius, 0, Math.PI * 2, true); ctx.fill(); ctx.closePath(); ctx.restore(); }; this.tick = function(dt) { this.position.x += this.velocity.x * dt; this.position.y += this.velocity.y * dt; if (this.position.y > height - this.radius) { this.velocity.y *= this.restitution; this.position.y = height - this.radius; } if (this.position.x > width - this.radius) { this.velocity.x *= this.restitution; this.position.x = width - this.radius; } if (this.position.x < this.radius) { this.velocity.x *= this.restitution; this.position.x = this.radius; } if (this.position.y < this.radius) { this.velocity.y *= this.restitution; this.position.y = this.radius; } } }; var balls = []; var newBall; var mouse = { x: 0, y: 0, isDown: false }; function getMousePosition(event) { mouse.x = event.pageX - canvas.offsetLeft; mouse.y = event.pageY - canvas.offsetTop; } function mouseDown(event) { if (event.which == 1) { getMousePosition(event); mouse.isDown = true; if (!newBall) newBall = new ball(); newBall.position.x = mouse.x; newBall.position.y = mouse.y; } } function mouseUp(event) { if (event.which == 1) { mouse.isDown = false; newBall.velocity.y = (newBall.position.y - mouse.y); newBall.velocity.x = (newBall.position.x - mouse.x); balls.push(newBall); newBall = null; } } function setup() { canvas = document.getElementById("canvas"); width = canvas.getBoundingClientRect().width; height = canvas.getBoundingClientRect().height; ctx = canvas.getContext("2d"); canvas.onmousemove = getMousePosition; canvas.onmousedown = mouseDown; canvas.onmouseup = mouseUp; ctx.fillStyle = 'blue'; ctx.strokeStyle = '#000000'; requestAnimationFrame(drawFrame); frameTimer = setInterval(drawFrame, frameDelay); tickTimer = setInterval(tick, tickDelay); } function tick() { for (var ball of balls) ball.tick(tickDelay * .001); } function drawFrame() { ctx.clearRect(0, 0, width, height); for (var ball of balls) ball.show(); if (newBall) newBall.show(ctx); if (mouse.isDown && newBall) { ctx.beginPath(); ctx.moveTo(newBall.position.x, newBall.position.y); ctx.lineTo(mouse.x, mouse.y); ctx.stroke(); ctx.closePath(); } } setup(); 
 #canvas { border: solid 1px #ccc; } 
 <canvas id="canvas"></canvas> 

一种非常简单的方法可以做与现在完全相同的操作,但是不能将所有函数都初始化为变量。 将所有作为函数的变量更改为仅函数,以及在何处调用它们。 至少变量称为ball。 然后,您可以像这样创建两个变量

ball1 = new ball();
ball2 = new ball();

您的脚本有点混乱,因此我很难说这是否可以顺利进行,但是如果可以,我非常乐意提供帮助。 如果仅按照我现在介绍的方式进行操作,这不是最好的解决方案,因此请不要将其用作解决方案,而应将其作为入门的一种方法。 如果我们给您答案,您也不会真正学到任何东西

编辑:

值得一提的是,由于JavaScript是单线程的,因此将setInterval用于游戏和图形项目可能不是一个好主意。 更好的解决方案是使用requestAnimationFrame()

看起来像这样

function mainLoop() {
update();
draw();
requestAnimationFrame(mainLoop);
}

// Start things off
requestAnimationFrame(mainLoop);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM