Pygame用數(shù)學(xué)公式實(shí)現(xiàn)心之律動(dòng)動(dòng)畫(huà)
效果演示

一、引言
在數(shù)字世界中,如何用代碼創(chuàng)造出浪漫而富有生命力的視覺(jué)效果?本文將帶你探索如何使用 Python 的 Pygame 庫(kù)實(shí)現(xiàn)一個(gè)名為"心之律動(dòng)"的粒子動(dòng)畫(huà),通過(guò)數(shù)學(xué)公式生成心形軌跡,并加入煙花爆炸、鼠標(biāo)交互等元素,打造出一個(gè)充滿活力的動(dòng)態(tài)心形場(chǎng)景。
二、效果預(yù)覽與功能介紹
我們的動(dòng)畫(huà)將實(shí)現(xiàn)以下核心功能:
- 基于數(shù)學(xué)公式生成的動(dòng)態(tài)心形粒子分布
- 隨時(shí)間變化的心跳效果,讓心形呈現(xiàn)呼吸感
- 鼠標(biāo)移動(dòng)時(shí)產(chǎn)生彩色拖尾軌跡
- 鼠標(biāo)點(diǎn)擊時(shí)觸發(fā)絢麗的煙花爆炸效果
- 可交互的控制界面,支持重置、暫停和調(diào)整粒子數(shù)量
下面讓我們一步步實(shí)現(xiàn)這個(gè)動(dòng)畫(huà)效果。
三、數(shù)學(xué)原理-心形曲線方程
要生成心形圖案,我們需要使用數(shù)學(xué)中的心形線(Cardioid)方程。心形線是一個(gè)圓上的固定點(diǎn)在該圓繞著與其相切且半徑相同的另外一個(gè)圓滾動(dòng)時(shí)所形成的軌跡,其參數(shù)方程通常表示為:
x = 16 * sin³(t)
y = 13 * cos(t) - 5 * cos(2t) - 2 * cos(3t) - cos(4t)
其中 t 是參數(shù),范圍通常為 0 到 2π。這個(gè)方程可以生成一個(gè)標(biāo)準(zhǔn)的心形曲線。在我們的代碼中,將使用這個(gè)方程來(lái)確定粒子的位置:
def generate_heart_point(self, t: float, scale: float = 1.0) -> Dict[str, float]:
"""生成心形參數(shù)方程的點(diǎn)"""
# 心形參數(shù)方程: x=16sin3t, y=13cost-5cos2t-2cos3t-cos4t
x = 16 * math.sin(t)**3
y = 13 * math.cos(t) - 5 * math.cos(2*t) - 2 * math.cos(3*t) - math.cos(4*t)
# 映射到畫(huà)布中心并縮放
center_x, center_y = WIDTH // 2, HEIGHT // 2
heart_scale = min(WIDTH, HEIGHT) * 0.35 * scale
return {
"x": center_x + x * heart_scale / 16,
"y": center_y - y * heart_scale / 16 # 反轉(zhuǎn)y軸
}四、粒子系統(tǒng)設(shè)計(jì)
粒子系統(tǒng)是實(shí)現(xiàn)這個(gè)動(dòng)畫(huà)的核心,我們定義了四種類型的粒子:
- 心形粒子:構(gòu)成基礎(chǔ)心形圖案的粒子
- 鼠標(biāo)軌跡粒子:跟隨鼠標(biāo)移動(dòng)產(chǎn)生的拖尾效果
- 煙花粒子:鼠標(biāo)點(diǎn)擊時(shí)爆炸產(chǎn)生的粒子
- 墜落粒子:從煙花粒子轉(zhuǎn)變而來(lái),模擬墜落效果
每個(gè)粒子都有自己的屬性,包括位置、速度、顏色、生命周期等。以下是粒子類的核心代碼:
class Particle:
def __init__(self, x: float, y: float, particle_type: str = "heart"):
self.x = x
self.y = y
self.type = particle_type
# 初始化屬性
self.current_size = 0
self.current_alpha = 0
# 根據(jù)粒子類型設(shè)置屬性
if particle_type == "heart":
self.setup_heart_particle()
elif particle_type == "mouse":
self.setup_mouse_particle()
elif particle_type == "firework":
self.setup_firework_particle()
else: # falling
self.setup_falling_particle()
# 煙花粒子延遲效果
if particle_type == "firework":
self.delay = random.random() * 15
self.is_active = False
def update(self) -> None:
"""更新粒子狀態(tài)"""
# 根據(jù)粒子類型執(zhí)行不同的物理模擬
# ... (省略具體實(shí)現(xiàn))
def draw(self) -> None:
"""繪制粒子"""
if self.type == "firework" and not self.is_active:
return
# 確保透明度在有效范圍內(nèi)
r, g, b = self.color
alpha = max(0, min(255, int(255 * self.current_alpha)))
if alpha > 0: # 只繪制可見(jiàn)粒子
# 創(chuàng)建帶透明度的表面
size = max(0.5, self.current_size)
surf = pygame.Surface((int(size * 2), int(size * 2)), pygame.SRCALPHA)
pygame.draw.circle(surf, (r, g, b, alpha), (int(size), int(size)), int(size))
screen.blit(surf, (self.x - size, self.y - size))五、煙花物理模擬
煙花效果是動(dòng)畫(huà)的一大亮點(diǎn),我們使用物理引擎模擬煙花的爆炸和墜落過(guò)程。主要考慮以下物理因素:
- 重力:使粒子向下墜落
- 摩擦力:使粒子速度逐漸減慢
- 延遲激活:實(shí)現(xiàn)多層爆炸效果
def setup_firework_particle(self) -> None:
"""初始化煙花粒子屬性"""
self.color = random.choice(particle_colors)
self.size = 1.5 + random.random() * 4
self.base_speed = 2 + random.random() * 3 # 較高初始速度
self.angle = random.random() * math.pi * 2
self.life = 100 + random.random() * 80
self.max_life = self.life
self.gravity = 0.05 # 重力
self.friction = 0.97 + random.random() * 0.01 # 摩擦力
# 笛卡爾坐標(biāo)速度
self.vx = math.cos(self.angle) * self.base_speed
self.vy = math.sin(self.angle) * self.base_speed
def update(self) -> None:
# 煙花粒子物理模擬
if self.type == "firework" and self.is_active:
self.vx *= self.friction # 摩擦力
self.vy += self.gravity # 重力
self.x += self.vx
self.y += self.vy
# 轉(zhuǎn)換為墜落粒子
if abs(self.vy) > 0.3 and random.random() < 0.08 and self.life > 40:
self.type = "falling"
self.setup_falling_particle()六、鼠標(biāo)交互與用戶界面
為了增強(qiáng)用戶體驗(yàn),我們添加了鼠標(biāo)交互和簡(jiǎn)單的控制面板:
- 鼠標(biāo)移動(dòng)時(shí)生成彩色軌跡
- 鼠標(biāo)點(diǎn)擊時(shí)觸發(fā)煙花爆炸
- 通過(guò)鍵盤控制重置、暫停和調(diào)整粒子數(shù)量
def handle_mouse_move(self, x: int, y: int) -> None:
"""處理鼠標(biāo)移動(dòng)"""
self.mouse["x"] = x
self.mouse["y"] = y
# 生成鼠標(biāo)軌跡粒子
for _ in range(6):
offset_x = (random.random() - 0.5) * 20
offset_y = (random.random() - 0.5) * 20
self.particles.append(Particle(
self.mouse["x"] + offset_x,
self.mouse["y"] + offset_y,
"mouse"
))
def handle_mouse_down(self) -> None:
"""處理鼠標(biāo)按下 - 創(chuàng)建煙花"""
self.mouse["is_down"] = True
self.create_firework(self.mouse["x"], self.mouse["y"])
def draw_ui(self) -> None:
"""繪制用戶界面"""
# 標(biāo)題
title = font.render("心之律動(dòng)", True, (255, 255, 255))
subtitle = font.render("鼠標(biāo)移動(dòng)生成軌跡,點(diǎn)擊釋放煙花", True, (230, 230, 230))
screen.blit(title, (WIDTH//2 - title.get_width()//2, 20))
screen.blit(subtitle, (WIDTH//2 - subtitle.get_width()//2, 55))
# 粒子數(shù)量
particle_count_text = font.render(f"粒子數(shù)量: {self.particle_count}", True, (255, 255, 255))
screen.blit(particle_count_text, (20, 20))
# 操作提示
help_text1 = font.render("R: 重置 | P: 暫停 | +: 增加粒子 | -: 減少粒子", True, (200, 200, 200))
screen.blit(help_text1, (WIDTH//2 - help_text1.get_width()//2, HEIGHT - 40))七、優(yōu)化與擴(kuò)展建議
- 性能優(yōu)化:當(dāng)粒子數(shù)量較多時(shí),可能會(huì)影響性能??梢钥紤]使用批處理渲染或粒子池技術(shù)來(lái)提高效率。
- 視覺(jué)增強(qiáng):可以添加背景圖片、背景音樂(lè)或更多的粒子效果,增強(qiáng)整體視覺(jué)沖擊力。
- 交互擴(kuò)展:可以添加更多的交互方式,如鍵盤控制煙花顏色、調(diào)整物理參數(shù)等。
- 藝術(shù)風(fēng)格:可以嘗試不同的顏色方案或粒子形狀,創(chuàng)造出不同的藝術(shù)風(fēng)格。
八、總結(jié)
通過(guò)這個(gè)項(xiàng)目,我們不僅學(xué)習(xí)了如何使用 Pygame 創(chuàng)建動(dòng)態(tài)粒子系統(tǒng),還探索了數(shù)學(xué)公式在圖形渲染中的應(yīng)用。從心形曲線方程到物理模擬,每一步都展示了代碼與藝術(shù)的完美結(jié)合。希望這個(gè)教程能激發(fā)你更多的創(chuàng)意,用代碼創(chuàng)造出更多美麗而有趣的視覺(jué)效果!
九、完整代碼
import pygame
import math
import random
import sys
from typing import List, Dict, Tuple
# 初始化Pygame
pygame.init()
# 確保中文正常顯示
pygame.font.init()
font = pygame.font.SysFont(["SimHei", "WenQuanYi Micro Hei", "Heiti TC"], 24)
# 屏幕設(shè)置
WIDTH, HEIGHT = 1000, 700
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("心之律動(dòng) - Pygame粒子動(dòng)畫(huà)")
# 顏色定義
particle_colors = [
(255, 94, 135),
(255, 133, 162),
(255, 179, 198),
(255, 194, 209),
(255, 215, 228),
(255, 154, 162),
(255, 183, 178),
(255, 218, 193),
(226, 240, 203),
(181, 234, 215),
(199, 206, 234),
(167, 154, 255),
(194, 167, 255),
(216, 167, 255),
(234, 167, 255),
(245, 167, 255),
]
# 粒子類
class Particle:
def __init__(self, x: float, y: float, particle_type: str = "heart"):
self.x = x
self.y = y
self.type = particle_type # heart, mouse, firework, falling
# 初始化屬性
self.current_size = 0
self.current_alpha = 0
# 根據(jù)粒子類型設(shè)置屬性
if particle_type == "heart":
self.setup_heart_particle()
elif particle_type == "mouse":
self.setup_mouse_particle()
elif particle_type == "firework":
self.setup_firework_particle()
else: # falling
self.setup_falling_particle()
# 煙花粒子延遲效果
if particle_type == "firework":
self.delay = random.random() * 15
self.is_active = False
def setup_heart_particle(self) -> None:
"""初始化心形粒子屬性"""
self.layer = random.randint(0, 3) # 粒子層次
# 根據(jù)層次選擇顏色
color_pools = [
particle_colors[0:3], # 外層
particle_colors[3:6], # 中層
particle_colors[6:9], # 內(nèi)層
particle_colors[9:], # 中心
]
self.color = random.choice(color_pools[self.layer])
# 根據(jù)層次設(shè)置大小和速度
self.size = 2 + random.random() * (8 - self.layer * 2)
self.speed = 0.1 + random.random() * 0.3 + self.layer * 0.05
self.angle = random.random() * math.pi * 2 # 隨機(jī)方向
# 生命周期
self.life = 150 + random.random() * 100 - self.layer * 30
self.max_life = self.life
def setup_mouse_particle(self) -> None:
"""初始化鼠標(biāo)軌跡粒子屬性"""
self.color = random.choice(particle_colors)
self.size = 1 + random.random() * 3
self.speed = 0.05 + random.random() * 0.1 # 較慢速度
self.angle = random.random() * math.pi * 2
self.life = 100 + random.random() * 80 # 較長(zhǎng)壽命
self.max_life = self.life
def setup_firework_particle(self) -> None:
"""初始化煙花粒子屬性"""
self.color = random.choice(particle_colors)
self.size = 1.5 + random.random() * 4
self.base_speed = 2 + random.random() * 3 # 較高初始速度
self.angle = random.random() * math.pi * 2
self.life = 100 + random.random() * 80
self.max_life = self.life
self.gravity = 0.05 # 重力
self.friction = 0.97 + random.random() * 0.01 # 摩擦力
# 笛卡爾坐標(biāo)速度
self.vx = math.cos(self.angle) * self.base_speed
self.vy = math.sin(self.angle) * self.base_speed
def setup_falling_particle(self) -> None:
"""初始化墜落粒子屬性"""
self.color = random.choice(particle_colors)
self.size = 0.5 + random.random() * 2
self.speed = 0.5 + random.random() * 1.5
# 主要向下的角度
self.angle = math.pi + (random.random() - 0.5) * math.pi * 0.6
self.life = 80 + random.random() * 120
self.max_life = self.life
self.gravity = 0.03 # 重力
self.wind = (random.random() - 0.5) * 0.003 # 風(fēng)力
def update(self) -> None:
"""更新粒子狀態(tài)"""
# 煙花粒子延遲激活
if self.type == "firework" and not self.is_active:
self.delay -= 1
if self.delay <= 0:
self.is_active = True
return
# 煙花粒子物理模擬
if self.type == "firework" and self.is_active:
self.vx *= self.friction # 摩擦力
self.vy += self.gravity # 重力
self.x += self.vx
self.y += self.vy
# 轉(zhuǎn)換為墜落粒子
if abs(self.vy) > 0.3 and random.random() < 0.08 and self.life > 40:
self.type = "falling"
self.setup_falling_particle()
else:
# 其他粒子使用極坐標(biāo)移動(dòng)
self.x += math.cos(self.angle) * self.speed
self.y += math.sin(self.angle) * self.speed
# 墜落粒子額外處理
if self.type == "falling":
self.speed += self.gravity
self.x += self.wind
# 生命周期遞減
self.life -= 1
# 心跳效果 - 大小和透明度變化
heartbeat_phase = (pygame.time.get_ticks() / 800) % (math.pi * 2)
heartbeat_factor = 1.0 + 0.15 * math.sin(heartbeat_phase)
if self.type == "heart":
self.current_size = (
self.size * heartbeat_factor * (self.life / self.max_life)
)
self.current_alpha = (self.life / self.max_life) * (
0.8 + 0.2 * math.sin(heartbeat_phase + self.layer * 0.5)
)
else:
self.current_size = self.size * (self.life / self.max_life)
self.current_alpha = self.life / self.max_life
def draw(self) -> None:
"""繪制粒子"""
if self.type == "firework" and not self.is_active:
return
# 確保透明度在有效范圍內(nèi)
r, g, b = self.color
alpha = max(0, min(255, int(255 * self.current_alpha)))
if alpha > 0: # 只繪制可見(jiàn)粒子
# 創(chuàng)建帶透明度的表面
size = max(0.5, self.current_size) # 確保大小至少為0.5
surf = pygame.Surface((int(size * 2), int(size * 2)), pygame.SRCALPHA)
pygame.draw.circle(
surf, (r, g, b, alpha), (int(size), int(size)), int(size)
)
screen.blit(surf, (self.x - size, self.y - size))
def is_alive(self) -> bool:
"""檢查粒子是否存活"""
return self.life > 0
# 心形動(dòng)畫(huà)類
class HeartAnimation:
def __init__(self):
self.particles: List[Particle] = []
self.is_paused = False
self.mouse = {"x": WIDTH // 2, "y": HEIGHT // 2, "is_down": False}
self.particle_count = 0
self.heart_particle_count = 1000 # 心形粒子目標(biāo)數(shù)量
self.heart_regen_rate = 5 # 每幀再生數(shù)量
# 生成初始心形粒子
self.generate_heart_particles(self.heart_particle_count)
def is_inside_heart(self, x: float, y: float, scale: float = 1.0) -> bool:
"""判斷點(diǎn)是否在心形內(nèi)部"""
center_x, center_y = WIDTH // 2, HEIGHT // 2
nx = (x - center_x) / (WIDTH / 2)
ny = (y - center_y) / (HEIGHT / 2)
# 心形方程: (x2 + y2 - 1)3 - x2y3 ≤ 0
heart_eq = (nx**2 + ny**2 - 1) ** 3 - nx**2 * ny**3
return heart_eq <= 0
def generate_heart_point(self, t: float, scale: float = 1.0) -> Dict[str, float]:
"""生成心形參數(shù)方程的點(diǎn)"""
# 心形參數(shù)方程: x=16sin3t, y=13cost-5cos2t-2cos3t-cos4t
x = 16 * math.sin(t) ** 3
y = (
13 * math.cos(t)
- 5 * math.cos(2 * t)
- 2 * math.cos(3 * t)
- math.cos(4 * t)
)
# 映射到畫(huà)布中心并縮放
center_x, center_y = WIDTH // 2, HEIGHT // 2
heart_scale = min(WIDTH, HEIGHT) * 0.35 * scale
return {
"x": center_x + x * heart_scale / 16,
"y": center_y - y * heart_scale / 16, # 反轉(zhuǎn)y軸
}
def generate_heart_particles(self, count: int) -> None:
"""生成心形粒子"""
for _ in range(count):
layer = random.randint(0, 3) # 隨機(jī)層次
# 根據(jù)層次設(shè)置縮放
if layer == 0:
scale = 1.0 # 外層
elif layer == 1:
scale = 0.95 # 中層
elif layer == 2:
scale = 0.85 # 內(nèi)層
else:
scale = 0.7 # 中心層
t = random.random() * math.pi * 2 # 隨機(jī)角度
point = self.generate_heart_point(t, scale)
# 中心層添加隨機(jī)偏移
if layer == 3:
offset = random.random() * 0.2 * (WIDTH / 2)
point["x"] += (random.random() - 0.5) * offset
point["y"] += (random.random() - 0.5) * offset
# 確保點(diǎn)在心形內(nèi)
if not self.is_inside_heart(point["x"], point["y"]):
continue
# 創(chuàng)建粒子
self.particles.append(Particle(point["x"], point["y"], "heart"))
self.update_particle_count()
def regenerate_heart_particles(self, count: int) -> None:
"""再生心形粒子"""
for _ in range(count):
layer = random.randint(0, 3)
scale = (
1.0
if layer == 0
else 0.95 if layer == 1 else 0.85 if layer == 2 else 0.7
)
t = random.random() * math.pi * 2
point = self.generate_heart_point(t, scale)
if layer == 3:
offset = random.random() * 0.2 * (WIDTH / 2)
point["x"] += (random.random() - 0.5) * offset
point["y"] += (random.random() - 0.5) * offset
if not self.is_inside_heart(point["x"], point["y"]):
continue
self.particles.append(Particle(point["x"], point["y"], "heart"))
def handle_mouse_move(self, x: int, y: int) -> None:
"""處理鼠標(biāo)移動(dòng)"""
self.mouse["x"] = x
self.mouse["y"] = y
# 生成鼠標(biāo)軌跡粒子
for _ in range(6): # 生成多個(gè)粒子形成連續(xù)軌跡
offset_x = (random.random() - 0.5) * 20
offset_y = (random.random() - 0.5) * 20
self.particles.append(
Particle(
self.mouse["x"] + offset_x, self.mouse["y"] + offset_y, "mouse"
)
)
self.update_particle_count()
def handle_mouse_down(self) -> None:
"""處理鼠標(biāo)按下 - 創(chuàng)建煙花"""
self.mouse["is_down"] = True
self.create_firework(self.mouse["x"], self.mouse["y"])
def handle_mouse_up(self) -> None:
"""處理鼠標(biāo)釋放"""
self.mouse["is_down"] = False
def create_firework(self, x: float, y: float) -> None:
"""創(chuàng)建煙花效果"""
# 主爆炸
self.create_firework_wave(x, y, 180, 0)
# 延遲爆炸 - 外層
pygame.time.set_timer(pygame.USEREVENT + 1, 150, True)
# 精細(xì)粒子
pygame.time.set_timer(pygame.USEREVENT + 2, 250, True)
self.update_particle_count()
def create_firework_wave(
self,
x: float,
y: float,
count: int,
base_delay: int,
fine_particles: bool = False,
speed_multiplier: float = 1.0,
) -> None:
"""創(chuàng)建一波煙花粒子"""
for _ in range(count):
p = Particle(x, y, "firework")
if fine_particles:
p.size = 0.5 + random.random() * 1.5
p.base_speed = 1.5 + random.random() * 2
p.life = 80 + random.random() * 60
else:
p.size = 1 + random.random() * 3
p.base_speed = (2 + random.random() * 3) * speed_multiplier
p.delay = base_delay + random.random() * 10
p.vx = math.cos(p.angle) * p.base_speed
p.vy = math.sin(p.angle) * p.base_speed
self.particles.append(p)
def handle_reset(self) -> None:
"""重置動(dòng)畫(huà)"""
self.particles = []
self.generate_heart_particles(self.heart_particle_count)
def handle_pause(self) -> None:
"""暫停/繼續(xù)動(dòng)畫(huà)"""
self.is_paused = not self.is_paused
def handle_increase(self) -> None:
"""增加粒子數(shù)量"""
self.heart_particle_count += 200
self.generate_heart_particles(200)
def handle_decrease(self) -> None:
"""減少粒子數(shù)量"""
if self.heart_particle_count > 200:
self.heart_particle_count -= 200
# 移除舊的心形粒子
removed = 0
for i in range(len(self.particles) - 1, -1, -1):
if self.particles[i].type == "heart":
self.particles.pop(i)
removed += 1
if removed >= 200:
break
self.update_particle_count()
def update_particle_count(self) -> None:
"""更新粒子數(shù)量顯示"""
self.particle_count = len(self.particles)
def draw_ui(self) -> None:
"""繪制用戶界面"""
# 標(biāo)題
title = font.render("心之律動(dòng)", True, (255, 255, 255))
subtitle = font.render("鼠標(biāo)移動(dòng)生成軌跡,點(diǎn)擊釋放煙花", True, (230, 230, 230))
screen.blit(title, (WIDTH // 2 - title.get_width() // 2, 20))
screen.blit(subtitle, (WIDTH // 2 - subtitle.get_width() // 2, 55))
# 粒子數(shù)量
particle_count_text = font.render(
f"粒子數(shù)量: {self.particle_count}", True, (255, 255, 255)
)
screen.blit(particle_count_text, (20, 20))
# 操作提示
help_text1 = font.render(
"R: 重置 | P: 暫停 | +: 增加粒子 | -: 減少粒子", True, (200, 200, 200)
)
screen.blit(help_text1, (WIDTH // 2 - help_text1.get_width() // 2, HEIGHT - 40))
# 主函數(shù)
def main():
clock = pygame.time.Clock()
heart_animation = HeartAnimation()
# 主循環(huán)
running = True
while running:
# 事件處理
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEMOTION:
heart_animation.handle_mouse_move(event.pos[0], event.pos[1])
elif event.type == pygame.MOUSEBUTTONDOWN:
heart_animation.handle_mouse_down()
elif event.type == pygame.MOUSEBUTTONUP:
heart_animation.handle_mouse_up()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
heart_animation.handle_reset()
elif event.key == pygame.K_p:
heart_animation.handle_pause()
elif event.key == pygame.K_PLUS or event.key == pygame.K_KP_PLUS:
heart_animation.handle_increase()
elif event.key == pygame.K_MINUS or event.key == pygame.K_KP_MINUS:
heart_animation.handle_decrease()
elif event.type == pygame.USEREVENT + 1: # 延遲煙花
heart_animation.create_firework_wave(
heart_animation.mouse["x"],
heart_animation.mouse["y"],
120,
10,
False,
1.5,
)
elif event.type == pygame.USEREVENT + 2: # 精細(xì)粒子
heart_animation.create_firework_wave(
heart_animation.mouse["x"],
heart_animation.mouse["y"],
150,
15,
True,
)
# 填充背景
screen.fill((26, 26, 46)) # 深色背景
# 更新和繪制粒子
if not heart_animation.is_paused:
# 更新粒子
for i in range(len(heart_animation.particles) - 1, -1, -1):
heart_animation.particles[i].update()
if not heart_animation.particles[i].is_alive():
heart_animation.particles.pop(i)
# 補(bǔ)充心形粒子
heart_count = sum(1 for p in heart_animation.particles if p.type == "heart")
if heart_count < heart_animation.heart_particle_count:
to_add = min(
heart_animation.heart_regen_rate,
heart_animation.heart_particle_count - heart_count,
)
heart_animation.regenerate_heart_particles(to_add)
# 繪制所有粒子
for particle in heart_animation.particles:
particle.draw()
# 繪制UI
heart_animation.draw_ui()
# 更新顯示
pygame.display.flip()
# 控制幀率
clock.tick(60)
pygame.quit()
sys.exit()
if __name__ == "__main__":
main()以上就是Pygame用數(shù)學(xué)公式實(shí)現(xiàn)心之律動(dòng)動(dòng)畫(huà)的詳細(xì)內(nèi)容,更多關(guān)于Pygame心之律動(dòng)動(dòng)畫(huà)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Python 基于 pygame 實(shí)現(xiàn)輪播圖動(dòng)畫(huà)效果
- 使用python+pygame實(shí)現(xiàn)中秋節(jié)動(dòng)畫(huà)效果
- Pygame淺析動(dòng)畫(huà)精靈和碰撞檢測(cè)實(shí)現(xiàn)方法
- Python+Pygame實(shí)現(xiàn)代碼雨動(dòng)畫(huà)效果
- Python pygame 動(dòng)畫(huà)游戲循環(huán)游戲時(shí)鐘實(shí)現(xiàn)原理
- Python?pygame項(xiàng)目實(shí)戰(zhàn)英雄動(dòng)畫(huà)特效實(shí)現(xiàn)
相關(guān)文章
Python自動(dòng)化導(dǎo)出zabbix數(shù)據(jù)并發(fā)郵件腳本
這篇文章主要介紹了Python自動(dòng)化導(dǎo)出zabbix數(shù)據(jù)并發(fā)郵件腳本,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08
深入理解NumPy 的 np.column_stack的實(shí)現(xiàn)
本文主要介紹了NumPy 的 np.column_stack的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2026-01-01
Python實(shí)現(xiàn)采集網(wǎng)站ip代理并檢測(cè)是否可用
這篇文章主要介紹了如何利用Python爬蟲(chóng)實(shí)現(xiàn)采集網(wǎng)站ip代理,并檢測(cè)IP代理是否可用。文中的示例代碼講解詳細(xì),感興趣的可以試一試2022-01-01
詳解LyScript 內(nèi)存掃描與查殼實(shí)現(xiàn)
這篇文章主要為大家介紹了詳解LyScript 內(nèi)存掃描與查殼實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
Python使用BeautifulSoup庫(kù)解析網(wǎng)頁(yè)
在Python的網(wǎng)絡(luò)爬蟲(chóng)中,網(wǎng)頁(yè)解析是一項(xiàng)重要的技術(shù)。而在眾多的網(wǎng)頁(yè)解析庫(kù)中,BeautifulSoup庫(kù)憑借其簡(jiǎn)單易用而廣受歡迎,在本篇文章中,我們將學(xué)習(xí)BeautifulSoup庫(kù)的基本用法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2023-08-08
詳解tensorflow實(shí)現(xiàn)遷移學(xué)習(xí)實(shí)例
本篇文章主要介紹了詳解tensorflow實(shí)現(xiàn)遷移學(xué)習(xí)實(shí)例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02

