• 实现小球随机碰撞,最好分析


    其实用flash actionscript实现地更快更好...

    这个程序很锻炼新手能力哦~

    面向对象的分析与设计:
    1.把小球看成是一个对象,且自身就是一个线程,能控制自身的运动。

    设计具有以下属性和(行为)方法,
    属性:
      x:横坐标
      y:纵坐标
      speed:小球运动的直线速度
      alpha:小球运动的方向。记为小球运动方向和12点钟的顺时针的夹角
       

    方法:
      move():根据小球当前的属性值来运动
      run():控制小球运动的线程

    2.运动的分析:
    设在某一时刻t0,小球处于屏幕中任意一点,即其位置为x和y,如果小球是

    水平或垂直运动的话,那么在下一时刻t1,只需将小球的横或纵坐标加或减

    一个值,并将这个加后或减后的值重新作为小球的x,y就能实现小球位置的

    变化,只要t1-t0足够小,运动就能产生。
    但这里有两个问题:
    a:小球的坐标要加或减的值是多少?
    这个值是t1-t0的一段时间,小球移动的一段距离,这个距离值实际上就是

    小球的速度值,即speed,单位是pixel/(1/36)s,叫做"像素每36分之一秒"

    ,为什么是36分之一秒内移动speed个像素?因为这样一来,1秒钟就能显

    示36幅小球在不同位置的画面,根据电影原理,人眼在每秒看到36幅画面

    时,感觉最为流畅。

    b.假设小球不是水平或垂直运动,而是向任意方向运动的话,这个距离如何

    计算?
    在面板中的坐标系,横轴是向右,纵轴是向下,原点在面板的左上角。这一

    点跟我们在中学数学中学习到的坐标系不同。在图中我以小球为中心原点,

    建立的这个坐标系,主要为了便于分析小球的运动过程,方便推理和计算。
    另外,面板中只能进行横向运动和纵向运动,要产生斜向运动,必须将横向

    运动和纵向运动进行合成。


    在t1-t0的时间段内,小球向右上角运动一个speed的距离,这个运动过程

    无法直接在程序中表达,只能由横向运动和纵向运动合成而来。根据我们定

    义的小球的运动方向的概念,分别得到横向运动距离dx和纵向运动距离dy.

    在这个时间段内,只需要将小球的横坐标x加上这个dx,纵坐标减去这个dy,

    得到的新的坐标点,就是小球应该到达的位置。
    注意这个时候alpha的值处于第一象限,根据正弦函数和余弦函数的图像可

    知,此时sina和cosa的值都为正数,即:
    x+=dx;
    y-=dy
    之后,小球的位置正好处于原来位置的右上角,到达了既定位置.

    在第二象限内,根据正弦函数和余弦函数的图像,这次sina的值依然是正

    数,cosa的值却是一个负数,在:
    x+=dx;
    y-=dy
    之后,小球也还是能正确运动到达正确位置。

    按照此种方式继续分析第三象限和第四象限的情况可知,方程组:
    x+=speed*sina;
    y-=speed*cosa;
    是小球运动的一般规律,而水平和垂直方向的运动,也是这个方程组描述的

    一种特殊情况.

    3.边界碰撞检测:
    根据光的反射定律,光的入射角等于反射角。在这里,将小球看成是一个光

    子,四周的边界看成是绝对光滑的镜面,那么小球对边界的碰撞也遵从反射

    定律。
    看图:


    如果碰撞上边框,小球反射前的运动方向alpha在碰撞到边框的一瞬间,立即变成反射后的运动方向,才能让小球正确呈现反弹效果。即让反弹后的运动方向值,替代反射前的运动方向值,如果运动分析没有错,那么,小球的碰撞和反弹也会按照预期正确出现。画出法线,经过简单的几何证明:

    反射后的方向=180-反射前的方向,即对应的代码应该为:
    alpha=180-alpha;(简单的不可思议!)

    如果按照相反的方向入射和反射,或者碰撞到下边框,依然遵从该方程!你可以自己试着推理证明。

    这次是碰撞左边框,经过一番简单的证明,得到结论是:
    反射后的角度=360-反射前的角度,即对应的代码应该为:
    alpha=360-alpha;(同样简单的不可思议!)

    你也可以画图证明碰撞右边框的情形,也同样遵照上述方程。

    如果边框宽600pix,高400pix,小球宽高都为20pix的话,核心代码为:

    Java code

    publicvoid move(){ x+=speed*Math.sin(alpha*Math.PI/180); y-=speed*Math.cos(alpha*Math.PI/180);if(x<0||x>580)alpha=360-alpha;if(y<0||y>480)alpha=180-alpha; setLocation(x,y); }


    在线程体中使用死循环反复调用move()方法,线程的休眠间隔是(1000/36)毫秒,不要约分,否则就失去了这个数值所表达的意义了。




  • 相关阅读:
    【水】希望之花
    如何不用狄利克雷卷积证明莫比乌斯函数性质二
    【数学】gcd
    挂分宝典
    [luogu P6042]「ACOI2020」学园祭 题解
    [luogu P6041]「ACOI2020」布丁暗杀计划 题解
    11.19模拟
    「CSP-S2020」题解
    11.11模拟
    「洛谷P1445」樱花
  • 原文地址:https://www.cnblogs.com/xieyuan/p/3787450.html
Copyright © 2020-2023  润新知