获取本游戏代码
如果需要本游戏的代码,请扫描关注我的公众号,回复“台球源码”即可。
游戏运行示例
基础物理知识
- 摩擦力
f = m * af
摩擦力产生的加速度af
使得台球的速度减小,最终减小为0。 - 动能守恒公式
1/2 * m1 * v1^2 + 1/2 * m2 * v2^2 = 1/2 * m1 * v1’^2 + 1/2 * m2 * v2’^2
- 动量守恒公式
m1 * v1 + m2 * v2 = m1 * v1’ + m2 * v2’
构建物理模型
桌台及小球
如下图,把桌台抽象成一个二维坐标系,每个台球的中心抽象为坐标(x,y)。
横向为向右延伸的x轴,
纵向为向下延伸的y轴。
对应到代码中,就是元素的margin-left
与 margin-right
值。
摩擦力
在小球的运动过程中,始终在其相反方向上施加一个摩擦力的加速度af。
小球间的碰撞检测
对于两个小球,判断是否碰撞的公式为:(x1 - x2) ^ 2 + (y1 - y2) ^ 2 <= (2*r) ^ 2
小球间的碰撞反应
首先,小球碰撞抽象为物理模型中的完全弹性碰撞,且小球的质量相等。即碰撞瞬间,二者遵循动能守恒与动量守恒。
选取两球圆心的直线为切向, 垂直于圆心直线的为法向。
于是我们可以得出结论:
(一)在切向, 两球交换速度, 而在法向, 两球分速度不变。
由此,我们拓展到当V1不为0,V2为0时,此时就相当于一个白球去撞一个静止不动的其他球。于是我们可以得出结论:
(二)在切向, 球1切向速度不变, 而在法向, 球1的法向速度给了球2。
【注】通常我们把游戏设置为1秒60帧,当小球的速度过大时,在前一帧两个小球还没相撞,但在下一帧两个球就直接重叠了。这对我们利用圆心构建法向和切向会产生很大误差。此时我们可以在小球即将重叠的前一帧,控制小球按照原有方向无限逼近,最终达到碰撞但不重叠的状态。
小球与边界的碰撞
当小球碰撞到边界时,直接把小球垂直于边界方向的速度取负数即可。
检测落袋
如上图边框的标红部分。我们在检测边界碰撞时,如果小球进入这些标红边界,那么小球不发生反弹。
之后,我们记录下6个球袋的坐标,利用球袋坐标与小球坐标之间的距离来判断小球是否落袋。公式:
(x袋 - x) ^ 2 + (y袋 - y) ^ 2 <= d ^ 2
电脑玩家的基本思路
- 首先明确电脑打的球是什么类别。例如:实心球,花球。此处假设电脑打的是实心球。
- 电脑遍历白球与每个还没入袋的实心球之间是否有其他球挡着。这关系到白球是否能击打这个
- 对于每个能击打的球,电脑再计算每个球打哪个袋子为最优选项。
- 现在有了白球,要击打的球,目标袋。电脑计算角度,开始击球!球进了!
电脑判断击目标球路径上是否有阻碍
如图,判断击目标球路径上是否有阻碍,我们需要计算,“可能会阻碍的球”与白球击球路径的距离是否小于球的半径r。这里用到点与直线的距离公式。
我们已知三个球的球心坐标,先算出“白球”与“目标球”的斜率K
,然后代入“白球”的坐标得到直线方程L
,最后利用点到直线的距离公式算出“可能会阻碍的球”与直线L的距离D
。如果D小于球的半径r,说明击球过程会被阻碍。
电脑计算击球角度
如图,我们在小球的碰撞反应中,得出过结论二:
当球1初速度不为0,球2初速度为0:
(二)在切向, 球1切向速度不变, 而在法向, 球1的法向速度给了球2。
根据此结论,我们不难发现,“白球”在击完“目标球”后,它的切向速度会给“目标球”,而此时切向应当是与“目标球”和“目标袋”的连线重合。若要使“目标球”入袋,我们只要反过来推导。
首先算出“目标球”与“目标袋”的斜率K;
沿着斜率K的方向,在“目标球”的球心位置,向反方向计算出一个球的直径长度的坐标(P1,P2);
使“白球”击打坐标(P1,P2),即可把“目标球”击入袋中!
进行下一个游戏的开发!
注意事项
【1】 原创博客,转载本篇请与我联系,尊重版权。
【2】 关于阅读本篇博客的所有问题、代码源码、图片素材、编程技巧、编程经历都可联系我或者关注公众号"三黄工作室",交流讨论。
【3】 本人部分时间承接各种毕业作业、网站编写、微信小程序编写。需要请加QQ:1460787433。