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 = [ 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 = [
            [[], (255, 0, 0)],
            [[, ], (0, 255, 0)],
            [[, ], (0, 0, 255)],
            [[, ], (255, 255, 0)],
            [[, ], (0, 255, 255)],
            [[, ], (255, 0, 255)],
            [[, ], (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:
                  pygame.draw.rect(surface, self.board, (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) 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) <= 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.color
      # 消除填满一行的方块
      for y in range(self.height):
            if all(self.board):
                self.board.pop(y)
                self.board.insert(0, )
                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:
                            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()

仲舒 发表于 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. 调整游戏速度参数:通过调整游戏速度参数,可以在流畅性和游戏难度之间取得平衡。可以尝试逐渐增加或减少帧率限制,找到最佳的游戏速度。

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

仲舒 发表于 2023-5-22 16:59

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 = [
    [],# I
    [, ],# O
    [, ],# Z
    [, ],# S
    [, ],# T
    [, ],# L
    [, ]# J
]

# 方块颜色对应关系
tetrimino_colors =

# 初始化游戏区域
grid = [ * 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) // 2
current_tetrimino_y = 0

# 绘制游戏区域
def draw_grid():
    for row in range(grid_height):
      for col in range(grid_width):
            if grid != 0:
                pygame.draw.rect(window, tetrimino_colors - 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)):
            if tetrimino == 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)):
            if tetrimino == 1:
                if x + col < 0 or x + col >= grid_width or y + row >= grid_height or grid != 0:
                  return False
    return True

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

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

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

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

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

# 游戏主循环
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) // 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
import pygame
import random



找了以前写的一个例子,希望对你有帮助

wasd71 发表于 2023-5-22 17:26

引入pygame库和random库吗

TR小米哥 发表于 2023-5-22 18:04

有一说一,看着很不错{:301_997:}
我试着改了下下,这么运行下去的话要好些,你可以看看。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 = [ 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 = [
            [[], (255, 0, 0)],
            [[, ], (0, 255, 0)],
            [[, ], (0, 0, 255)],
            [[, ], (255, 255, 0)],
            [[, ], (0, 255, 255)],
            [[, ], (255, 0, 255)],
            [[, ], (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:
                  rect.topleft = (x*25+1, y*25+1)
                  pygame.draw.rect(surface, self.board, 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) 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) <= 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.color
      # 消除填满一行的方块
      for y in range(self.height):
            if all(self.board):
                self.board.pop(y)
                self.board.insert(0, )
                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:
                            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]
查看完整版本: 新手用python写了一个俄罗斯方块目前个人只能做到这样,而且流畅性不佳求大佬指点