Загрузка данных
import pygame as pg
import random
import time
import sys
from pygame.locals import *
fps = 25
window_w, window_h = 600, 500
block = 20
cup_h = 20
cup_w = 10
side_freq = 0.15
down_freq = 0.1
side_margin = int((window_w - cup_w * block) / 2)
top_margin = window_h - (cup_h * block) - 5
empty = 0
figures = {
'O': [['oooo', 'oooo', 'oxxo', 'oxxo', 'oooo']],
'I': [
['oooo', 'oooo', 'xxxx', 'oooo', 'oooo'],
['ooxo', 'ooxo', 'ooxo', 'ooxo', 'oooo']
],
'T': [
['oooo', 'oooo', 'oxxo', 'xxo', 'oooo'],
['oooo', 'oxo', 'xxo', 'oxo', 'oooo'],
['oooo', 'oxx', 'oxo', 'oooo', 'oooo'],
['oooo', 'oxo', 'oxx', 'oxo', 'oooo']
],
'S': [
['oooo', 'oooo', 'oxx', 'xxo', 'oooo'],
['oooo', 'oxo', 'oxx', 'oox', 'oooo']
],
'Z': [
['oooo', 'oooo', 'xxo', 'oxx', 'oooo'],
['oooo', 'oox', 'oxx', 'oxo', 'oooo']
],
'L': [
['oooo', 'oooo', 'oxxx', 'oxo', 'oooo'],
['oooo', 'oxo', 'oxo', 'oxx', 'oooo'],
['oooo', 'oox', 'oxxx', 'oooo', 'oooo'],
['oooo', 'xxo', 'oxo', 'oxo', 'oooo']
],
'J': [
['oooo', 'oooo', 'oxxx', 'oox', 'oooo'],
['oooo', 'oxo', 'oxo', 'xxo', 'oooo'],
['oooo', 'xoo', 'oxxx', 'oooo', 'oooo'],
['oooo', 'oxx', 'oxo', 'oxo', 'oooo']
]
}
colors = {
'O': (255, 255, 0),
'I': (0, 255, 255),
'T': (128, 0, 128),
'S': (0, 255, 0),
'Z': (255, 0, 0),
'L': (255, 165, 0),
'J': (0, 0, 255)
}
lightcolors = {
'O': (255, 255, 150),
'I': (150, 255, 255),
'T': (200, 100, 200),
'S': (150, 255, 150),
'Z': (255, 150, 150),
'L': (255, 200, 100),
'J': (100, 100, 255)
}
bg_color = (0, 0, 0)
fig_w, fig_h = 5, 5
pg.init()
fps_clock = pg.time.Clock()
display_surf = pg.display.set_mode((window_w, window_h))
basic_font = pg.font.Font(None, 18)
big_font = pg.font.Font(None, 45)
small_font = pg.font.Font(None, 24)
pg.display.set_caption('Тетрис')
try:
start_sound = pg.mixer.Sound('start.wav')
move_sound = pg.mixer.Sound('move.wav')
gameover_sound = pg.mixer.Sound('gameover.wav')
pg.mixer.music.load('bg_music.mp3')
pg.mixer.music.set_volume(0.5)
sound_enabled = True
except:
sound_enabled = False
def showText(text, font=big_font, color=(255,255,255), y_offset=0):
text_surf = font.render(text, True, color)
text_rect = text_surf.get_rect()
text_rect.center = (window_w // 2, window_h // 2 + y_offset)
display_surf.blit(text_surf, text_rect)
def drawButton(text, x, y, w, h, color, text_color):
pg.draw.rect(display_surf, color, (x, y, w, h))
pg.draw.rect(display_surf, (255,255,255), (x, y, w, h), 2)
surf = small_font.render(text, True, text_color)
rect = surf.get_rect(center=(x + w//2, y + h//2))
display_surf.blit(surf, rect)
return pg.Rect(x, y, w, h)
def getPlayerName():
name = ""
active = True
while active:
display_surf.fill(bg_color)
showText("Введите имя:", big_font, (255,255,255), -50)
name_surf = basic_font.render(name + "_", True, (255,255,255))
name_rect = name_surf.get_rect(center=(window_w//2, window_h//2))
display_surf.blit(name_surf, name_rect)
pg.display.update()
for event in pg.event.get():
if event.type == QUIT:
pg.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_RETURN and name.strip() != "":
active = False
elif event.key == K_BACKSPACE:
name = name[:-1]
elif event.key == K_ESCAPE:
pg.quit()
sys.exit()
else:
if len(name) < 15 and event.unicode.isprintable():
name += event.unicode
return name.strip()
def chooseDifficulty():
difficulties = ["Легкая", "Средняя", "Сложная"]
selected = 0
while True:
display_surf.fill(bg_color)
showText("Выбери сложность:", big_font, (255,255,255), -100)
for i, diff in enumerate(difficulties):
color = (255,255,0) if i == selected else (255,255,255)
y = window_h//2 - 30 + i * 50
showText(diff, big_font, color, y - window_h//2)
pg.display.update()
for event in pg.event.get():
if event.type == QUIT:
pg.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_UP:
selected = (selected - 1) % 3
elif event.key == K_DOWN:
selected = (selected + 1) % 3
elif event.key == K_RETURN:
if selected == 0:
return 0.5
elif selected == 1:
return 0.8
else:
return 1.2
def stopGame():
pg.quit()
sys.exit()
def convertCoords(x, y):
return (side_margin + (x * block)), (top_margin + (y * block))
def drawBlock(block_x, block_y, color, pixelx=None, pixely=None):
if color == empty or color is None:
return
if pixelx is None and pixely is None:
pixelx, pixely = convertCoords(block_x, block_y)
pg.draw.rect(display_surf, colors[color], (pixelx + 1, pixely + 1, block - 1, block - 1), 0, 3)
pg.draw.rect(display_surf, lightcolors[color], (pixelx + 1, pixely + 1, block - 4, block - 4), 0, 3)
pg.draw.circle(display_surf, colors[color], (pixelx + block // 2, pixely + block // 2), 5)
def emptycup():
return [[empty for _ in range(cup_h)] for _ in range(cup_w)]
def incup(x, y):
return 0 <= x < cup_w and 0 <= y < cup_h
def checkPos(cup, fig, adjX=0, adjY=0):
for x in range(fig_w):
for y in range(fig_h):
if figures[fig['shape']][fig['rotation']][y][x] != 'o':
if not incup(x + fig['x'] + adjX, y + fig['y'] + adjY):
return False
if cup[x + fig['x'] + adjX][y + fig['y'] + adjY] != empty:
return False
return True
def addToCup(cup, fig):
for x in range(fig_w):
for y in range(fig_h):
if figures[fig['shape']][fig['rotation']][y][x] != 'o':
cup[x + fig['x']][y + fig['y']] = fig['color']
def isCompleted(cup, y):
for x in range(cup_w):
if cup[x][y] == empty:
return False
return True
def clearCompleted(cup):
removed = 0
y = cup_h - 1
while y >= 0:
if isCompleted(cup, y):
for push in range(y, 0, -1):
for x in range(cup_w):
cup[x][push] = cup[x][push-1]
for x in range(cup_w):
cup[x][0] = empty
removed += 1
else:
y -= 1
return removed
def gamecup(cup):
for x in range(cup_w):
for y in range(cup_h):
if cup[x][y] != empty:
drawBlock(x, y, cup[x][y])
def drawFig(fig):
for x in range(fig_w):
for y in range(fig_h):
if figures[fig['shape']][fig['rotation']][y][x] != 'o':
drawBlock(fig['x'] + x, fig['y'] + y, fig['color'])
def drawnextFig(fig):
surf = pg.Surface((100, 100))
surf.fill(bg_color)
start_x, start_y = window_w - 100, 100
for x in range(fig_w):
for y in range(fig_h):
if figures[fig['shape']][fig['rotation']][y][x] != 'o':
pixelx = start_x + x * 15
pixely = start_y + y * 15
pg.draw.rect(surf, colors[fig['color']], (pixelx - (window_w-100) + 1, pixely-100 + 1, 13, 13), 0, 2)
pg.draw.rect(surf, lightcolors[fig['color']], (pixelx - (window_w-100) + 1, pixely-100 + 1, 9, 9), 0, 2)
display_surf.blit(surf, (window_w-100, 100))
def drawInfo(points, level):
showText(f"Счёт: {points}", basic_font, (255,255,255), -180)
showText(f"Уровень: {level}", basic_font, (255,255,255), -150)
showText("Следующая:", basic_font, (255,255,255), -220)
def drawTitle():
showText("ТЕТРИС", big_font, (255,255,0), -230)
def getNewFig():
shape = random.choice(list(figures.keys()))
return {
'shape': shape,
'rotation': 0,
'x': cup_w // 2 - 2,
'y': -2,
'color': shape
}
def calcSpeed(points):
level = points // 10 + 1
speed = max(0.1, 0.8 - (level - 1) * 0.05)
return level, speed
def pauseScreen():
pause = True
while pause:
for event in pg.event.get():
if event.type == QUIT:
stopGame()
if event.type == KEYDOWN:
if event.key == K_SPACE:
pause = False
if event.key == K_ESCAPE:
stopGame()
s = pg.Surface((window_w, window_h), pg.SRCALPHA)
s.fill((0, 0, 255, 100))
display_surf.blit(s, (0, 0))
showText("Пауза. Пробел - продолжить", basic_font, (255,255,255), 0)
pg.display.update()
fps_clock.tick(fps)
def runTetris(speed_factor, player_name):
cup = emptycup()
last_move_down = time.time()
last_side_move = time.time()
last_fall = time.time()
going_down = False
going_left = False
going_right = False
points = 0
level, fall_speed = calcSpeed(points)
fall_speed = max(0.05, fall_speed * speed_factor)
fallingFig = getNewFig()
nextFig = getNewFig()
move_repeat_delay = 0.1
if sound_enabled:
pg.mixer.music.play(-1)
while True:
if fallingFig is None:
fallingFig = nextFig
nextFig = getNewFig()
last_fall = time.time()
if not checkPos(cup, fallingFig):
if sound_enabled:
pg.mixer.music.stop()
gameover_sound.play()
return points
for event in pg.event.get():
if event.type == QUIT:
stopGame()
if event.type == KEYUP:
if event.key == K_LEFT:
going_left = False
elif event.key == K_RIGHT:
going_right = False
elif event.key == K_DOWN:
going_down = False
if event.type == KEYDOWN:
if event.key == K_SPACE:
if sound_enabled:
pg.mixer.music.pause()
pauseScreen()
if sound_enabled:
pg.mixer.music.unpause()
if event.key == K_LEFT and checkPos(cup, fallingFig, adjX=-1):
fallingFig['x'] -= 1
going_left = True
going_right = False
last_side_move = time.time()
if sound_enabled:
move_sound.play()
elif event.key == K_RIGHT and checkPos(cup, fallingFig, adjX=1):
fallingFig['x'] += 1
going_right = True
going_left = False
last_side_move = time.time()
if sound_enabled:
move_sound.play()
elif event.key == K_UP:
fallingFig['rotation'] = (fallingFig['rotation'] + 1) % len(figures[fallingFig['shape']])
if not checkPos(cup, fallingFig):
fallingFig['rotation'] = (fallingFig['rotation'] - 1) % len(figures[fallingFig['shape']])
if sound_enabled:
move_sound.play()
elif event.key == K_DOWN:
going_down = True
if checkPos(cup, fallingFig, adjY=1):
fallingFig['y'] += 1
last_move_down = time.time()
if sound_enabled:
move_sound.play()
elif event.key == K_RETURN:
going_down = False
going_left = False
going_right = False
for i in range(1, cup_h):
if not checkPos(cup, fallingFig, adjY=i):
break
fallingFig['y'] += i - 1
if sound_enabled:
move_sound.play()
if (going_left or going_right) and time.time() - last_side_move > side_freq:
if going_left and checkPos(cup, fallingFig, adjX=-1):
fallingFig['x'] -= 1
elif going_right and checkPos(cup, fallingFig, adjX=1):
fallingFig['x'] += 1
last_side_move = time.time()
if going_down and time.time() - last_move_down > down_freq and checkPos(cup, fallingFig, adjY=1):
fallingFig['y'] += 1
last_move_down = time.time()
if time.time() - last_fall > fall_speed:
if not checkPos(cup, fallingFig, adjY=1):
addToCup(cup, fallingFig)
removed = clearCompleted(cup)
points += removed * 10
level, new_speed = calcSpeed(points)
fall_speed = max(0.05, new_speed * speed_factor)
fallingFig = None
else:
fallingFig['y'] += 1
last_fall = time.time()
display_surf.fill(bg_color)
drawTitle()
gamecup(cup)
drawInfo(points, level)
drawnextFig(nextFig)
if fallingFig is not None:
drawFig(fallingFig)
pg.display.update()
fps_clock.tick(fps)
def main():
player_name = getPlayerName()
speed_factor = chooseDifficulty()
if sound_enabled:
start_sound.play()
time.sleep(0.5)
final_score = runTetris(speed_factor, player_name)
if sound_enabled:
pg.mixer.music.stop()
gameover_sound.play()
while True:
display_surf.fill(bg_color)
showText("ИГРА ЗАКОНЧЕНА", big_font, (255,0,0), -80)
showText(f"{player_name}, твой счёт: {final_score}", big_font, (255,255,0), -20)
showText("Нажми R для повтора или ESC для выхода", basic_font, (255,255,255), 60)
pg.display.update()
for event in pg.event.get():
if event.type == QUIT:
stopGame()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
stopGame()
if event.key == K_r:
main()
return
if __name__ == '__main__':
main()