当前位置: 首页 > >

「动画中的数学与物理基础」点和直线

发布时间:

开篇




如果你想制作一款酷炫的动画效果或者做一款h5的小游戏,但又不知道如何入手?计算机动画怎么知道一个物体放到何处的?它又是怎么让物体移动的?等等类似的问题,解决这些问题,肯定少不了数学与物理基础知识的应用,从本系列文章起,笔者将介绍一些基础的数学与物理知识,希望对你有所帮助。




本篇文章先从最基础的点和直线开始介绍,主要涉及以下内容:


    坐标系和点

    直线及计算直线的斜率

    检测直线是否相交及计算交点

    在网页上绘制直线和箭头

    文末电子书福利




    本篇文章阅读时间预计8分钟。




    01


    坐标系和点




    让我们先来思考一个问题,计算机是怎么将我们指定的物体放置到对应的位置?一般来说,我们开发人员是通过使用笛卡尔坐标系确定物体的具体位置,笛卡尔坐标系由一个水*轴x和一个垂直轴y组成,每个点都可以写成类似(x,y),其中x和y分别为该点在x轴和y轴上的坐标值。坐标系的原点(0,0)是量轴相交的地方。从原点出发,向右是x轴的正方向,向左是x轴的负方向;同样,y轴的正方向向上,y轴的负方向向下。




    在二维坐标系里表示点




    例1:?现在有个需求在屏幕上放置6个物体A-F,并在笛卡尔坐标系进行表示。


    A(0,0)、B(1,2)、C(4,3)、D(-1,2),E(-2,-1)和 F(3,-2)。





    在三维坐标系里表示点




    所谓的三维坐标,就是在二维的基础上,添加第三个坐标轴??Z轴而已。z轴的具体方向在哪,目前还没有统一的标准。目前有两个标准:左手系统和右手系统。




    伸出你的右手,弯曲你的无名指和小拇指,让大拇指指向右方(X轴的正方向),并且让食指指向上方(Y轴的正方向),那你会发现中指指向屏幕的外部(Z轴的正方向)。如果用左手做同样的事情,让左大拇指指向右方(X轴的正方向),食指向上(Y轴的正方向),那么你的中指指向屏幕的内部(左手系统中Z轴的正方向)。本系列文章会选择y轴向上的右手系统,原因有以下几点:


      它是传统数学中采用的坐标系

      它是大多数开发人员采用的坐标系

      它是OPENGL中采用的坐标系。




      在这种坐标系中,我们可以用(x,y,z)来表示三维空间的任意一个位置。




      例2:?如图所示,给出P点的坐标:



      我们做了黄色的辅助线,可以清楚看出p的坐标,其实p点沿着原点右移了2个单位,然后向上移了4个单位,再沿着z轴移动了5个单位,因此p点的坐标为(2,4,5)




      屏幕中的坐标系




      前面我们讲过,在笛卡尔坐标系中y轴正方向是向上的,然而显示器则是被设置成从上往下读,因此屏幕坐标系使用向下作为y轴的正方向。如下图示意:





      02


      直线及计算直线的斜率


      直线的定义




      我们都知道两点确定一条直线,在数学中我们一般用类似y=2x这样的函数方程表示直线,而方程的全解则是满足该方程的点。




      如何根据一个函数方程画一条直线呢?


        首先对方程进行变换,使方程的一边只有y

        然后选择一个x值,并代入方程式计算出一个y值。(一般选择三个值)




        例3:?画出方程3x-2y=8表示的直线。




        1、首先变换方程将y移动到方程的一边。


        y=(3/2)x-4


        2、在画点时,使用整数坐标比较容易些,因此x取值0,2,4。将这3个值带入方程后,将会得到以下三个点:


        (0,4)、(2,-1)、(4,2)。


        3、在坐标系里画出这3个点,并用线将它们连接起来如图所示:





        斜率




        斜率是直线的一个重要属性,如图所示展示了一个斜面(直线),一个物体以速度50m/s沿垂直方向上升,以速度100m/s沿水*方向运动,该斜面的斜率是通过垂直上升的速度与水*运动的速度比率来确定的,在该图的比率就是50/100,或50%。如果用函数方程表示这条斜线:1/2x-y=c。



        1、两点之间的斜率


        接下来让我们来看坐标系中的P点(x1,y1)和Q点(x2,y2),用m来表示斜率,其对应的计算斜率公式如下:



        斜率=m=△y/△x=(y2-y1)/(x2-x1)




        例4:?计算点(1,5)和(-2,0)之间的斜率。




        斜率=m=△y/△x=(y2-y1)/(x2-x1)=(0-5)/(-2-1)=5/3




        2、计算直线的斜率


        对于标准的直线方程形如Ax+By=C这样的方程,其计算斜率的公式为m=-A/B。




        例5:?计算直线2x+y=5的斜率。


        如果y前没数字,这意味着B=1,如果没有y项,则B=0,带入斜率公式:


        斜率=m=-A/B=-2/1=-2


        除了Ax+By=C这种标准的直线函数方程,我们还会见到如下的表示形式:


        斜截式:y=mx+b


        点斜式:(y-y1)=m(x-x1),其中(x1,y1)是直线上任一点。




        3、关于斜率应用的一些重要特征


          如果斜率为负值,那么直线就沿着左上??右下方向延伸

          如果斜率为正值,那么它就向左下??右上方向延伸

          如果斜率为0,该直线将会是一条水*的直线

          如果斜率公式中,分母为0(y不存在),则是一条垂直线。

          如果两条直线相互垂直,那么m1*m2=-1

          如果两条直线*行,那么他们的斜率是相等的。




          4、有趣的练*


          例6:?假如人物角色在游戏中的位置为(50,200),当玩家在点(150,400)点击了鼠标,这说明它想要到此位置,那么就需要找到一条到达目的直线的路径,请计算出该直线方程。




          解答思路:


          1、首先我们需要通过两点之间的斜率公式,计算出直线斜率:


          斜率=m=(400-200)/(150-50)=200/100=2


          2、然后将其中一点和斜率m带入点斜式方程:


          (y-y1)=m(x-x1)


          (y-200)=2(x-50)


          如果你不*惯点斜式的表述方式,你可以改成斜截式,只需要多几部运算而已:


          y=2x+100


          有了直线方程,现在我们可以让人物角色按照直线路径动起来了。




          例7:?在你的游戏中角色正沿着直线y=(2/3)x+20移动,当它到达位置(30,40)时玩家按了下方向按钮,命令它向左转90。然后继续沿着直线前进,请计算出新的路径直线方程。




          解答思路:


          1、根据斜率的属性我们得知,两条直线垂直,其斜率相乘等于-1,由此我们可以得出另一条直线方程的斜率为-3/2。


          2、然后我们把斜率和点带入点斜式方程中:


          (y-40)=(-2/3)(x-30)


          如果你不*惯点斜式的表述方式,你可以改成斜截式,只需要多几步运算而已:


          y=(-3/2)x+85




          03


          检测直线是否相交及计算交点


          在游戏和动画编程中,我们经常要判断两条直线是否相交,如果相交的话交点在哪里?直线在游戏或动画里可以代表建筑的边界、地面或者物体路径,因此需要思考如何判断两直线是否相交以及直线在哪里。其实计算交点,就相当两个方程组求解,计算出同时满足两个方程中的(x,y)的点而已。




          如果同一*面的两条直线,其解的情况如下:


            如果两条直线的斜率不相等,则仅有一组解

            如果两条直线的斜率及在y轴上的截距分别相等,则有无穷组解

            如果两条直线斜率相等,而在y轴上的截距不相等,则方程组无解

            方程组的求解方法一般分为两种??消元法和带入法




            消元法的步骤:




              选择你要消去的变量(x或y)

              将两个方程分别乘上一个非0值,使你想要消去的变量前系数相同

              用一个方程减去另一个方程,得到联合方程

              求解出方程组第一个变量的值

              将得出的变量带入原始方程,求出另外一个变量的值。




              带入法的步骤:




                从原始方程组中选择一个等式,对其进行变换使一个未知数用另外一个未知数表示出来,即一个未知数位于方程式的一边,而其余的元素全部位于等式另一边。

                将在上步中得到的等式带入原始方程组中的另一个方程中,此时就可以消去一个未知数。

                求解出一个未知数的值

                将上步骤中得到值带入原始方程中,从而求出另外一个未知数的值。




                接下来让我们来看一个例子,加深下对消元法和代入法的理解,示例如下:




                例8:?假如在你的游戏中,一辆汽车沿着直线3x+5y=8的方向行驶,而一堵墙被放置在直线x+3y=4处,如果汽车沿着原来的路线前进,它是否会撞到墙上?如果发生碰撞,那么碰撞点是多少?




                解题思路:


                消元法求解


                1、是否会碰到墙上,我们需要确认两条直线的斜率,第一条直线为 -3/5,第二条直线为 -1/3,因此必相交


                2、利用消元法求解直线方程组


                3x+5y=8


                x+3y=4


                3、选择你将要消去的变量,假如我们在这里要消去x。


                4、我们在第二个方程的两边同时乘以3,从而得到下面方程组:


                3x+5y=8


                3x+9y=12


                5、用上面的方程减去下面的方程,可以得到0x-4y=-4,y=1。


                6、将y值带入任意一个方程,我们带入下面一个方程,得到x=1,因此方程组求解就是(1,1)




                带入法求解:


                1、从x+3y=4这个方程中,我们得出x=4-3y


                2、把x=4-3y,带入3x+5y=8这个方程中,得出-4y=-4,然后得出y=1


                3、然后把y=1,带入任意一方程进行求解,得出x=1,因此方程组求解就是(1,1)




                04


                网页上绘制直线和箭头


                了解了点和直线的基础知识后,我们开始在电脑上进行实践,这里需要用到html5的canvas,通过这个技术我们可以画图以及进行更加灵活的的高级动画设计,甚至可以进行3D绘图,今天我们先利用其实现简单的直线和箭头的绘制。




                关于线条的绘制主要包含以下几个常用方法:


                context.moveTo(x,y):把画笔移动到(x,y)坐标,建立新的子路径。


                context.lineTo(x,y):用于建立上一个点到(x,y)坐标的直线,如果没有上一个点,则等同moveTo(x,y),把(x,y)点添加到子路径中。


                context.stroke():使用lineWidth、lineCap、lineJoin及strokeStyle对所有子路径进行描边。


                context.closePath():如果当前路子路径是打开的,则关闭它。




                给画布绘制一条对角线




                假如我们从画布左上角的点(0,0)画一条对角线,我们需要知道右下角点的坐标,其实右下角的坐标即为画布的(宽,高),因此我们的代码部分如下:



                效果如下图:





                绘制箭头




                如果我们需要绘制一个箭头,如下图所示,我们需要知道其对应关键点的集合,如下图所示,然后不断的使用lineTo方法进行各个关键点的连接:




                文末福利




                如果你热爱WebGL,这本书绝对是一个不错的选择??《


                Real-Time 3D Graphics with WebGL 2 - Second Edition






                作者Farhad Ghayour是一名专业的技术顾问,其公司总部位于加利福尼亚州旧金山。




                目前,他专注于计算机图形学,视觉和机器学*的交叉点的技术解决方案。他热衷于哲学,数学,代码和设计。当他不工作时,赛车和吃中国的火锅则是他最大的爱好。





                精彩推荐



                太惊艳了,这些画都是CSS的杰作!




                css基础丨如何理解transform的matrix()用法



                css基础丨如何理解Display的属性:None,Block,Inline,Inline-Block



                ES6基础丨let和作用域




                ES6基础丨const介绍




                ES6基础丨默认参数值




                ES6基础丨展开语法(Spread syntax)




                ES6基础丨解构赋值(destructuring assignment)




                ES6基础丨箭头函数(Arrow functions)




                ES6基础丨模板字符串(Template String)




                ES6基础丨Set与WeakSet




                ES6基础丨Map与WeakMap




                ES6基础丨Symbol介绍:独一无二的值




                ES6基础丨Object的新方法




                ES6基础丨迭代器(iterator)




                ES6基础丨生成器(Generator)




                数据结构基础丨栈简介(使用ES6)




                数据结构基础丨队列简介(使用ES6)




                JavaScript基础丨前端不懂它,会再多框架也不过只是会用而已!




                JavaScript基础丨你真的了解JavaScript吗?




                JavaScript基础丨回调(callback)是什么?




                JavaScript基础丨Promise使用指南




                JavaScript基础丨深入学*async/await




                JS加载慢?谷歌大神带你飞!(文末送电子书)




                19年你应该关注这50款前端热门工具(上)




                19年你应该关注这50款前端热门工具(中)




                19年你应该关注这50款前端热门工具(下)



                专注分享当下最实用的前端技术。关注前端达人,与达人一起学*进步!


                长按关注"前端达人"



友情链接: