Python009: Python大作业之移动的小火车动画(二)设计思路

书接上文:Python008: Python大作业之移动的小火车动画(一)

1. 设计思路(书接上文)

1 拆分为这个3部分

Class车厢(实例化1个)
Class轨道(实例化1个)
动画部分,按照一定的频率动态刷新即可

2 整体实现的算法概述

  • STEP_1----先完成Class Carriages,在车厢类内部包含绘制车厢的函数–draw_carriages
    绘制车厢的算法

    1. 假设已知车轮的位置 P 1 P_1 P1 P 2 P_2 P2,如何绘制出整个车厢的呢? 车厢必须是可以任意角度倾斜的

    2. 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以方便调用) Python009: Python大作业之移动的小火车动画(二)设计思路_第1张图片

    3. 于是我们可以求出车钩的坐标车框的四个顶点的坐标,如下图2所示: Python009: Python大作业之移动的小火车动画(二)设计思路_第2张图片

    4. 于是利用pygame.draw.circle和pygame.draw.lines即可完成车厢的绘制

    5. 注意: 这里用的是pygame.draw.lines,而不是rect,因为我想画的是可以任意角度倾斜的车厢。由此,我们的整体思路就确定了,只要可以获得4个点,就可以画出2节车厢(这个车厢可以是任意角度倾斜的

    6. 车厢中车钩位置作为函数draw_carriages的返回值,用于后期绘制车钩


  • STEP_2 — 完成轨道类Class Tracks,该类中包含轨道的绘制函数draw_tracks()和获取轨道上的点函数getstartlist()

    绘制轨道的算法

    • (一)绘制轨道的算法—对应的实现是draw_tracks()
      • 第一段直线 l 1 l_1 l1: 起点和终点
      • 第一段圆弧 a 1 a_1 a1:
        1. 由圆弧起点( l 1 l_1 l1末端)算出圆心,结合半径求出圆弧外接的矩形的pos
        2. 由给定的圆弧半径和弧长求出跨越角度
        3. 绘制圆弧,pygame.draw.arc()
      • 第二段直线 l 1 l_1 l1:
        1. 求出第一段圆弧的圆心 O 1 O_1 O1
        2. 求出 O 1 P 1 ⃗ \vec{O_1P_1} O1P1 向量的方向角 θ \theta θ (方向角与画图时的角度是不一样的,关于x轴镜像)( P 1 P_1 P1点是第一段圆弧的末端点)
        3. 求出cur1_end_p点(表示第一段圆弧的末端点)
        4. 偏移90°得到第二段直线的方向角(因为相切的原理)
        5. 有了方向就有了方向余弦 cos ⁡ ( θ ) \cos(\theta) cos(θ)和方向正弦 sin ⁡ ( θ ) \sin(\theta) sin(θ)
        6. 结合 l 2 l_2 l2的长度求出 l 2 l_2 l2的终点
        7. 有了起点和终点,调用pygame.draw.line画线即可
      • 第二段圆弧 a 2 a_2 a2:
        1. 求出 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
        2. 根据 O 2 O_2 O2和半径 r 2 r_2 r2求出外界矩形的pos
          • 插一句: Pygame中的画圆弧的原理是先用pos(形如[x, y, w, h])指定一个正方形,然后根据起始弧度终止弧度绘制出其圆弧切线
        3. 根据第三段直线的水平特性(我默认他是水平的),求出圆弧的起始和终止弧度
        4. 绘制圆弧,pygame.draw.arc()
      • 第三段直线 l 3 l_3 l3:
        1. 结合圆心坐标 O 2 O_2 O2和半径求出 l 3 l_3 l3的起点
        2. 结合 l 3 l_3 l3的长度求出终点
        3. pygame.draw.line绘制直线即可
    • (二)获取轨道上的点的算法—对应的实现是getstartlist()
      1. 对于直线上的点, 根据步长挨个取,然后和直线终点位置的点求距离,大于一定精度时, 取点停止
      2. 圆弧上的点,也是步长,不过此时的步长是角度,每次 Δ = 1 ° \Delta=1° Δ=1°, 同样是利用上文中的向量原理,(因为已知圆心,并且半径,角度已知)求出圆弧上的点 P 1 P_1 P1
      3. 判断的是圆弧末端的点与点 P 1 P_1 P1的距离,用于判断精度,大于一定精度时,取点停止
      4. 至此,我们获得了覆盖在整个轨道上的所有的点(离散的)—我把它叫做点源

  • 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不就好了吗?
    • 问题是怎么求呢?我的方法如下:
      1. 遍历,给个精度,求最优解即可
      2. 先拿到一个点作为 P 1 P_1 P1,然后遍历 P 1 P_1 P1在点源列表中之后的100个点,根据 P 1 P_1 P1 P 2 P_2 P2之间的距离为定长即 (车轮间距), 然后给他们做差
      3. 当差达到我们的精度时,我们将此点作为 P 2 P_2 P2
      4. 同理我们求得 P 3 P_3 P3 P 4 P_4 P4
      5. 这是一个点求其余3点的算法。同样的道理,我们遍历点源中所有的点(其实不是全部),于是获得了n组4个点

至此:准备工作全部就绪


  • STEP_4 — 有了上边的工作铺垫,就可以开始动画的工作了(简述就是一句话)
    • 每隔一段时间,从4个点为一组的点集中拿出一组, 绘制一张带有小火车和轨道的图片,然后渲染到窗口,如此循环即可
    • 注意:时间决定了小车的速度

  • 综上所示即为我整个大作业的实现思路(说高级点就是算法)
  • 我始终认为,算法是最重要的,创新也是最重要的,创新往往隐藏在算法之中,
  • 代码实现不是问题,也即最重要的是思路和算法,只要确定了一条正确的思路,就可以多种语言实现想要的功能
  • 也即代码只是工具,算法才是灵魂
    书接下文:Python010: Python大作业之移动的小火车动画(三)结果显示

你可能感兴趣的:(Python,算法,pygame,游戏开发,python)