吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1490|回复: 6
收起左侧

[讨论] 新手用python写了一个俄罗斯方块目前个人只能做到这样,而且流畅性不佳求大佬指点

[复制链接]
suneryzgg123 发表于 2023-5-22 15:36
[Python] 纯文本查看 复制代码
import random
import pygame

# 定义方块类
class Block:
    def __init__(self, shape, color, x, y):
        self.shape = shape
        self.color = color
        self.x = x
        self.y = y

    def draw(self, surface):
        pygame.draw.rect(surface, self.color, (self.x*25+1, self.y*25+1, 24, 24))

# 定义游戏类
class Game:
    def __init__(self, width=10, height=20):
        self.width = width
        self.height = height
        self.board = [[0 for x in range(self.width)] for y in range(self.height)]
        self.score = 0
        self.level = 1
        self.falling_block = None
        self.next_block = None
        self.game_over = False

    def new_block(self):
        # 随机生成新的方块
        shapes = [
            [[[1, 1, 1, 1]], (255, 0, 0)],
            [[[1, 1], [1, 1]], (0, 255, 0)],
            [[[1, 1, 0], [0, 1, 1]], (0, 0, 255)],
            [[[0, 1, 1], [1, 1, 0]], (255, 255, 0)],
            [[[1, 1, 1], [0, 1, 0]], (0, 255, 255)],
            [[[1, 1, 0], [0, 1, 1]], (255, 0, 255)],
            [[[0, 1, 0], [1, 1, 1]], (128, 0, 128)]
        ]
        shape, color = random.choice(shapes)
        self.falling_block = Block(shape, color, self.width//2-2, 0)
        shape, color = random.choice(shapes)
        self.next_block = Block(shape, color, 0, 0)

    def draw_board(self, surface):
        # 绘制游戏区域
        for y in range(self.height):
            for x in range(self.width):
                pygame.draw.rect(surface, (255, 255, 255), (x*25, y*25, 25, 25), 1)
                if self.board[y][x]:
                    pygame.draw.rect(surface, self.board[y][x], (x*25+1, y*25+1, 24, 24))

    def draw_falling_block(self, surface):
        # 绘制当前下落的方块
        if self.falling_block:
            for y, row in enumerate(self.falling_block.shape):
                for x, val in enumerate(row):
                    if val:
                        b = Block(self.falling_block.shape, self.falling_block.color, self.falling_block.x+x, self.falling_block.y+y)
                        b.draw(surface)

    def draw_next_block(self, surface):
        # 绘制下一个方块
        if self.next_block:
            for y, row in enumerate(self.next_block.shape):
                for x, val in enumerate(row):
                    if val:
                        b = Block(self.next_block.shape, self.next_block.color, self.width+x, y)
                        b.draw(surface)

    def move_left(self):
        # 向左移动方块
        if self.falling_block:
            if self.falling_block.x > 0 and not self.collides(self.falling_block, -1):
                self.falling_block.x -= 1

    def move_right(self):
        # 向右移动方块
        if self.falling_block:
            if self.falling_block.x < self.width-len(self.falling_block.shape[0]) and not self.collides(self.falling_block, 1):
                self.falling_block.x += 1

    def rotate(self):
        # 旋转方块
        if self.falling_block:
            tmp = list(zip(*self.falling_block.shape[::-1]))
            if self.falling_block.x + len(tmp[0]) <= self.width and not self.collides(Block(tmp, self.falling_block.color, self.falling_block.x, self.falling_block.y), 0):
                self.falling_block.shape = tmp

    def fall(self):
        # 下落方块
        if self.falling_block:
            if self.falling_block.y < self.height-len(self.falling_block.shape) and not self.collides(self.falling_block, 0, 1):
                self.falling_block.y += 1
                return False
            else:
                self.merge_falling_block()
                self.new_block()
                return True

    def merge_falling_block(self):
        # 将当前方块合并到游戏区域
        for y, row in enumerate(self.falling_block.shape):
            for x, val in enumerate(row):
                if val:
                    self.board[self.falling_block.y+y][self.falling_block.x+x] = self.falling_block.color
        # 消除填满一行的方块
        for y in range(self.height):
            if all(self.board[y]):
                self.board.pop(y)
                self.board.insert(0, [0 for x in range(self.width)])
                self.score += 10
                if self.score % 100 == 0:
                    self.level += 1

    def collides(self, block, dx=0, dy=0):
        # 判断方块是否与游戏区域或已有方块重叠
        for y, row in enumerate(block.shape):
            for x, val in enumerate(row):
                if val:
                    try:
                        if self.board[block.y+y+dy][block.x+x+dx]:
                            return True
                    except IndexError:
                        return True
        return False

# 游戏主循环
def main():
    pygame.init()
    screen = pygame.display.set_mode((320, 480))
    clock = pygame.time.Clock()
    game = Game()
    game.new_block()
    paused = False
    font = pygame.font.SysFont('Arial', 20)
    while not game.game_over:
        clock.tick(game.level * 5)
        screen.fill((0, 0, 0))
        game.draw_board(screen)
        game.draw_falling_block(screen)
        game.draw_next_block(screen)

        # 显示分数
        text = font.render('Score: ' + str(game.score), True, (255, 255, 255))
        screen.blit(text, (10, 10))

        # 监听键盘事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game.game_over = True
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    game.move_left()
                elif event.key == pygame.K_RIGHT:
                    game.move_right()
                elif event.key == pygame.K_UP:
                    game.rotate()
                elif event.key == pygame.K_DOWN:
                    if not paused:
                        game.fall()
                elif event.key == pygame.K_p:
                    paused = not paused
                elif event.key == pygame.K_SPACE:
                    if paused:
                        game = Game()
                        game.new_block()
                        paused = False
        # 游戏暂停时不更新屏幕
        if not paused:
            if game.fall():
                if game.collides(game.falling_block, 0, 0):
                    # 游戏结束
                    text = font.render('Game Over', True, (255, 255, 255))
                    screen.blit(text, (100, 200))
                    paused = True

        pygame.display.update()
    pygame.quit()

if __name__ == '__main__':
    main()

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
blindcat + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

仲舒 发表于 2023-5-22 16:06
可以尝试以下几种优化方法:

1. 减少绘制次数:在每一帧中,你的代码会多次调用`draw()`方法来绘制方块和游戏区域。如果绘制操作过于频繁,会导致性能下降。你可以考虑减少绘制次数,只在方块状态发生变化或需要更新时进行绘制。

2. 使用双缓冲技术:双缓冲技术可以提高绘制效率。你可以创建一个后台缓冲区,在其中进行绘制操作,然后将缓冲区的内容一次性绘制到屏幕上,减少屏幕刷新次数,从而提高性能。

3. 优化碰撞检测:在`collides()`方法中,你通过逐个检查方块位置来判断碰撞。这种方法可能会随着方块数量的增加而变得低效。你可以考虑使用更高效的碰撞检测算法,例如使用边界框或分割区域来加速碰撞检测过程。

4. 使用图像缓存:在每一帧中,方块的形状和颜色都是不变的。你可以将方块的绘制结果缓存为图像,而不是每次都重新绘制。这样可以减少绘制操作的数量,提高性能。

5. 优化事件处理:在事件处理的部分,你使用了`pygame.event.get()`来获取所有的事件。这会一次性获取所有的事件,可能会导致输入响应的延迟。你可以考虑使用`pygame.event.poll()`或者`pygame.event.wait()`来获取单个事件,以提高输入的实时性。

6. 使用适当的图像格式:在绘制和加载图像时,使用适当的图像格式可以提高性能。例如,使用压缩格式(如PNG)而不是无损格式(如BMP)可以减少图像的内存占用和加载时间。

7. 调整游戏速度参数:通过调整游戏速度参数,可以在流畅性和游戏难度之间取得平衡。可以尝试逐渐增加或减少帧率限制,找到最佳的游戏速度。

这些是一些常见的优化方法,但具体的优化策略可能因游戏的复杂性和硬件平台而有所不同。建议你逐步实施这些优化措施,并进行性能测试和调整,以找到最适合你的游戏的优化方案。

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
jjjzw + 1 + 1 热心回复!

查看全部评分

仲舒 发表于 2023-5-22 16:59
[Python] 纯文本查看 复制代码
import pygame
import random

# 游戏区域的宽度和高度
grid_width = 10
grid_height = 20

# 方块大小和窗口尺寸
block_size = 30
window_width = grid_width * block_size
window_height = grid_height * block_size

# 初始化Pygame
pygame.init()
window = pygame.display.set_mode((window_width, window_height))
pygame.display.set_caption("Tetris Game")

# 颜色定义
BLACK = (0, 0, 0)
CYAN = (0, 255, 255)
YELLOW = (255, 255, 0)
PURPLE = (255, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
ORANGE = (255, 165, 0)

# 方块的形状和颜色
tetriminos = [
    [[1, 1, 1, 1]],  # I
    [[1, 1], [1, 1]],  # O
    [[1, 1, 0], [0, 1, 1]],  # Z
    [[0, 1, 1], [1, 1, 0]],  # S
    [[1, 1, 1], [0, 1, 0]],  # T
    [[1, 1, 1], [0, 0, 1]],  # L
    [[1, 1, 1], [1, 0, 0]]  # J
]

# 方块颜色对应关系
tetrimino_colors = [CYAN, YELLOW, PURPLE, GREEN, RED, BLUE, ORANGE]

# 初始化游戏区域
grid = [[0] * grid_width for _ in range(grid_height)]

# 当前方块的形状、颜色和位置
current_tetrimino = random.choice(tetriminos)
current_tetrimino_color = random.choice(tetrimino_colors)
current_tetrimino_x = grid_width // 2 - len(current_tetrimino[0]) // 2
current_tetrimino_y = 0

# 绘制游戏区域
def draw_grid():
    for row in range(grid_height):
        for col in range(grid_width):
            if grid[row][col] != 0:
                pygame.draw.rect(window, tetrimino_colors[grid[row][col] - 1],
                                 (col * block_size, row * block_size, block_size, block_size))
            pygame.draw.rect(window, BLACK, (col * block_size, row * block_size, block_size, block_size), 1)

# 绘制方块
def draw_tetrimino(tetrimino, x, y, color):
    for row in range(len(tetrimino)):
        for col in range(len(tetrimino[row])):
            if tetrimino[row][col] == 1:
                pygame.draw.rect(window, color,
                                 ((x + col) * block_size, (y + row) * block_size, block_size, block_size))
                pygame.draw.rect(window, BLACK,
                                 ((x + col) * block_size, (y + row) * block_size, block_size, block_size), 1)

# 检查方块是否可以放置到游戏区域中
def can_place_tetrimino(tetrimino, x, y):
    for row in range(len(tetrimino)):
        for col in range(len(tetrimino[row])):
            if tetrimino[row][col] == 1:
                if x + col < 0 or x + col >= grid_width or y + row >= grid_height or grid[y + row][x + col] != 0:
                    return False
    return True

# 将方块放置到游戏区域中
def place_tetrimino(tetrimino, x, y, color):
    for row in range(len(tetrimino)):
        for col in range(len(tetrimino[row])):
            if tetrimino[row][col] == 1:
                grid[y + row][x + col] = color

# 旋转方块形状
def rotate_tetrimino(tetrimino):
    return list(zip(*reversed(tetrimino)))

# 消除满行的方块
def clear_lines():
    full_rows = []
    for row in range(grid_height):
        if all(grid[row]):
            full_rows.append(row)

    for row in full_rows:
        del grid[row]
        grid.insert(0, [0] * grid_width)

# 判断游戏是否结束
def is_game_over():
    return any(grid[0])

# 游戏主循环
clock = pygame.time.Clock()
game_over = False

while not game_over:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            game_over = True

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                if can_place_tetrimino(current_tetrimino, current_tetrimino_x - 1, current_tetrimino_y):
                    current_tetrimino_x -= 1
            elif event.key == pygame.K_RIGHT:
                if can_place_tetrimino(current_tetrimino, current_tetrimino_x + 1, current_tetrimino_y):
                    current_tetrimino_x += 1
            elif event.key == pygame.K_DOWN:
                if can_place_tetrimino(current_tetrimino, current_tetrimino_x, current_tetrimino_y + 1):
                    current_tetrimino_y += 1
            elif event.key == pygame.K_UP:
                rotated_tetrimino = rotate_tetrimino(current_tetrimino)
                if can_place_tetrimino(rotated_tetrimino, current_tetrimino_x, current_tetrimino_y):
                    current_tetrimino = rotated_tetrimino

    # 移动方块下落
    if can_place_tetrimino(current_tetrimino, current_tetrimino_x, current_tetrimino_y + 1):
        current_tetrimino_y += 1

    # 检查是否需要固定方块并生成新的方块
    if not can_place_tetrimino(current_tetrimino, current_tetrimino_x, current_tetrimino_y + 1):
        place_tetrimino(current_tetrimino, current_tetrimino_x, current_tetrimino_y, tetrimino_colors.index(current_tetrimino_color) + 1)
        clear_lines()

        current_tetrimino = random.choice(tetriminos)
        current_tetrimino_color = random.choice(tetrimino_colors)
        current_tetrimino_x = grid_width // 2 - len(current_tetrimino[0]) // 2
        current_tetrimino_y = 0

        if not can_place_tetrimino(current_tetrimino, current_tetrimino_x, current_tetrimino_y):
            game_over = True

    # 渲染游戏界面
    window.fill(BLACK)
    draw_grid()
    draw_tetrimino(current_tetrimino, current_tetrimino_x, current_tetrimino_y, current_tetrimino_color)
    pygame.display.update()

    # 控制游戏帧率
    clock.tick(5)

# 游戏结束后退出
pygame.quit()
friendnabs 发表于 2023-5-22 16:59
仲舒 发表于 2023-5-22 16:06
可以尝试以下几种优化方法:

1. 减少绘制次数:在每一帧中,你的代码会多次调用`draw()`方法来绘制方块 ...

这明显就是chatgpt的答案
仲舒 发表于 2023-5-22 17:00
仲舒 发表于 2023-5-22 16:59
[mw_shl_code=python,true]import pygame
import random

找了以前写的一个例子,希望对你有帮助
wasd71 发表于 2023-5-22 17:26
引入pygame库和random库吗
TR小米哥 发表于 2023-5-22 18:04
有一说一,看着很不错
我试着改了下下,这么运行下去的话要好些,你可以看看。
[Python] 纯文本查看 复制代码
import randomimport pygame

# 定义方块类
class Block:
    def __init__(self, shape, color, x, y):
        self._shape = shape
        self._color = color
        self.x = x
        self.y = y

    @property
    def shape(self):
        return self._shape

    @property
    def color(self):
        return self._color

    def draw(self, surface):
        rect = (self.x*25+1, self.y*25+1, 24, 24)
        pygame.draw.rect(surface, self.color, rect)

# 定义游戏类
class Game:
    def __init__(self, width=10, height=20):
        self.width = width
        self.height = height
        self._board = [[0 for x in range(self.width)] for y in range(self.height)]
        self.score = 0
        self.level = 1
        self.falling_block = None
        self.next_block = None
        self.game_over = False

    @property
    def board(self):
        return self._board

    def new_block(self):
        # 随机生成新的方块
        shapes = [
            [[[1, 1, 1, 1]], (255, 0, 0)],
            [[[1, 1], [1, 1]], (0, 255, 0)],
            [[[1, 1, 0], [0, 1, 1]], (0, 0, 255)],
            [[[0, 1, 1], [1, 1, 0]], (255, 255, 0)],
            [[[1, 1, 1], [0, 1, 0]], (0, 255, 255)],
            [[[1, 1, 0], [0, 1, 1]], (255, 0, 255)],
            [[[0, 1, 0], [1, 1, 1]], (128, 0, 128)]
        ]
        shape, color = random.choice(shapes)
        self.falling_block = Block(shape, color, self.width//2-2, 0)
        shape, color = random.choice(shapes)
        self.next_block = Block(shape, color, 0, 0)

    def draw_board(self, surface):
        # 绘制游戏区域
        rect = pygame.Rect(0, 0, 25, 25)
        for y in range(self.height):
            for x in range(self.width):
                rect.topleft = (x*25, y*25)
                pygame.draw.rect(surface, (255, 255, 255), rect, 1)
                if self.board[y][x]:
                    rect.topleft = (x*25+1, y*25+1)
                    pygame.draw.rect(surface, self.board[y][x], rect)

    def draw_falling_block(self, surface):
        # 绘制当前下落的方块
        if self.falling_block:
            for y, row in enumerate(self.falling_block.shape):
                for x, val in enumerate(row):
                    if val:
                        b = Block(self.falling_block.shape, self.falling_block.color, self.falling_block.x+x, self.falling_block.y+y)
                        b.draw(surface)

    def draw_next_block(self, surface):
        # 绘制下一个方块
        if self.next_block:
            for y, row in enumerate(self.next_block.shape):
                for x, val in enumerate(row):
                    if val:
                        b = Block(self.next_block.shape, self.next_block.color, self.width+x, y)
                        b.draw(surface)

    def move_left(self):
        # 向左移动方块
        if self.falling_block:
            if self.falling_block.x > 0 and not self.collides(self.falling_block, -1):
                self.falling_block.x -= 1

    def move_right(self):
        # 向右移动方块
        if self.falling_block:
            if self.falling_block.x < self.width-len(self.falling_block.shape[0]) and not self.collides(self.falling_block, 1):
                self.falling_block.x += 1

    def rotate(self):
        # 旋转方块
        if self.falling_block:
            tmp = list(zip(*self.falling_block.shape[::-1]))
            if self.falling_block.x + len(tmp[0]) <= self.width and not self.collides(Block(tmp, self.falling_block.color, self.falling_block.x, self.falling_block.y), 0):
                self.falling_block.shape = tmp

    def fall(self):
        # 下落方块
        if self.falling_block:
            if self.falling_block.y < self.height-len(self.falling_block.shape) and not self.collides(self.falling_block, 0, 1):
                self.falling_block.y += 1
                return False
            else:
                self.merge_falling_block()
                self.new_block()
                return True

    def merge_falling_block(self):
        # 将当前方块合并到游戏区域
        for y, row in enumerate(self.falling_block.shape):
            for x, val in enumerate(row):
                if val:
                    self.board[self.falling_block.y+y][self.falling_block.x+x] = self.falling_block.color
        # 消除填满一行的方块
        for y in range(self.height):
            if all(self.board[y]):
                self.board.pop(y)
                self.board.insert(0, [0 for x in range(self.width)])
                self.score += 10
                if self.score % 100 == 0:
                    self.level += 1

    @staticmethod
    def collides(block, dx=0, dy=0, board=None):
        # 判断方块是否与游戏区域或已有方块重叠
        board = board or []
        for y, row in enumerate(block.shape):
            for x, val in enumerate(row):
                if val:
                    try:
                        if board[block.y+y+dy][block.x+x+dx]:
                            return True
                    except IndexError:
                        return True
        return False

# 游戏主循环
def main():
    pygame.init()
    screen = pygame.display.set_mode((320, 480))
    clock = pygame.time.Clock()
    game = Game()
    game.new_block()
    paused = False
    font = pygame.font.SysFont('Arial', 20)
    while not game.game_over:
        clock.tick(game.level * 5)
        screen.fill((0, 0, 0))
        game.draw_board(screen)
        game.draw_falling_block(screen)
        game.draw_next_block(screen)

        # 显示分数
        text = font.render('Score: ' + str(game.score), True, (255, 255, 255))
        screen.blit(text, (10, 10))

        # 监听键盘事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game.game_over = True
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    game.move_left()
                elif event.key == pygame.K_RIGHT:
                    game.move_right()
                elif event.key == pygame.K_UP:
                    game.rotate()
                elif event.key == pygame.K_DOWN:
                    if not paused:
                        game.fall()
                elif event.key == pygame.K_p:
                    paused = not paused
                elif event.key == pygame.K_SPACE:
                    if paused:
                        game = Game()
                        game.new_block()
                        paused = False
        # 游戏暂停时不更新屏幕
        if not paused:
            if game.fall():
                if game.collides(game.falling_block, 0, 0, game.board):
                    # 游戏结束
                    text = font.render('Game Over', True, (255, 255, 255))
                    screen.blit(text, (100, 200))
                    paused = True

        pygame.display.update()
    pygame.quit()

if __name__ == '__main__':
    main()

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
suneryzgg123 + 1 + 1 谢谢@Thanks!

查看全部评分

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 22:49

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表