Commit 3971f0d4 authored by Dimitris Strovolidis's avatar Dimitris Strovolidis

Tetris v2.0

Add levels
Add assist blocks
Add drop tetromino function
Change move down function
Change font
Change game background
Change menu background
Change grid background
Update README
parent bdc63828
......@@ -7,7 +7,7 @@ Requirements
Run
python tetris.py
python main.py
How to play
......@@ -16,13 +16,15 @@ How to play
Rotate Clockwise Up Arrow
Rotate Counterclockwise Down Arrow
Speed Up Space
Drop D
Pause / Resume P
Return to main menu ESC
Menu Navigation
Use arrows and press enter to select an option
Font Creator
codeman38 | [email protected] | http://www.zone38.net/
Font
https://www.dafont.com/sadana-square.font?l[]=10
Background
https://pixabay.com/en/background-abstract-music-notes-1064993/
Thanks for downloading one of codeman38's retro video game fonts, as seen on Memepool, BoingBoing, and all around the blogosphere.
So, you're wondering what the license is for these fonts? Pretty simple; it's based upon that used for Bitstream's Vera font set <http://www.gnome.org/fonts/>.
Basically, here are the key points summarized, in as little legalese as possible; I hate reading license agreements as much as you probably do:
With one specific exception, you have full permission to bundle these fonts in your own free or commercial projects-- and by projects, I'm referring to not just software but also electronic documents and print publications.
So what's the exception? Simple: you can't re-sell these fonts in a commercial font collection. I've seen too many font CDs for sale in stores that are just a repackaging of thousands of freeware fonts found on the internet, and in my mind, that's quite a bit like highway robbery. Note that this *only* applies to products that are font collections in and of themselves; you may freely bundle these fonts with an operating system, application program, or the like.
Feel free to modify these fonts and even to release the modified versions, as long as you change the original font names (to ensure consistency among people with the font installed) and as long as you give credit somewhere in the font file to codeman38 or zone38.net. I may even incorporate these changes into a later version of my fonts if you wish to send me the modifed fonts via e-mail.
Also, feel free to mirror these fonts on your own site, as long as you make it reasonably clear that these fonts are not your own work. I'm not asking for much; linking to zone38.net or even just mentioning the nickname codeman38 should be enough.
Well, that pretty much sums it up... so without further ado, install and enjoy these fonts from the golden age of video games.
[ codeman38 | [email protected] | http://www.zone38.net/ ]
\ No newline at end of file
import pygame
class GameArea:
class Grid:
def __init__(self, columns, rows, block_dimensions, screen_res, background_path):
self.score = 0
......@@ -14,15 +14,15 @@ class GameArea:
self.area_height = rows * self.block_height
# top left corner of game area
self.min_coord = (screen_res[0] / 2.1,
self.min_coord = ((screen_res[0] - self.area_width - 80),
(screen_res[1] - self.area_height) / 2)
# bottom right corner of game area
self.max_coord = (self.min_coord[0] + self.area_width,
self.min_coord[1] + self.area_height)
# center coord of game area
# center coord of game area (tetromino start coord)
self.center_coord = (self.min_coord[0] + (columns // 2) * self.block_width,
self.min_coord[1])
self.min_coord[1] + self.block_height)
self.columns = columns
self.rows = rows
......@@ -31,47 +31,66 @@ class GameArea:
self.background = pygame.image.load(background_path).convert()
self.background = pygame.transform.scale(self.background, (self.area_width, self.area_height))
self.background.set_alpha(200)
def collides(self, tetromino_coords):
def overlap(self, tetromino_coords):
"""
Detects collision between blocks.
:param tetromino_coords: list of coordinates (x, y)
:return: True if blocks collide
:return: True if blocks overlap
"""
for coord in tetromino_coords:
column_index = int((coord[0] - self.min_coord[0]) // self.block_width)
row_index = int((coord[1] + self.block_height - self.min_coord[1]) // self.block_height)
indexes_list = self.convert_coords(tetromino_coords)
for row_index, column_index in indexes_list:
if row_index >= self.rows or self.grid[row_index][column_index] >= 0:
return True
return False
def is_out_of_bounds(self, tetromino_coords):
"""
:param tetromino_coords: list of coordinates (x, y)
:return: True if a block is out of bounds
"""
for x, y in tetromino_coords:
if x > self.max_coord[0] - self.block_width or x < self.min_coord[0]:
return True
return False
def is_game_over(self):
return self.game_over
def get_grid_indexes(self, coords):
def convert_coords(self, coords):
"""
Convert coordinates to grid indexes.
:param coords: list of coordinates (x, y)
:return: list of indexes (row, column)
:return: list of indexes (row_index, column_index)
"""
grid_index_list = []
indexes_list = []
for coord in coords:
column_index = int((coord[0] - self.min_coord[0]) // self.block_width)
row_index = int((coord[1] - self.min_coord[1]) // self.block_height)
grid_index_list.append((row_index, column_index))
return grid_index_list
indexes_list.append((row_index, column_index))
return indexes_list
def update_grid(self, coords, color_index):
def convert_indexes(self, indexes):
"""
Convert grid indexes to coordinates
:param indexes: list of indexes (row_index, column_index)
:return: list of coordinates (x, y)
"""
Converts coordinates to grid indexes using get_grid_indexes
and assigns color_index to the corresponding cells.
coords_list = []
for index in indexes:
x = int(index[1] * self.block_width + self.min_coord[0])
y = int(index[0] * self.block_height + self.min_coord[1])
coords_list.append((x, y))
return coords_list
def update(self, coords, color_index):
"""
Converts coordinates to grid indexes and
assigns color_index to the corresponding cells.
:param coords: list of coordinates (x, y)
:param color_index: tetromino color index
"""
indexes_list = self.get_grid_indexes(coords)
indexes_list = self.convert_coords(coords)
for row_index, column_index in indexes_list:
if row_index >= 0 and column_index >= 0:
self.grid[row_index][column_index] = color_index
......@@ -95,9 +114,41 @@ class GameArea:
# insert a new line at the beginning of the grid
self.grid.insert(0, [-1 for i in range(self.columns)])
def get_assist_coords(self, tetromino_coords):
"""
:param tetromino_coords: list of coordinates (x, y)
:return: coordinates of the assist blocks
"""
indexes_list = self.convert_coords(tetromino_coords)
bottom = False
overlap = False
# tetromino reached bottom
for row_index, column_index in indexes_list:
if row_index >= self.rows - 1:
return tetromino_coords
while not bottom and not overlap:
# for every block
for i in range(len(indexes_list)):
row_index, column_index = indexes_list[i]
indexes_list[i] = (row_index + 1, column_index)
# check next row
if self.grid[row_index + 1][column_index] >= 0:
overlap = True
elif row_index + 1 >= self.rows - 1:
bottom = True
if overlap:
i = 0
for row_index, column_index in indexes_list:
indexes_list[i] = (row_index - 1, column_index)
i += 1
return self.convert_indexes(indexes_list)
def show(self, screen, color_blocks):
"""
Blit background and all blocks.
Display background and all blocks.
:param screen: screen surface
:param color_blocks: block sprites tuple
"""
......@@ -114,18 +165,12 @@ class GameArea:
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
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_min_coord(self):
return self.min_coord
def get_max_coord(self):
return self.max_coord
def get_center_coord(self):
return self.center_coord
This diff is collapsed.
......@@ -3,7 +3,7 @@ import pygame
class Menu:
margin_x = 35
margin_x = 0
margin_y = 50 # space between items(y axis)
text_color = (255, 255, 255)
selected_color = (0, 255, 255)
......@@ -16,8 +16,8 @@ class Menu:
self.items = []
self.selected_item = 0
self.title_font = pygame.font.Font(os.path.join('fonts', font), 26)
self.items_font = pygame.font.Font(os.path.join('fonts', font), 18)
self.title_font = pygame.font.Font(os.path.join('fonts', font), 58)
self.items_font = pygame.font.Font(os.path.join('fonts', font), 46)
self.title_coord = tuple(coord)
self.items_coord = (coord[0] + Menu.margin_x, coord[1] + Menu.margin_y)
......@@ -32,7 +32,8 @@ class Menu:
"""
screen.blit(self.background, (0, 0))
title_surface = write(self.title_font, self.title, self.text_color)
screen.blit(title_surface, self.title_coord)
screen.blit(title_surface, (self.title_coord[0] - title_surface.get_width()
/ 2, self.title_coord[1]))
# blit menu items
offset_y = Menu.margin_y
......@@ -43,8 +44,8 @@ class Menu:
color = self.text_color
item_surface = write(self.items_font, self.items[i], color)
screen.blit(item_surface, (self.items_coord[0],
self.items_coord[1] + offset_y))
screen.blit(item_surface, (self.items_coord[0] - item_surface.get_width()
/ 2, self.items_coord[1] + offset_y))
offset_y += Menu.margin_y
def check_input(self, event):
......@@ -70,4 +71,3 @@ def write(font, message, color):
text = font.render(str(message), True, color)
text = text.convert_alpha()
return text
screenshot.png

22.9 KB | W: | H:

screenshot.png

261 KB | W: | H:

screenshot.png
screenshot.png
screenshot.png
screenshot.png
  • 2-up
  • Swipe
  • Onion skin
sprites/background.png

28.6 KB | W: | H:

sprites/background.png

967 KB | W: | H:

sprites/background.png
sprites/background.png
sprites/background.png
sprites/background.png
  • 2-up
  • Swipe
  • Onion skin
sprites/grid_background.png

5.83 KB | W: | H:

sprites/grid_background.png

25 KB | W: | H:

sprites/grid_background.png
sprites/grid_background.png
sprites/grid_background.png
sprites/grid_background.png
  • 2-up
  • Swipe
  • Onion skin
This diff is collapsed.
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