Python每日一练:通过Pygame制作小球追踪鼠标

思路

   一、通过Pygame模块绘制小球、获取鼠标焦点,设置起点为小球坐标,终点为鼠标焦点位置。

   二、通过math不断分解速度V,得到横向瞬时速度Vx,纵向瞬时速度Vy。

    1、全局速度:V = 800;

    2、小球坐标为:(c_x, c_y);

    3、鼠标焦点坐标为:(pos_x, pos_y);

    由三角函数可知:Vx = V*Sinθ;

            Vy = V*Cosθ;

    由欧氏距离公式可知:d = sqrt((x2-x1)^2+(y2-y1)^2)可得:

       小球到焦点的距离(也就是斜边)为:d = sqrt((pos_x-c_x)^2+( pos_y-c_y)^2)

    所以可求出:V*Sinθ = V*(pos_x-c_x)/d→Vx

          V*Cosθ =  V*(pos_y-c_y)/d→Vy

    最后只需要在x轴与y轴分别加上此数值,便可让小球按预定的轨迹动起来。

代码

  一、模块

    使用的模块有:

      Pygame:用于实现动画效果

      Math:用于计算上文中的计算公式

      random:用于小球随机位置生成

      sys:用于退出程序

import pygame
import math
import sys
import random

  二、初始化pygame

pygame.init()

  三、设置窗口大小为800*800

screen = pygame.display.set_mode((800, 800))

  四、设置帧率为60

clock = pygame.time.Clock()
clock.tick(60)

  五、背景设置为黑色

screen.fill((0, 0, 0))
screen.fill(color='black')

  六、构造小球类(用于生成多个小球)

    1、小球具有的属性包括:速度speed、半径r、起点x坐标pos_x、起点y坐标pos_y

class A:
    def __init__(self, speed, r, pos_x, pos_y):
        self.speed = speed
        self.r = r
        self.pos_x = pos_x
        self.pos_y = pos_y

  七、构造方法:绘制小球

    1、需要的参数有:screen绘制的窗口,color小球的颜色

    def circle(self, screen, color):
        pygame.draw.circle(screen, color, [self.pos_x, self.pos_y], self.r)

  八、构造方法:向目标移动

    1、根据上文给出的思路计算横向速度与纵向速度,分别加到小球的x坐标与y坐标上

    2、需要的的参数:target_x目标x轴坐标,target_y目标y轴坐标

    def track(self, target_x, target_y):
        m_ab = math.sqrt(math.pow(target_x - self.pos_x, 2)+math.pow(target_y - self.pos_y, 2))
        sina = (target_x - self.pos_x)/m_ab
        cosa = (target_y - self.pos_y)/m_ab
        self.pos_x += self.speed/60 * sina
        self.pos_y += self.speed/60 * cosa

  九、构造方法:绘制指向线段,使活动更明显

    1、需要的参数:screen绘制的窗口,target_x目标x轴坐标,target_y目标y轴坐标

    def line(self, screen, target_x, target_y):
        pygame.draw.line(screen, (255, 255, 255), (self.pos_x, self.pos_y), (target_x, target_y), 1)

  十、构造主函数main()

    1、其中for循环的作用是生成6个速度随机、半径随机、初始位置随机的小球,并将其通过面向对象的方式装在列表ab中

    2、其次for迭代器是为了检测程序是否退出,用来关闭窗口

    3、主迭代器是遍历ab列表中的小球实例,通过构造的各类方法从而实现目标

def main():
    pygame.init()
    screen = pygame.display.set_mode((800, 800))
    clock = pygame.time.Clock()
    ab = []
    for i in range(6):
        x = random.randint(100, 700)
        y = random.randint(100, 700)
        n_r = random.randint(3, 17)
        n_speed = random.randint(60, 300)
        ab.append(A(n_speed, n_r, x, y))
    while 1:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
        clock.tick(60)
        target_x, target_y = pygame.mouse.get_pos()
        screen.fill((0, 0, 0))
        for a in ab:
            a.track(target_x, target_y)
            a.circle(screen, (255, 255, 255))
            a.line(screen, target_x, target_y)
        pygame.display.flip()

  十一、运行程序

    1、如何简单理解:if __name__ == '__main__',我看到过的最简单的一个说法是,只有当你在当前py程序中运行时,他才会发生作用,当你从其他程序引入时则不会产生效果。

if __name__ == '__main__':
    main()

全部代码

import pygame
import math
import sys
import random


class A:
    def __init__(self, speed, r, pos_x, pos_y):
        self.speed = speed
        self.r = r
        self.pos_x = pos_x
        self.pos_y = pos_y

    def circle(self, screen, color):
        pygame.draw.circle(screen, color, [self.pos_x, self.pos_y], self.r)

    def track(self, target_x, target_y):
        m_ab = math.sqrt(math.pow(target_x - self.pos_x, 2)+math.pow(target_y - self.pos_y, 2))
        sina = (target_x - self.pos_x)/m_ab
        cosa = (target_y - self.pos_y)/m_ab
        self.pos_x += self.speed/60 * sina
        self.pos_y += self.speed/60 * cosa

    def line(self, screen, target_x, target_y):
        pygame.draw.line(screen, (255, 255, 255), (self.pos_x, self.pos_y), (target_x, target_y), 1)


def main():
    pygame.init()
    screen = pygame.display.set_mode((800, 800))
    clock = pygame.time.Clock()
    ab = []
    for i in range(6):
        x = random.randint(100, 700)
        y = random.randint(100, 700)
        n_r = random.randint(3, 17)
        n_speed = random.randint(60, 300)
        ab.append(A(n_speed, n_r, x, y))
    while 1:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
        clock.tick(60)
        target_x, target_y = pygame.mouse.get_pos()
        screen.fill((0, 0, 0))
        for a in ab:
            a.track(target_x, target_y)
            a.circle(screen, (255, 255, 255))
            a.line(screen, target_x, target_y)
        pygame.display.flip()


if __name__ == '__main__':
    main()

最后

  一个小白的理解与描述,致力于让另一个小白也看得懂,就酱。

  程序虽然不是完美与标准的,但能跑得起来<手动狗头>

posted @ 2022-01-30 23:45  梦月剑心  阅读(432)  评论(0编辑  收藏  举报