前言
嗨喽,大家好呀~这里是爱看美女的茜茜呐
image🌙 遇见我以后,我们的故事就开始了,愿你历经山河,仍觉得人间值得🌙
明天情人节啦~大家对自家女(男)朋友的节日礼物准备好啦嘛
没准备的我保证不会对你幸灾乐祸的 👻
image分手了不要害怕,单身的狼狗随时准备扑上来~哈哈哈哈
image这里博主给大家带来一些编程表白小程序,来给大家助助兴呀~
月遇从云,花遇和风,今晚上的夜空很美。👇
原句:“月遇从云,花遇和风,今晚上的夜空很美,我又想你。”——太宰治
烟花表白🎇
1)环境安装🎊
准备好:Python3、Pycharm、Tkinter、Pygame、Pillow以及一些自带模块。
安装命令统一:
pip install -i https://pypi.douban.com/simple/ +模块名
2)素材展示🎨
2.1音乐背景(可自选)
image2.2图片素材(可修改)
image✨ 从此烟花,不止刹那,如我的祝福,不会随寂寞瞬间落下
3)正式敲代码🎊
导入模块
import random
import pygame as py
import tkinter as tk
from time import time, sleep
from tkinter import filedialog
from PIL import Image, ImageTk
from math import sin, cos, radians
from random import choice, uniform, randint
生成随机颜色
def randomcolor():
colArr = ['1','2','3','4','5','6','7','8','9','A','B','C','D','E','F']
color = ""
for i in range(6):
color += colArr[random.randint(0,14)]
return "#"+color
重力变量
GRAVITY = 0.06
颜色列表
colors = ['red', 'blue', 'yellow', 'white', 'green', 'orange', 'purple', 'seagreen','indigo', 'cornflowerblue', 'pink']
'''
Attributes(属性):
-
id: 粒子的id
-
x, y: 粒子的坐标
-
vx, vy: 粒子在对应坐标的变化速度
-
total:一颗烟花里的粒子总数
-
age: 粒子在画布上停留的时间
-
color: 自我移植
-
cv: 画布
-
lifespan: 粒子在画布上停留的时间
'''
为每一个烟花绽放出来的粒子单独构建一个类的对象 ,
每个粒子都会有一些重要的属性,决定它的外观(大小、颜色)、移动速度等
class part:
def __init__(self, cv, idx, total, explosion_speed, x=0., y=0., vx = 0., vy = 0., size=3., color = 'red', lifespan = 2, **kwargs):
每个烟花的特定标识符
self.id = idx
烟花绽放x轴
self.x = x
烟花绽放y轴
self.y = y
粒子初始速度
self.initial_speed = explosion_speed
粒子运动x轴速度
self.vx = vx
粒子运动y轴速度
self.vy = vy
绽放粒子数
self.total = total
粒子已停留时间
self.age = 0
粒子颜色
self.color = color
画布
self.cv = cv
指定一个限定矩形(Tkinter 会自动在这个矩形内绘制一个椭圆)
self.cid = self.cv.create_oval(x - size, y - size, x + size,y + size, fill=self.color, outline='white',width=0.01)
粒子在画布上停留的时间
self.lifespan = lifespan
def update(self, dt):
self.age += dt
#更新粒子停留时间
if self.alive() and self.expand():
#如果粒子既存活又处于扩张阶段
move_x = cos(radians(self.id*360/self.total))*self.initial_speed
#粒子x轴继续膨胀
move_y = sin(radians(self.id*360/self.total))*self.initial_speed
#粒子y轴继续膨胀
self.cv.move(self.cid, move_x, move_y)
#根据id把画布上的粒子移动x和y个距离
self.vx = move_x/(float(dt)*1000)
#粒子x轴的速度
elif self.alive():
columnFont = ('华文行楷',40)
#如果粒子仅存活不扩张(只是停留时间足够,说明膨胀到最大了),则自由坠落
self.cv.create_text(150, 80, text='圣',tag="write_tag", fill=choice(colors),font = columnFont) #字体
self.cv.create_text(250, 80, text='诞',tag="write_tag", fill=choice(colors),font = columnFont)
self.cv.create_text(350, 80, text='快',tag="write_tag", fill=choice(colors),font = columnFont)
self.cv.create_text(450, 80, text='乐',tag="write_tag", fill=choice(colors),font = columnFont)
#删除文字标签
move_x = cos(radians(self.id*360/self.total))
#x轴的移动位移
# we technically don't need to update x, y because move will do the job
self.cv.move(self.cid, self.vx + move_x, self.vy+GRAVITY*dt)
self.vy += GRAVITY*dt
#更新y轴
elif self.cid is not None:
#如果粒子生命周期已过,则将其移除
cv.delete(self.cid)
#在画布上移除该粒子对象
self.cv.delete("write_tag")
#同时移除字体
self.cid = None
def expand (self):
#定义膨胀效果时间帧
return self.age <= 1.2
#判断膨胀时间是否小于1.2秒
def alive(self):
#判断粒子是否仍在生命周期内
return self.age <= self.lifespan
#判断已停留时间是否小于应该停留时间
'''
Firework simulation loop:
Recursively call to repeatedly emit new fireworks on canvas
a list of list (list of stars, each of which is a list of particles)
is created and drawn on canvas at every call,
via update protocol inside each 'part' object
'''
可以在这一段修改烟花的位置
def simulate(cv):
t = time()
#返回自1970年后经过的浮点秒数,精确到小数点后7位
explode_points = []
#爆炸点列表,烟花列表
wait_time = randint(10,100)
#等待时间为10到100之间整数
numb_explode = randint(8,20)
#爆炸烟花个数时6到10之间的随机整数
# create list of list of all particles in all simultaneous explosion
for point in range(numb_explode):
#为所有模拟烟花绽放的全部粒子创建一列列表
if point<=6:
objects = []
#每个点的爆炸粒子列表粒子列表
x_cordi = 150 + point*50
#每个爆炸点的x轴
y_cordi = 80
#每个爆炸点的y轴
speed = uniform (0.5, 5.5)
#每个爆炸点的速度
size = uniform (0.5,3)
#每个爆炸点的大小
color = choice(colors)
#每个爆炸点的颜色
explosion_speed = uniform(0.6, 4)
#爆炸的绽放速度
total_particles = randint(10,50)
#烟花的总粒子数
for i in range(2,total_particles):
#同一个烟花爆炸出来的粒子大小、速度、坐标都是相同的
r = part(cv, idx = i, total = total_particles, explosion_speed = explosion_speed, x = x_cordi, y = y_cordi, vx = speed, vy = speed, color=color, size = size, lifespan = uniform(0.7,1.75))
#把上述参数代入part函数,但是每个粒子的生存时间是自己独立的
objects.append(r)
#把r添加进粒子列表
explode_points.append(objects)
#把粒子列表添加进烟花列表
else:
objects = []
#每个点的爆炸粒子列表粒子列表
x_cordi = randint(50,550)
#每个爆炸点的x轴
y_cordi = randint(50, 550)
#每个爆炸点的y轴
speed = uniform (0.5, 6.5)
#每个爆炸点的速度
size = uniform (0.4,3)
#每个爆炸点的大小
color = choice(colors)
#每个爆炸点的颜色
explosion_speed = uniform(0.3, 2)
#爆炸的绽放速度
total_particles = randint(10,40)
#烟花的总粒子数
for i in range(2,total_particles):
#同一个烟花爆炸出来的粒子大小、速度、坐标都是相同的
r = part(cv, idx = i, total = total_particles, explosion_speed = explosion_speed, x = x_cordi, y = y_cordi, vx = speed, vy = speed, color=color, size = size, lifespan = uniform(0.6,1.75))
#把上述参数代入part函数,但是每个粒子的生存时间是自己独立的
objects.append(r)
#把r添加进粒子列表
explode_points.append(objects)
#把粒子列表添加进烟花列表
total_time = .0
#初始化总时间
# keeps undate within a timeframe of 1.8 second
while total_time < 2:
#当总时间小于1.8秒时运行该循环
sleep(0.03)
#让画面暂停0.01秒
tnew = time()
#刷新时间
t, dt = tnew, tnew - t
#时间等于新时间,和上次时间间隔为tnew-t
for point in explode_points:
#遍历烟花列表
for item in point:
#遍历烟花里的粒子列表
item.update(dt)
#粒子更新时间
cv.update()
#刷新画布
total_time += dt
#为while循环增加时间
root.after(wait_time, simulate, cv)
#将组件置于其他组件之后,放在最顶层,覆盖下面的,递归调用自己,形成新一轮的爆炸
def close(*ignore):
#打开模拟循环并关闭窗口
"""Stops simulation loop and closes the window."""
global root
root.quit()
## 完整源码加Q君羊:261823976
if __name__ == '__main__':
root = tk.Tk()
root.title('圣诞快乐') # 设置窗体的标题栏
cv = tk.Canvas(root, height=600, width=600)
#绘制一个高600,宽600的画布
bgpath = filedialog.askopenfilename(title='请选择背景图片')
#选择背景图片
image = Image.open(bgpath)
#打开背景图片
image = image.resize((600,600), Image.ANTIALIAS)
#把背景图片调整成窗口大小
photo = ImageTk.PhotoImage(image)
cv.create_image(0, 0, image=photo, anchor='nw')
#在画布上绘制加载的背景图片
bgmusic = filedialog.askopenfilename(title='请选择背景音乐')
py.mixer.init()
# 初始化
py.mixer.music.load(bgmusic)
# 文件加载
py.mixer.music.play(-1, 0, fade_ms=50)
# 播放 第一个是播放值 -1代表循环播放, 第二个参数代表开始播放的时间
py.mixer.music.pause()
#暂停
py.mixer.music.unpause()
#取消暂停
cv.pack()
#把cv添加进去
root.protocol("WM_DELETE_WINDOW", close)
root.after(200, simulate, cv)
#在0.1秒后再调用stimulate函数,生成一轮烟花绽放效果
root.mainloop()
#执行root,生成窗口
🌙 “因为你,我愿意成为一个更好的人,不想成为你的包袱,因此发奋努力,
只是为了想要证明我足以与你相配。” ——《侧耳倾听》
4)效果展示💐
imageimage
🌙 "月色暗淡还有星辰—山河失色你还有我"
——《告白文案》
“无套路"表白版 💌
这个就厉害了,在没点击好呀之前点击叉叉也是关不掉她的
所需素材
image图片
image字体
image音乐
image素材 点击此处文字👍领取哦~
🌙 你知道吗?在我的世界观念里,我希望都有你的存在,因为你在我的世界里对于我而言是那么的重要。
You know what? In my view of the world, I hope you exist, because you are so important to me in my world.
'''配置文件'''
import os
# 窗口大小(width, height)
SCREENSIZE = (500, 260)
# 定义一些颜色
RED = (255, 0, 0)
BLACK = (0, 0, 0)
AZURE = (240, 255, 255)
WHITE = (255, 255, 255)
MISTYROSE = (255, 228, 225)
PALETURQUOISE = (175, 238, 238)
PAPAYAWHIP = (255, 239, 213)
LIGHTGRAY = (211, 211, 211)
GAINSBORO = (230, 230, 230)
WHITESMOKE = (245, 245, 245)
DARKGRAY = (169, 169, 169)
BLUE = (0, 0, 255)
DEEPSKYBLUE = (0, 191, 255)
SKYBLUE = (135, 206, 235)
LIGHTSKYBLUE = (135, 206, 250)
# 背景音乐路径
BGM_PATH = os.path.join(os.getcwd(), 'resources/music/bgm.mp3')
# 字体路径
FONT_PATH = os.path.join(os.getcwd(), 'resources/font/STXINGKA.TTF')
# 背景图片路径
BG_IMAGE_PATH = os.path.join(os.getcwd(), 'resources/images/bg.png')
# ICON路径
ICON_IMAGE_PATH = os.path.join(os.getcwd(), 'resources/images/icon.png')
import sys
import cfg
import random
import pygame
from tkinter import Tk, messagebox
'''
Function:
按钮类
Initial Args
:
--x, y: 按钮左上角坐标
--width, height: 按钮宽高
--text: 按钮显示的文字
--fontpath: 字体路径
--fontsize: 字体大小
--fontcolor: 字体颜色
--bgcolors: 按钮背景颜色
--is_want_to_be_selected: 按钮是否想被玩家选中
--screensize: 软件屏幕大小
'''
class Button(pygame.sprite.Sprite):
def __init__(self, x, y, width, height, text, fontpath, fontsize, fontcolor, bgcolors, edgecolor, edgesize=1, is_want_to_be_selected=True, screensize=None, **kwargs):
pygame.sprite.Sprite.__init__(self)
self.rect = pygame.Rect(x, y, width, height)
self.text = text
self.font = pygame.font.Font(fontpath, fontsize)
self.fontcolor = fontcolor
self.bgcolors = bgcolors
self.edgecolor = edgecolor
self.edgesize = edgesize
self.is_want_tobe_selected = is_want_to_be_selected
self.screensize = screensize
'''自动根据各种情况将按钮绑定到屏幕'''
def draw(self, screen, mouse_pos):
# 鼠标在按钮范围内
if self.rect.collidepoint(mouse_pos):
# --不想被选中
if not self.is_want_tobe_selected:
while self.rect.collidepoint(mouse_pos):
self.rect.left, self.rect.top = random.randint(0, self.screensize[0]-self.rect.width), random.randint(0, self.screensize[1]-self.rect.height)
pygame.draw.rect(screen, self.bgcolors[0], self.rect, 0)
pygame.draw.rect(screen, self.edgecolor, self.rect, self.edgesize)
# 鼠标不在按钮范围内
else:
pygame.draw.rect(screen, self.bgcolors[1], self.rect, 0)
pygame.draw.rect(screen, self.edgecolor, self.rect, self.edgesize)
text_render = self.font.render(self.text, True, self.fontcolor)
fontsize = self.font.size(self.text)
screen.blit(text_render, (self.rect.x+(self.rect.width-fontsize[0])/2, self.rect.y+(self.rect.height-fontsize[1])/2))
'''在指定位置显示文字'''
def showText(screen, text, position, fontpath, fontsize, fontcolor, is_bold=False):
font = pygame.font.Font(fontpath, fontsize)
font.set_bold(is_bold)
text_render = font.render(text, True, fontcolor)
screen.blit(text_render, position)
'''主函数'''
def main():
# 初始化
pygame.init()
screen = pygame.display.set_mode(cfg.SCREENSIZE, 0, 32)
pygame.display.set_icon(pygame.image.load(cfg.ICON_IMAGE_PATH))
pygame.display.set_caption('来自一位喜欢你的小哥哥')
# 背景音乐
pygame.mixer.music.load(cfg.BGM_PATH)
pygame.mixer.music.play(-1, 30.0)
# biu爱心那个背景图片
bg_image = pygame.image.load(cfg.BG_IMAGE_PATH)
bg_image = pygame.transform.smoothscale(bg_image, (150, 150))
# 实例化两个按钮
button_yes = Button(x=20, y=cfg.SCREENSIZE[1]-70, width=120, height=35,
text='好呀', fontpath=cfg.FONT_PATH, fontsize=15, fontcolor=cfg.BLACK, edgecolor=cfg.SKYBLUE,
edgesize=2, bgcolors=[cfg.DARKGRAY, cfg.GAINSBORO], is_want_to_be_selected=True, screensize=cfg.SCREENSIZE)
button_no = Button(x=cfg.SCREENSIZE[0]-140, y=cfg.SCREENSIZE[1]-70, width=120, height=35,
text='算了吧', fontpath=cfg.FONT_PATH, fontsize=15, fontcolor=cfg.BLACK, edgecolor=cfg.DARKGRAY,
edgesize=1, bgcolors=[cfg.DARKGRAY, cfg.GAINSBORO], is_want_to_be_selected=False, screensize=cfg.SCREENSIZE)
# 是否点击了好呀按钮
is_agree = False
# 主循环
clock = pygame.time.Clock()
while True:
# --背景图片
screen.fill(cfg.WHITE)
screen.blit(bg_image, (cfg.SCREENSIZE[0]-bg_image.get_height(), 0))
# --鼠标事件捕获
for event in pygame.event.get():
if event.type == pygame.QUIT:
# ----没有点击好呀按钮之前不许退出程序
if is_agree:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN and event.button:
if button_yes.rect.collidepoint(pygame.mouse.get_pos()):
button_yes.is_selected = True
root = Tk()
root.withdraw()
messagebox.showinfo('', '❤❤❤么么哒❤❤❤')
root.destroy()
is_agree = True
# --显示文字
showText(screen=screen, text='小姐姐, 我观察你很久了', position=(40, 50),
fontpath=cfg.FONT_PATH, fontsize=25, fontcolor=cfg.BLACK, is_bold=False)
showText(screen=screen, text='做我女朋友好不好?', position=(40, 100),
fontpath=cfg.FONT_PATH, fontsize=25, fontcolor=cfg.BLACK, is_bold=True)
# --显示按钮
button_yes.draw(screen, pygame.mouse.get_pos())
button_no.draw(screen, pygame.mouse.get_pos())
# --刷新
pygame.display.update()
clock.tick(60)
'''run'''
if __name__ == '__main__':
main()
image
✨ 如果我逐日一追求你的时候,我会被风吹向大海,因为大海的深蓝才可以表达我对你爱意的真相。
恋爱时,我不要只和 你谈风花雪月,我还要和你谈未来,因为我希望你所有的计划当中都把我包含其中。
尾语
感谢你观看我的文章呐~本次航班到这里就结束啦 🛬
希望本篇文章有对你带来帮助 🎉,有学习到一点知识~
躲起来的星星🍥也在努力发光,你也要努力加油(让我们一起努力叭)。
image
网友评论