俄罗斯方块之一——构建游戏区域
我们知道俄罗斯方块是由四个小格组成,结合动画的原理,其实就是将小格子按照需求一副静态图片一副静态图片的展示。那么,四格拼板的游戏区域可以定制成由小格子组成的网格图,然后控制小格子的显示就能达到需求。
构建四格拼版游戏区域是俄罗斯方块中及其重要的一步,只有理解了这一步,才能理解俄罗斯方块游戏的真谛。
1、绘制窗体
if __name__ == "__main__":
pygame.init() # 使用 pygame 之前先进行初始化
screen = pygame.display.set_mode((800, 600), 0, 32)
# 上面一行代码的功能为设置屏幕大小,此实例为 800*600,
# 第二个参数是 0,表示打开一个不可改变大小的窗口,
# 第三个参数是 32 位真彩色。
pygame.display.set_caption("俄罗斯方块") # 设置窗体名称
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT: # 检测退出动作
exit()
pygame.display.update()
利用以上代码,可以创建一个 800*600 的窗体,如果觉得默认的背景颜色不符合自己的期望,可以在 while True:
代码的下一行添加 screen.fill(( 30, 25, 25))
。
2、绘制小方格
俄罗斯游戏中的四格拼板是有四个小方格组成,那么我首先要做的就是在窗体中绘制小方格。小方格该如何绘制呢?我们可以利用 pygame.Rect
类,Rect 是用于存储矩形坐标的 Pygame 对象。语法如下:
Rect(left, top, width, height) -> Rect
Rect((left, top), (width, height)) -> Rect
Rect(object) -> Rect
其中,参数 left 代表的是窗体左上角横向距离到小方格左上角的像素单位,top 代表的是窗体左上角竖向距离到小方格左上角的像素单位,width 代表的是矩形的宽度,height 代表的是矩形的高度。
我们利用函数来定义一个小方格:
def box(x:"x表示在窗体内的横坐标", y:"y表示在窗体内的纵坐标"):
''' 功能:画出用于组成图形的单个正方形
'''
rect = pygame.Rect(x, y, 20, 20)
pygame.Surface.fill(screen, (255, 245, 40), rect) # 填充方格内的颜色
pygame.draw.rect(screen, (255, 245, 245), rect, 1) # 画出方格的线条
return rect
然后在窗体的代码的 while True:
循环结构体内部添加 box(50, 50)
函数即可呈现出小方格。如下图:
![](https://img.haomeiwen.com/i259976/2c1fd6330f85068d.png)
3、绘制游戏区域
还是利用 pygame.Rect
类来绘制一个矩形的活动区域,活动区域的大小是宽度为 360,高度为 540。
def area():
''' 功能:画出游戏区域
'''
rect = pygame.Rect(((800-360)//4, 600-540), (360, 540))
pygame.draw.rect(screen, ( 20, 20, 175), rect, 5) # 画出游戏区域
然后在窗体的代码的 while True:
循环结构体内部添加 area
函数即可呈现出小方格。如下图:
![](https://img.haomeiwen.com/i259976/a0f1d39cf06cc685.png)
4、绘制游戏区域网格
小方格是在游戏区域内移动,那么为了确定小方格的呈现位置,可以将游戏区域分解成 N 个小方格。结合 pygame.Rect
类的使用方法,我们需要知道每个小方格的左上角的坐标。而将游戏区域分解就是要将每个小方格的坐标组合成一个二维数组。
------------------------------------------------------------>
|
| **********************************************
| *(0, 0) (0, 1) (0, 2) ............... (0, y) *
| *(1, 0) (1, 1) (1, 2) ............... (1, y) *
| *(2, 0) (2, 1) (2, 2) ............... (2, y) *
| * .......................................... *
| * .......................................... *
| * .......................................... *
| * .......................................... *
| * .......................................... *
| * .......................................... *
| * .......................................... *
| * .......................................... *
| *(x, 0) (x, 1) (x, 2) ............... (x, y) *
|
|
可以利用 Python 列表推导的特性,来对代码进行优化,代码如下:
def matrix():
''' 功能:以游戏区域为基础,画出用于呈现方块图形左上角坐标的矩阵。
'''
# 下面一行列表推导的代码用于构造小方格左上角坐标的二维列表
box_coordinate_list = [[((coordinate[0] + x*edge + 2),
(coordinate[1] + y*edge + 2))
for x in range(box_col)] for y in range(box_row)]
# 以下代码是画出游戏区域的网格,网格线是白色,网格内填充灰色。
for i in range(len(box_coordinate_list)):
for j in box_coordinate_list[i]:
rect = pygame.Rect(j[0], j[1], edge, edge)
pygame.Surface.fill(screen, gray, rect)
pygame.draw.rect(screen, white, rect, 2)
return box_coordinate_list
然后在窗体的代码的 while True:
循环结构体内部添加 matrix()
函数即可呈现出游戏区域网格。如下图:
![](https://img.haomeiwen.com/i259976/ca47ac9f3a728f1c.png)
一般情况下,我们不需要在游戏区域背景中显示网格,那么我的 matrix()
函数需要调整一下,就是不需要双重 for 循环的代码部分了。
5、优化代码
上面的编码步骤是根据 pygame 库的特性以及如何创建 Rect 矩形的思路来一步一步进行编码的,像窗体、小方格和游戏区域的大小以及颜色等变量的管理比较凌乱。所以到这一步,我将相关变量进行统一管理,对代码进行优化。
# -*- coding: utf-8 -*-
import pygame
__author__ = {
'name': "东方鹗",
'github': "https://github.com/eastossifrage",
'B 站主页': "https://space.bilibili.com/194359739",
'知乎专栏': "https://zhuanlan.zhihu.com/ousi-python",
'简书专栏': "https://www.jianshu.com/c/2036276cf0e8",
'version': "1.0"
}
# 定义几个颜色 R G B
bgcolor = ( 30, 25, 25) # 背景设置为黑色
yellow = (255, 245, 40) # 黄色
light_yellow = (175, 175, 20)
white = (255, 245, 245)
gray = (185, 185, 185)
black = ( 0, 0, 0)
red = (155, 0, 0)
light_red = (175, 20, 20)
green = ( 0, 155, 0)
light_green = ( 20, 175, 20)
blue = ( 0, 0, 155)
light_blue = ( 20, 20, 175)
# 定义屏幕大小
s_width = 800
s_height = 600
# 定义俄罗斯方块游戏区域的大小
a_width = 364
a_height = 544
# 定义正方形的大小
edge = 20
# 定义游戏区域左上角坐标,主要为了 Rect 类的使用方便。
coordinate = ((s_width-a_width)//4, s_height-a_height)
# 定义游戏区域中的小方格的行列数
box_row = int(a_height/edge) # 小方格的每列个数,也就是行数
box_col = int(a_width/edge) # 小方格的每行个数,也就是列数
def box(x:"x表示在窗体内的横坐标", y:"y表示在窗体内的纵坐标"):
''' 功能:画出用于组成图形的单个正方形
'''
rect = pygame.Rect(x, y, 20, 20)
pygame.Surface.fill(screen, yellow, rect) # 填充方格内的颜色
pygame.draw.rect(screen, white, rect, 1) # 画出方格的线条
return rect
def area():
''' 功能:画出游戏区域
'''
rect = pygame.Rect(coordinate, (a_width, a_height))
pygame.draw.rect(screen, light_blue, rect, 5) # 画出游戏区域
def matrix():
''' 功能:以游戏区域为基础,画出用于呈现方块图形左上角坐标的矩阵。
'''
# 下面一行列表推导的代码用于构造小方格左上角坐标的二维列表
box_coordinate_list = [[((coordinate[0] + x*edge + 2),
(coordinate[1] + y*edge + 2))
for x in range(box_col)] for y in range(box_row)]
# 以下代码是画出游戏区域的网格,网格线是白色,网格内填充灰色。
for i in range(len(box_coordinate_list)):
for j in box_coordinate_list[i]:
rect = pygame.Rect(j[0], j[1], edge, edge)
pygame.Surface.fill(screen, gray, rect)
pygame.draw.rect(screen, white, rect, 2)
return box_coordinate_list
if __name__ == "__main__":
pygame.init() # 使用 pygame 之前先进行初始化
screen = pygame.display.set_mode((s_width, s_height), pygame.RESIZABLE, 32)
# 上面一行代码的功能为设置屏幕大小,此实例为 800*600,
# 第二个参数是 RESIZABLE,表示打开一个可以改变大小的窗口,
# 第三个参数是 32 位真彩色。
pygame.display.set_caption("俄罗斯方块") # 设置窗体名称
while True:
screen.fill(bgcolor) # 表示填充背景颜色。
for event in pygame.event.get():
if event.type == pygame.QUIT: # 检测退出动作
exit()
area() # 绘制游戏区域
matrix() # 绘制游戏区域的网格线
box(50, 50) # 在坐标 (50, 50) 处绘制一个小方格
pygame.display.update()