Python开发俄罗斯方块游戏(自学记录)

参考:(https://gitbook.cn/gitchat/column/5b1a31bc862a01660e35955c/topic/5b1a86c33d723c686c3101ed
2019-06-18

任务:绘制方块(1.定义各种方块的表示方法(类属性);2.绘制每个方块)

1.定义方块的表示方法

俄罗斯方块游戏中有七种方块,我们可以用七个大写字母表示它们:J、L、S、Z、I、T、O.
我们定义一个Piece类来表示方块,这个Piece类带有两个属性:shape表示是七种方块的哪一个方块;screen表示屏幕对象。(新建piece.py文件)

class Piece():
    def __init__(self, shape, screen):
        self.x = 3
        self.y = 0
        self.shape = shape
        self.screen = screen

类名称的第一个字母最好大写,否则与文件名piece重复。知识点: Python 语言的类定义内部,赋值给属性 t 或者访问属性 t 的值,都要写作 self.t。调用方法 m,要写作 self.m。
接下来有三个问题:
1.如何记住方块的类型?
2.如何根据方块类型得出方块形状?
3.如何在游戏区域定位方块?

1.如何记住方块的类型?

我们已经创建了piece.py的文件,定义了Piece类属性,则在main.py中加入

from piece import Piece

表示引入了Piece类,并将要画方块的类型赋给piece变量:

piece = Piece('S', screen)

'S' 代表的是方块的类型;screen 是绘制方块时会用到的屏幕对象。这里'S'可以换为TLJ等其它类型。以下用'S'类型作为例子。

2.如何根据方块类型得出方块形状?

首先定义每个类型的形状矩阵,例如'S'可以这样定义:

S_SHAPE_TEMPLETE = ['.OO.',
                    'OO..',
                    '....']

大写字母O表示此处有小方块,'.'表示此处为空。
参照下图想象以下:


图1.jpg

故定义七种方块类型的形状矩阵:

S_SHAPE_TEMPLETE = ['.OO.',
                    'OO..',
                    '....']
I_SHAPE_TEMPLETE = ['.O..',
                    '.O..,'
                    '.O..',
                    '.O..']
Z_SHAPE_TEMPLETE = ['OO..',
                    '.OO.',
                    '....']
T_SHAPE_TEMPLETE = ['.O..',
                    'OOO.',
                    '....']
L_SHAPE_TEMPLETE = ['.O..',
                    '.O..',
                    '.OO.',]
J_SHAPE_TEMPLETE = ['..O.',
                    '..O.',
                    '.OO.']
O_SHAPE_TEMPLETE = ['.OO',
                    '.OO',
                    '...']

定义字典PIECES: 键为表示每个形状的字母,值为上边定义的形状矩阵。

PIECES = {'S':S_SHAPE_TEMPLETE,
                  'I':  I_SHAPE_TEMPLETE,
                  'Z':Z_SHAPE_TEMPLETE,
                  'T':T_SHAPE_TEMPLETE,
                  'L':L_SHAPE_TEMPLETE,
                  'J':J_SHAPE_TEMPLETE,
                  'O':O_SHAPE_TEMPLETE}

形状矩阵和字典都可以写在settings.py中,这里放的都是常量,调用时开头加一句:

from settings import *

3.如何在游戏区域定位方块?

想让'S'方块处于图中这样的位置

图2.jpg

需让x=3,y=0。(下面解释为什么)x的范围是09,y的范围是019.这样'S'方块的定位点是第一行第四列,由于'S'的形状矩阵为:

['.OO.',
 'OO..',
 '....']

且'O'画 '.'不画,所以画出的'S'的四个小方块分别在一行五列、一行六列、二行四列、二行五列,如图2。

Piece类完整代码:

from settings import *
import pygame
class Piece():
    def __init__(self, shape, screen):
        self.x = 3
        self.y = 0
        self.shape = shape
        self.screen = screen
    def paint(self):
        shape_templete = PIECES[self.shape]
        for r in range(len(shape_templete)):
            for c in range(len(shape_templete[0])):
                if shape_templete[r][c] == 'O':
                    self.draw_cell(self.x+c,self.y+r)
    def draw_cell(self, x, y):
        cell_position = (x * CELL_WIDTH + GAME_AREA_LEFT + 1, 
                                 y * CELL_WIDTH + GAME_AREA_TOP + 1)
        cell_width_height = (CELL_WIDTH - 2, CELL_WIDTH - 2)
        cell_rect = pygame.Rect(cell_position, cell_width_height)
        pygame.draw.rect(self.screen, CELL_COLOR, cell_rect)

paint()用作方块绘制,首先self.shape存储的是

piece = Piece('S', screen) #回看“1.如何记住方块的类型?”

中Piece类所带有的shape属性,也就是'S',故

shape_templete = PIECES[self.shape]

中 shape_templete表示的是PIECES字典中的键'S'对应的值S_SHAPE_TEMPLETE,对照形状矩阵可得:

S_SHAPE_TEMPLETE = ['.OO.',
                    'OO..',
                    '....']

是一个列表。
而这两句:

        for r in range(len(shape_templete)):
            for c in range(len(shape_templete[0])):

表示先按行(raw),再按列(column)依次遍历列表 S_SHAPE_TEMPLETE,遍历顺序为:0行0列、0行1列、0行2列、0行3列、1行0列、1行1列......。这样更易理解:

#                    行           0           1         2
#                    列        0123   0123   0123
S_SHAPE_TEMPLETE = ['.OO.', 'OO..', '. . . .']

之后进行判断,如果某行某列为'O',则这个位置要画小方块,调用draw_cell()画。
定义draw_cell():有两个属性x,y,实际上和上次绘制小方块函数差不多,都要定左上角点,定宽度高度,再画方块。
解释需让x=3,y=0:对于形状'S',paint()中遍历'O'所在行列,遍历到的第一个行列值为r=0,c=1,所以paint()中调用draw_cell(4, 0).
带入draw_cell()中,可以绘制这样一个小方块:
1.左上角坐标(4CELL_WIDTH + GAME_AREA_LEFT + 1, 0CELL_WIDTH + GAME_AREA_TOP + 1).至于每个都加1像素,可以试试去掉后什么效果。
2.该方块长宽都为CELL_WIDTH - 2.至于减2,也可以去掉试试。
绘制出这样的效果:(我把加1、减2去掉了)

图3.jpg

对比图2看看。
最后两句显然是1.构建矩形对象2.填充矩形对象。
main()中

 while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
        screen.fill(bg_color)
        draw_game_area(screen)
       # draw_cell(screen, GAME_AREA_LEFT + CELL_WIDTH * 4, GAME_AREA_TOP)
        piece.paint() #加入此句绘制“piece = Piece('S', screen)”中规定的方块
        pygame.display.flip()

修改为:

piece = Piece('T', screen)

则有


图4.jpg

明天继续!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343