21、《每周一点canvas动画》——万有引力

36人阅读 评论(0) 收藏 举报
分类:

每周一点canvas动画代码文件

本章介绍,另一个动画应用——万有引力。听起来似乎有些玄乎,但是多事情千万不要被表面现象所迷惑,理解了原理就很简单!不管是地球上的是物体,还是宇宙中的星辰,物体与物体之间总是存在着一种看不见摸不着的的力场作用,这也就是为什么牛顿会被苹果砸,地球会围绕太阳做运动。

在上一章我们讲解动量守恒,让很多人头疼不已,因为那应该算是这个系列最难的部分了吧。但我心中始终坚信:让自己难受的,就是能让自己成长的,希望你也坚信这一点!下面我们介绍如何把万有引力应用于我们的动画效果中。

1.万有引力

百度百科上这样说:

任意两个质点有通过连心线方向上的力相互吸引。该引力大小与它们质量的乘积成正比与它们距离的平方成反比,与两物体的化学组成和其间介质种类无关

简单来说,就是两个物体,他们之间存在一种引力,满足如下表达式:

force = G * m1 * m2 / distance^2

其中,m1 m2 是物体的质量,distance是物体间的距离,G是引力常数,是个非常小的值6.674*10^-11。在动画中可以忽略这个值。最后,表达式就变为

force = m1 * m2 / distance^2

2.粒子

还是老规矩,先上效果图:

注意效果图中,我们并没有给动画中的粒子设置任何的速度,但是粒子却发生了移动。下面我们来具体分析代码的实现。

   

代码很简单,这里主要讲一下引力函数。在引力函数中,我们传入两个物体作为参数partA, partB。首先,计算两物体间的距离。然后,带入公式中计算引力的大小。

物体间的引力分解到水平和竖直两个方向,作用于物体的加速度,注意这里的分解方式比较隐晦,用的是dx/dist,相当于cos值。最后,将物体的加速度作用于速度。

在移动函数中,我们引入的是多物体碰撞检测策略,保证粒子与粒子之间的相互作用,同时提高了程序的高效性,关于它的具体分析你可以看《每周一点canvas动画》——碰撞检测(2)这里就不多解释了,源代码文件gravity.html

2.加入碰撞检测

注意上面的动画效果,当两个粒子靠的非常近的时候,并没有发生碰撞,如果你想要让两物体间发生碰撞效果,我们只需要在move函数中中加入碰撞检测的代码即可!

function move (partA, i) {
        partA.x += partA.vx;
        partA.y += partA.vy;
    for (var partB, j = i + 1; j < numParticles; j++) {
        partB = particles[j];
        checkCollision(partA, partB); //碰撞检测
        gravitate(partA, partB); //万有引力
    }
}

碰撞检测的代码在《每周一点canvas动画》——桌球运动(2)中有详细的解释,完全一模一样只需要拿过来用就好了,这里我就不做过多解释了,我们直接看效果图, 源代码文件gravity-bounce.html

3.太阳系

既然是万有引力,那怎么少的了经典的太阳系呢!虽然你完全可以不使用万有引力来做物体的轨道运动,只需要使用简单的三角函数就可以让物体做圆形或椭圆环绕。但是,那都不是真的。ok,在这里我们只是简单的让水星,金星,地球围绕太阳的运动,其他的星球你可以自己往上加。

代码与上面加入碰撞效果的代码一样,唯一不同的是我们只引入了4个物体,每一个物体都有不同的质量,和初速度等属性,比如太阳的各项属性如下:

sun.x = canvas.width/2;
sun.y = canvas.height/2;
sun.mass = 10000;
particles.push(sun);

太阳的质量非常大,有10000,看一下地球的属性:

 earth.x = canvas.width/2+300;
 earth.y = canvas.height/2;
 earth.mass = 1;
 earth.vy = 5.8;
 earth.name = "地球";

地球的质量很小,只有1。并且它有一个竖直的速度vy,为的就是让地球在一开始就在竖直方向做运动,这样太阳对地球的引力就会使它偏离原来的运动方向,经过合适的调试,可以得到一个完美的绕太阳做圆周运动的地球。

这里解释两个我认为比较重要的点:

第一个,为什么说要经过调试呢?你可以打开源代码试试改变地球的速度。你会发现减小地球的速度时,地球会被太阳吸引到自己的身上,和地球上的飞机由于速度限制无法逃离地球一个道理。当加大地球的速度,你就会发现太阳的引力不足以把地球拉向自身,就会发生地球逃离太阳吸引的现象。

第二个,为什么太阳没动呢?在我们的代码中,你应该会注意到在将加速度作用于物体的速度上时,我们并不是直接让速度值与加速度相加,而是:

 partA.vx += ax/partA.mass;    //加速度作用于速度
 partA.vy += ay/partA.mass;
 partB.vx -= ax/partB.mass;
 partB.vy -= ay/partB.mass;

让加速度的大小除以物体的质量。所以你会发现,太阳纹丝不动,那是因为它的质量太大,其他星球对它的影响微乎其微,这是不是十分的合乎情理呢?你可以试着让地球的质量也很大,那么你就会发现,太阳也移动了!

具体代码,请查看:orbit.html

4.粒子花园

和上一章《每周一点canvas动画》——桌球运动(2)中结尾处的粒子效果不一样,尝尝万有引力的粒子效果是个什么味道。

由于电脑太实在不行了,可能你看到的效果有些卡,但实际效果更加顺滑。代码没什么难的,我们只是让物体之间的距离如果小于某个值时就连线。

if (dist < minDist) {                   
                context.save();
                context.strokeStyle = "rgba(255,255,255,.3)";
                context.beginPath();
                context.moveTo(ballA.x, ballA.y);
                context.lineTo(ballB.x, ballB.y);
                context.closePath();
                context.stroke();
                context.restore();  
}

具体代码,请看node-garden-line.html

5.总结

本章重要公式:

function gravitate(partA, partB){
     var dx = partB.x - partA.x;
     var dy = partB.y - partA.y;
     var distQ = dx*dx + dy*dy;
     var dist = Math.sqrt(distQ);
     var F = (partA.mass * partB.mass)/distQ;

     var ax = F * dx/dist;
     var ay = F * dy/dist;

     partA.vx += ax/partA.mass;
     partA.vy += ay/partA.mass;
     partB.vx -= ax/partB.mass;
     partB.vy -= ay/partB.mass;
 }

到这里,canvas动画系列的前半部分就介绍完了,如果这些你都掌握了,结合canvas的API, 你完全可以做出很多绚丽的动画效果。下一部分,我们介绍canvas动画的黑科技——3D。不是webGL, 就是在2d的canvas平面实现三维效果,敬请期待!

查看评论

11、《每周一点canvas动画》 —— 弹性动画

本系列文章代码文件 在上一章我们介绍了缓动动画,并且对弹性动画的概念做了简单的介绍。弹性动画(spring)与缓动动画都是基于距离的百分比动画,两者的不同之处在于,一个作用于速度(ease), ...
  • qq_39759115
  • qq_39759115
  • 2018-01-15 17:20:02
  • 100

8、《每周一点canvas动画》——边界检测与摩擦力(2)

到目前为止,我们最常见的两种情形: 物体按照一定的速度做任意运动直到碰上边界 物体自身,或者通过外部的作用力,运用加速度来改变物体的速度 不管怎样,除非我们...
  • qq_39759115
  • qq_39759115
  • 2018-01-03 09:56:51
  • 91

7、《每周一点canvas动画》——边界检测与摩擦力(1)

本章已经是《Canvas 动画系列》动画的第七篇了,我保证这一章不会再有难的数学公式和物理概念。鉴于有的同学并不是从第一章开始看这个系列,我将会把本文所用到的一些 类...
  • qq_39759115
  • qq_39759115
  • 2018-01-02 11:49:18
  • 118

14、《每周一点canvas动画》——碰撞检测(1)

每周一点canvas动画代码文件 在前面的几章中我介绍了一些动画效果,这些动画效果都相对基础。但是通过这些基础的动画形式和概念,你可以设计出更复杂的动画。本章将介绍在动画中相对来说比较难的物理概...
  • qq_39759115
  • qq_39759115
  • 2018-01-15 17:22:53
  • 113

《每周一点canvas动画》——圆周运动

效果源码 终于到年底了,再过两天我也要回家过年了,想想就激动呢!今天给大家带来一个基于移动端的canvas价格选择效果。 主要功能就是拖动标尺变动价格。而且支付宝和京东金融的里也有这样的效果(...
  • qq_39759115
  • qq_39759115
  • 2018-04-17 15:40:18
  • 5

11、《每周一点canvas动画》——缓动动画

本系列文章代码文件 前面的章节我们介绍了许多基本的动画,在本节我们将使用这些基本的动画来创建一些高级动画。今天我们介绍的第一个高级动画叫做缓动动画(ease),也许在写css动画的时候已经接触过...
  • qq_39759115
  • qq_39759115
  • 2018-01-15 17:19:07
  • 49

16、《每周一点canvas动画》——坐标旋转

每周一点canvas动画代码文件 在上一节中我们介绍了一些碰撞检测的方法。这一节本来打算讲解一个基于距离碰撞检测的小游戏。但是,因为最近比较忙,一直没来的及把游戏的整个过程完整的写出来。所以,这...
  • qq_39759115
  • qq_39759115
  • 2018-01-15 17:25:06
  • 49

17、《每周一点canvas动画》——星球守护

代码文件 在介绍完碰撞检测的内容后,总感觉不拿它做点什么事情有点虚啊!本章的内容应该在上周就更新完成,但是由于这几天实在比较忙。一直没空把这个小游戏的过程写出来,就一直拖到了现在。如题,我取了个...
  • qq_39759115
  • qq_39759115
  • 2018-01-15 17:26:22
  • 60

15、《每周一点canvas动画》——碰撞检测(2)

每周一点canvas动画代码文件 如果你的画布上只有两个物体,那么他们之间的碰撞检测很容易就能实现。但是,当物体越来越多,你就需要一些必要的策略去检测物体之间的碰撞,不能漏掉任何的可能性,同时还...
  • qq_39759115
  • qq_39759115
  • 2018-01-15 17:23:57
  • 42
    个人资料
    持之以恒
    等级:
    访问量: 1万+
    积分: 786
    排名: 6万+
    最新评论