Python通过Pygame实现一个简化版弹幕射击躲避游戏

 更新时间:2026年06月24日 09:10:22   作者:Wang ruoxi  
本文介绍使用用Pygame实现的弹幕射击游戏,融合五种弹幕模式与血量系统,玩家需通过鼠标操作在满屏弹幕中生存,游戏难度递增,提供丰富操作体验,需要的朋友可以参考下

项目概述

本文通过 Pygame 实现一个简化版弹幕射击躲避游戏(Bullet Hell)。

游戏以鼠标控制玩家小点,在持续涌来的满屏弹幕中生存尽可能长的时间。弹幕按阶段切换模式,难度随生存时间线性提升,血量耗尽即游戏结束。其中:

  • 鼠标操控:玩家小点实时跟随鼠标位置移动,操作直觉自然,无需学习成本。
  • 五种弹幕模式:散射、追踪、旋转、扇形、密集,每隔约 5 秒自动切换,节奏变化丰富。
  • 判定碰撞:玩家判定圆半径仅 8px,子弹半径 5px,碰撞采用圆心距离精确计算,手感宽松不误判。
  • 无敌帧机制:受伤后有 90 帧(约 1.5 秒)无敌时间,玩家有机会脱离危险区域。
  • 血量系统:5 点 HP,以圆形图标逐个展示,低血量时视觉警示明显。
  • 变速机制:子弹基础速度 2.5px/帧,随分数线性递增(每分 +0.008px/帧),越到后期越考验走位。
  • 键盘操作:鼠标点击:开始/重新开始;ESC:退出。

游戏实现

初始化与基础设置

游戏启动时初始化 Pygame,定义窗口尺寸和颜色常量。

pygame.init()

W, H = 600, 680
FPS = 60

PLAYER_R = 8
BULLET_R = 5
INVINCIBLE_TIME = 90   # 帧

PLAYER_RBULLET_R 分别定义玩家与子弹的碰撞半径,两者之和(13px)即为触发碰撞的最大圆心间距。INVINCIBLE_TIME = 90 对应 60FPS 下约 1.5 秒的无敌窗口,保证受击后有足够时间脱身。

颜色定义

C_BG       = (8,   5,  20)
C_PLAYER   = (80, 220, 255)
C_BULLET   = [(255, 80, 120), (255, 180, 50), (120, 255, 150), (180, 100, 255)]
C_HP       = (80, 200, 120)
C_HP_LOW   = (220, 80, 60)
C_SHIELD   = (100, 180, 255)
C_STAR     = (255, 240, 100)

整体延续深色宇宙风格:接近纯黑的深蓝背景搭配高饱和霓虹色子弹,四种弹幕颜色随阶段轮换,让玩家在混乱中仍能直觉分辨当前弹幕模式;玩家以冷蓝色呈现,在暖色弹幕中突出醒目。

子弹类设计

class Bullet:
    def __init__(self, x, y, vx, vy, color_idx=0, r=BULLET_R):
        self.x, self.y = float(x), float(y)
        self.vx, self.vy = vx, vy
        self.color = C_BULLET[color_idx % len(C_BULLET)]
        self.r = r
        self.trail = []

    def update(self):
        self.trail.append((self.x, self.y))
        if len(self.trail) > 6:
            self.trail.pop(0)
        self.x += self.vx
        self.y += self.vy

    def alive(self):
        return -50 < self.x < W+50 and -50 < self.y < H+50

trail 列表保存最近 6 帧的历史坐标,形成拖尾轨迹。每帧先追加当前坐标再移动,保证拖尾始终落后于弹头。alive() 在边界外 50px 才判定为失效,避免子弹在画面边缘突然消失的视觉跳变。

子弹渲染

def draw(self, surf):
    for i, (tx, ty) in enumerate(self.trail):
        a = int(40 * (i+1) / len(self.trail))
        r = max(1, self.r - 2)
        s = pygame.Surface((r*2+1, r*2+1), pygame.SRCALPHA)
        pygame.draw.circle(s, (*self.color, a), (r, r), r)
        surf.blit(s, (tx-r, ty-r))
    pygame.draw.circle(surf, self.color, (int(self.x), int(self.y)), self.r)
    pygame.draw.circle(surf, (255,255,255,200), (int(self.x), int(self.y)), max(1, self.r-2), 1)

拖尾透明度按序号线性递增(最老的帧 alpha 最低),形成渐隐效果。弹头上额外叠加一圈白色高光描边,使子弹在任意背景色下保持清晰可辨的立体感。

粒子系统

class Particle:
    def __init__(self, x, y, color=(255,255,255)):
        self.x, self.y = x, y
        a = random.uniform(0, math.pi*2)
        s = random.uniform(1, 5)
        self.vx, self.vy = math.cos(a)*s, math.sin(a)*s
        self.life = 1.0
        self.color = color
        self.r = random.randint(2, 5)

    def update(self):
        self.x += self.vx
        self.y += self.vy
        self.vx *= 0.92
        self.vy *= 0.92
        self.life -= 0.03
        return self.life > 0

粒子初速度方向随机均匀分布于整个圆周(全向爆炸感),速度大小 1–5px/帧。每帧对速度分量乘以摩擦系数 0.92,模拟空气阻力减速,使粒子在靠近中心时自然刹车而非骤停。life 约 33 帧(0.55 秒)归零,同步控制透明度淡出。

受伤时一次性生成 20 颗红色粒子,数量与颜色共同强调冲击感:

for _ in range(20):
    particles.append(Particle(px, py, (255, 100, 100)))

五种弹幕模式

散射(phase 0)

def spawn_scatter(cx, cy, count, speed, ci):
    bullets = []
    for i in range(count):
        a = (2*math.pi*i/count)
        bullets.append(Bullet(cx, cy, math.cos(a)*speed, math.sin(a)*speed, ci))
    return bullets

以固定角度间隔在 360° 内均匀散射 count 颗子弹,从画面随机边缘点发射。发射源位置随机、圆心均匀,玩家需时刻注意来球方向。随分数提升 count 增大(8 + score//60),后期散射圈数更密。

追踪扇形(phase 1)

def spawn_aimed(px, py, ox, oy, speed, spread=3, ci=0):
    dx, dy = px-ox, py-oy
    for s in range(-spread, spread+1):
        a = math.atan2(dy, dx) + s * 0.15
        bullets.append(Bullet(ox, oy, math.cos(a)*speed, math.sin(a)*speed, ci))

atan2 实时计算玩家方向角,在此基础上以 0.15 弧度(约 8.6°)间隔生成 2*spread+1 颗子弹构成扇形。追踪弹从屏幕左右两侧发射,迫使玩家保持横向走位。

旋转(phase 2)

spin_angle += 0.3
for j in range(3):
    a = spin_angle + j * 2.1
    bullets.append(Bullet(W//2, H//2, math.cos(a)*spd, math.sin(a)*spd, ci))

从画面中心每帧旋转 0.3 弧度(约 17°/帧),以 120° 间隔同时发射 3 颗,形成旋转三叉星弹幕。spin_angle 在主循环中持续累加,弹幕轨迹不断螺旋外扩,玩家须绕圈走位。

顶部扇形(phase 3)

def spawn_fan(cx, cy, base_angle, count, spread, speed, ci):
    for i in range(count):
        a = base_angle - spread/2 + spread*i/(max(1,count-1))
        bullets.append(Bullet(cx, cy, math.cos(a)*speed, math.sin(a)*speed, ci))

在顶部随机 x 坐标向下发射扇形子弹群,基准角加上随机偏转(±0.5 弧度),每次出现方向略有不同。扇形宽度 1.2 弧度、7 颗子弹,覆盖约 69° 的扇面,迫使玩家左右机动躲避。

密集追踪(phase 4)

edge = random.randint(0, 3)
# 根据 edge 决定四条边上的随机发射点
dx, dy = px-cx, py-cy
a = math.atan2(dy, dx)
for k in range(-1, 2):
    bullets.append(Bullet(cx, cy, math.cos(a+k*0.25)*speed, math.sin(a+k*0.25)*speed, ci))

从四条边随机位置向玩家发射三联弹,0.25 弧度(约 14°)偏角形成小扇面覆盖,容错空间极小。四边同时可能出现发射源,叠加前期残余弹幕,后期画面弹幕密度最高。

弹幕调度与难度曲线

phase_timer += 1
if phase_timer > 300 + phase * 20:
    phase = (phase + 1) % 5
    phase_timer = 0

interval = max(8, 30 - score//30)
spd = 2.5 + score * 0.008

每个阶段持续时间随阶段编号递增(300、320、340……帧),使前期阶段切换更频繁、后期单一模式持续更久,考验玩家对特定弹幕的应对深度。发射间隔从 30 帧压缩至最低 8 帧(密度上限约为原来的 4 倍);速度线性递增无上限,理论上游戏难度可以无限提升。

碰撞检测

if math.hypot(b.x-px, b.y-py) < PLAYER_R + b.r - 2:
    bullets.remove(b)
    hp -= 1
    invincible = INVINCIBLE_TIME
    ...

使用 math.hypot 计算圆心距,与两圆半径之和比较。-2 的容差有意将有效碰撞半径缩小 2px,给玩家略多的"擦边而过"空间,降低误判带来的挫败感——这是弹幕游戏的通行设计惯例。无敌帧期间完全跳过碰撞检测,受击子弹不被移除(避免无敌时无意"吃掉"更多子弹后重置无敌计时)。

玩家渲染与无敌反馈

pc = C_PLAYER if invincible == 0 else (
    C_SHIELD if shield > 0 else
    ((255,255,255) if (invincible//5)%2 else C_PLAYER)
)
# 光晕
glow = pygame.Surface((PLAYER_R*6, PLAYER_R*6), pygame.SRCALPHA)
pygame.draw.circle(glow, (*pc, 40), (PLAYER_R*3, PLAYER_R*3), PLAYER_R*3)
screen.blit(glow, (px-PLAYER_R*3, py-PLAYER_R*3))
pygame.draw.circle(screen, pc, (px, py), PLAYER_R)
pygame.draw.circle(screen, C_PLAYER_C, (px, py), 3)

无敌状态下玩家每 5 帧切换一次颜色(白色/原色交替),产生规律闪烁,让玩家和观看者清晰感知无敌持续时间。内圈叠加浅色中心点强调判定核心位置,提醒玩家真正需要避开的是这个核心。半径 3 倍的半透明光晕以 alpha=40 叠加,增强玩家在深色背景上的辨识度。

星空背景

STARS = [(random.randint(0,W), random.randint(0,H), random.random()*2+1) for _ in range(80)]

def draw_stars(surf, t):
    for sx, sy, sr in STARS:
        a = int((math.sin(t*0.02 + sx) * 0.5 + 0.5) * 180 + 60)
        pygame.draw.circle(surf, (a, a, a), (sx, sy), int(sr))

80 颗星点在初始化时一次性随机生成并固定位置,运行时零额外内存分配。亮度以 math.sin(t*0.02 + sx) 随帧数缓慢变化,每颗星的 sx 作为相位偏移,使星点彼此错开闪烁节奏而非同步。亮度映射到 60–240 区间,避免全灭或过曝。

绘制层次

绘制顺序为:星空背景 → 粒子 → 子弹(含拖尾)→ 玩家(光晕 + 实体) → UI(分数/HP/阶段提示/最高分)→ 游戏结束遮罩。严格保证层次正确,玩家始终在子弹之上以便定位,UI 文字不被弹幕遮挡。

HP 圆形图标

for i in range(max_hp):
    hc = (C_HP if i < hp else (40, 40, 60))
    pygame.draw.circle(screen, hc, (20 + i*26, 24), 10)
    if i < hp:
        pygame.draw.circle(screen, (200,255,220), (20 + i*26, 24), 4)

以离散圆形代替条状血条,每格代表一条命,视觉上比百分比更直观。现存 HP 内叠加浅色中心点,视觉上强调"满格"状态;空格以暗色填充表示消耗,无需额外文字说明。

游戏结束弹窗

lines = [
    (FONT_LG, "GAME OVER", C_BULLET[0], -55),
    (FONT_MD, f"生存时间:{score} 分", C_TEXT, 0),
    (FONT_MD, f"最高纪录:{best} 分", C_STAR, 35),
    (FONT_SM, "点击鼠标重新开始", C_GREY, 80),
]
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))

best 变量在整个进程生命周期内保留最高分(死亡后不重置),鼓励玩家反复挑战自己记录。弹窗背景以半透明黑色遮罩叠加在游戏画面之上而非清空屏幕,让玩家在结算界面仍能看到"最后的弹幕",增强现场感。

主循环

while True:
    mx, my = pygame.mouse.get_pos()
    dt = clock.tick(FPS) / 1000.0
    frame += 1
    score = frame // 6

score 直接由帧数整除 6 换算(60FPS 下约每 0.1 秒 +1 分),避免浮点累加误差,也使分数增长速率在任何帧率下保持一致。鼠标坐标每帧顶部获取一次,保证玩家位置与系统光标严格同步。

全部代码

"""
躲避弹幕 — 操控小点在满屏弹幕中生存
操作:鼠标移动控制玩家,生存越久分越高
弹幕模式随时间切换:散射、旋转、追踪、扇形
"""

import pygame
import sys
import random
import math
import time

pygame.init()

W, H = 600, 680
FPS = 60

C_BG       = (8,   5,  20)
C_PLAYER   = (80, 220, 255)
C_PLAYER_C = (200, 240, 255)
C_BULLET   = [(255, 80, 120), (255, 180, 50), (120, 255, 150), (180, 100, 255)]
C_TEXT     = (220, 220, 255)
C_GREY     = (100, 100, 140)
C_HP       = (80, 200, 120)
C_HP_LOW   = (220, 80, 60)
C_SHIELD   = (100, 180, 255)
C_STAR     = (255, 240, 100)


CHINESE_FONT_PATH = r"C:/Windows/Fonts/simsun.ttc"

FONT_LG = pygame.font.Font(CHINESE_FONT_PATH, 32)
FONT_MD = pygame.font.Font(CHINESE_FONT_PATH, 20)
FONT_SM = pygame.font.Font(CHINESE_FONT_PATH, 15)

PLAYER_R = 8
BULLET_R = 5
INVINCIBLE_TIME = 90   # 帧
SHIELD_TIME = 180

class Bullet:
    def __init__(self, x, y, vx, vy, color_idx=0, r=BULLET_R):
        self.x, self.y = float(x), float(y)
        self.vx, self.vy = vx, vy
        self.color = C_BULLET[color_idx % len(C_BULLET)]
        self.r = r
        self.trail = []

    def update(self):
        self.trail.append((self.x, self.y))
        if len(self.trail) > 6:
            self.trail.pop(0)
        self.x += self.vx
        self.y += self.vy

    def alive(self):
        return -50 < self.x < W+50 and -50 < self.y < H+50

    def draw(self, surf):
        for i, (tx, ty) in enumerate(self.trail):
            a = int(40 * (i+1) / len(self.trail))
            r = max(1, self.r - 2)
            s = pygame.Surface((r*2+1, r*2+1), pygame.SRCALPHA)
            pygame.draw.circle(s, (*self.color, a), (r, r), r)
            surf.blit(s, (tx-r, ty-r))
        pygame.draw.circle(surf, self.color, (int(self.x), int(self.y)), self.r)
        pygame.draw.circle(surf, (255,255,255,200), (int(self.x), int(self.y)), max(1, self.r-2), 1)

class Particle:
    def __init__(self, x, y, color=(255,255,255)):
        self.x, self.y = x, y
        a = random.uniform(0, math.pi*2)
        s = random.uniform(1, 5)
        self.vx, self.vy = math.cos(a)*s, math.sin(a)*s
        self.life = 1.0
        self.color = color
        self.r = random.randint(2, 5)

    def update(self):
        self.x += self.vx
        self.y += self.vy
        self.vx *= 0.92
        self.vy *= 0.92
        self.life -= 0.03
        return self.life > 0

    def draw(self, surf):
        a = int(self.life * 255)
        s = pygame.Surface((self.r*2+1, self.r*2+1), pygame.SRCALPHA)
        pygame.draw.circle(s, (*self.color, a), (self.r, self.r), self.r)
        surf.blit(s, (int(self.x)-self.r, int(self.y)-self.r))

# ── 弹幕模式 ─────────────────────────────────────────────────────────
def spawn_scatter(cx, cy, count, speed, ci):
    bullets = []
    for i in range(count):
        a = (2*math.pi*i/count)
        bullets.append(Bullet(cx, cy, math.cos(a)*speed, math.sin(a)*speed, ci))
    return bullets

def spawn_aimed(px, py, ox, oy, speed, spread=3, ci=0):
    bullets = []
    dx, dy = px-ox, py-oy
    dist = math.hypot(dx, dy) or 1
    for s in range(-spread, spread+1):
        a = math.atan2(dy, dx) + s * 0.15
        bullets.append(Bullet(ox, oy, math.cos(a)*speed, math.sin(a)*speed, ci))
    return bullets

def spawn_fan(cx, cy, base_angle, count, spread, speed, ci):
    bullets = []
    for i in range(count):
        a = base_angle - spread/2 + spread*i/(max(1,count-1))
        bullets.append(Bullet(cx, cy, math.cos(a)*speed, math.sin(a)*speed, ci))
    return bullets

# ── 星星背景 ─────────────────────────────────────────────────────────
STARS = [(random.randint(0,W), random.randint(0,H), random.random()*2+1) for _ in range(80)]

def draw_stars(surf, t):
    for sx, sy, sr in STARS:
        a = int((math.sin(t*0.02 + sx) * 0.5 + 0.5) * 180 + 60)
        pygame.draw.circle(surf, (a, a, a), (sx, sy), int(sr))

# ── 主循环 ────────────────────────────────────────────────────────────
def main():
    screen = pygame.display.set_mode((W, H))
    pygame.display.set_caption("躲避弹幕")
    clock = pygame.time.Clock()
    pygame.mouse.set_visible(False)

    bullets = []
    particles = []
    score = 0
    best = 0
    hp = 5
    max_hp = 5
    invincible = 0
    shield = 0
    frame = 0
    game_over = False
    started = False
    spawn_timer = 0
    phase_timer = 0
    phase = 0
    spin_angle = 0
    px, py = W//2, H//2

    def reset():
        nonlocal bullets, particles, score, hp, invincible, shield
        nonlocal frame, game_over, started, spawn_timer, phase_timer, phase, spin_angle
        bullets.clear()
        particles.clear()
        score = 0; hp = max_hp; invincible = 0; shield = 0
        frame = 0; game_over = False; started = True
        spawn_timer = 0; phase_timer = 0; phase = 0; spin_angle = 0

    while True:
        mx, my = pygame.mouse.get_pos()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.mouse.set_visible(True)
                pygame.quit(); sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.mouse.set_visible(True)
                    pygame.quit(); sys.exit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if not started or game_over:
                    reset()

        if started and not game_over:
            px, py = mx, my
            frame += 1
            score = frame // 6
            if invincible > 0: invincible -= 1
            if shield > 0: shield -= 1

            # 切换弹幕阶段
            phase_timer += 1
            if phase_timer > 300 + phase * 20:
                phase = (phase + 1) % 5
                phase_timer = 0

            spawn_timer += 1
            interval = max(8, 30 - score//30)
            ci = phase % len(C_BULLET)
            spd = 2.5 + score * 0.008

            if spawn_timer >= interval:
                spawn_timer = 0
                if phase == 0:   # 四面散射
                    cx, cy = random.choice([W//2, 0, W, 0, W]), random.choice([0, H, H//2, 0, H])
                    bullets += spawn_scatter(cx, cy, 8+score//60, spd, ci)
                elif phase == 1: # 追踪扇形
                    ex = random.choice([0, W])
                    ey = random.randint(100, H-100)
                    bullets += spawn_aimed(px, py, ex, ey, spd, 2, ci)
                elif phase == 2: # 旋转
                    spin_angle += 0.3
                    for j in range(3):
                        a = spin_angle + j * 2.1
                        bullets.append(Bullet(W//2, H//2, math.cos(a)*spd, math.sin(a)*spd, ci))
                elif phase == 3: # 顶部扇形
                    ca = math.pi/2 + random.uniform(-0.5, 0.5)
                    bullets += spawn_fan(random.randint(50,W-50), -10, ca, 7+score//80, 1.2, spd, ci)
                elif phase == 4: # 全方向密集
                    edge = random.randint(0, 3)
                    if edge==0: cx,cy=random.randint(0,W),0
                    elif edge==1: cx,cy=W,random.randint(0,H)
                    elif edge==2: cx,cy=random.randint(0,W),H
                    else: cx,cy=0,random.randint(0,H)
                    dx,dy=px-cx,py-cy; dist=math.hypot(dx,dy) or 1
                    a=math.atan2(dy,dx)
                    for k in range(-1,2):
                        bullets.append(Bullet(cx,cy, math.cos(a+k*0.25)*spd, math.sin(a+k*0.25)*spd, ci))

            # 更新子弹
            for b in bullets[:]:
                b.update()
                if not b.alive():
                    bullets.remove(b)
                elif invincible == 0 and shield == 0:
                    if math.hypot(b.x-px, b.y-py) < PLAYER_R + b.r - 2:
                        bullets.remove(b)
                        hp -= 1
                        invincible = INVINCIBLE_TIME
                        for _ in range(20):
                            particles.append(Particle(px, py, (255,100,100)))
                        if hp <= 0:
                            game_over = True
                            best = max(best, score)

            particles = [p for p in particles if p.update()]

        # ── 绘制 ──────────────────────────────────────────────────────
        screen.fill(C_BG)
        draw_stars(screen, frame)

        if started:
            for p in particles: p.draw(screen)
            for b in bullets: b.draw(screen)

            # 玩家
            if not game_over:
                pc = C_PLAYER if invincible == 0 else (
                    C_SHIELD if shield > 0 else
                    ((255,255,255) if (invincible//5)%2 else C_PLAYER)
                )
                # 光晕
                glow = pygame.Surface((PLAYER_R*6, PLAYER_R*6), pygame.SRCALPHA)
                pygame.draw.circle(glow, (*pc, 40), (PLAYER_R*3, PLAYER_R*3), PLAYER_R*3)
                screen.blit(glow, (px-PLAYER_R*3, py-PLAYER_R*3))
                pygame.draw.circle(screen, pc, (px, py), PLAYER_R)
                pygame.draw.circle(screen, C_PLAYER_C, (px, py), 3)

            # UI
            st = FONT_LG.render(f"{score}", True, C_TEXT)
            screen.blit(st, st.get_rect(centerx=W//2, y=8))

            # HP
            for i in range(max_hp):
                hc = (C_HP if i < hp else (40, 40, 60))
                pygame.draw.circle(screen, hc, (20 + i*26, 24), 10)
                if i < hp:
                    pygame.draw.circle(screen, (200,255,220), (20 + i*26, 24), 4)

            # 阶段提示
            phase_names = ["散射", "追踪", "旋转", "扇形", "密集"]
            pt = FONT_SM.render(f"模式:{phase_names[phase]}", True, C_GREY)
            screen.blit(pt, (W-120, 8))

            # 最高分
            bt = FONT_SM.render(f"最高:{best}", True, C_GREY)
            screen.blit(bt, (W-100, 28))

            # 游戏结束
            if game_over:
                ov = pygame.Surface((W, H), pygame.SRCALPHA)
                ov.fill((0,0,0,150))
                screen.blit(ov, (0,0))
                box = pygame.Rect(W//2-160, H//2-100, 320, 210)
                pygame.draw.rect(screen, (15,10,35), box, border_radius=16)
                pygame.draw.rect(screen, C_BULLET[0], box, 2, border_radius=16)
                lines = [
                    (FONT_LG, "GAME OVER", C_BULLET[0], -55),
                    (FONT_MD, f"生存时间:{score} 分", C_TEXT, 0),
                    (FONT_MD, f"最高纪录:{best} 分", C_STAR, 35),
                    (FONT_SM, "点击鼠标重新开始", C_GREY, 80),
                ]
                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))

        else:
            # 开始界面
            t1 = FONT_LG.render("☄  躲避弹幕", True, C_PLAYER)
            t2 = FONT_MD.render("移动鼠标控制白点", True, C_TEXT)
            t3 = FONT_SM.render("点击鼠标开始", True, C_GREY)
            screen.blit(t1, t1.get_rect(centerx=W//2, centery=H//2-60))
            screen.blit(t2, t2.get_rect(centerx=W//2, centery=H//2))
            screen.blit(t3, t3.get_rect(centerx=W//2, centery=H//2+50))

        pygame.display.flip()
        clock.tick(FPS)

if __name__ == "__main__":
    main()

以上就是Python通过Pygame实现一个简化版弹幕射击躲避游戏的详细内容,更多关于Python Pygame躲避弹幕游戏的资料请关注脚本之家其它相关文章!

相关文章

最新评论