用Pygame库怎么实现时钟,详细的步骤过程是什么
Admin 2022-06-18 群英技术资讯 315 次浏览
用pygame做一个时钟,供大家参考,具体内容如下
刚刚学习pygame,由于基础实在太差,每个例子都要反复写逐句研究才能基本弄懂,这次做一个简单的有时针、分针、秒针,能正确行走的表。。。例子不难,但是还是能掌握一些基本的知识点,比如xy坐标的计算,画圆,文字处理等。小白如我可以借鉴下,我认为学习还是以逻辑为主,所以我尽量还原初学时候的逻辑步骤,开整!
这次我们用到的主要是pygame,math,datetime几个库,datetime.today()可以获取当前时间,math.sin()和math.cos()用于计算表针的坐标。用到的方法主要是pygame.draw.circle()画圆,和pygame.draw.line()画线
先把pygame初始化,再弄个窗口出来,准备工作做好
import math, pygame from pygame.locals import * from datetime import datetime, date, time pygame.init() screen = pygame.display.set_mode((600, 600)) pygame.display.set_caption("Clock")
然后画个圆当表盘,这样就需要确定位置和半径
pos_x = 300 pos_y = 300 radius = 250
考虑到区分三个表针的颜色,先设置好四种颜色
white = 255, 255, 255 red = 240, 0, 0 green = 0, 240, 0 blue = 0, 0, 240
计算表针的坐标,需要用到角度,所以先把角度设好
hour_angle = 0 minute_angle = 0 second_angle = 0
写数字需要用到文字处理,把文字样式设置一下
font = pygame.font.Font(None, 24)
最后还要写两个方法一个是输出文字的,一个是规范角度的。这俩以后都经常用
# abs()是取绝对值,%运算符号很有意思,效果是360取余数,保证了角度在360以内 def wrap_angle(angle): return abs(angle % 360) # 把打印文字的步骤封装在一个方法里,每次方便调用,简化代码 def print_text(font, x, y, text, color): imgText = font.render(text, True, color) screen.blit(imgText, (x, y))
好了,准备工作做完了,我们来写循环
while True: for event in pygame.event.get(): if event.type == QUIT: exit() keys = pygame.key.get_pressed() if keys[K_ESCAPE]: exit()
这一段都是常规格式了,不解释了,就是让窗口能关掉。
然后把背景涂上一个颜色,不止一个人说我审美有问题了,所以我随便选了个颜色,我都觉得有点丑
screen.fill((131, 139, 139))
我们先画一个表盘
# 画表盘 pygame.draw.circle(screen, white, (pos_x, pos_y), radius, 2)
在表盘上写数字
# 写表盘数字 for n in range(1, 13): # 一共12个数字,平均分到一个圆内 每两个数字之间的角度为 360/12 x = math.cos(math.radians(angle)) * (radius - 10) - 5 y = math.sin(math.radians(angle)) * (radius - 10) - 7 print_text(font, pos_x + x, pos_y + y, str(n), white)
这里说道说道几个常用函数和概念,防止以后时间长了自己都忘
range(x,y)
作用是从x开始到y结束,但不包括y,所以range(1,13) 就是从1到12,如果x不填,则默认从0开始
math.randians(angle)、math.sin()、math.cos()
这里比较绕了,要遍历一个圆周,我们需要三个参数,圆心坐标(pos_x,pos_y),半径(radius),和角度 (angle),然后通过三角函数里的正弦和余弦两个函数乘以半径,计算出每个点的坐标(x,y),而正弦和余弦函数需要的参数是弧度,所以需要用 math.randians(angle)将角度转化成弧度
问题来了,为啥正弦余弦乘以半径可以得出圆周上点的坐标呢?
给个图自己看,很简单
想象一下A点是圆心,B点是圆周上的点,AB是圆的半径,那么B点的x坐标就是 cosA乘以AB,y坐标就是sinA乘以AB
计算x,y坐标时候 -5 -7又是为啥呢?
因为pygame里画模型的时候,坐标是模型的左上角并不是模型的中心点,无论图片还是文字还是其他什么都是这样,所以需要减掉几个像素,使模型出现在正确的位置,不然会往右下偏,这点以后要经常用到
目前为止,表盘画好了 ,是这个样子的
开始画表针
我们首先拿到当前的时间
# 获取时间 time = datetime.today() hour = time.hour % 12 minute = time.minute second = time.second
画秒针
# 画秒针 second_angle = wrap_angle(second * (360 / 60) - 90) # 秒针是60进制,所以一秒的角度为 360/60 second_x = math.cos(math.radians(second_angle)) * (radius - 3) second_y = math.sin(math.radians(second_angle)) * (radius - 3) pygame.draw.line(screen, blue, (pos_x, pos_y), (pos_x + second_x, pos_y + second_y), 2)
问题又来了,为啥要 -90
因为画圆的时候,0度是在3点钟方向的,而实际情况下,我们希望0度在12点钟方向,所以要减掉90度,达到需要
radius - 3 是为了让秒针短一些,不至于戳到表盘上
解决了秒针,分针时针就简单了
画分针和时针
# 画分针 minute_angle = wrap_angle(minute * (360 / 60) - 90) # 分针也是60进制,原理同秒针 minute_x = math.cos(math.radians(minute_angle)) * (radius - 40) minute_y = math.sin(math.radians(minute_angle)) * (radius - 40) pygame.draw.line(screen, green, (pos_x, pos_y), (pos_x + minute_x, pos_y + minute_y), 4) # 画时针 # 时针算角度时增加了一部分,因为钟表分针走的时候,时针也在走一个很小的角度 即30/60, # 加上这个角度,表才更加逼真,否则分针走的时候,时针一直保持指到整点,是错误的 hour_angle = wrap_angle(hour * (360 / 12) - 90) + minute * 30 / 60 hour_x = math.cos(math.radians(hour_angle)) * (radius - 80) hour_y = math.sin(math.radians(hour_angle)) * (radius - 80) pygame.draw.line(screen, red, (pos_x, pos_y), (pos_x + hour_x, pos_y + hour_y), 6)
这里有点小技巧,我们看到计算hour_angle的时候,在后面加了 minute * 30 / 60,这里实际上应该这么写minute / 60* (360/12) minute是当前的分钟数,拿他除以60分钟得到一个比例,然后12个小时,每两个数字之间的角度是360/12即30度
加上这一块,使分针每走一分钟,时针也会相应的走一点,更逼真不是
然后写上当前时间,比较表针位置是不是当前时间
# 写时间 print_text(font, 10, 10, str(hour) + " : " + str(minute) + " : " + str(second), white)
最后在圆点位置画一个点,盖住三个表针交叉的位置,好看一点
# 画表中心的圆点 之所以放在最后是想盖住三个针的原点 pygame.draw.circle(screen, white, (pos_x, pos_y), 8, 0)
最最后,别忘了刷新
pygame.display.update()
完整代码如下
import math, pygame from pygame.locals import * from datetime import datetime, date, time pygame.init() screen = pygame.display.set_mode((600, 600)) pygame.display.set_caption("Clock") pos_x = 300 pos_y = 300 radius = 250 white = 255, 255, 255 red = 240, 0, 0 green = 0, 240, 0 blue = 0, 0, 240 hour_angle = 0 minute_angle = 0 second_angle = 0 font = pygame.font.Font(None, 24) def wrap_angle(angle): return abs(angle % 360) def print_text(font, x, y, text, color): imgText = font.render(text, True, color) screen.blit(imgText, (x, y)) while True: for event in pygame.event.get(): if event.type == QUIT: exit() keys = pygame.key.get_pressed() if keys[K_ESCAPE]: exit() screen.fill((131, 139, 139)) # 画表盘 pygame.draw.circle(screen, white, (pos_x, pos_y), radius, 2) # 写表盘数字 for n in range(1, 13): # range(x,y)是从x开始到y结束 但不包括y,所以这里是1-13 # 一共12个数字,平均分到一个圆内 每两个数字之间的角度为 360/12 # 减90是因为默认开始点是3点钟方向,而实际上是12点钟方向,下面画分针、时针、秒针时也是这个道理 angle = n * 360 / 12 - 90 # 这里x,y减5减7,是因为写文字的时候坐标不是文字的中心点而是文字的左上角 # ,所以文字会显得往右下角偏,稍微的修正看起来更舒服 x = math.cos(math.radians(angle)) * (radius - 10) - 5 y = math.sin(math.radians(angle)) * (radius - 10) - 7 print_text(font, pos_x + x, pos_y + y, str(n), white) # 获取时间 time = datetime.today() hour = time.hour % 12 minute = time.minute second = time.second # 画秒针 second_angle = wrap_angle(second * (360 / 60) - 90) # 秒针是60进制,所以一秒的角度为 360/60 second_x = math.cos(math.radians(second_angle)) * (radius - 3) second_y = math.sin(math.radians(second_angle)) * (radius - 3) pygame.draw.line(screen, blue, (pos_x, pos_y), (pos_x + second_x, pos_y + second_y), 2) # 画分针 minute_angle = wrap_angle(minute * (360 / 60) - 90) # 分针也是60进制,原理同秒针 minute_x = math.cos(math.radians(minute_angle)) * (radius - 40) minute_y = math.sin(math.radians(minute_angle)) * (radius - 40) pygame.draw.line(screen, green, (pos_x, pos_y), (pos_x + minute_x, pos_y + minute_y), 4) # 画时针 # 时针算角度时增加了一部分,因为钟表分针走的时候,时针也在走一个很小的角度 即30/60, # 加上这个角度,表才更加逼真,否则分针走的时候,时针一直保持指到整点,是错误的 hour_angle = wrap_angle(hour * (360 / 12) - 90) + minute * 30 / 60 hour_x = math.cos(math.radians(hour_angle)) * (radius - 80) hour_y = math.sin(math.radians(hour_angle)) * (radius - 80) pygame.draw.line(screen, red, (pos_x, pos_y), (pos_x + hour_x, pos_y + hour_y), 6) # 写时间 print_text(font, 10, 10, str(hour) + " : " + str(minute) + " : " + str(second), white) # 画表中心的圆点 之所以放在最后是想盖住三个针的原点 pygame.draw.circle(screen, white, (pos_x, pos_y), 8, 0) pygame.display.update()
还是很丑,但是基本功能都实现了。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
目录元组的创建元组的删除元组部分元素的输出元组的嵌套元组元素的个数计算:len()元组中的元素最大最小值的求解:max(),min()元组中某元素出现的次数:count函数元组中某元素的
这篇文章主要介绍了Python matplotlib绘图建立画布及坐标系,建立画布 figsize,它用width和height来控制画布的宽和高,下面来一起俩姐更多内容吧
这篇文章主要为大家介绍了如何利用Python实现电脑壁纸的采集以及轮换效果,文中的示例代码讲解详细,对我们学习Python有一定帮助,需要的可以参考一下
这篇文章主要为大家详细介绍了用python实现五子棋实例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
这篇文章主要介绍了基于Python实现的购物商城管理系统,帮助大家更好的理解和学习使用python,感兴趣的朋友可以了解下
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008