有一个球以自由落体的速度落下。我不能写出让球碰到表面并反弹的逻辑。我希望物理更接近真实。
请帮我解决这个问题。提前感谢您)
下面是代码;)
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>
发布于 2020-12-30 15:20:38
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>
发布于 2020-12-30 17:46:05
这是我前段时间设置的一个小型物理模拟器的碰撞检测代码。
你的世界似乎是由一个圆圈或球体和一个平面组成的,除了墙壁和天花板之外,我还有许多粒子。我的所有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);}
}update-loop完全是微不足道的,绘制、移动和碰撞每个帧。
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);
}
)
}你可以看到,我从来没有花时间去实现我所有的想法。我甚至从来没有接触过这里输入的平面,而是在我走的过程中创建了一个边界框。
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('.');
}
}
);
}
);
}发布于 2021-01-04 16:17:20
以下是我的解决方案
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>
https://stackoverflow.com/questions/65494070
复制相似问题