首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >球从地板上弹起来

球从地板上弹起来
EN

Stack Overflow用户
提问于 2020-12-29 22:51:30
回答 3查看 98关注 0票数 0

有一个球以自由落体的速度落下。我不能写出让球碰到表面并反弹的逻辑。我希望物理更接近真实。

请帮我解决这个问题。提前感谢您)

下面是代码;)

代码语言:javascript
复制
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();
}
代码语言:javascript
复制
canvas {
  width: 100%;
  height: 80vh;
  background: gray
}
代码语言:javascript
复制
<!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>

EN

回答 3

Stack Overflow用户

发布于 2020-12-30 15:20:38

代码语言:javascript
复制
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;
};
代码语言:javascript
复制
html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
}
代码语言:javascript
复制
<script src="https://cdn.jsdelivr.net/npm/janvas/dist/janvas.min.js"></script>
<p></p>
<div id="app" style="width: 100%;height: 100%;"></div>

票数 0
EN

Stack Overflow用户

发布于 2020-12-30 17:46:05

这是我前段时间设置的一个小型物理模拟器的碰撞检测代码。

你的世界似乎是由一个圆圈或球体和一个平面组成的,除了墙壁和天花板之外,我还有许多粒子。我的所有4个平面都是轴对齐的,并且存在于距原点0.75个单位处。

每个粒子都包含一些关于它们自身的信息,就像我用于边界框的平面一样。

代码语言:javascript
复制
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完全是微不足道的,绘制、移动和碰撞每个帧。

代码语言:javascript
复制
function update2()
{
    drawParts(partArray);
    move(partArray, 1/60);
    handleCollisions2(partArray);
    requestAnimationFrame(update2);
}

我想你会发现所有有趣的东西都存在于代码中,既可以移动粒子,也可以碰撞粒子。

代码语言:javascript
复制
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);
        }
    )
}

你可以看到,我从来没有花时间去实现我所有的想法。我甚至从来没有接触过这里输入的平面,而是在我走的过程中创建了一个边界框。

代码语言:javascript
复制
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('.');   
                    }
                }
            );
        }
    );
}
票数 0
EN

Stack Overflow用户

发布于 2021-01-04 16:17:20

以下是我的解决方案

代码语言:javascript
复制
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();
}
代码语言:javascript
复制
canvas {
  width: 100%;
  height: 80vh;
  background: gray
}
代码语言:javascript
复制
<!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>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65494070

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档