Blocks

Tags: pgzero, game

https://simplegametutorials.github.io/pygamezero/

blocks.py
  1import pgzrun
  2import random
  3
  4GAME_X = 10
  5GAME_Y = 18
  6TILE_WIDTH = 20
  7TICK = 0.5
  8HUD = 4
  9WIDTH = GAME_X * TILE_WIDTH
 10HEIGHT = (GAME_Y + HUD) * TILE_WIDTH
 11
 12class Game(object): # {{{
 13    class Piece(object): # {{{
 14        def __init__(self, parent): # {{{
 15            self.parent = parent
 16            self.x = GAME_X // 2 - 2
 17            self.y = 0
 18            self.rotation = 0
 19            self.type = parent.sequence.pop()
 20            if len(parent.sequence) == 0: 
 21                self.parent.sequence = self.parent.new_sequence()
 22            # }}}
 23        def draw(self): # {{{
 24            for y in range(4):
 25                for x in range(4):
 26                    block = self.parent.PIECES[self.type][self.rotation][y][x]
 27                    if block > 0: self.parent.draw_block(block, x + self.x, y + self.y + HUD)
 28        # }}}
 29        def move(self, direction): # {{{
 30            test_offset = self.x + direction
 31            if self.can_move(test_x=test_offset):
 32                self.x = test_offset
 33        # }}}
 34        def rotate(self, direction): # {{{
 35            test_rotation = self.rotation
 36            test_rotation = (test_rotation + direction) % len(self.parent.PIECES[self.type])
 37            if self.can_move(test_x=self.x, test_y=self.y, test_r=self.rotation):
 38                self.rotation = test_rotation
 39
 40        # }}}
 41        def drop(self): # {{{
 42            while self.can_move(self.x, self.y+1, self.rotation):
 43                self.y += 1
 44                self.parent.timer = TICK
 45        # }}}
 46        def can_move(self, test_x=None, test_y=None, test_r=None): # {{{
 47            if not test_x: test_x = self.x
 48            if not test_y: test_y = self.y
 49            if not test_r: test_r = self.rotation
 50
 51            for y in range(4):
 52                for x in range(4):
 53                    if (
 54                            self.parent.PIECES[self.type][self.rotation][y][x] != 0
 55                            and
 56                            (
 57                                ((test_x + x) not in range(GAME_X))
 58                                or
 59                                test_y + y >= GAME_Y
 60                                or
 61                                self.parent.area[test_y + y][test_x + x] != 0
 62                                )
 63                            ): return False
 64            return True
 65        # }}}
 66        # }}}
 67    def __init__(self): # {{{
 68        self.COLOURS = { # {{{
 69            0: (0xaa, 0xaa, 0xaa),
 70            1: (120, 195, 239),
 71            2: (236, 231, 108),
 72            3: (124, 218, 193),
 73            4: (234, 177, 121),
 74            5: (211, 136, 236),
 75            6: (248, 147, 196),
 76            7: (169, 221, 118),
 77            }
 78        #  }}}
 79        # self.COLOURS = { # {{{
 80        #     0: (0xaa, 0xaa, 0xaa),
 81        #     1: (255, 0, 0),
 82        #     2: (0, 255, 0),
 83        #     3: (0, 0, 255),
 84        #     4: (255, 255, 0),
 85        #     5: (0, 255, 255),
 86        #     6: (255, 0, 255),
 87        #     7: (255, 128, 0),
 88        #     }
 89        # #  }}}
 90        self.PIECES = [] # {{{
 91        self.PIECES.append([ # {{{ I
 92            [ [0, 0, 0, 0],
 93              [1, 1, 1, 1],
 94              [0, 0, 0, 0],
 95              [0, 0, 0, 0] ],
 96
 97            [ [0, 1, 0, 0],
 98              [0, 1, 0, 0],
 99              [0, 1, 0, 0],
100              [0, 1, 0, 0] ]
101            ]) # }}}
102        self.PIECES.append([ # {{{ O
103            [ [0, 0, 0, 0],
104              [0, 2, 2, 0],
105              [0, 2, 2, 0],
106              [0, 0, 0, 0] ]
107            ]) # }}}
108        self.PIECES.append([ # {{{ J
109            [ [0, 0, 0, 0],
110              [3, 3, 3, 0],
111              [0, 0, 3, 0],
112              [0, 0, 0, 0] ],
113
114            [ [0, 3, 0, 0],
115              [0, 3, 0, 0],
116              [3, 3, 0, 0],
117              [0, 0, 0, 0] ],
118
119            [ [3, 0, 0, 0],
120              [3, 3, 3, 0],
121              [0, 0, 0, 0],
122              [0, 0, 0, 0] ],
123
124            [ [0, 3, 3, 0],
125              [0, 3, 0, 0],
126              [0, 3, 0, 0],
127              [0, 0, 0, 0] ],
128            ]) # }}}
129        self.PIECES.append([ # {{{ L
130            [ [0, 0, 0, 0],
131              [4, 4, 4, 0],
132              [4, 0, 0, 0],
133              [0, 0, 0, 0] ],
134
135            [ [0, 4, 0, 0],
136              [0, 4, 0, 0],
137              [0, 4, 4, 0],
138              [0, 0, 0, 0] ],
139
140            [ [0, 0, 4, 0],
141              [4, 4, 4, 0],
142              [0, 0, 0, 0],
143              [0, 0, 0, 0] ],
144
145            [ [4, 4, 0, 0],
146              [0, 4, 0, 0],
147              [0, 4, 0, 0],
148              [0, 0, 0, 0] ],
149            ]) # }}}
150        self.PIECES.append([ # {{{ T
151            [ [0, 0, 0, 0],
152              [5, 5, 5, 0],
153              [0, 5, 0, 0],
154              [0, 0, 0, 0] ],
155
156            [ [0, 5, 0, 0],
157              [0, 5, 5, 0],
158              [0, 5, 0, 0],
159              [0, 0, 0, 0] ],
160
161            [ [0, 5, 0, 0],
162              [5, 5, 5, 0],
163              [0, 0, 0, 0],
164              [0, 0, 0, 0] ],
165
166            [ [0, 5, 0, 0],
167              [5, 5, 0, 0],
168              [0, 5, 0, 0],
169              [0, 0, 0, 0] ],
170            ]) # }}}
171        self.PIECES.append([ # {{{ S
172            [ [0, 0, 0, 0],
173              [0, 6, 6, 0],
174              [6, 6, 0, 0],
175              [0, 0, 0, 0] ],
176
177            [ [0, 6, 0, 0],
178              [0, 6, 6, 0],
179              [0, 0, 6, 0],
180              [0, 0, 0, 0] ],
181            ]) # }}}
182        self.PIECES.append([ # {{{ Z
183            [ [0, 0, 0, 0],
184              [7, 7, 0, 0],
185              [0, 7, 7, 0],
186              [0, 0, 0, 0] ],
187
188            [ [0, 0, 7, 0],
189              [0, 7, 7, 0],
190              [0, 7, 0, 0],
191              [0, 0, 0, 0] ],
192            ]) # }}}
193        # }}}
194        self.reset()
195    # }}}
196    def reset(self): # {{{
197        self.timer = 0
198        self.score = 0
199        self.area = []
200        for y in range(GAME_Y):
201            self.area.append([0 for x in range(GAME_X)])
202        self.sequence = self.new_sequence()
203        self.piece = self.Piece(self)
204    # }}}
205    def update(self, dt): # {{{
206        self.timer += dt
207
208        if self.timer > TICK:
209            self.timer = 0
210
211            test_offset_y = self.piece.y + 1
212            if self.piece.can_move(test_y=test_offset_y): 
213                self.piece.y = test_offset_y
214            else:
215                for y in range(4):
216                    for x in range(4):
217                        block = self.PIECES[self.piece.type][self.piece.rotation][y][x]
218                        if block != 0:
219                            self.area[self.piece.y + y][self.piece.x + x] = block
220
221                completes = []
222                for y in range(GAME_Y):
223                    if 0 not in self.area[y]:
224                        completes.append(y)
225
226                for i in completes:
227                    self.area.pop(i)
228                    self.area.insert(0, [0 for i in range(GAME_X)])
229                    self.score += 1
230
231
232                self.piece = self.Piece(self)
233                if not self.piece.can_move(self.piece.x, self.piece.y, self.piece.rotation): self.reset()
234    # }}}
235    def draw(self): # {{{
236        screen.fill((0, 0, 0))
237
238        for y in range(GAME_Y):
239            for x in range(GAME_X):
240                block = self.area[y][x]
241                self.draw_block(block, x, y+HUD)
242
243        self.piece.draw()
244
245        for y in range(4):
246            for x in range(4):
247                block = self.PIECES[self.sequence[-1]][0][y][x]
248                if block > 0: self.draw_block(block, x + 3, y + 0) 
249
250        screen.draw.text('%d' % self.score, (5,5))
251    # }}}
252    def new_sequence(self): # {{{
253        sequence = list(range(7))
254        # random.shuffle(sequence)
255        return sequence
256    # }}}
257    def draw_block(self, block, x, y): # {{{
258        colour = self.COLOURS[block]
259        r = Rect(
260                x * TILE_WIDTH,
261                y * TILE_WIDTH,
262                TILE_WIDTH-1,
263                TILE_WIDTH-1
264                )
265        screen.draw.filled_rect(r, color=colour)
266        # }}}
267# }}}
268def on_key_down(key): # {{{
269    if   key == keys.A: game.piece.move(-1)
270    elif key == keys.D: game.piece.move(1)
271    elif key == keys.S: game.piece.rotate(-1)
272    elif key == keys.W: game.piece.rotate(1)
273    elif key == keys.SPACE: game.piece.drop()
274# }}}
275def update(dt): game.update(dt)
276def draw(): game.draw()
277game = Game()
278pgzrun.go()