[英]ball bouncing off the floor
有一個球以自由落體的速度下落。 我無法編寫使球撞擊表面並反彈的邏輯。 我希望物理接近真實
請幫助解決問題。 先感謝您)
下面是代碼;)
window.onload = () => { const out = document.getElementById('out') const ctx = document.getElementById('canvas').getContext('2d'); let metr = 0.1; let seconds = 1000; let speed = 9.8; const vector = { x: 0, y: 1} const position = {x: 300, y: 0} function draw(timeDelta) { ctx.clearRect(0, 0, 600, 600) const dX = (vector.x * (metr * (timeDelta / seconds) * speed) || 0) const dY = (vector.y * (metr * (timeDelta / seconds) * speed) || 0) position.x += dX position.y += dY out.innerText = `${position.x}, ${position.y}, ${dX}, ${dY}` ctx.beginPath(); ctx.arc(position.x, position.y, 5, 0, Math.PI * 2, true); ctx.fill(); ctx.lineWidth = 10; ctx.moveTo(0, 550); ctx.lineTo(600, 550); ctx.stroke(); window.requestAnimationFrame(draw) } draw(); }
canvas { width: 100%; height: 80vh; background: gray }
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>JS Bin</title> </head> <body> <div id="out">Out</div> <canvas id="canvas" width="600" height="600"></canvas> </body> </html>
var dropBall = new janvas.Canvas({ container: "#app", interval: 16, // animation loop interval props: { background: void (0), ball: void (0) // target object }, methods: { init: function () { this.background = new janvas.Rect(this.$ctx, 0, 0); // init background this.background.getStyle().setFillStyle("white").setLineWidth(10); // set style this.ball = new janvas.Arc(this.$ctx, 0, 50, 50); // init target ball this.ball.vy = 0; // velocity y this.ball.g = 1; // acceleration this.$raf.start(); // start the default animation with requestAnimationFrame }, update: function () { this.ball.vy += this.ball.g; // every loop velocity += acceleration this.ball.setStartY(this.ball.getStartY() + this.ball.vy); // set ball position if (this.ball.getStartY() + this.ball.getRadius() > this.$height) { this.ball.setStartY(this.$height - this.ball.getRadius()); this.ball.vy *= -1; // if ball touch the bottom, inverse velocity y } this.onPositionChange(this.ball.getStartX(), this.ball.getStartY()); // position callback }, draw: function () { this.background.fillStroke(); // draw the background and stroke this.ball.fill(); // draw the ball } }, events: { resize: function () { // change some props on resize this.ball.setStartX(this.$width / 2); this.background.setWidth(this.$width).setHeight(this.$height); }, onPositionChange: janvas.Utils.noop } }); var p = document.querySelector("p"); dropBall.onPositionChange = function (x, y) { p.innerHTML = x + "," + y; };
html, body { margin: 0; padding: 0; width: 100%; height: 100%; }
<script src="https://cdn.jsdelivr.net/npm/janvas/dist/janvas.min.js"></script> <p></p> <div id="app" style="width: 100%;height: 100%;"></div>
這是我不久前設置的一個小型物理模擬的碰撞檢測代碼。
在你的世界似乎由一個圓圈或球體和一個平面組成的地方,除了牆壁和天花板之外,我還有許多粒子。 我的所有 4 個平面都是軸對齊的,並且距離原點 0.75 個單位。
每個粒子都包含一些關於它們自己的信息,我用於邊界框的平面也是如此。
class particle
{
constructor( pos=new vec2d(0,0), vel=new vec2d(0), restCoef=1 )
{
this.mPos = vec2d.clone(pos);
this.mVel = vec2d.clone(vel);
this.mCoefRest = restCoef;
}
get pos(){return this.mPos}
set pos(newPos){this.mPos.setTo(newPos)}
get vel(){return this.mVel}
set pos(newVel){this.mVel.setTo(newVel)}
get restCoef(){return this.mCoefRest;}
set restCoef(newCoef){this.mCoefRest = newCoef;}
};
class plane
{
constructor(normalX, normalY, distToOrigin)
{
this.mNormal = new vec2d(normalX,normalY);
this.mDist = distToOrigin;
}
get dist(){return this.mDist;}
set dist(newDist){this.mDist = newDist;}
get normal(){return this.mNormal;}
set normal(newNormal){this.mNormal.setTo(newNormal);}
}
更新循環完全是微不足道的,繪制移動和碰撞每一幀。
function update2()
{
drawParts(partArray);
move(partArray, 1/60);
handleCollisions2(partArray);
requestAnimationFrame(update2);
}
我想你會發現所有有趣的東西都存在於代碼中,用於移動和碰撞粒子。
function move(parts, timeStep) // array, seconds
{
parts.forEach(
function(part)
{
var grav = new vec2d(0,-9.8);
grav.timesEquals(1/60); // should be timeStep, not 1/60 (I had timeStep = 1/60)
part.vel.plusEquals(grav);
var dist = part.vel.clone();
dist.timesEquals(timeStep);
part.pos.plusEquals(dist);
part.vel.timesEquals(0.99);
}
)
}
你可以看到我從來沒有時間去實現我所有的想法。 我什至從不觸摸這里輸入的平面,而是像我一樣組成一個邊界框 go..
function handleCollisions2(parts, planes)
{
var planeArray=[];
planeArray.push( new plane(1, 0, 0.75) );
planeArray.push( new plane(0, -1, 0.75) );
planeArray.push( new plane(-1, 0, 0.75) );
planeArray.push( new plane(0, 1, 0.75) );
partArray.forEach(
function(part,idx)
{
planeArray.forEach(
function(plane)
{
var N = plane.normal;
var dist = part.pos.dotProd(plane.normal) + plane.dist;
var dp = part.vel.dotProd(N);
if (dist<0 && dp < 0) // wrong side of plane and penetrating further (not moving away)
{
// collision response, reflect particle
var nDotV = vec2d.clone(plane.normal);
//nDotV.timesEquals(2);
nDotV.timesEquals(1+part.restCoef);
nDotV.timesEquals(dp);
part.vel.minusEquals(nDotV);
var tmpN = plane.normal.clone();
part.pos.minusEquals( tmpN.timesEquals(dist) );
//V[i] -= 2*N*N•V[i];
//console.log('.');
}
}
);
}
);
}
這是我的解決方案
window.onload = () => { const out = document.getElementById('out') const ctx = document.getElementById('canvas').getContext('2d'); var dpi = (document.getElementById('dpi').offsetWidth * 2.54) const m = 1 / dpi; const w = 600, h = 600, r = 5; const box = [10, 10, h - 10, w - 10] const g = 9.8 * m; const speed = { x: -1350 * m, y: -560 * m } const friction = 0.95 const position = {x: (box[2] - box[0]) / 2, y: (box[2] - box[0]) / 2 } let i = 0; function draw(timeDelta) { ctx.clearRect(0, 0, 600, 600) ctx.strokeStyle = "black"; speed.y += (g * m * timeDelta) || 0 // speed.x += (m * timeDelta) || 0 position.y = Math.max(box[1] + r, Math.min(box[3] - r, position.y + speed.y)); position.x = Math.max(box[0] + r, Math.min(box[2] - r, position.x + speed.x)); if (position.y + r >= box[3] || position.y - r <= box[1]) { speed.y = -(speed.y * friction) speed.x = speed.x * friction } if (position.x + r >= box[2] || position.x - r <= box[0]) { out.innerText = ++i speed.y = speed.y * friction speed.x = -(speed.x * friction) } //out.innerText = `${Math.round(position.y)}, ${Math.round(position.x)}, ${Math.round(speed.y * 1000) / 1000}, ${Math.round(speed.x * 1000) / 1000}` ctx.beginPath(); ctx.arc(position.x, position.y, r, 0, Math.PI * 2, true); ctx.fill(); ctx.lineWidth = 1; ctx.moveTo(box[0], box[1]); ctx.lineTo(box[2], box[1]); ctx.lineTo(box[2], box[3]); ctx.lineTo(box[0], box[3]); ctx.lineTo(box[0], box[1]); ctx.strokeStyle = "white"; ctx.stroke(); window.requestAnimationFrame(draw) } draw(); }
canvas { width: 100%; height: 80vh; background: gray }
<:DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>JS Bin</title> </head> <body> <div id="out">Out</div> <div id="dpi" style="height; 1in: width; 1in: left; 100%: position; fixed: top; 100%:pointer-events:none"></div> <canvas id="canvas" width="600" height="600"></canvas> </body> </html>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.