画圆的基本数学知识
制作一个时钟,首先要解决的问题就是画一个圆,而且在众多游戏中,如炮弹的飞行轨迹,子弹的射击轨迹等,都需要用到圆的相关知识,那么由数学的参数方程有:
x = R * cost
y = R * sint
然后我们开始尝试画一个圆,源代码如下:
import math
import random
import sys
import pygame
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((600, 500))
pygame.display.set_caption("Circle Demo")
screen.fill((0, 0, 200))
pos_x = 300
pos_y = 250
radius = 200
angle = 360
while True:
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
keys = pygame.key.get_pressed()
if keys[K_ESCAPE]:
sys.exit()
angle = (angle + 1) % 360
color = random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
x = radius * math.cos(math.radians(angle))
y = radius * math.sin(math.radians(angle))
pos = (int(pos_x + x), int(pos_y + y))
pygame.draw.circle(screen, color, pos, 10, 0)
pygame.display.update()
运行结果如下:
Analog Clock程序
那么将前面的代码进一步深化,就可以制作一个时钟程序。我们还有几个问题要解决,那就是时针、分针、秒针的计算方法有些不一样,时针是12小时制(或者24小时制),分针和秒针是60制的,同时要将数字转换成对应的角度以实现正确的显示。
对于时针,角度与数字之间的转换如下:
hour * (360 / 12) - 90
减去90度是因为角度0是指向x轴的正半轴的,但是角度0对应的是12点,应该指向y轴正半轴。而Pygame中画线的角度是顺时针递增的,注意!!这里与我们数学中所熟知的逆时针角度递增不一样!!例子如下:
import math
import sys
import pygame
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((600, 500))
pos_x = 300
pos_y = 250
radius = 250
while True:
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
keys = pygame.key.get_pressed()
if keys[K_ESCAPE]:
sys.exit()
screen.fill((0, 0, 100))
angle = math.radians(45)
x = math.cos(angle) * radius
y = math.sin(angle) * radius
pygame.draw.line(screen, (255, 255, 255), (pos_x, pos_y), (pos_x + x, pos_y + y), 20)
pygame.display.update()
运行结果如下:
可以看到,45度角指向的是第四象限而不是第一象限。
而对于分针和秒针,角度与数字之间的转换一样:
minute * (360 / 60) - 90
second * (360 / 60) - 90
源代码如下:
import math
import sys
import pygame
from pygame.locals import *
from datetime import datetime
def print_text(font, x, y, text, color=(255, 255, 255), shadow=True):
imgText = font.render(text, True, color)
screen.blit(imgText, (x, y))
def wrap_angle(angle):
return angle % 360
if __name__ == "__main__":
# 初始化操作
pygame.init()
screen = pygame.display.set_mode((600, 500))
pygame.display.set_caption("Analog Clock")
font = pygame.font.Font(None, 36)
orange = 220, 180, 0
white = 255, 255, 255
yellow = 255, 255, 0
pink = 255, 100, 100
pos_x = 300
pos_y = 250
radius = 250
angle = 360
while True:
for event in pygame.event.get():
if event.type == QUIT:
sys.exit()
keys = pygame.key.get_pressed()
if keys[K_ESCAPE]:
sys.exit()
screen.fill((0, 0, 100))
# 画一个圆
pygame.draw.circle(screen, white, (pos_x, pos_y), radius, 6)
# 画数字
for n in range(1, 13):
angle = math.radians(n * (360 / 12) - 90)
x = (radius - 20) * math.cos(angle) - 10
y = (radius - 20) * math.sin(angle) - 10
print_text(font, pos_x + x, pos_y + y, str(n))
# 获取当前时间
today = datetime.today()
hour = today.hour % 12
minute = today.minute
second = today.second
# 绘制时针
hour_angle = wrap_angle(hour * (360 / 12) - 90)
hour_angle = math.radians(hour_angle)
hour_x = math.cos(hour_angle) * (radius - 80)
hour_y = math.sin(hour_angle) * (radius - 80)
target = (pos_x + hour_x, pos_y + hour_y)
pygame.draw.line(screen, pink, (pos_x, pos_y), target, 25)
# 绘制分针
minute_angle = wrap_angle(minute * (360 / 60) - 90)
minute_angle = math.radians(minute_angle)
minute_x = math.cos(minute_angle) * (radius - 60)
minute_y = math.sin(minute_angle) * (radius - 60)
target = (pos_x + minute_x, pos_y + minute_y)
pygame.draw.line(screen, orange, (pos_x, pos_y), target, 12)
# 绘制秒针
second_angle = wrap_angle(second * (360 / 60) - 90)
second_angle = math.radians(second_angle)
second_x = math.cos(second_angle) * (radius - 40)
second_y = math.sin(second_angle) * (radius - 40)
target = (pos_x + second_x, pos_y + second_y)
pygame.draw.line(screen, yellow, (pos_x, pos_y), target, 6)
pygame.draw.circle(screen, white, (pos_x, pos_y), 20)
print_text(font, 0, 0, str(today.hour) + ":" + str(minute) + ":" + str(second))
pygame.display.update()
运行结果如下: