当前位置:首页>python>【吾爱】Python开发的俄罗斯方块游戏(霓虹炫彩带音效)源代码、EXE

【吾爱】Python开发的俄罗斯方块游戏(霓虹炫彩带音效)源代码、EXE

  • 2026-06-29 23:50:04
【吾爱】Python开发的俄罗斯方块游戏(霓虹炫彩带音效)源代码、EXE

感谢您抽出

.

.

阅读本文

大家好!我是“锋说你听”,欢迎关注本小号!

点击上方“锋说你听”,关注后了解更多精彩内容!!

创作不易,希望也欢迎喜欢的朋友点赞、转发,让周围的朋友也能获得帮助,如果是商业用途,请提前联系我。

有的文章末尾会有关键词,在公众号发消息处回复正确的关键词即可获取相关链接,回复词须“精确”,随便输入的内容,机器人会统一回复“已失效”等,望周知。

所有软件和资源都有时效性,教程有时也有时效性(比如系统更新、软件被打补丁等),请尽量在第一时间阅读,以免错过机会。

忙的时候有了素材也没时间整理并写出来,等到闲下来时,有的内容已经忘了,有的已经过了时了,再写无意义了。希望大家在工作、生活中发现的电脑、手机小问题、困惑,可以发送给我,我可以尝试给大家解决一下,这样既帮了你,给我增加了素材,写出来也可能会帮到更多人!

最近在教舅舅家上初二的儿子Python编程,每次教完基本语法,都会用一个小游戏来帮助他提高兴趣。今天为大家带来Python开发的俄罗斯方块游戏,使用pygame 2.5.2 (SDL 2.28.3, Python 3.12.6)开发,一共1338行代码。带霓虹炫彩和音效,自己玩了挺多遍,体验还不错,欢迎大家下载试玩。(带exe格式的游戏约27MB,源代码和音乐素材)

能把教的过程写下来吗?每次都用什么项目练习。

一般都会先讲基础语法,如顺序、选择、循环;字符串、列表、字典、元组、集合;函数,类等等。每个知识点都用一些比较简短生动的例子,然后用一个Pygame开发的游戏做综合训练,一边玩游戏,一边改代码,用“控制变量法”,让小朋友感受Python代码是如何控制游戏里的逻辑、精灵等等。

同时把源代码分享如下:

import pygame

import random

import math

import os

import sys

from typing import List, Tuple, Optional, Dict, Any

from pygame import gfxdraw

import json

# 初始化 Pygame

pygame.init()

pygame.mixer.init()

# 获取当前文件所在目录

folder_name = os.path.dirname(__file__)

# 加载背景音乐

bg_music = os.path.join(folder_name, '丛林.ogg')

try:

    pygame.mixer.music.load(bg_music)

    pygame.mixer.music.play(-1)

    pygame.mixer.music.set_volume(0.3)  # 降低背景音乐音量

except Exception as e:

    print(f"加载背景音乐失败: {e}")

# 屏幕尺寸

SCREEN_WIDTH = 1100

SCREEN_HEIGHT = 900

GRID_SIZE = 35

GRID_WIDTH = 10

GRID_HEIGHT = 20

SIDEBAR_WIDTH = 300

HEADER_HEIGHT = 100

# 色彩方案 - 霓虹未来风

COLORS = {

    'bg_dark': (10, 10, 20),

    'bg_grid': (20, 20, 35),

    'game_area_line': (230, 230, 230, 100), 

    'grid_line': (40, 40, 60, 100),

    'text_primary': (240, 240, 255),

    'text_secondary': (180, 180, 220),

    'text_accent': (100, 220, 255),

    'panel_bg': (25, 25, 45, 200),

    'button_bg': (50, 50, 80),

    'button_hover': (70, 70, 110),

    'shadow': (0, 0, 0, 150),

    'glow': (100, 200, 255, 50)

}

# 方块颜色 (霓虹色)

BLOCK_COLORS = [

    (0, 240, 240),    # I - 青色

    (30, 144, 255),   # J - 亮蓝

    (255, 165, 0),    # L - 橙色

    (255, 255, 0),    # O - 黄色

    (50, 205, 50),    # S - 绿色

    (186, 85, 211),   # T - 紫色

    (255, 69, 0)      # Z - 红色

]

# 方块发光颜色

BLOCK_GLOW = [

    (100, 255, 255, 100),   # I

    (100, 180, 255, 100),   # J

    (255, 200, 100, 100),   # L

    (255, 255, 100, 100),   # O

    (100, 255, 100, 100),   # S

    (200, 100, 255, 100),   # T

    (255, 100, 100, 100)    # Z

]

# 方块形状定义

SHAPES = [

    [[1, 1, 1, 1]],                              # I

    [[1, 0, 0], [1, 1, 1]],                      # J

    [[0, 0, 1], [1, 1, 1]],                      # L

    [[1, 1], [1, 1]],                            # O

    [[0, 1, 1], [1, 1, 0]],                      # S

    [[0, 1, 0], [1, 1, 1]],                      # T

    [[1, 1, 0], [0, 1, 1]]                       # Z

]

# 方块初始位置

SHAPE_START_POS = [3, 0]

# 字体

def load_font(size, bold=False):

    """加载字体,支持多种回退方案"""

    fonts = [

        "Microsoft YaHei UI", "simhei", "simsun", "Segoe UI", "Arial", "Helvetica", 

        "DroidSansFallback", "sans-serif"

    ]

    for font_name in fonts:

        try:

            if bold:

                return pygame.font.SysFont(font_name, size, bold=True)

            else:

                return pygame.font.SysFont(font_name, size)

        except:

            continue

    return pygame.font.Font(None, size)

# 粒子系统

class Particle:

    """粒子特效"""

    def __init__(self, x, y, color, particle_type="sparkle"):

        self.x = x

        self.y = y

        self.color = color

        self.type = particle_type

        self.life = 1.0

        if particle_type == "sparkle":

            self.size = random.randint(2, 6)

            self.speed_x = random.uniform(-2, 2)

            self.speed_y = random.uniform(-3, -1)

            self.decay = random.uniform(0.02, 0.05)

            self.gravity = 0.2

        elif particle_type == "trail":

            self.size = random.randint(1, 3)

            self.speed_x = random.uniform(-0.5, 0.5)

            self.speed_y = random.uniform(-0.2, 0.2)

            self.decay = random.uniform(0.01, 0.03)

            self.gravity = 0.05

    def update(self):

        self.x += self.speed_x

        self.y += self.speed_y

        self.speed_y += self.gravity

        self.life -= self.decay

        return self.life > 0

    def draw(self, surface):

        alpha = int(self.life * 255)

        if self.type == "sparkle":

            # 绘制发光粒子

            s = pygame.Surface((self.size * 2, self.size * 2), pygame.SRCALPHA)

            gfxdraw.filled_circle(s, self.size, self.size, self.size, 

                                (*self.color[:3], alpha))

            gfxdraw.aacircle(s, self.size, self.size, self.size, 

                           (*self.color[:3], alpha))

            surface.blit(s, (int(self.x) - self.size, int(self.y) - self.size))

        else:

            pygame.draw.circle(surface, (*self.color[:3], alpha), 

                             (int(self.x), int(self.y)), self.size)

# 方块类

class Tetromino:

    def __init__(self, x, y):

        self.x = x

        self.y = y

        self.shape_idx = random.randint(0, len(SHAPES) - 1)

        self.color_idx = self.shape_idx

        self.rotation = 0

        self.last_move_time = pygame.time.get_ticks()

        self.move_delay = 600

        self.drop_time = pygame.time.get_ticks()

        self.last_rotate_time = 0

        self.ghost_y = 0

        # 旋转状态

        self.rotate_state = 0

        self.rotate_progress = 0

        self.rotate_target = 0

        # 移动效果

        self.move_offset = 0

        self.wobble = 0

    @property

    def shape(self):

        shape = SHAPES[self.shape_idx]

        rotated = shape

        for _ in range(self.rotation % 4):

            rotated = list(zip(*reversed(rotated)))

        return rotated

    def calculate_ghost(self, grid):

        """计算阴影位置"""

        ghost = Tetromino(self.x, self.y)

        ghost.shape_idx = self.shape_idx

        ghost.rotation = self.rotation

        ghost.color_idx = self.color_idx

        while not ghost.collision(grid):

            ghost.y += 1

        ghost.y -= 1

        return ghost.y

    def rotate(self, grid):

        """旋转方块"""

        old_rotation = self.rotation

        self.rotation = (self.rotation + 1) % 4

        # 尝试墙壁踢

        if self.collision(grid):

            # 向右移动尝试

            self.x += 1

            if self.collision(grid):

                self.x -= 2

                if self.collision(grid):

                    self.x += 1

                    # 向左移动尝试

                    if self.x > 0:

                        self.x -= 1

                        if self.collision(grid):

                            self.x += 1

                    self.rotation = old_rotation

                    return False

        self.last_rotate_time = pygame.time.get_ticks()

        return True

    def move(self, dx, dy, grid):

        """移动方块"""

        self.x += dx

        self.y += dy

        if self.collision(grid):

            self.x -= dx

            self.y -= dy

            return False

        # 移动效果

        if dx != 0:

            self.move_offset = dx * 3

        return True

    def hard_drop(self, grid):

        """硬降到底部"""

        distance = 0

        while self.move(0, 1, grid):

            distance += 1

        return distance

    def collision(self, grid):

        """碰撞检测"""

        shape = self.shape

        for y, row in enumerate(shape):

            for x, cell in enumerate(row):

                if cell:

                    board_x = self.x + x

                    board_y = self.y + y

                    # 检查x坐标是否在网格内

                    if board_x < 0 or board_x >= GRID_WIDTH:

                        return True

                    # 检查y坐标是否超出底部

                    if board_y >= GRID_HEIGHT:

                        return True

                    # 检查是否与已固定的方块碰撞(只检查在网格内的位置)

                    if board_y >= 0 and grid[board_y][board_x] is not None:

                        return True

        return False

    def draw(self, surface, x_offset, y_offset, is_ghost=False, particles=None):

        """绘制方块"""

        shape = self.shape

        block_size = GRID_SIZE

        glow_size = block_size + 6

        for y, row in enumerate(shape):

            for x, cell in enumerate(row):

                if cell:

                    # 计算位置

                    pos_x = x_offset + (self.x + x) * block_size

                    pos_y = y_offset + (self.y + y) * block_size

                    # 添加移动偏移

                    if self.move_offset != 0:

                        pos_x += self.move_offset

                        self.move_offset *= 0.8

                        if abs(self.move_offset) < 0.5:

                            self.move_offset = 0

                    # 添加摆动效果

                    if self.wobble != 0:

                        wobble_offset = math.sin(self.wobble) * 2

                        pos_y += wobble_offset

                        self.wobble *= 0.9

                        if abs(self.wobble) < 0.1:

                            self.wobble = 0

                    if is_ghost:

                        # 绘制阴影方块

                        self._draw_ghost_block(surface, pos_x, pos_y, block_size)

                    else:

                        # 绘制主方块

                        self._draw_main_block(surface, pos_x, pos_y, block_size, particles)

        # 添加方块粒子

        if particles is not None and not is_ghost:

            for y, row in enumerate(shape):

                for x, cell in enumerate(row):

                    if cell and random.random() < 0.1:

                        pos_x = x_offset + (self.x + x) * block_size + block_size // 2

                        pos_y = y_offset + (self.y + y) * block_size + block_size // 2

                        particles.append(Particle(pos_x, pos_y, BLOCK_GLOW[self.color_idx], "trail"))

    def _draw_ghost_block(self, surface, x, y, size):

        """绘制阴影方块"""

        # 外发光

        glow_surf = pygame.Surface((size + 8, size + 8), pygame.SRCALPHA)

        color = (*BLOCK_COLORS[self.color_idx][:3], 80)

        pygame.draw.rect(glow_surf, color, (0, 0, size + 8, size + 8), 

                        border_radius=4)

        surface.blit(glow_surf, (x - 4, y - 4))

        # 内透明方块

        inner_surf = pygame.Surface((size - 4, size - 4), pygame.SRCALPHA)

        color = (*BLOCK_COLORS[self.color_idx][:3], 30)

        pygame.draw.rect(inner_surf, color, (0, 0, size - 4, size - 4), 

                        border_radius=3)

        surface.blit(inner_surf, (x + 2, y + 2))

        # 边框

        pygame.draw.rect(surface, (*BLOCK_COLORS[self.color_idx][:3], 100), 

                        (x, y, size, size), 1, border_radius=3)

    def _draw_main_block(self, surface, x, y, size, particles):

        """绘制主方块"""

        color = BLOCK_COLORS[self.color_idx]

        glow_color = BLOCK_GLOW[self.color_idx]

        # 底部阴影

        shadow_offset = 3

        shadow_surf = pygame.Surface((size, size), pygame.SRCALPHA)

        pygame.draw.rect(shadow_surf, (0, 0, 0, 100), 

                        (shadow_offset, shadow_offset, size, size), 

                        border_radius=5)

        surface.blit(shadow_surf, (x, y))

        # 主方块

        pygame.draw.rect(surface, color, (x, y, size, size), 

                        border_radius=5)

        # 3D效果 - 高光

        highlight_surf = pygame.Surface((size, size), pygame.SRCALPHA)

        # 左上高光

        pygame.draw.polygon(highlight_surf, (255, 255, 255, 60), 

                           [(0, 0), (size, 0), (0, size)])

        # 右下阴影

        pygame.draw.polygon(highlight_surf, (0, 0, 0, 30), 

                           [(size, 0), (0, size), (size, size)])

        surface.blit(highlight_surf, (x, y))

        # 内发光

        inner_size = size - 6

        inner_surf = pygame.Surface((inner_size, inner_size), pygame.SRCALPHA)

        pygame.draw.rect(inner_surf, (*color[:3], 100), 

                        (0, 0, inner_size, inner_size), border_radius=3)

        surface.blit(inner_surf, (x + 3, y + 3))

        # 发光边框

        pygame.draw.rect(surface, (255, 255, 255, 150), 

                        (x, y, size, size), 2, border_radius=5)

        # 高光点

        highlight_size = 8

        highlight_surf = pygame.Surface((highlight_size, highlight_size), pygame.SRCALPHA)

        pygame.draw.circle(highlight_surf, (255, 255, 255, 150), 

                          (highlight_size//2, highlight_size//2), highlight_size//2)

        surface.blit(highlight_surf, (x + 5, y + 5))

        # 添加粒子效果

        if particles is not None and random.random() < 0.05:

            particles.append(Particle(

                x + size//2, y + size//2, 

                glow_color, "sparkle"

            ))

# 游戏主类

class TetrisGame:

    def __init__(self):

        # 初始化屏幕

        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), 

                                             pygame.DOUBLEBUF | pygame.HWSURFACE)

        pygame.display.set_caption("&#127918; 俄罗斯方块霓虹特别版")

        # 设置图标

        try:

            icon_surf = pygame.Surface((32, 32))

            icon_surf.fill(BLOCK_COLORS[0])

            pygame.display.set_icon(icon_surf)

        except:

            pass

        self.clock = pygame.time.Clock()

        self.font_large = load_font(48, True)

        self.font_medium = load_font(28)

        self.font_small = load_font(20)

        # 计算游戏区域位置

        self.grid_left = (SCREEN_WIDTH - SIDEBAR_WIDTH - GRID_WIDTH * GRID_SIZE) // 2

        self.grid_top = HEADER_HEIGHT + 20

        # 游戏状态

        self.reset_game()

        # 创建半透明表面

        self.panel_surf = pygame.Surface((SIDEBAR_WIDTH - 40, SCREEN_HEIGHT - 100), 

                                        pygame.SRCALPHA)

        self.panel_surf.fill(COLORS['panel_bg'])

        # 背景动画

        self.bg_particles = []

        self.bg_stars = []

        self._init_background()

        # 音效

        self.sounds = self._init_sounds()

        # 游戏状态

        self.state = "playing"  # playing, paused, gameover

        self.last_state_change = 0

        # 动画

        self.animations = []

        # 调试信息

        self.debug_info = []

    def reset_game(self):

        """重置游戏状态"""

        self.grid = [[None for _ in range(GRID_WIDTH)] for _ in range(GRID_HEIGHT)]

        self.current_piece = Tetromino(GRID_WIDTH // 2 - 1, 0)

        self.next_piece = Tetromino(0, 0)

        self.hold_piece = None

        self.can_hold = True

        self.game_over = False

        self.score = 0

        self.level = 1

        self.lines_cleared = 0

        self.total_pieces = 0

        self.combo = 0

        self.last_clear_time = 0

        self.particles = []

        self.clear_effects = []

        # 计算阴影

        self.current_piece.ghost_y = self.current_piece.calculate_ghost(self.grid)

    def _init_background(self):

        """初始化背景"""

        # 创建星空背景

        for _ in range(100):

            x = random.randint(0, SCREEN_WIDTH)

            y = random.randint(0, SCREEN_HEIGHT)

            size = random.randint(1, 3)

            speed = random.uniform(0.1, 0.5)

            self.bg_stars.append({

                'x': x, 'y': y, 'size': size, 'speed': speed,

                'brightness': random.uniform(0.5, 1.0)

            })

    def _init_sounds(self):

        """初始化音效"""

        sounds = {}

        try:

            # 单行消除音效

            clear_sound_path = os.path.join(folder_name, 'clear.ogg')

            if os.path.exists(clear_sound_path):

                sounds['clear'] = pygame.mixer.Sound(clear_sound_path)

                sounds['clear'].set_volume(0.5)

                print(f"&#10003; 加载单行消除音效: {clear_sound_path}")

            else:

                print(f"&#10007; 找不到单行消除音效: {clear_sound_path}")

            # 多行消除/连击音效

            combo_sound_path = os.path.join(folder_name, 'combo.ogg')

            if os.path.exists(combo_sound_path):

                sounds['combo'] = pygame.mixer.Sound(combo_sound_path)

                sounds['combo'].set_volume(0.6)

                print(f"&#10003; 加载连击音效: {combo_sound_path}")

            else:

                print(f"&#10007; 找不到连击音效: {combo_sound_path}")

        except Exception as e:

            print(f"加载音效时出错: {e}")

            print("游戏将继续运行,但没有音效")

        return sounds

    def spawn_new_piece(self):

        """生成新方块"""

        self.current_piece = self.next_piece

        self.current_piece.x = GRID_WIDTH // 2 - 1

        self.current_piece.y = 0

        self.next_piece = Tetromino(0, 0)

        self.can_hold = True

        # 计算新方块的阴影

        self.current_piece.ghost_y = self.current_piece.calculate_ghost(self.grid)

        # 检查游戏是否结束

        if self.current_piece.collision(self.grid):

            self.game_over = True

            self.state = "gameover"

            return False

        self.total_pieces += 1

        return True

    def hold_current_piece(self):

        """暂存当前方块"""

        if not self.can_hold:

            return

        if self.hold_piece is None:

            self.hold_piece = Tetromino(0, 0)

            self.hold_piece.shape_idx = self.current_piece.shape_idx

            self.hold_piece.color_idx = self.current_piece.color_idx

            self.spawn_new_piece()

        else:

            # 交换当前方块和暂存方块

            temp_idx = self.current_piece.shape_idx

            temp_color = self.current_piece.color_idx

            self.current_piece.shape_idx = self.hold_piece.shape_idx

            self.current_piece.color_idx = self.hold_piece.color_idx

            self.current_piece.rotation = 0

            self.current_piece.x = GRID_WIDTH // 2 - 1

            self.current_piece.y = 0

            self.hold_piece.shape_idx = temp_idx

            self.hold_piece.color_idx = temp_color

        self.can_hold = False

        self.current_piece.ghost_y = self.current_piece.calculate_ghost(self.grid)

    def clear_lines(self):

        """清除已满的行"""

        lines_to_clear = []

        # 调试:打印网格状态

        self.debug_info = []

        for y in range(GRID_HEIGHT):

            row_count = sum(1 for cell in self.grid[y] if cell is not None)

            if row_count > 0:

                self.debug_info.append(f"行{y}: {row_count}/10")

                if row_count == GRID_WIDTH:

                    lines_to_clear.append(y)

        if not lines_to_clear:

            self.combo = 0

            return 0

        # 计算连击

        current_time = pygame.time.get_ticks()

        if current_time - self.last_clear_time < 2000:  # 2秒内

            self.combo += 1

        else:

            self.combo = 1

        self.last_clear_time = current_time

        # 创建消除特效

        for line in lines_to_clear:

            self._create_clear_effect(line)

        # 播放消除音效

        cleared = len(lines_to_clear)

        self._play_clear_sound(cleared)

        # 创建多行消除特效

        if cleared >= 2:

            self._create_multi_line_effect(cleared, lines_to_clear)

        # 计分

        self.lines_cleared += cleared

        # 计分规则

        points_per_line = [0, 100, 300, 500, 800]

        base_points = points_per_line[cleared] * self.level

        # 连击加成

        combo_bonus = self.combo * 50 * self.level

        # 全清奖励

        is_all_clear = all(cell is None for row in self.grid for cell in row)

        all_clear_bonus = 2000 if is_all_clear else 0

        self.score += base_points + combo_bonus + all_clear_bonus

        # 升级

        self.level = self.lines_cleared // 10 + 1

        self.current_piece.move_delay = max(50, 600 - (self.level - 1) * 50)

        # 移除行

        for line in sorted(lines_to_clear, reverse=True):

            del self.grid[line]

            self.grid.insert(0, [None for _ in range(GRID_WIDTH)])

        return cleared

    def _play_clear_sound(self, lines_cleared):

        """播放消除音效"""

        if not self.sounds:

            return

        try:

            if lines_cleared == 1:

                # 单行消除

                if 'clear' in self.sounds:

                    self.sounds['clear'].play()

            elif lines_cleared >= 2:

                # 多行消除/连击

                if 'combo' in self.sounds:

                    # 根据消除行数调整音量和音高

                    sound = self.sounds['combo']

                    # 计算音量 - 消除行数越多音量越大

                    volume = min(0.8, 0.5 + (lines_cleared - 1) * 0.1)

                    sound.set_volume(volume)

                    # 尝试改变音高

                    try:

                        # 简单的音高调整:通过播放速度

                        from pygame import mixer

                        # 重新创建音效以实现音高变化

                        original_array = pygame.sndarray.array(sound)

                        if original_array is not None:

                            # 计算音高因子 - 消除行数越多音高越高

                            pitch_factor = 1.0 + (lines_cleared - 2) * 0.1

                            # 创建新的音效

                            new_sound = pygame.mixer.Sound(original_array)

                            new_sound.set_volume(volume)

                            new_sound.play()

                    except:

                        # 如果音高调整失败,直接播放

                        sound.play()

        except Exception as e:

            print(f"播放音效时出错: {e}")

    def _create_clear_effect(self, line):

        """创建行消除特效"""

        for x in range(GRID_WIDTH):

            if self.grid[line][x] is not None:

                color_idx = self.grid[line][x]

                center_x = self.grid_left + x * GRID_SIZE + GRID_SIZE // 2

                center_y = self.grid_top + line * GRID_SIZE + GRID_SIZE // 2

                # 创建粒子

                for _ in range(15):

                    angle = random.uniform(0, math.pi * 2)

                    speed = random.uniform(2, 5)

                    particle = Particle(

                        center_x, center_y,

                        BLOCK_GLOW[color_idx],

                        "sparkle"

                    )

                    particle.speed_x = math.cos(angle) * speed

                    particle.speed_y = math.sin(angle) * speed

                    particle.gravity = 0.1

                    particle.decay = random.uniform(0.01, 0.03)

                    self.clear_effects.append(particle)

                # 创建爆炸动画

                for _ in range(5):

                    size = random.randint(20, 40)

                    self.animations.append({

                        'type': 'explosion',

                        'x': center_x,

                        'y': center_y,

                        'size': size,

                        'max_size': size * 2,

                        'color': BLOCK_COLORS[color_idx],

                        'life': 1.0,

                        'decay': 0.05

                    })

    def _create_multi_line_effect(self, lines_cleared, lines_to_clear):

        """创建多行消除特效"""

        center_x = SCREEN_WIDTH // 2

        center_y = SCREEN_HEIGHT // 2

        # 根据消除行数设置不同的颜色和文字

        if lines_cleared == 2:

            text = f"DOUBLE!"

            color = (100, 200, 255)  # 蓝色

            size = 50

        elif lines_cleared == 3:

            text = f"TRIPLE!"

            color = (100, 255, 100)  # 绿色

            size = 60

        elif lines_cleared == 4:

            text = f"TETRIS!"

            color = (255, 100, 100)  # 红色

            size = 70

        else:

            text = f"COMBO x{lines_cleared}!"

            color = (255, 255, 100)  # 黄色

            size = 80

        # 创建多行消除动画

        self.animations.append({

            'type': 'multi_line',

            'text': text,

            'x': center_x,

            'y': center_y,

            'size': size,

            'color': color,

            'life': 1.0,

            'decay': 0.02

        })

        # 添加粒子特效

        for _ in range(30 * lines_cleared):

            angle = random.uniform(0, math.pi * 2)

            speed = random.uniform(3, 8)

            particle = Particle(

                center_x, center_y,

                (*color, 200),

                "sparkle"

            )

            particle.speed_x = math.cos(angle) * speed

            particle.speed_y = math.sin(angle) * speed

            particle.gravity = 0.1

            particle.decay = random.uniform(0.01, 0.03)

            self.clear_effects.append(particle)

    def lock_piece(self):

        """锁定当前方块 - 修复版本"""

        shape = self.current_piece.shape

        placed_blocks = 0

        # 先检查所有方块的位置

        for y, row in enumerate(shape):

            for x, cell in enumerate(row):

                if cell:

                    # 计算方块在网格中的实际位置

                    board_x = self.current_piece.x + x

                    board_y = self.current_piece.y + y

                    # 确保位置在网格范围内

                    if (0 <= board_x < GRID_WIDTH and

                        0 <= board_y < GRID_HEIGHT):

                        # 检查这个位置是否已经被占用

                        if self.grid[board_y][board_x] is None:

                            self.grid[board_y][board_x] = self.current_piece.color_idx

                            placed_blocks += 1

                        else:

                            # 这个位置已经被占用,记录错误

                            print(f"错误: 位置 ({board_x}, {board_y}) 已被占用!")

                            print(f"当前方块位置: ({self.current_piece.x}, {self.current_piece.y})")

                            print(f"方块形状: {shape}")

        # 确保至少放置了一个方块

        if placed_blocks == 0:

            print("警告: 没有放置任何方块!")

        # 添加锁定粒子

        for y, row in enumerate(shape):

            for x, cell in enumerate(row):

                if cell:

                    board_x = self.current_piece.x + x

                    board_y = self.current_piece.y + y

                    if (0 <= board_x < GRID_WIDTH and

                        0 <= board_y < GRID_HEIGHT):

                        center_x = self.grid_left + board_x * GRID_SIZE + GRID_SIZE // 2

                        center_y = self.grid_top + board_y * GRID_SIZE + GRID_SIZE // 2

                        for _ in range(5):

                            self.particles.append(Particle(

                                center_x, center_y,

                                BLOCK_GLOW[self.current_piece.color_idx],

                                "sparkle"

                            ))

        cleared = self.clear_lines()

        if cleared > 0:

            # 添加连击特效

            if self.combo > 1:

                self._create_combo_effect()

        if not self.spawn_new_piece():

            self.game_over = True

    def _create_combo_effect(self):

        """创建连击特效"""

        center_x = SCREEN_WIDTH // 2

        center_y = SCREEN_HEIGHT // 2

        # 连击文字

        combo_text = f"COMBO x{self.combo}!"

        # 根据连击次数设置不同的颜色

        if self.combo == 2:

            color = (100, 200, 255)  # 蓝色

            size = 40

        elif self.combo == 3:

            color = (100, 255, 100)  # 绿色

            size = 45

        elif self.combo == 4:

            color = (255, 100, 100)  # 红色

            size = 50

        elif self.combo >= 5:

            color = (255, 255, 100)  # 黄色

            size = 55

        else:

            color = (255, 100, 255)  # 紫色

            size = 40

        self.animations.append({

            'type': 'combo',

            'text': combo_text,

            'x': center_x,

            'y': center_y - 100,  # 在屏幕上方显示,避免与多行消除重叠

            'size': size + self.combo * 2,

            'color': color,

            'life': 1.0,

            'decay': 0.02

        })

        # 播放连击音效

        if self.combo > 1 and 'combo' in self.sounds:

            try:

                # 连击次数越多,音量越大

                volume = min(1.0, 0.5 + (self.combo - 1) * 0.1)

                self.sounds['combo'].set_volume(volume)

                self.sounds['combo'].play()

            except:

                pass

    def update(self):

        """更新游戏状态"""

        current_time = pygame.time.get_ticks()

        # 更新背景星星

        for star in self.bg_stars:

            star['y'] += star['speed']

            if star['y'] > SCREEN_HEIGHT:

                star['y'] = 0

                star['x'] = random.randint(0, SCREEN_WIDTH)

        # 更新粒子

        for particle in self.particles[:]:

            if not particle.update():

                self.particles.remove(particle)

        for particle in self.clear_effects[:]:

            if not particle.update():

                self.clear_effects.remove(particle)

        # 更新动画

        for anim in self.animations[:]:

            anim['life'] -= anim.get('decay', 0.05)

            if anim['life'] <= 0:

                self.animations.remove(anim)

            else:

                if anim['type'] == 'explosion':

                    anim['size'] += 5

                elif anim['type'] in ['combo', 'multi_line']:

                    anim['y'] -= 2

                    # 让文字逐渐变大然后缩小

                    if anim['life'] > 0.5:

                        anim['size'] += 0.5

                    else:

                        anim['size'] -= 0.5

        # 自动下落

        if not self.game_over and self.state == "playing":

            if current_time - self.current_piece.drop_time > self.current_piece.move_delay:

                if not self.current_piece.move(0, 1, self.grid):

                    self.lock_piece()

                self.current_piece.drop_time = current_time

                self.current_piece.ghost_y = self.current_piece.calculate_ghost(self.grid)

    def draw(self):

        """绘制游戏画面"""

        # 绘制背景

        self.screen.fill(COLORS['bg_dark'])

        # 绘制星空

        for star in self.bg_stars:

            brightness = int(star['brightness'] * 255)

            color = (brightness, brightness, brightness)

            pygame.draw.circle(self.screen, color, 

                             (int(star['x']), int(star['y'])), star['size'])

        # 绘制标题

        title = self.font_large.render("俄罗斯方块霓虹版", True, COLORS['text_accent'])

        title_shadow = self.font_large.render("俄罗斯方块霓虹版", True, (0, 0, 0))

        self.screen.blit(title_shadow, (SCREEN_WIDTH//2 - title.get_width()//2 + 2, 32))

        self.screen.blit(title, (SCREEN_WIDTH//2 - title.get_width()//2, 30))

        # 绘制游戏区域

        self._draw_game_area()

        # 绘制侧边栏

        self._draw_sidebar()

        # 绘制特效

        self._draw_effects()

        # 绘制调试信息

        self._draw_debug_info()

        # 绘制游戏状态

        if self.state == "paused":

            self._draw_pause_screen()

        elif self.state == "gameover":

            self._draw_game_over_screen()

        pygame.display.flip()

    def _draw_game_area(self):

        """绘制游戏区域"""

        # 绘制游戏区域背景

        game_area = pygame.Surface((GRID_WIDTH * GRID_SIZE + 20, 

                                  GRID_HEIGHT * GRID_SIZE + 20), pygame.SRCALPHA)

        game_area.fill((0, 0, 0, 100))

        pygame.draw.rect(game_area, COLORS['game_area_line'], 

                        (0, 0, GRID_WIDTH * GRID_SIZE + 20, GRID_HEIGHT * GRID_SIZE + 20), 

                        2, border_radius=10)

        self.screen.blit(game_area, (self.grid_left - 10, self.grid_top - 10))

        # 绘制网格背景

        grid_bg = pygame.Surface((GRID_WIDTH * GRID_SIZE, GRID_HEIGHT * GRID_SIZE), 

                               pygame.SRCALPHA)

        grid_bg.fill((*COLORS['bg_grid'][:3], 100))

        self.screen.blit(grid_bg, (self.grid_left, self.grid_top))

        # 绘制网格线

        for x in range(GRID_WIDTH + 1):

            pygame.draw.line(self.screen, COLORS['grid_line'],

                           (self.grid_left + x * GRID_SIZE, self.grid_top),

                           (self.grid_left + x * GRID_SIZE, 

                            self.grid_top + GRID_HEIGHT * GRID_SIZE))

        for y in range(GRID_HEIGHT + 1):

            pygame.draw.line(self.screen, COLORS['grid_line'],

                           (self.grid_left, self.grid_top + y * GRID_SIZE),

                           (self.grid_left + GRID_WIDTH * GRID_SIZE, 

                            self.grid_top + y * GRID_SIZE))

        # 绘制已固定的方块

        self._draw_fixed_blocks()

        # 绘制阴影方块

        if not self.game_over and self.state == "playing":

            ghost = Tetromino(self.current_piece.x, self.current_piece.y)

            ghost.shape_idx = self.current_piece.shape_idx

            ghost.rotation = self.current_piece.rotation

            ghost.color_idx = self.current_piece.color_idx

            ghost.y = self.current_piece.ghost_y

            ghost.draw(self.screen, self.grid_left, self.grid_top, True)

        # 绘制当前方块

        if not self.game_over and self.state == "playing":

            self.current_piece.draw(self.screen, self.grid_left, self.grid_top, 

                                  particles=self.particles)

    def _draw_fixed_blocks(self):

        """绘制已固定的方块"""

        for y in range(GRID_HEIGHT):

            for x in range(GRID_WIDTH):

                if self.grid[y][x] is not None:

                    color_idx = self.grid[y][x]

                    pos_x = self.grid_left + x * GRID_SIZE

                    pos_y = self.grid_top + y * GRID_SIZE

                    # 绘制方块

                    color = BLOCK_COLORS[color_idx]

                    pygame.draw.rect(self.screen, color, 

                                   (pos_x, pos_y, GRID_SIZE, GRID_SIZE), 

                                   border_radius=4)

                    # 3D效果

                    pygame.draw.rect(self.screen, (255, 255, 255, 50), 

                                   (pos_x, pos_y, GRID_SIZE, GRID_SIZE), 2, border_radius=4)

                    # 内发光

                    inner_size = GRID_SIZE - 6

                    inner_surf = pygame.Surface((inner_size, inner_size), pygame.SRCALPHA)

                    pygame.draw.rect(inner_surf, (*color[:3], 150), 

                                   (0, 0, inner_size, inner_size), border_radius=2)

                    self.screen.blit(inner_surf, (pos_x + 3, pos_y + 3))

    def _draw_sidebar(self):

        """绘制侧边栏"""

        sidebar_x = SCREEN_WIDTH - SIDEBAR_WIDTH + 20

        # 绘制面板背景

        panel = pygame.Surface((SIDEBAR_WIDTH - 40, SCREEN_HEIGHT - 100), pygame.SRCALPHA)

        panel.fill(COLORS['panel_bg'])

        pygame.draw.rect(panel, COLORS['text_secondary'], 

                        (0, 0, SIDEBAR_WIDTH - 40, SCREEN_HEIGHT - 100), 2, border_radius=10)

        self.screen.blit(panel, (sidebar_x, 80))

        y_offset = 100

        # 分数

        self._draw_panel_text(f"分数: {self.score:,}", sidebar_x + 20, y_offset)

        y_offset += 50

        # 等级

        self._draw_panel_text(f"等级: {self.level}", sidebar_x + 20, y_offset)

        y_offset += 50

        # 已消除行数

        self._draw_panel_text(f"消除行数: {self.lines_cleared}", sidebar_x + 20, y_offset)

        y_offset += 50

        # 连击

        if self.combo > 1:

            combo_text = self.font_small.render(f"连击: x{self.combo}", True, 

                                              (255, 100, 100))

            self.screen.blit(combo_text, (sidebar_x + 20, y_offset))

            y_offset += 40

        # 下一个方块

        self._draw_panel_text("下一个:", sidebar_x + 20, y_offset)

        y_offset += 40

        # 绘制下一个方块预览

        self._draw_next_piece_preview(sidebar_x + 50, y_offset)

        y_offset += 120

        # 暂存方块

        self._draw_panel_text("暂存:", sidebar_x + 20, y_offset)

        y_offset += 40

        # 绘制暂存方块

        self._draw_hold_piece_preview(sidebar_x + 50, y_offset)

        y_offset += 120

        # 操作说明

        self._draw_controls(sidebar_x + 20, y_offset)

    def _draw_panel_text(self, text, x, y, color=None):

        """绘制面板文本"""

        if color is None:

            color = COLORS['text_primary']

        text_surface = self.font_small.render(text, True, color)

        self.screen.blit(text_surface, (x, y))

    def _draw_next_piece_preview(self, x, y):

        """绘制下一个方块预览"""

        preview_surf = pygame.Surface((120, 100), pygame.SRCALPHA)

        preview_surf.fill((0, 0, 0, 50))

        pygame.draw.rect(preview_surf, COLORS['text_secondary'], 

                        (0, 0, 120, 100), 2, border_radius=8)

        # 绘制下一个方块

        shape = self.next_piece.shape

        shape_width = len(shape[0]) if shape else 0

        shape_height = len(shape)

        preview_x = (120 - shape_width * 20) // 2

        preview_y = (100 - shape_height * 20) // 2

        for sy, row in enumerate(shape):

            for sx, cell in enumerate(row):

                if cell:

                    block_x = preview_x + sx * 20

                    block_y = preview_y + sy * 20

                    color = BLOCK_COLORS[self.next_piece.color_idx]

                    pygame.draw.rect(preview_surf, color, 

                                   (block_x, block_y, 18, 18), border_radius=3)

                    pygame.draw.rect(preview_surf, (255, 255, 255, 150), 

                                   (block_x, block_y, 18, 18), 1, border_radius=3)

        self.screen.blit(preview_surf, (x, y))

    def _draw_hold_piece_preview(self, x, y):

        """绘制暂存方块预览"""

        preview_surf = pygame.Surface((120, 100), pygame.SRCALPHA)

        preview_surf.fill((0, 0, 0, 50))

        pygame.draw.rect(preview_surf, COLORS['text_secondary'], 

                        (0, 0, 120, 100), 2, border_radius=8)

        if self.hold_piece:

            shape = self.hold_piece.shape

            shape_width = len(shape[0]) if shape else 0

            shape_height = len(shape)

            preview_x = (120 - shape_width * 20) // 2

            preview_y = (100 - shape_height * 20) // 2

            for sy, row in enumerate(shape):

                for sx, cell in enumerate(row):

                    if cell:

                        block_x = preview_x + sx * 20

                        block_y = preview_y + sy * 20

                        color = BLOCK_COLORS[self.hold_piece.color_idx]

                        pygame.draw.rect(preview_surf, color, 

                                       (block_x, block_y, 18, 18), border_radius=3)

                        pygame.draw.rect(preview_surf, (255, 255, 255, 150), 

                                       (block_x, block_y, 18, 18), 1, border_radius=3)

        self.screen.blit(preview_surf, (x, y))

    def _draw_controls(self, x, y):

        """绘制操作说明"""

        controls = [

            "by xhlbudd@52pojie",

            "← → : 左右移动",

            "↑   : 旋转",

            "↓   : 加速下落",

            "空格 : 硬降到底部",

            "C   : 暂存方块",

            "P   : 暂停/继续",

            "R   : 重新开始",

            "ESC : 退出游戏"

        ]

        for i, text in enumerate(controls):

            color = COLORS['text_accent'] if i == 0 else COLORS['text_secondary']

            text_surf = self.font_small.render(text, True, color)

            self.screen.blit(text_surf, (x, y + i * 25))

    def _draw_debug_info(self):

        """绘制调试信息"""

        if self.debug_info:

            debug_y = 50

            for info in self.debug_info[:5]:  # 只显示前5行

                debug_text = self.font_small.render(info, True, (255, 255, 0))

                self.screen.blit(debug_text, (20, debug_y))

                debug_y += 25

    def _draw_effects(self):

        """绘制特效"""

        # 绘制粒子

        for particle in self.particles:

            particle.draw(self.screen)

        for particle in self.clear_effects:

            particle.draw(self.screen)

        # 绘制动画

        for anim in self.animations:

            if anim['type'] == 'explosion':

                self._draw_explosion(anim)

            elif anim['type'] == 'combo':

                self._draw_combo_text(anim)

            elif anim['type'] == 'multi_line':

                self._draw_multi_line_text(anim)

    def _draw_explosion(self, anim):

        """绘制爆炸特效"""

        alpha = int(anim['life'] * 255)

        size = anim['size']

        # 创建爆炸表面

        explosion = pygame.Surface((size * 2, size * 2), pygame.SRCALPHA)

        # 绘制多个同心圆

        for i in range(3):

            radius = int(size * (1 - i * 0.3))

            color = (*anim['color'][:3], alpha // (i + 1))

            pygame.draw.circle(explosion, color, (size, size), radius)

        self.screen.blit(explosion, (anim['x'] - size, anim['y'] - size))

    def _draw_combo_text(self, anim):

        """绘制连击文字"""

        alpha = int(anim['life'] * 255)

        font = load_font(int(anim['size']), True)

        text = font.render(anim['text'], True, (*anim['color'], alpha))

        text_shadow = font.render(anim['text'], True, (0, 0, 0, alpha))

        text_rect = text.get_rect(center=(anim['x'], anim['y']))

        shadow_rect = text_shadow.get_rect(center=(anim['x'] + 3, anim['y'] + 3))

        self.screen.blit(text_shadow, shadow_rect)

        self.screen.blit(text, text_rect)

    def _draw_multi_line_text(self, anim):

        """绘制多行消除文字"""

        alpha = int(anim['life'] * 255)

        font = load_font(int(anim['size']), True)

        # 绘制文字

        text = font.render(anim['text'], True, (*anim['color'], alpha))

        text_shadow = font.render(anim['text'], True, (0, 0, 0, alpha))

        text_rect = text.get_rect(center=(anim['x'], anim['y']))

        shadow_rect = text_shadow.get_rect(center=(anim['x'] + 4, anim['y'] + 4))

        self.screen.blit(text_shadow, shadow_rect)

        self.screen.blit(text, text_rect)

        # 绘制发光效果

        if alpha > 100:

            glow_size = int(anim['size'] * 1.5)

            glow_font = load_font(glow_size, True)

            glow_text = glow_font.render(anim['text'], True, (*anim['color'], alpha // 3))

            glow_rect = glow_text.get_rect(center=(anim['x'], anim['y']))

            self.screen.blit(glow_text, glow_rect)

    def _draw_pause_screen(self):

        """绘制暂停屏幕"""

        overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)

        overlay.fill((0, 0, 0, 180))

        self.screen.blit(overlay, (0, 0))

        pause_text = self.font_large.render("游戏暂停", True, COLORS['text_accent'])

        pause_shadow = self.font_large.render("游戏暂停", True, (0, 0, 0))

        self.screen.blit(pause_shadow, (SCREEN_WIDTH//2 - pause_text.get_width()//2 + 2, 302))

        self.screen.blit(pause_text, (SCREEN_WIDTH//2 - pause_text.get_width()//2, 300))

        continue_text = self.font_medium.render("按 P 键继续游戏", True, COLORS['text_primary'])

        self.screen.blit(continue_text, (SCREEN_WIDTH//2 - continue_text.get_width()//2, 380))

    def _draw_game_over_screen(self):

        """绘制游戏结束屏幕"""

        overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)

        overlay.fill((0, 0, 0, 200))

        self.screen.blit(overlay, (0, 0))

        game_over = self.font_large.render("游戏结束!", True, (255, 100, 100))

        game_over_shadow = self.font_large.render("游戏结束!", True, (0, 0, 0))

        self.screen.blit(game_over_shadow, (SCREEN_WIDTH//2 - game_over.get_width()//2 + 2, 252))

        self.screen.blit(game_over, (SCREEN_WIDTH//2 - game_over.get_width()//2, 250))

        score_text = self.font_medium.render(f"最终分数: {self.score:,}", True, COLORS['text_primary'])

        self.screen.blit(score_text, (SCREEN_WIDTH//2 - score_text.get_width()//2, 320))

        restart_text = self.font_medium.render("按 R 键重新开始", True, COLORS['text_accent'])

        self.screen.blit(restart_text, (SCREEN_WIDTH//2 - restart_text.get_width()//2, 380))

    def handle_events(self):

        """处理事件"""

        for event in pygame.event.get():

            if event.type == pygame.QUIT:

                return False

            elif event.type == pygame.KEYDOWN:

                if event.key == pygame.K_ESCAPE:

                    return False

                elif event.key == pygame.K_r:

                    self.reset_game()

                    self.state = "playing"

                elif event.key == pygame.K_p:

                    if self.state == "playing":

                        self.state = "paused"

                    elif self.state == "paused":

                        self.state = "playing"

                if not self.game_over and self.state == "playing":

                    if event.key == pygame.K_c:

                        self.hold_current_piece()

                    elif event.key == pygame.K_LEFT:

                        self.current_piece.move(-1, 0, self.grid)

                        self.current_piece.ghost_y = self.current_piece.calculate_ghost(self.grid)

                    elif event.key == pygame.K_RIGHT:

                        self.current_piece.move(1, 0, self.grid)

                        self.current_piece.ghost_y = self.current_piece.calculate_ghost(self.grid)

                    elif event.key == pygame.K_UP:

                        self.current_piece.rotate(self.grid)

                        self.current_piece.ghost_y = self.current_piece.calculate_ghost(self.grid)

                    elif event.key == pygame.K_DOWN:

                        if self.current_piece.move(0, 1, self.grid):

                            self.current_piece.ghost_y = self.current_piece.calculate_ghost(self.grid)

                    elif event.key == pygame.K_SPACE:

                        distance = self.current_piece.hard_drop(self.grid)

                        if distance > 0:

                            # 添加硬降特效

                            for _ in range(distance * 2):

                                self.particles.append(Particle(

                                    self.grid_left + self.current_piece.x * GRID_SIZE + GRID_SIZE // 2,

                                    self.grid_top + self.current_piece.y * GRID_SIZE + GRID_SIZE // 2,

                                    BLOCK_GLOW[self.current_piece.color_idx],

                                    "sparkle"

                                ))

                        self.lock_piece()

        return True

    def run(self):

        """运行游戏主循环"""

        print("&#127918; 霓虹俄罗斯方块 已启动!")

        print("=" * 50)

        print("操作说明:")

        print("  ← →   : 左右移动方块")

        print("  ↑     : 旋转方块")

        print("  ↓     : 加速下落")

        print("  空格   : 硬降到底部")

        print("  C     : 暂存当前方块")

        print("  P     : 暂停/继续游戏")

        print("  R     : 重新开始游戏")

        print("  ESC   : 退出游戏")

        print("=" * 50)

        print("游戏特点:")

        print("  &#8226; 霓虹未来风格界面")

        print("  &#8226; 粒子特效和动画")

        print("  &#8226; 阴影预测和暂存功能")

        print("  &#8226; 连击系统和分数加成")

        print("  &#8226; 背景星空动画")

        print("  &#8226; 音效系统(单行/多行消除)")

        print("  &#8226; 多行消除特效(DOUBLE/TRIPLE/TETRIS)")

        print("  &#8226; 调试信息显示(左上角)")

        print("=" * 50)

        running = True

        while running:

            running = self.handle_events()

            self.update()

            self.draw()

            self.clock.tick(60)

        pygame.quit()

        sys.exit()

# 主程序入口

if __name__ == "__main__":

    # 检查依赖

    try:

        import pygame

    except ImportError:

        print("错误: 需要安装 pygame 库")

        print("请运行: pip install pygame")

        sys.exit(1)

    # 运行游戏

    game = TetrisGame()

    game.run()

回复“1188”获取下载,下图是教程。

原创不易,你的关注就是持续更新的源泉。

  • 好了,本文就说到这里。
    • 欢迎关注转发在看❤❤❤❤
      喜欢的朋友点击上面公众号关注,以免漏掉文章。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-04 02:46:00 HTTP/2.0 GET : https://f.mffb.com.cn/a/492022.html
  2. 运行时间 : 0.139412s [ 吞吐率:7.17req/s ] 内存消耗:4,910.35kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=b3e984a10e2131824406f37f7aa6cc4e
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000602s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000610s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.007911s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000312s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000568s ]
  6. SELECT * FROM `set` [ RunTime:0.009685s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000735s ]
  8. SELECT * FROM `article` WHERE `id` = 492022 LIMIT 1 [ RunTime:0.000724s ]
  9. UPDATE `article` SET `lasttime` = 1783104360 WHERE `id` = 492022 [ RunTime:0.018797s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.004347s ]
  11. SELECT * FROM `article` WHERE `id` < 492022 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.004544s ]
  12. SELECT * FROM `article` WHERE `id` > 492022 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000549s ]
  13. SELECT * FROM `article` WHERE `id` < 492022 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.015679s ]
  14. SELECT * FROM `article` WHERE `id` < 492022 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.001852s ]
  15. SELECT * FROM `article` WHERE `id` < 492022 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.002193s ]
0.141097s