最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python使用Pygame實(shí)現(xiàn)一個(gè)簡易節(jié)奏點(diǎn)擊游戲

 更新時(shí)間:2026年06月12日 09:26:10   作者:Wang ruoxi  
本文通過 Pygame 實(shí)現(xiàn)一個(gè)簡化版節(jié)奏音游(Rhythm Game),游戲畫面由四條縱向軌道組成,音符從頂部不斷下落,在抵達(dá)底部判定線時(shí)按下對應(yīng)按鍵即可得分,感興趣的小伙伴可以自己動手嘗試一下

項(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)文章

最新評論

广德县| 清丰县| 鸡泽县| 昌乐县| 凉城县| 永靖县| 韶山市| 山西省| 车险| 汝城县| 郯城县| 尉犁县| 都昌县| 海丰县| 越西县| 延长县| 屏东县| 康平县| 白城市| 瓦房店市| 文昌市| 邻水| 石屏县| 扶风县| 永春县| 禹城市| 库车县| 政和县| 大庆市| 蓬溪县| 东港市| 宣城市| 台江县| 鄱阳县| 岫岩| 班戈县| 盈江县| 于都县| 青铜峡市| 佛坪县| 类乌齐县|