使用Python+Pygame实现弹幕效果
为什么要写这么个东西,还是因为某室友在宿舍群里写骚代码来迫害我们无辜的室友们。于是,我也花了一晚上时间来搞了这么个迫害他的东西。此处应该大喊吴鸿声牛逼!
程序实现的效果是从一个包含弹幕内容的数组中随机抽取弹幕,并以随机的位置、随机的颜色显示在窗口内。 程序主要实现了一个弹幕类,其中包括生成弹幕、显示弹幕以及弹幕移动等。弹幕类的构造函数中,首先随机生成所有参数,并将弹幕位置的x坐标定位到屏幕宽度处(刚好在屏幕右侧的外部)。如果随机生成的y坐标处已经存在弹幕,为了防止遮挡会重新产生一个y坐标。若这个过程重复超过100次以上,说明可能当前弹幕已经满了(即屏幕宽度处已经没有空行了),就抛出异常。 弹幕的移动使用每秒像素数作为速度,弹幕类中的移动函数接收一个时间,该时间为程序循环一次所耗费的时间,函数使用时间计参数算弹幕在此时间内应移动的像素数,并将弹幕的x坐标减去对应像素数,通过在主循环中不断调用此函数,实现弹幕的连续移动。 最终,在主循环当中,不断获取上次循环的时间控制弹幕移动,并随机产生新的弹幕,删除已经溢出屏幕外的弹幕,最终通过弹幕类中的显示函数显示到屏幕上。
下面是全部代码。
import pygame
from random import randint
danmaku_text = ['吴鸿声牛逼', '我永远喜欢吴鸿声', '吴鸿声天下第一', '吴鸿声tql', '吴鸿声太强了',
'吴鸿声太强了8', '爱了爱了', '呜呜呜太强了', '声声永远牛逼!'] # 弹幕文本
danmaku_height = 32 # 弹幕字号
danmaku_speed = 200 # 弹幕速度 每秒200像素
danmaku_color = [(255,255,255), (255,255,255), (255,255,255), (255,255,255), (255,255,255), (255,255,255), (255,255,255)
, (255, 255, 255), (255, 255, 255), (255,0,0), (0,255,0), (255,255,0)] # 弹幕颜色 白色概率大一些
width, height = 1280, 720 # 屏幕分辨率
class Danmaku(object): # 弹幕类
def __init__(self, existing_danmaku): # 构造函数
self.x = width
self.speed = danmaku_speed
self.text = danmaku_text[randint(0, danmaku_text.__len__()-1)]
self.color = danmaku_color[randint(0, danmaku_color.__len__()-1)]
retry = 0
while True: # 防止弹幕重叠
self.y = randint(0, height//danmaku_height-1) * danmaku_height
overlay = False
for danmaku in existing_danmaku:
if danmaku.y == self.y:
if len(danmaku.text)*danmaku_height + danmaku.x > self.x: # 弹幕会重叠
overlay = True
break
retry += 1
if retry > 100: # 重试次数超出阈值 说明可能无处创建新的弹幕了
raise Exception # 抛出异常
if not overlay:
break
def shift(self, seconds): # 弹幕移动
self.x -= seconds * self.speed
def show(self, font, screen):
text_serface = font.render(self.text, True, self.color)
screen.blit(text_serface, (self.x, self.y))
def run(): # 函数
pygame.init() # pygame初始化
pygame.display.set_caption('By 王远泽') # 设置窗口标题
screen = pygame.display.set_mode((width, height)) # 设置分辨率
font = pygame.font.SysFont('SimHei', danmaku_height) # 设置字体 这是Windows下的黑体名称
clock = pygame.time.Clock() # Clock对象
danmaku_list = []
while True: # 主循环
for event in pygame.event.get():
if event.type == pygame.QUIT: # 检测退出键按下
return
time_passed = clock.tick() / 1000 # 获取程序执行时间
if randint(0, 19) == 0: # 每次循环5%几率新增一个弹幕
try:
danmaku_list.append(Danmaku(danmaku_list)) # 新增弹幕
except Exception:
pass # 如果无法创建 不执行任何操作
screen.fill((0, 0, 0)) # 清屏
for danmaku in danmaku_list:
danmaku.show(font, screen) # 显示弹幕
danmaku.shift(time_passed) # 更新所有弹幕的位置
def is_on_screen(danmaku_obj): # 判断弹幕是否还在屏幕上
return not danmaku_obj.x < -len(danmaku_obj.text) * danmaku_height
danmaku_list = list(filter(is_on_screen, danmaku_list)) # 去除已经溢出屏幕的弹幕
pygame.display.update() # 刷新显示
if __name__ == "__main__":
run()