Python使用Pygame實(shí)現(xiàn)一個(gè)簡易節(jié)奏點(diǎn)擊游戲
項(xiàng)目概述
本文通過 Pygame 實(shí)現(xiàn)一個(gè)簡化版節(jié)奏音游(Rhythm Game)。
游戲畫面由四條縱向軌道組成,音符從頂部不斷下落,在抵達(dá)底部判定線時(shí)按下對應(yīng)按鍵即可得分。連擊越高分?jǐn)?shù)倍率越大,隨游戲時(shí)間推進(jìn)音符下落速度自動加快,血量耗盡(Miss 過多)即游戲結(jié)束。其中:
- 四軌操作:D、F、J、K 四鍵分別對應(yīng)四條軌道,符合主流音游的手指分布習(xí)慣。
- 判定等級:落點(diǎn)與判定線偏差 <20px 為 Perfect(得 300 分),<50px 為 Good(得 100 分),超出范圍未接為 Miss(扣血 10 點(diǎn))。
- 連擊倍率:當(dāng)前連擊數(shù)每滿 10 次,分?jǐn)?shù)倍率 +1,鼓勵保持連擊。
- 變速機(jī)制:音符基礎(chǔ)速度為 5px/幀,隨游戲時(shí)長線性遞增(每秒 +0.03px/幀),越到后期越考驗(yàn)反應(yīng)。
- 隨機(jī)節(jié)拍:每拍隨機(jī)選取 1–2 條軌道生成音符,下一拍間隔在 0.5、1.0、1.5 拍中隨機(jī)選取,節(jié)奏感豐富不單調(diào)。
- 音效反饋:命中時(shí)播放對應(yīng)軌道音調(diào)的短促音效(由程序?qū)崟r(shí)合成,無需外部音頻文件)。
- 粒子特效:命中時(shí)在判定線處爆發(fā)彩色粒子,帶有重力與透明度衰減,視覺反饋直觀。
- 血量系統(tǒng):HP 條實(shí)時(shí)顯示,低于 30 時(shí)變紅警示;歸零即觸發(fā)游戲結(jié)束畫面。
- 鍵盤操作:D/F/J/K:打擊對應(yīng)軌道;R:重新開始;ESC:退出。
游戲?qū)崿F(xiàn)

初始化與基礎(chǔ)設(shè)置
游戲啟動時(shí)初始化 Pygame 及混音器,并定義窗口尺寸、軌道布局和顏色常量。
pygame.init() pygame.mixer.init(frequency=44100, size=-16, channels=2, buffer=512) W, H = 480, 680 FPS = 60 LANES = 4 LANE_W = 90 LANE_GAP = 10 TOTAL_W = LANES * LANE_W + (LANES-1) * LANE_GAP OFFSET_X = (W - TOTAL_W) // 2 JUDGE_Y = H - 110 NOTE_H = 22 NOTE_SPD = 5
pygame.mixer.init 的參數(shù)需精確指定:frequency=44100(CD 音質(zhì)采樣率)、size=-16(有符號 16 位整數(shù))、channels=2(立體聲)、buffer=512(小緩沖區(qū)降低打擊延遲)。四條軌道居中排布,OFFSET_X 自動計(jì)算使軌道組水平居中于窗口。
顏色定義
C_BG = (15, 12, 30) # 深紫黑背景 C_LANE = (30, 25, 55) # 軌道底色 C_NOTE = [(220,80,120),(80,180,220),(120,220,100),(220,180,60)] # 四軌音符色 C_PERFECT = (255, 230, 50) # Perfect 判定文字金黃 C_GOOD = (100, 220, 255) # Good 判定文字藍(lán) C_MISS = (200, 60, 60) # Miss / 游戲結(jié)束紅 C_KEY = [(180,50,90),(50,140,180),(80,180,70),(180,140,40)] # 四軌鍵位底色
整體采用深色背景搭配高飽和度的四色軌道,與音游常見的霓虹風(fēng)格保持一致;判定顏色則沿用大多數(shù)音游的金(Perfect)/ 藍(lán)(Good)/ 紅(Miss)視覺慣例,讓玩家無需學(xué)習(xí)即可理解。
字體加載
CHINESE_FONT_PATH = r"C:/Windows/Fonts/simsun.ttc" FONT_LG = pygame.font.Font(CHINESE_FONT_PATH, 36) # 分?jǐn)?shù) FONT_MD = pygame.font.Font(CHINESE_FONT_PATH, 22) # 連擊 / 鍵位標(biāo)簽 FONT_SM = pygame.font.Font(CHINESE_FONT_PATH, 16) # 小說明文字 FONT_SC = pygame.font.Font(CHINESE_FONT_PATH, 48) # 結(jié)束畫面大字
音效合成
本游戲不依賴任何外部音頻文件,所有音效均由程序?qū)崟r(shí)生成。
def gen_beep(freq=440, duration=0.08, vol=0.4):
sr = 44100
n = int(sr * duration)
buf = bytearray(n * 4)
for i in range(n):
t = i / sr
v = math.sin(2 * math.pi * freq * t) # 正弦波
env = 1.0 - i / n # 線性衰減包絡(luò)
s = int(v * env * vol * 32767)
s = max(-32768, min(32767, s))
buf[i*4] = s & 0xFF
buf[i*4+1] = (s >> 8) & 0xFF
buf[i*4+2] = s & 0xFF
buf[i*4+3] = (s >> 8) & 0xFF
return _make_sound(buf, sr, n)
HIT_SOUNDS = [gen_beep(f) for f in [330, 392, 440, 523]]
核心思路:用 math.sin 生成指定頻率的正弦波,乘以線性衰減包絡(luò) (1 - i/n) 使音符結(jié)尾自然收音,避免爆音。四條軌道對應(yīng) Do–Sol–La–Do(330/392/440/523 Hz)四個(gè)音調(diào),命中時(shí)聲音各有不同,兼具功能性與音樂感。
生成的字節(jié)流通過 numpy 轉(zhuǎn)換為 Pygame 可播放的 Sound 對象。若環(huán)境未安裝 numpy,則靜默降級為無音效模式,游戲仍可正常運(yùn)行。
粒子系統(tǒng)
class Particle:
def __init__(self, x, y, color):
self.x, self.y = x, y
self.vx = random.uniform(-3, 3)
self.vy = random.uniform(-5, -1)
self.life = 1.0
self.color = color
self.r = random.randint(3, 7)
def update(self):
self.x += self.vx
self.y += self.vy
self.vy += 0.2 # 重力加速度
self.life -= 0.04
return self.life > 0 # 返回 False 表示粒子已消亡
def draw(self, surf):
a = int(self.life * 255)
s = pygame.Surface((self.r*2, self.r*2), pygame.SRCALPHA)
pygame.draw.circle(s, (*self.color, a), (self.r, self.r), self.r)
surf.blit(s, (self.x - self.r, self.y - self.r))
粒子初始化時(shí)隨機(jī)設(shè)定水平速度與向上的初速度,update 中模擬重力(每幀 vy += 0.2),使粒子呈拋物線軌跡散開;life 從 1.0 每幀減少 0.04,約 25 幀(0.4 秒)后消亡,并同步映射到 alpha 透明度,產(chǎn)生自然淡出效果。
命中時(shí)在判定線位置一次性生成 12 顆粒子,顏色與軌道音符色一致,強(qiáng)化每條軌道的視覺辨識度:
for _ in range(12):
particles.append(Particle(lx, JUDGE_Y, C_NOTE[li]))
主循環(huán)中用列表推導(dǎo)式原地過濾消亡粒子,保持寫法簡潔:
particles = [p for p in particles if p.update()]
音符生成與節(jié)拍調(diào)度
def spawn_note(lane, speed):
return {"lane": lane, "y": -NOTE_H, "speed": speed}
音符以字典形式存儲,y 初始為 -NOTE_H(屏幕頂部之外),避免生成瞬間可見的跳變。
節(jié)拍調(diào)度在主循環(huán)中通過 frame_time 累計(jì)游戲時(shí)間控制:
if frame_time >= next_beat:
lane_count = random.randint(1, 2)
lanes_to_spawn = random.sample(range(LANES), lane_count)
for l in lanes_to_spawn:
notes.append(spawn_note(l, speed))
total_notes += 1
next_beat = frame_time + beat_interval * random.choice([0.5, 1.0, 1.0, 1.5])
speed = NOTE_SPD + frame_time * 0.03
每拍隨機(jī)決定本次生成 1 或 2 個(gè)音符,再從四條軌道中無重復(fù)地抽?。?code>random.sample 保證同一時(shí)刻同一軌道不出現(xiàn)兩個(gè)音符)。下一拍間隔在 0.5/1.0/1.5 拍中隨機(jī)選取,其中 1.0 拍權(quán)重更高,兼顧規(guī)律感與變化性。速度公式 NOTE_SPD + frame_time * 0.03 使難度隨時(shí)間平滑線性遞增。
判定系統(tǒng)
for li, k in enumerate(KEYS):
if event.key == k:
key_press_alpha[li] = 1.0
targets = [n for n in notes if n["lane"] == li]
if targets:
closest = min(targets, key=lambda n: abs(n["y"] - JUDGE_Y))
dist = abs(closest["y"] - JUDGE_Y)
if dist < 50:
rating = "Perfect" if dist < 20 else "Good"
notes.remove(closest)
sc = 300 if rating == "Perfect" else 100
combo += 1
score += sc * (1 + combo // 10)
...
按鍵觸發(fā)時(shí),先篩選出當(dāng)前軌道所有音符,再取距判定線最近的一個(gè)作為目標(biāo)(避免多音符同軌時(shí)誤判),按偏差距離分級:<20px 為 Perfect,<50px 為 Good,超出范圍視為空按(不扣分但不得分)。超過判定線 60px 的音符在 update 中自動判為 Miss 并扣血:
if n["y"] > JUDGE_Y + 60:
notes.remove(n)
stats["Miss"] += 1
combo = 0
hp -= 10
連擊加分公式 sc * (1 + combo // 10) 使連擊每滿 10 次倍率遞增 1,高連擊時(shí)分?jǐn)?shù)增長顯著加速,提供充足的追分動力。
繪制方法
按鍵高亮與軌道
for i in range(LANES):
lx = OFFSET_X + i * (LANE_W + LANE_GAP)
col = tuple(min(255, c + int(key_press_alpha[i] * 40)) for c in C_LANE)
pygame.draw.rect(screen, col, (lx, 60, LANE_W, H-160), border_radius=6)
kc = tuple(min(255, c + int(key_press_alpha[i] * 80)) for c in C_KEY[i])
kr = pygame.Rect(lx, JUDGE_Y + NOTE_H + 6, LANE_W, 38)
pygame.draw.rect(screen, kc, kr, border_radius=8)
key_press_alpha 在按鍵時(shí)置 1.0,每幀減少 0.15(約 7 幀淡出),軌道背景色和鍵位按鈕色均疊加該值對應(yīng)的亮度偏移,形成按下時(shí)一亮隨即漸暗的視覺反饋,而無需單獨(dú)管理高亮狀態(tài)。
音符渲染
r = pygame.Rect(lx + 4, n["y"], LANE_W - 8, NOTE_H)
pygame.draw.rect(screen, C_NOTE[i], r, border_radius=6)
pygame.draw.rect(screen, tuple(min(255, c+60) for c in C_NOTE[i]),
(r.x+4, r.y+3, r.w-8, 5), border_radius=3)
音符兩側(cè)各縮進(jìn) 4px 與軌道邊緣留出間距;頂部疊加一條更亮的高光條(顏色各通道 +60,寬度更窄),模擬光澤感,使平面矩形顯得更有立體質(zhì)感。
判定文字動畫
if judge_timer > 0:
alpha = min(255, judge_timer * 8)
jt = FONT_MD.render(judge_text, True, judge_color)
screen.blit(jt, jt.get_rect(centerx=W//2, y=JUDGE_Y - 50))
judge_timer -= 1
judge_timer 在命中時(shí)設(shè)為 40(Perfect/Good)或 30(Miss),每幀 -1 直至歸零,文字隨之淡出。顯示位置固定在判定線上方,不遮擋音符下落區(qū)域。
HP 條
hp_w = int((W - 40) * hp / 100)
pygame.draw.rect(screen, (60, 30, 30), (20, H-40, W-40, 16), border_radius=8)
pygame.draw.rect(screen, (220,80,80) if hp < 30 else (80,200,100),
(20, H-40, hp_w, 16), border_radius=8)
先繪制深紅色底條(滿寬),再繪制隨 HP 值縮短的前景條。HP 低于 30 時(shí)前景色由綠轉(zhuǎn)紅,給玩家直觀的危險(xiǎn)警示。
游戲結(jié)束遮罩
if game_over:
ov = pygame.Surface((W, H), pygame.SRCALPHA)
ov.fill((0, 0, 0, 160))
screen.blit(ov, (0, 0))
box = pygame.Rect(W//2-170, H//2-110, 340, 230)
pygame.draw.rect(screen, (25, 20, 50), box, border_radius=16)
pygame.draw.rect(screen, C_PERFECT, box, 2, border_radius=16)
lines = [
(FONT_LG, "GAME OVER", C_MISS, -70),
(FONT_MD, f"分?jǐn)?shù): {score:,}", C_TEXT, -20),
(FONT_SM, f"Perfect/Good/Miss 統(tǒng)計(jì)", C_GREY, 20),
(FONT_SM, f"最高連擊: {max_combo}", C_PERFECT, 50),
(FONT_SM, "按 R 重新開始", C_TEXT, 90),
]
for font, text, color, dy in lines:
t = font.render(text, True, color)
screen.blit(t, t.get_rect(centerx=W//2, centery=H//2+dy))
結(jié)束彈窗通過 lines 列表統(tǒng)一管理各行文字的字體、內(nèi)容、顏色和垂直偏移,便于增減條目而不影響整體布局。
繪制順序?yàn)椋罕尘?→ 軌道 → 判定線 → 音符 → 粒子 → UI(分?jǐn)?shù)/連擊/HP/判定文字)→ 游戲結(jié)束遮罩,嚴(yán)格保證層次正確。
主循環(huán) main:
while True:
dt = clock.tick(FPS) / 1000.0
frame_time += dt
# 事件處理 ...
# 邏輯更新 ...
# 繪制 ...
pygame.display.flip()
clock.tick(FPS) 返回距上次調(diào)用的毫秒數(shù),轉(zhuǎn)換為秒后累加到 frame_time,所有時(shí)間相關(guān)邏輯(節(jié)拍調(diào)度、速度計(jì)算)均基于此,與幀率無關(guān),保證不同性能機(jī)器上游戲節(jié)奏一致。
全部代碼
"""
節(jié)奏點(diǎn)擊 — 簡化音游
下落音符到達(dá)判定線時(shí)按對應(yīng)鍵(D F J K)
評分:Perfect / Good / Miss
"""
import pygame
import sys
import random
import math
pygame.init()
pygame.mixer.init(frequency=44100, size=-16, channels=2, buffer=512)
W, H = 480, 680
FPS = 60
# 軌道設(shè)置
LANES = 4
LANE_W = 90
LANE_GAP = 10
TOTAL_W = LANES * LANE_W + (LANES-1) * LANE_GAP
OFFSET_X = (W - TOTAL_W) // 2
JUDGE_Y = H - 110
NOTE_H = 22
NOTE_SPD = 5 # 像素/幀(基礎(chǔ)速度)
KEYS = [pygame.K_d, pygame.K_f, pygame.K_j, pygame.K_k]
KEY_LABELS = ["D", "F", "J", "K"]
C_BG = (15, 12, 30)
C_LANE = (30, 25, 55)
C_LANE_HL = (50, 40, 90)
C_NOTE = [(220, 80, 120), (80, 180, 220), (120, 220, 100), (220, 180, 60)]
C_JUDGE = (255, 255, 255)
C_PERFECT = (255, 230, 50)
C_GOOD = (100, 220, 255)
C_MISS = (200, 60, 60)
C_TEXT = (220, 220, 255)
C_GREY = (100, 100, 130)
C_KEY = [(180, 50, 90), (50, 140, 180), (80, 180, 70), (180, 140, 40)]
CHINESE_FONT_PATH = r"C:/Windows/Fonts/simsun.ttc"
FONT_LG = pygame.font.Font(CHINESE_FONT_PATH, 36)
FONT_MD = pygame.font.Font(CHINESE_FONT_PATH, 22)
FONT_SM = pygame.font.Font(CHINESE_FONT_PATH, 16)
FONT_SC = pygame.font.Font(CHINESE_FONT_PATH, 48)
# ── 音效生成 ─────────────────────────────────────────────────────────
def gen_beep(freq=440, duration=0.08, vol=0.4):
sr = 44100
n = int(sr * duration)
buf = bytearray(n * 4)
for i in range(n):
t = i / sr
v = math.sin(2 * math.pi * freq * t)
env = 1.0 - i / n
s = int(v * env * vol * 32767)
s = max(-32768, min(32767, s))
buf[i*4] = s & 0xFF
buf[i*4+1] = (s >> 8) & 0xFF
buf[i*4+2] = s & 0xFF
buf[i*4+3] = (s >> 8) & 0xFF
return pygame.sndarray.make_sound(
pygame.sndarray.array(pygame.mixer.Sound(buffer=bytes(buf)))
) if False else _make_sound(buf, sr, n)
def _make_sound(buf, sr, n):
import numpy as np
arr = np.frombuffer(bytes(buf), dtype=np.int16).reshape((n, 2))
snd = pygame.sndarray.make_sound(arr)
return snd
try:
import numpy as np
HIT_SOUNDS = [gen_beep(f) for f in [330, 392, 440, 523]]
except ImportError:
HIT_SOUNDS = [None] * 4
# ── 粒子系統(tǒng) ─────────────────────────────────────────────────────────
class Particle:
def __init__(self, x, y, color):
self.x, self.y = x, y
self.vx = random.uniform(-3, 3)
self.vy = random.uniform(-5, -1)
self.life = 1.0
self.color = color
self.r = random.randint(3, 7)
def update(self):
self.x += self.vx
self.y += self.vy
self.vy += 0.2
self.life -= 0.04
return self.life > 0
def draw(self, surf):
a = int(self.life * 255)
s = pygame.Surface((self.r*2, self.r*2), pygame.SRCALPHA)
pygame.draw.circle(s, (*self.color, a), (self.r, self.r), self.r)
surf.blit(s, (self.x - self.r, self.y - self.r))
# ── 音符生成器 ───────────────────────────────────────────────────────
def spawn_note(lane, speed):
return {"lane": lane, "y": -NOTE_H, "speed": speed}
# ── 主循環(huán) ────────────────────────────────────────────────────────────
def main():
screen = pygame.display.set_mode((W, H))
pygame.display.set_caption("節(jié)奏點(diǎn)擊")
clock = pygame.time.Clock()
notes = []
particles = []
score = 0
combo = 0
max_combo = 0
stats = {"Perfect": 0, "Good": 0, "Miss": 0}
game_over = False
total_notes = 0
key_press_alpha = [0.0] * LANES # 按鍵高亮
# 生成節(jié)拍時(shí)間表(BPM=120,變速)
bpm = 120
beat_interval = 60 / bpm # 秒/拍
next_beat = 0.5
frame_time = 0.0
speed = NOTE_SPD
judge_text = ""
judge_color = C_PERFECT
judge_timer = 0
hp = 100 # 血量
while True:
dt = clock.tick(FPS) / 1000.0
frame_time += dt
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit(); sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit(); sys.exit()
if event.key == pygame.K_r and game_over:
main(); return
if not game_over:
for li, k in enumerate(KEYS):
if event.key == k:
key_press_alpha[li] = 1.0
# 找最近的音符
targets = [n for n in notes if n["lane"] == li]
if targets:
closest = min(targets, key=lambda n: abs(n["y"] - JUDGE_Y))
dist = abs(closest["y"] - JUDGE_Y)
if dist < 50:
rating = "Perfect" if dist < 20 else "Good"
notes.remove(closest)
sc = 300 if rating == "Perfect" else 100
combo += 1
max_combo = max(max_combo, combo)
score += sc * (1 + combo // 10)
stats[rating] += 1
judge_text = rating
judge_color = C_PERFECT if rating == "Perfect" else C_GOOD
judge_timer = 40
lx = OFFSET_X + li*(LANE_W+LANE_GAP) + LANE_W//2
for _ in range(12):
particles.append(Particle(lx, JUDGE_Y, C_NOTE[li]))
if HIT_SOUNDS[li]:
HIT_SOUNDS[li].play()
if not game_over:
# 生成音符
if frame_time >= next_beat:
lane_count = random.randint(1, 2)
lanes_to_spawn = random.sample(range(LANES), lane_count)
for l in lanes_to_spawn:
notes.append(spawn_note(l, speed))
total_notes += 1
next_beat = frame_time + beat_interval * random.choice([0.5, 1.0, 1.0, 1.5])
# 加速
speed = NOTE_SPD + frame_time * 0.03
# 更新音符
for n in notes[:]:
n["y"] += n["speed"]
if n["y"] > JUDGE_Y + 60:
notes.remove(n)
stats["Miss"] += 1
combo = 0
judge_text = "MISS"
judge_color = C_MISS
judge_timer = 30
hp -= 10
if hp <= 0:
game_over = True
# 更新粒子
particles = [p for p in particles if p.update()]
# 按鍵高亮淡出
for i in range(LANES):
key_press_alpha[i] = max(0, key_press_alpha[i] - 0.15)
if judge_timer > 0:
judge_timer -= 1
# ── 繪制 ──────────────────────────────────────────────────────
screen.fill(C_BG)
# 軌道
for i in range(LANES):
lx = OFFSET_X + i*(LANE_W+LANE_GAP)
col = tuple(min(255, c + int(key_press_alpha[i]*40)) for c in C_LANE)
pygame.draw.rect(screen, col, (lx, 60, LANE_W, H-160), border_radius=6)
# 鍵位標(biāo)簽
kc = tuple(min(255, c+int(key_press_alpha[i]*80)) for c in C_KEY[i])
kr = pygame.Rect(lx, JUDGE_Y+NOTE_H+6, LANE_W, 38)
pygame.draw.rect(screen, kc, kr, border_radius=8)
kt = FONT_MD.render(KEY_LABELS[i], True, C_TEXT)
screen.blit(kt, kt.get_rect(center=kr.center))
# 判定線
pygame.draw.rect(screen, C_JUDGE, (OFFSET_X-4, JUDGE_Y-2, TOTAL_W+8, 5), border_radius=3)
# 音符
for n in notes:
i = n["lane"]
lx = OFFSET_X + i*(LANE_W+LANE_GAP)
r = pygame.Rect(lx+4, n["y"], LANE_W-8, NOTE_H)
pygame.draw.rect(screen, C_NOTE[i], r, border_radius=6)
# 高光
pygame.draw.rect(screen, tuple(min(255,c+60) for c in C_NOTE[i]),
(r.x+4, r.y+3, r.w-8, 5), border_radius=3)
# 粒子
for p in particles:
p.draw(screen)
# UI
sc_t = FONT_LG.render(f"{score:,}", True, C_TEXT)
screen.blit(sc_t, sc_t.get_rect(centerx=W//2, y=8))
combo_t = FONT_MD.render(f"× {combo}" if combo > 1 else "", True, C_PERFECT)
screen.blit(combo_t, combo_t.get_rect(x=10, y=50))
# HP條
hp_w = int((W-40) * hp / 100)
pygame.draw.rect(screen, (60,30,30), (20, H-40, W-40, 16), border_radius=8)
pygame.draw.rect(screen, (220,80,80) if hp < 30 else (80,200,100),
(20, H-40, hp_w, 16), border_radius=8)
# 判定文字
if judge_timer > 0:
alpha = min(255, judge_timer * 8)
jt = FONT_MD.render(judge_text, True, judge_color)
screen.blit(jt, jt.get_rect(centerx=W//2, y=JUDGE_Y-50))
# 時(shí)間/進(jìn)度
ft_t = FONT_SM.render(f"? {int(frame_time)}s 速度×{speed/NOTE_SPD:.1f}", True, C_GREY)
screen.blit(ft_t, (10, H-60))
# 游戲結(jié)束
if game_over:
ov = pygame.Surface((W, H), pygame.SRCALPHA)
ov.fill((0,0,0,160))
screen.blit(ov, (0,0))
box = pygame.Rect(W//2-170, H//2-110, 340, 230)
pygame.draw.rect(screen, (25,20,50), box, border_radius=16)
pygame.draw.rect(screen, C_PERFECT, box, 2, border_radius=16)
lines = [
(FONT_LG, "GAME OVER", C_MISS, -70),
(FONT_MD, f"分?jǐn)?shù): {score:,}", C_TEXT, -20),
(FONT_SM, f"Perfect:{stats['Perfect']} Good:{stats['Good']} Miss:{stats['Miss']}", C_GREY, 20),
(FONT_SM, f"最高連擊: {max_combo}", C_PERFECT, 50),
(FONT_SM, "按 R 重新開始", C_TEXT, 90),
]
for font, text, color, dy in lines:
t = font.render(text, True, color)
screen.blit(t, t.get_rect(centerx=W//2, centery=H//2+dy))
pygame.display.flip()
if __name__ == "__main__":
main()
以上就是Python使用Pygame實(shí)現(xiàn)的簡易節(jié)奏點(diǎn)擊游戲的詳細(xì)內(nèi)容,更多關(guān)于Python Pygame節(jié)奏點(diǎn)擊游戲的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
分享3個(gè)簡單的Python代碼高效運(yùn)行技巧
這篇文章主要介紹了分享3個(gè)簡單的Python代碼高效運(yùn)行技巧,下面主要分享三個(gè)有效的,方便理解的,執(zhí)行高效的實(shí)用技巧,需要的朋友可以參考一下2022-03-03
基于Python開發(fā)一個(gè)選擇題訓(xùn)練工具
選擇題作為一種高效的方式被廣泛應(yīng)用于各類培訓(xùn)與考試中,為了幫助學(xué)生高效學(xué)習(xí)與自測,本篇文章將采用Python編寫一款基于?Python?開發(fā)的選擇題訓(xùn)練工具,需要的可以參考下2024-12-12
python 計(jì)算平均平方誤差(MSE)的實(shí)例
今天小編就為大家分享一篇python 計(jì)算平均平方誤差的實(shí)例 (MSE),具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-06-06
Python使用Spire.XLS創(chuàng)建柱形圖和條形圖
Spire.XLS for Python 提供了便捷的圖表創(chuàng)建功能,讓開發(fā)者能夠僅用幾行代碼就創(chuàng)建各種專業(yè)圖表,下面我們就來看看怎么使用 Spire.XLS 創(chuàng)建柱形圖和條形圖吧2025-07-07
python創(chuàng)建多個(gè)logging日志文件的方法實(shí)現(xiàn)
本文主要介紹了python創(chuàng)建多個(gè)logging日志文件的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
Python urls.py的三種配置寫法實(shí)例詳解
這篇文章主要介紹了Python urls.py的三種配置寫法實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-04-04
win10下tensorflow和matplotlib安裝教程
這篇文章主要為大家詳細(xì)介紹了win10下tensorflow和matplotlib安裝教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-09-09
命令行傳遞參數(shù)argparse.ArgumentParser的使用解析
這篇文章主要介紹了命令行傳遞參數(shù)argparse.ArgumentParser的使用解析,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02
python中內(nèi)置庫os與sys模塊的詳細(xì)介紹
這篇文章主要介紹了python中內(nèi)置庫os與sys模塊的詳細(xì)介紹,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-08-08

