Go back

# Tutorial #2

## Drawing the Grid

This function will simply draw the grey grid lines in the play area so that we can see which square our pieces are in. You may recall us calling this function in our draw_window function from the last tutorial.

``````def draw_grid(surface, row, col):
# This function draws the grey grid lines that we see
sx = top_left_x
sy = top_left_y
for i in range(row):
pygame.draw.line(surface, (128,128,128), (sx, sy+ i*30), (sx + play_width, sy + i * 30))  # horizontal lines
for j in range(col):
pygame.draw.line(surface, (128,128,128), (sx + j * 30, sy), (sx + j * 30, sy + play_height))  # vertical lines
``````

## Converting Shape Formats

At this point in time each of our pieces is represented by a multidimensional list. We need something that can translate this list into a form that the computer can understand. Ideally given a shape format we want to convert it to a list of positions that we can then return. That is what convert_shape_format() will do for us.

If you'd like a detailed explanation of this code please watch the video starting at 4:30.

``````def convert_shape_format(shape):
positions = []
format = shape.shape[shape.rotation % len(shape.shape)]

for i, line in enumerate(format):
row = list(line)
for j, column in enumerate(row):
if column == \'0\':
positions.append((shape.x + j, shape.y + i))

for i, pos in enumerate(positions):
positions[i] = (pos[0] - 2, pos[1] - 4)

return positions
``````

## Determine a Valid Space

When we are moving and rotating our shape we need to make sure that it is moving into a valid space. We are going to use the valid_space() function to check this. This function will have two parameters: grid and shape. We will check the grid to ensure that the current position we are trying to move into is not occupied. We can do this by seeing if any of the positions in the grid that the shape is attempting to move into have a color. If they have a color other than black than that means they are occupied, otherwise they are free.

``````def valid_space(shape, grid):
accepted_positions = [[(j, i) for j in range(10) if grid[i][j] == (0,0,0)] for i in range(20)]
accepted_positions = [j for sub in accepted_positions for j in sub]
formatted = convert_shape_format(shape)

for pos in formatted:
if pos not in accepted_positions:
if pos[1] > -1:
return False

return True
``````

## Checking if We Lose the Game

In order to end the game we need to constantly be checking if the user has lost the game. The check_lost() function will do this for us. We are simply going to check if any position in the given list is above the screen. If it is we have reached the top and therefore lost the game.

``````def check_lost(positions):
for pos in positions:
x, y = pos
if y < 1:
return True
return False
``````

## Modifying the Game Loop

Now we are going to add some code into game loop that will move our pieces down the screen at a certain time interval.

Look for the comments to see which code it new.

``````def main():
global grid

locked_positions = {}  # (x,y):(255,0,0)
grid = create_grid(locked_positions)
change_piece = False
run = True
current_piece = get_shape()
next_piece = get_shape()
clock = pygame.time.Clock()
fall_time = 0

while run:
# -------NEW CODE---------
fall_speed = 0.27

grid = create_grid(locked_positions)
fall_time += clock.get_rawtime()
clock.tick()

# PIECE FALLING CODE
if fall_time/1000 >= fall_speed:
fall_time = 0
current_piece.y += 1
if not (valid_space(current_piece, grid)) and current_piece.y > 0:
current_piece.y -= 1
change_piece = True
# --------END NEW CODE---------

for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.display.quit()
quit()

if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
current_piece.x -= 1
if not valid_space(current_piece, grid):
current_piece.x += 1

elif event.key == pygame.K_RIGHT:
current_piece.x += 1
if not valid_space(current_piece, grid):
current_piece.x -= 1
elif event.key == pygame.K_UP:
# rotate shape
current_piece.rotation = current_piece.rotation + 1 % len(current_piece.shape)
if not valid_space(current_piece, grid):
current_piece.rotation = current_piece.rotation - 1 % len(current_piece.shape)

if event.key == pygame.K_DOWN:
# move shape down
current_piece.y += 1
if not valid_space(current_piece, grid):
current_piece.y -= 1

# -------NEW CODE--------
shape_pos = convert_shape_format(current_piece)

# add color of piece to the grid for drawing
for i in range(len(shape_pos)):
x, y = shape_pos[i]
if y > -1: # If we are not above the screen
grid[y][x] = current_piece.color
# IF PIECE HIT GROUND
if change_piece:
for pos in shape_pos:
p = (pos[0], pos[1])
locked_positions[p] = current_piece.color
current_piece = next_piece
next_piece = get_shape()
change_piece = False

#-------END NEW CODE-------

draw_window(win, grid)

#------NEW CODE--------
# Check if user lost
if check_lost(locked_positions):
run = False
#------END NEW CODE--------
``````
Design & Development by