簡體   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