新手用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
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()
可以尝试以下几种优化方法:
1. 减少绘制次数:在每一帧中,你的代码会多次调用`draw()`方法来绘制方块和游戏区域。如果绘制操作过于频繁,会导致性能下降。你可以考虑减少绘制次数,只在方块状态发生变化或需要更新时进行绘制。
2. 使用双缓冲技术:双缓冲技术可以提高绘制效率。你可以创建一个后台缓冲区,在其中进行绘制操作,然后将缓冲区的内容一次性绘制到屏幕上,减少屏幕刷新次数,从而提高性能。
3. 优化碰撞检测:在`collides()`方法中,你通过逐个检查方块位置来判断碰撞。这种方法可能会随着方块数量的增加而变得低效。你可以考虑使用更高效的碰撞检测算法,例如使用边界框或分割区域来加速碰撞检测过程。
4. 使用图像缓存:在每一帧中,方块的形状和颜色都是不变的。你可以将方块的绘制结果缓存为图像,而不是每次都重新绘制。这样可以减少绘制操作的数量,提高性能。
5. 优化事件处理:在事件处理的部分,你使用了`pygame.event.get()`来获取所有的事件。这会一次性获取所有的事件,可能会导致输入响应的延迟。你可以考虑使用`pygame.event.poll()`或者`pygame.event.wait()`来获取单个事件,以提高输入的实时性。
6. 使用适当的图像格式:在绘制和加载图像时,使用适当的图像格式可以提高性能。例如,使用压缩格式(如PNG)而不是无损格式(如BMP)可以减少图像的内存占用和加载时间。
7. 调整游戏速度参数:通过调整游戏速度参数,可以在流畅性和游戏难度之间取得平衡。可以尝试逐渐增加或减少帧率限制,找到最佳的游戏速度。
这些是一些常见的优化方法,但具体的优化策略可能因游戏的复杂性和硬件平台而有所不同。建议你逐步实施这些优化措施,并进行性能测试和调整,以找到最适合你的游戏的优化方案。 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()
仲舒 发表于 2023-5-22 16:06
可以尝试以下几种优化方法:
1. 减少绘制次数:在每一帧中,你的代码会多次调用`draw()`方法来绘制方块 ...
这明显就是chatgpt的答案 仲舒 发表于 2023-5-22 16:59
import pygame
import random
找了以前写的一个例子,希望对你有帮助 引入pygame库和random库吗 有一说一,看着很不错{: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]