【Dison夏令营 Day 16】如何使用 Python 中的 PyGame 制作俄罗斯方块游戏

俄罗斯方块(Tetris)是一款经典的益智游戏,游戏的目的是将落下的几何图形片(称为 “俄罗斯方块”)排列起来,填满水平线,不留空隙。当一条线被完全填满时,它就被清除了,玩家就能获得分数。随着四角棋的下落速度加快,游戏的挑战性也逐渐增加,及时排列四角棋也变得更加困难。

在这里插入图片描述

在本教程中,我们将指导您使用 PyGame 逐步创建一个简单的俄罗斯方块游戏。我们将介绍以下内容:

  • 设置开发环境并安装 Pygame
  • 创建游戏窗口并定义俄罗斯方块棋子
  • 实现俄罗斯方块和俄罗斯方块类以管理游戏逻辑
  • 处理用户输入和游戏事件
  • 在屏幕上绘制游戏状态、分数和游戏结束信息
  • 执行主游戏循环

在本教程结束时,您将拥有一个功能齐全的俄罗斯方块游戏,并可以进行游戏和自定义。这个项目还将帮助您了解使用 Python 和 Pygame 开发游戏的基础知识,并为创建其他类型的游戏打下基础。下面是它的外观:

在这里插入图片描述

入门

安装好 Python 后,打开终端或命令提示符,输入以下命令安装 Pygame 库:

$ pip install pygame

创建游戏窗口

现在我们的开发环境已经准备就绪,让我们开始创建游戏窗口并定义四面体形状。

首先,我们需要导入俄罗斯方块游戏所需的模块。在 Python 脚本中添加以下几行:

import sys
import pygame
import random

要使用 Pygame 库,我们需要对其进行初始化。在 import 语句后添加以下一行:

pygame.init()

定义屏幕尺寸、颜色和四角棋形状

接下来,我们需要为游戏定义一些常量,如屏幕尺寸、网格大小、颜色和四角棋的形状。在脚本中添加以下几行:

# Screen dimensions
WIDTH, HEIGHT = 800, 600
GRID_SIZE = 25# Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
COLORS = [RED, BLUE, GREEN]# Tetromino shapes
SHAPES = [[['.....','.....','.....','OOOO.','.....'],['.....','..O..','..O..','..O..','..O..']],[['.....','.....','..O..','.OOO.','.....'],['.....','..O..','.OO..','..O..','.....'],['.....','.....','.OOO.','..O..','.....'],['.....','..O..','..OO.','..O..','.....']],[['.....','.....','..OO.','.OO..','.....'],['.....','.....','.OO..','..OO.','.....'],['.....','.O...','.OO..','..O..','.....'],['.....','..O..','.OO..','.O...','.....']],[['.....','..O..','..O.','..OO.','.....'],['.....','...O.','.OOO.','.....','.....'],['.....','.OO..','..O..','..O..','.....'],['.....','.....','.OOO.','.O...','.....']],
]

在这里,我们定义了游戏窗口的宽度和高度、四角棋的网格大小以及游戏使用的颜色(白色、黑色和红色)。SHAPES 列表包含以字符串表示的四面体形状,您可以随意添加/编辑。您还可以随意调整颜色和网格大小。

实现 Tetromino 和 Tetris 类以管理游戏逻辑

现在,我们已经定义了游戏窗口和俄罗斯方块形状,让我们创建两个类来管理游戏逻辑:Tetromino 类和 Tetris 方块类。

创建 Tetromino 类

Tetromino 类将表示单个四面体,并具有位置、形状、颜色和旋转属性。在脚本中添加以下代码:

class Tetromino:def __init__(self, x, y, shape):self.x = xself.y = yself.shape = shapeself.color = random.choice(COLORS) # You can choose different colors for each shapeself.rotation = 0

创建 Tetris 类

俄罗斯方块类将处理主要的游戏逻辑。它将包含用于创建新棋子、检查走棋是否有效、清线、锁定棋子、更新游戏状态和绘制游戏的方法。在脚本中添加以下代码:

class Tetris:def __init__(self, width, height):self.width = widthself.height = heightself.grid = [[0 for _ in range(width)] for _ in range(height)]self.current_piece = self.new_piece()self.game_over = Falseself.score = 0  # Add score attribute

让我们来制作一个新的 Tetromino 棋子:

    def new_piece(self):# Choose a random shapeshape = random.choice(SHAPES)# Return a new Tetromino objectreturn Tetromino(self.width // 2, 0, shape)

接下来,valid_move() 方法会检查棋子是否能移动到指定位置:

    def valid_move(self, piece, x, y, rotation):"""Check if the piece can move to the given position"""for i, row in enumerate(piece.shape[(piece.rotation + rotation) % len(piece.shape)]):for j, cell in enumerate(row):try:if cell == 'O' and (self.grid[piece.y + i + y][piece.x + j + x] != 0):return Falseexcept IndexError:return Falsereturn True

clear_lines() 方法会清除已满的行,并返回已清除的行数,以便我们稍后计算分数:

    def clear_lines(self):"""Clear the lines that are full and return the number of cleared lines"""lines_cleared = 0for i, row in enumerate(self.grid[:-1]):if all(cell != 0 for cell in row):lines_cleared += 1del self.grid[i]self.grid.insert(0, [0 for _ in range(self.width)])return lines_cleared

现在是锁定棋子的方法:

    def lock_piece(self, piece):"""Lock the piece in place and create a new piece"""for i, row in enumerate(piece.shape[piece.rotation % len(piece.shape)]):for j, cell in enumerate(row):if cell == 'O':self.grid[piece.y + i][piece.x + j] = piece.color# Clear the lines and update the scorelines_cleared = self.clear_lines()self.score += lines_cleared * 100  # Update the score based on the number of cleared lines# Create a new pieceself.current_piece = self.new_piece()# Check if the game is overif not self.valid_move(self.current_piece, 0, 0, 0):self.game_over = Truereturn lines_cleared

update() 函数将四叶草向下移动一格:

    def update(self):"""Move the tetromino down one cell"""if not self.game_over:if self.valid_move(self.current_piece, 0, 1, 0):self.current_piece.y += 1else:self.lock_piece(self.current_piece)

最后,我们制作了绘制游戏网格和当前棋子的方法:

    def draw(self, screen):"""Draw the grid and the current piece"""for y, row in enumerate(self.grid):for x, cell in enumerate(row):if cell:pygame.draw.rect(screen, cell, (x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE - 1, GRID_SIZE - 1))if self.current_piece:for i, row in enumerate(self.current_piece.shape[self.current_piece.rotation % len(self.current_piece.shape)]):for j, cell in enumerate(row):if cell == 'O':pygame.draw.rect(screen, self.current_piece.color, ((self.current_piece.x + j) * GRID_SIZE, (self.current_piece.y + i) * GRID_SIZE, GRID_SIZE - 1, GRID_SIZE - 1))

为在游戏中绘制文本创建辅助函数

既然我们已经创建了俄罗斯方块类,那么让我们来创建两个绘制文本的辅助函数,一个用于显示得分,另一个用于显示 “Game Over!”:

def draw_score(screen, score, x, y):"""Draw the score on the screen"""font = pygame.font.Font(None, 36)text = font.render(f"Score: {score}", True, WHITE)screen.blit(text, (x, y))def draw_game_over(screen, x, y):"""Draw the game over text on the screen"""font = pygame.font.Font(None, 48)text = font.render("Game Over", True, RED)screen.blit(text, (x, y))

这些函数需要四个参数(draw_game_over()需要三个):

  • screen:要绘制的 Pygame 表面。
  • score:当前游戏得分。
  • x:分数显示位置的 x 坐标。
  • y:分数显示位置的 y 坐标。

这些函数使用 pygame.font.Font(None, 36) 创建字体对象,使用 font.render() 方法渲染得分文本,然后使用 screen.blit() 将文本显示在屏幕上。

使游戏循环

在运行循环之前,我们首先初始化 Pygame,创建时钟对象,然后创建游戏屏幕和游戏,即俄罗斯方块对象:

def main():# Initialize pygamescreen = pygame.display.set_mode((WIDTH, HEIGHT))pygame.display.set_caption('Tetris')# Create a clock objectclock = pygame.time.Clock()# Create a Tetris objectgame = Tetris(WIDTH // GRID_SIZE, HEIGHT // GRID_SIZE)fall_time = 0fall_speed = 50  # You can adjust this value to change the falling speed, it's in milliseconds

您可以调整 fall_speed 来降低它(使其更快),或增加它使其更慢。

下面是游戏循环:

    while True:# Fill the screen with blackscreen.fill(BLACK) for event in pygame.event.get():# Check for the QUIT eventif event.type == pygame.QUIT:pygame.quit()sys.exit()# Check for the KEYDOWN eventif event.type == pygame.KEYDOWN:if event.key == pygame.K_LEFT:if game.valid_move(game.current_piece, -1, 0, 0):game.current_piece.x -= 1 # Move the piece to the leftif event.key == pygame.K_RIGHT:if game.valid_move(game.current_piece, 1, 0, 0):game.current_piece.x += 1 # Move the piece to the rightif event.key == pygame.K_DOWN:if game.valid_move(game.current_piece, 0, 1, 0):game.current_piece.y += 1 # Move the piece downif event.key == pygame.K_UP:if game.valid_move(game.current_piece, 0, 0, 1):game.current_piece.rotation += 1 # Rotate the pieceif event.key == pygame.K_SPACE:while game.valid_move(game.current_piece, 0, 1, 0):game.current_piece.y += 1 # Move the piece down until it hits the bottomgame.lock_piece(game.current_piece) # Lock the piece in place# Get the number of milliseconds since the last framedelta_time = clock.get_rawtime() # Add the delta time to the fall timefall_time += delta_time if fall_time >= fall_speed:# Move the piece downgame.update()# Reset the fall timefall_time = 0# Draw the score on the screendraw_score(screen, game.score, 10, 10)# Draw the grid and the current piecegame.draw(screen)if game.game_over:# Draw the "Game Over" messagedraw_game_over(screen, WIDTH // 2 - 100, HEIGHT // 2 - 30)  # Draw the "Game Over" message# You can add a "Press any key to restart" message here# Check for the KEYDOWN eventif event.type == pygame.KEYDOWN:# Create a new Tetris objectgame = Tetris(WIDTH // GRID_SIZE, HEIGHT // GRID_SIZE)# Update the displaypygame.display.flip()# Set the framerateclock.tick(60)

主游戏循环是一个 while 循环,不断执行以下步骤:

  1. 用黑色填充屏幕,清空屏幕。
  2. 处理 Pygame 事件,如退出游戏或处理移动和旋转俄罗斯方块棋子的键盘输入。
  3. 更新游戏状态,包括将当前棋子向下移动一行,并在棋子到达底部时将其锁定。
  4. 在屏幕上绘制当前分数、游戏网格和当前棋子。
  5. 如果游戏结束,显示 "游戏结束 "信息。
  6. 更新 Pygame 显示屏,并使用时钟对象控制帧频。

最后的话

就是这样!俄罗斯方块游戏的简单实现现在应该可以运行了。您可以运行脚本来玩游戏,并对游戏玩法、图形或控件进行任何所需的定制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/870678.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

操作系统——内存管理(面试准备)

虚拟内存 单片机没有操作系统,每次写完代码,都需要借助工具把程序烧录进去,这样程序才能跑起来。 另外,单片机的CPU是直接操作内存的物理地址。 在这种情况下,想在内存中同时运行两个程序是不可能的,如果第…

(CVPR-2024)SwiftBrush:具有变分分数蒸馏的单步文本到图像扩散模型

SwiftBrush:具有变分分数蒸馏的单步文本到图像扩散模型 Paper Title:SwiftBrush: One-Step Text-to-Image Diffusion Model with Variational Score Distillation Paper 是 VinAI Research 发表在 CVPR 24 的工作 Paper地址 Code:地址 Abstract 尽管文本…

Flutter-实现物理小球碰撞效果

效果 引言 在Flutter应用中实现物理动画效果,可以大大提升用户体验。本文将详细介绍如何在Flutter中创建一个模拟物理碰撞的动画小球界面,主要代码实现基于集成sensors_plus插件来获取设备的加速度传感器数据。 准备工作 在开始之前,请确保…

一文详解DDL同步及其应用场景

目录 一、什么是DDL? 二、什么是DDL同步? 三、DDL同步的痛点 1、缺少自动DDL同步机制 2、缺少DDL变更监测预警 四、解决方案 五、应用场景及案例 案例一 案例二 案例三 在现代数据管理中,数据库的结构变更频繁且不可避免,特别是在…

Kubelet 认证

当我们执行kubectl exec -it pod [podName] sh命令时,apiserver会向kubelet发起API请求。也就是说,kubelet会提供HTTP服务,而为了安全,kubelet必须提供HTTPS服务,且还要提供一定的认证与授权机制,防止任何知…

HTTP3.0

HTTP/3是HTTP协议的最新版本,它基于QUIC协议,具有以下特点: 无队头阻塞: QUIC 使用UDP协议来传输数据。一个连接上的多个stream之间没有依赖, 如果一个stream丢了一个UDP包,不会影响后面的stream,不存在 队头阻塞问题…

迪卡斯特拉算法与前式链向星结合的易错点

进行迪克特斯拉算法的时候我们需要标记已经访问过的节点&#xff0c;而这个节点是否访问过的判断也是需要注意的 int dikj() {priority_queue<pair<int, int>> q;int ma 0;//vis[start] 1; // 记录一下 不用写for (int i 0; i < n; i) vis[i] 0,di[i] 0x…

C语言 | Leecode C语言题解之第229题多数元素II

题目&#xff1a; 题解&#xff1a; /*** Note: The returned array must be malloced, assume caller calls free().*//*假定 num1&#xff0c;num2 为出现次数大于 nums.length / 3 的两个数。&#xff08;最多出现两个&#xff09;遍历 nums&#xff0c; 若出现 num1、num2…

《C语言程序设计 第4版》笔记和代码 第十一章 指针和数组

第十一章 指针和数组 11.1 指针和一维数组间的关系 1 由于数组名代表数组元素的连续存储空间的首地址&#xff0c;因此&#xff0c;数组元素既可以用下标法也可以用指针来引用。 例11.1见文末 2 p1与p在本质上是两个不同的操作&#xff0c;前者不改变当前指针的指向&#xf…

无人机之遥控器保养

一、使用存放 1、避免让遥控器受到强烈的震动或从高处跌落&#xff0c;以免影响内部结构的精度&#xff1b; 2、遥控器在使用完后&#xff0c;需要将天线收拢&#xff0c;避免折断&#xff0c;养成定期检查天线的习惯&#xff1b; 3、定期检查遥控器按键有无裂纹、畸变、松旷…

LiteOS GPIO中断处理

在LiteOS系统里主要使用IoTGpioRegisterIsrFunc函数注册GPIO的中断&#xff1a; 函数原型&#xff1a; unsigned int IoTGpioRegisterIsrFunc(unsigned int id, IotGpioIntType intType, IotGpioIntPolarity intPolarity, GpioIsrCallbackFunc func, char *arg)参数功能&#…

vue + Lodop 实现浏览器自动打印 无需预览打印

官网地址&#xff1a;https://www.lodop.net/download.html 先去Lodop官网下载相应的安装包 解压安装将LodopFuncs.js放在项目中utils文件夹中加一行代码 export { getLodop }; //导出<template><div><div class"main"><ul class"btns&qu…

ISO/OIS的七层模型②

OSI模型是一个分层的模型&#xff0c;每一个部分称为一层&#xff0c;每一层扮演固定的角色&#xff0c;互不干扰。OSI有7层&#xff0c;从上到下分别是&#xff1a; 一&#xff0c;每层功能 7.应用层&#xff08;Application layer &#xff09;&#xff1a;应用层功能&#x…

Java发展过程中,JVM的演进

1. 初期的JVM&#xff08;Java 1.0 到 Java 1.1&#xff09; Java 1.0 于1996年发布&#xff0c;最初的JVM设计主要是为了跨平台兼容性和基本的垃圾回收功能。早期的JVM以解释执行字节码为主&#xff0c;性能相对较低。 2. 引入即时编译&#xff08;JIT&#xff09;&#xff…

如何从gitlab删除仓库

嗨&#xff0c;我是兰若姐姐。今天发现gitlab上有些仓库的代码没有用&#xff0c;是个多余的仓库&#xff0c;想要删掉&#xff0c;经过一番操作之后&#xff0c;成功的删除了&#xff0c;git上没有 多余的仓库&#xff0c;看着干净舒服很多&#xff0c;现在把删除的过程分享出…

基于ssm的图书管理系统的设计与实现

摘 要 在当今信息技术日新月异的时代背景下&#xff0c;图书管理领域正经历着深刻的变革&#xff0c;传统的管理模式已难以适应现代社会的快节奏和高要求&#xff0c;逐渐向数字化、智能化的方向演进。本论文聚焦于这一转变趋势&#xff0c;致力于设计并成功实现一个基于 SSM&…

开发不认可bug策略

作为测试&#xff0c;不仅仅要发现问题&#xff0c;更需要站在用户层面主动推进问题得到有效解决&#xff1b; 首先要积极耐心和开发进行沟通并共同复现bug&#xff0c;提供测试环境、操作步骤、测试数据、截图、日志等&#xff0c;确保rd对bug有充分的了解&#xff0c;更好地理…

U-net和U²-Net网络详解

目录 U-Net: Convolutional Networks for Biomedical Image Segmentation摘要U-net网络结构pixel-wise loss weight U-Net: Going Deeper with Nested U-Structure for Salient Object Detection摘要网络结构详解整体结构RSU-n结构RSU-4F结构saliency map fusion module -- 显著…

JavaFx+MySql学生管理系统

前言: 上个月学习了javafx和mysql数据库,于是写了一个学生管理系统,因为上个月在复习并且有一些事情,比较忙,所以没有更新博客了,这个项目页面虽然看着有点简陋了,但是大致内容还是比较简单的,于是现在跟大家分享一下我的学生管理系统,希望对这方面有兴趣的同学提供一些帮助 &a…

如何将canvas画布变成一张img图片

将Canvas画布转换成一张图片&#xff08;通常是PNG或JPEG格式&#xff09;可以通过Canvas的toDataURL()方法来实现。这个方法可以将Canvas上的内容转换为一个表示图像数据的URL&#xff0c;这个URL可以被用作<img>标签的src属性&#xff0c;或者通过JavaScript进一步处理…