Commit 6cbe2431 authored by Dimitris Strovolidis's avatar Dimitris Strovolidis

Improvements

Add pause
Add bag randomizer
Fix timestep
Update README
parent bcacbeaf
......@@ -16,7 +16,8 @@ How to play
Rotate Clockwise Up Arrow
Rotate Counterclockwise Down Arrow
Speed Up Space
Exit ESC
Pause / Resume P
Return to main menu ESC
Menu Navigation
Use arrows and press enter to select an option
......
import os
import pygame
class GameArea:
def __init__(self, columns, rows, block_dimensions, screen_res, background_path):
......@@ -32,7 +32,6 @@ class GameArea:
self.background = pygame.image.load(background_path).convert()
self.background = pygame.transform.scale(self.background, (self.area_width, self.area_height))
def collides(self, tetromino_coords):
"""
Detects collision between blocks.
......@@ -88,7 +87,7 @@ class GameArea:
full_row = True
for j in range(self.columns):
if self.grid[row_index][j] == -1: # cell is empty
if self.grid[row_index][j] == -1: # cell is empty
full_row = False
break
......@@ -99,7 +98,6 @@ class GameArea:
# insert a new line at the beginning of the grid
self.grid.insert(0, [-1 for i in range(self.columns)])
def show(self, screen, color_blocks):
"""
Blit background and all blocks.
......@@ -116,12 +114,16 @@ class GameArea:
coord_y = self.min_coord[1] + i * self.block_height
screen.blit(color_blocks[color_index], (coord_x, coord_y))
def display_message(self, screen, font, color, message):
text_surface = font.render(str(message), True, color).convert_alpha()
text_x = self.min_coord[0] + (self.area_width - text_surface.get_width()) / 2
text_y = self.min_coord[1] + self.area_height / 2
screen.blit(text_surface, (text_x, text_y))
pygame.display.flip()
def get_score(self):
return self.score
def get_width(self):
return self.area_width
def get_min_coord(self):
return self.min_coord
......@@ -129,4 +131,4 @@ class GameArea:
return self.max_coord
def get_center_coord(self):
return self.center_coord
\ No newline at end of file
return self.center_coord
import os
import pygame
class Menu:
margin_x = 35
margin_y = 50 # space between items(y axis)
text_color = (255, 255, 255)
selected_color = (0, 255, 255)
def __init__(self, title, background_path, screen_res, font, coord):
self.title = title
self.background = pygame.image.load(background_path).convert()
......
import random
class BagRandomizer:
def __init__(self, items_num):
self.current_item = 0
self.items = [i for i in range(items_num)]
random.shuffle(self.items)
def get_number(self):
if self.current_item == len(self.items):
self.current_item = 0
self.shuffle()
item = self.items[self.current_item]
self.current_item += 1
return item
def shuffle(self):
random.shuffle(self.items)
def reset(self):
self.current_item = 0
self.shuffle()
bag_randomizer = BagRandomizer(7)
get_number = bag_randomizer.get_number
reset = bag_randomizer.reset
import os
import pygame
import randomizer
from tetromino import Tetromino
from game_area import GameArea
from menu import Menu
......@@ -39,13 +40,12 @@ def write(font, message, color):
return text
def center_text(screen, surface):
return (screen.get_width() - surface.get_width()) / 2
def main():
pygame.init()
pygame.display.set_caption("Tetris")
screen = pygame.display.set_mode(screen_res)
pygame.key.set_repeat(100, 100)
blocks_path = os.path.join('sprites', 'blocks')
game_background_path = os.path.join('sprites', 'background.png')
......@@ -75,8 +75,7 @@ def main():
purple_block = pygame.image.load(os.path.join(blocks_path, 'purple_block.png')).convert()
purple_block = pygame.transform.scale(purple_block, (block_width, block_height))
color_blocks = (lightblue_block, yellow_block, purple_block, blue_block, orange_block,
green_block, red_block)
color_blocks = (lightblue_block, yellow_block, purple_block, blue_block, orange_block, green_block, red_block)
next_surface = write(font, "NEXT", text_color)
......@@ -89,6 +88,7 @@ def main():
# when game_over is True return to main menu
while True:
randomizer.reset()
display_menu = True
while display_menu:
main_menu.show(screen)
......@@ -101,7 +101,6 @@ def main():
if user_input == menu_items[0]:
display_menu = False
elif user_input == menu_items[1] or event.type == pygame.QUIT: # quit
pygame.quit()
exit()
# create game area
......@@ -109,25 +108,26 @@ def main():
grid_background_path)
# current random tetromino
current_tetromino = Tetromino((block_width, block_height), color_blocks,
game_area.get_center_coord(), game_area.get_min_coord(),
game_area.get_max_coord())
game_area.get_center_coord(), game_area.get_min_coord(),
game_area.get_max_coord())
# create next random tetromino
next_tetromino = Tetromino((block_width, block_height), color_blocks,
next_tetromino_coord, min_screen_coord, max_screen_coord)
next_tetromino_coord, min_screen_coord, max_screen_coord)
game_over = False
game_paused = False
clock = pygame.time.Clock()
total_time = 0
total_time = 0.0
while not game_over:
time = clock.tick(FPS) / 100.0
total_time += time / 10.0
dt = 1.0 / FPS
accumulator = 0.0
while not game_over:
game_over = game_area.is_game_over()
# check keyboard input
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
game_over = True
......@@ -157,7 +157,25 @@ def main():
elif event.type == pygame.KEYUP and event.key == pygame.K_SPACE:
# reset tetromino speed (normal speed)
current_tetromino.reset_speed()
elif event.type == pygame.KEYDOWN and event.key == pygame.K_p:
# Pause the game
pause = True
game_area.display_message(screen, font, text_color, 'Pause')
while pause:
event = pygame.event.wait()
if event.type == pygame.KEYDOWN and event.key == pygame.K_p:
pause = False
elif event.type == pygame.QUIT:
exit()
game_paused = True
if game_paused:
frame_time = dt
game_paused = False
clock.tick(FPS)
else:
frame_time = clock.tick(FPS) / 1000.0 # convert to seconds
total_time += frame_time
if display_time:
time_string = "Time " + '{0:02d}'.format(int(total_time // 60))\
......@@ -170,7 +188,22 @@ def main():
score_string = "Score: " + str(game_area.get_score())
score_surface = write(font, score_string, text_color)
accumulator += frame_time
while accumulator >= dt:
bottom = current_tetromino.move_down(dt)
collision = game_area.collides(current_tetromino.get_coords())
# tetromino collided with a block or reached bottom
if collision or bottom:
game_area.update_grid(current_tetromino.get_coords(), current_tetromino.get_color_index())
current_tetromino = next_tetromino
current_tetromino.set_coords(game_area.get_center_coord(),
game_area.get_min_coord(), game_area.get_max_coord())
next_tetromino = Tetromino((block_width, block_height), color_blocks,
next_tetromino_coord, min_screen_coord, max_screen_coord)
accumulator -= dt
# Draw
screen.blit(background, min_screen_coord)
screen.blit(score_surface, score_coord)
if display_time:
......@@ -183,25 +216,9 @@ def main():
next_tetromino.show(screen)
pygame.display.flip()
bottom = current_tetromino.move_down(time)
collision = game_area.collides(current_tetromino.get_coords())
# tetromino collided with a block or reached bottom
if collision or bottom:
game_area.update_grid(current_tetromino.get_coords(), current_tetromino.get_color_index())
current_tetromino = next_tetromino
current_tetromino.set_coords(game_area.get_center_coord(),
game_area.get_min_coord(), game_area.get_max_coord())
next_tetromino = Tetromino((block_width, block_height), color_blocks,
next_tetromino_coord, min_screen_coord, max_screen_coord)
# write and display game over
text_surface = write(font, "Game Over", text_color)
text_x = game_area.get_min_coord()[0] + (game_area.get_width() -
text_surface.get_width()) / 2
screen.blit(text_surface, (text_x, max_screen_coord[1] / 2))
pygame.display.flip()
game_area.display_message(screen, font, text_color, 'Game Over')
clock.tick(0.7)
if __name__ == '__main__':
main()
import pygame
import randomizer
from random import randint
class Tetromino:
# I tetromino
i_tetromino_angle_0 = [[".#.."],
......@@ -140,14 +142,14 @@ class Tetromino:
tetrominoes = (i_tetromino, o_tetromino, t_tetromino, j_tetromino,
l_tetromino, s_tetromino, z_tetromino)
normal_speed = 12
fast_speed = 100
normal_speed = 120
fast_speed = 1000
def __init__(self, block_dimensions, color_blocks, coord, min_coord, max_coord):
"""
Create a random tetromino.
"""
self.random_index = randint(0, len(Tetromino.tetrominoes) - 1)
self.random_index = randomizer.get_number()
self.random_tetromino = Tetromino.tetrominoes[self.random_index]
self.block_color = color_blocks[self.random_index]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment