概述
书接上文:Python008: Python大作业之移动的小火车动画(一)
1. 设计思路(书接上文)
1 拆分为这个3部分
Class车厢(实例化1个)
Class轨道(实例化1个)
动画部分,按照一定的频率动态刷新即可
2 整体实现的算法概述
-
STEP_1----先完成Class Carriages,在车厢类内部包含绘制车厢的函数–draw_carriages
绘制车厢的算法-
假设已知车轮的位置 P 1 P_1 P1、 P 2 P_2 P2,如何绘制出整个车厢的呢? 车厢必须是可以任意角度倾斜的
-
由 P 1 P_1 P1、 P 2 P_2 P2点可得一个向量, P 1 P 2 ⃗ vec{P_1P_2} P1P2或 P 2 P 1 ⃗ vec{P_2P_1} P2P1, 其方向相差180°,通过数学简单推导可以得到一个结论:给出任意一个向量,我们都可以求出该向量延长线上的某点的坐标,如下图1所示: (后面这个公式会被大量的调用,因此我将其用代码实现,并封装为一个函数two_get_third以方便调用)
-
于是我们可以求出车钩的坐标和车框的四个顶点的坐标,如下图2所示:
-
于是利用pygame.draw.circle和pygame.draw.lines即可完成车厢的绘制
-
注意: 这里用的是pygame.draw.lines,而不是rect,因为我想画的是可以任意角度倾斜的车厢。由此,我们的整体思路就确定了,只要可以获得4个点,就可以画出2节车厢(这个车厢可以是任意角度倾斜的)
-
车厢中车钩位置作为函数draw_carriages的返回值,用于后期绘制车钩
-
-
STEP_2 — 完成轨道类Class Tracks,该类中包含轨道的绘制函数draw_tracks()和获取轨道上的点函数getstartlist()
绘制轨道的算法
- (一)绘制轨道的算法—对应的实现是draw_tracks()
- 第一段直线 l 1 l_1 l1: 起点和终点
- 第一段圆弧
a
1
a_1
a1:
- 由圆弧起点( l 1 l_1 l1末端)算出圆心,结合半径求出圆弧外接的矩形的pos
- 由给定的圆弧半径和弧长求出跨越角度
- 绘制圆弧,pygame.draw.arc()
- 第二段直线
l
1
l_1
l1:
- 求出第一段圆弧的圆心 O 1 O_1 O1
- 求出 O 1 P 1 ⃗ vec{O_1P_1} O1P1向量的方向角 θ theta θ (方向角与画图时的角度是不一样的,关于x轴镜像)( P 1 P_1 P1点是第一段圆弧的末端点)
- 求出cur1_end_p点(表示第一段圆弧的末端点)
- 偏移90°得到第二段直线的方向角(因为相切的原理)
- 有了方向就有了方向余弦 cos ( θ ) cos(theta) cos(θ)和方向正弦 sin ( θ ) sin(theta) sin(θ)
- 结合 l 2 l_2 l2的长度求出 l 2 l_2 l2的终点
- 有了起点和终点,调用pygame.draw.line画线即可
- 第二段圆弧
a
2
a_2
a2:
- 求出 l 2 l_2 l2末端的点到 a 2 a_2 a2的圆心方向的向量 P 2 O 1 ⃗ vec{P_2O_1} P2O1的方向角,结合半径 r 2 r_2 r2求出圆心坐标 O 2 O_2 O2
- 根据
O
2
O_2
O2和半径
r
2
r_2
r2求出外界矩形的pos
- 插一句: Pygame中的画圆弧的原理是先用pos(形如[x, y, w, h])指定一个正方形,然后根据起始弧度和终止弧度绘制出其圆弧切线
- 根据第三段直线的水平特性(我默认他是水平的),求出圆弧的起始和终止弧度
- 绘制圆弧,pygame.draw.arc()
- 第三段直线
l
3
l_3
l3:
- 结合圆心坐标 O 2 O_2 O2和半径求出 l 3 l_3 l3的起点
- 结合 l 3 l_3 l3的长度求出终点
- pygame.draw.line绘制直线即可
- (二)获取轨道上的点的算法—对应的实现是getstartlist()
- 对于直线上的点, 根据步长挨个取,然后和直线终点位置的点求距离,大于一定精度时, 取点停止
- 圆弧上的点,也是步长,不过此时的步长是角度,每次 Δ = 1 ° Delta=1° Δ=1°, 同样是利用上文中的向量原理,(因为已知圆心,并且半径,角度已知)求出圆弧上的点 P 1 P_1 P1
- 判断的是圆弧末端的点与点 P 1 P_1 P1的距离,用于判断精度,大于一定精度时,取点停止
- 至此,我们获得了覆盖在整个轨道上的所有的点(离散的)—我把它叫做点源
- (一)绘制轨道的算法—对应的实现是draw_tracks()
- STEP_3 — 还记得第一步时,我们可以通过4个点准确画出两节车厢的工作吗?
- 现在我们有了点源,那么,如果我们把点源中的点挨个er作为4个点中的 P 1 P_1 P1,然后通过某种算法求出 P 2 P_2 P2、 P 3 P_3 P3、 P 4 P_4 P4不就好了吗?
- 问题是怎么求呢?我的方法如下:
- 遍历,给个精度,求最优解即可
- 先拿到一个点作为 P 1 P_1 P1,然后遍历 P 1 P_1 P1在点源列表中之后的100个点,根据 P 1 P_1 P1和 P 2 P_2 P2之间的距离为定长即 (车轮间距), 然后给他们做差
- 当差达到我们的精度时,我们将此点作为 P 2 P_2 P2
- 同理我们求得 P 3 P_3 P3、 P 4 P_4 P4
- 这是一个点求其余3点的算法。同样的道理,我们遍历点源中所有的点(其实不是全部),于是获得了n组4个点
至此:准备工作全部就绪
- STEP_4 — 有了上边的工作铺垫,就可以开始动画的工作了(简述就是一句话)
- 每隔一段时间,从4个点为一组的点集中拿出一组, 绘制一张带有小火车和轨道的图片,然后渲染到窗口,如此循环即可
- 注意:时间决定了小车的速度
- 综上所示即为我整个大作业的实现思路(说高级点就是算法)
- 我始终认为,算法是最重要的,创新也是最重要的,创新往往隐藏在算法之中,
- 代码实现不是问题,也即最重要的是思路和算法,只要确定了一条正确的思路,就可以多种语言实现想要的功能
- 也即代码只是工具,算法才是灵魂
书接下文:Python010: Python大作业之移动的小火车动画(三)结果显示
最后
以上就是虚心荷花为你收集整理的Python009: Python大作业之移动的小火车动画(二)设计思路的全部内容,希望文章能够帮你解决Python009: Python大作业之移动的小火车动画(二)设计思路所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复