Программа для питона тетрис

silvasur / tetris.py

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

#!/usr/bin/env python
#-*- coding: utf-8 -*-
# Very simple tetris implementation
#
# Control keys:
# Down — Drop stone faster
# Left/Right — Move stone
# Up — Rotate Stone clockwise
# Escape — Quit game
# P — Pause game
#
# Have fun!
# Copyright (c) 2010 «Kevin Chabowski»
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the «Software»), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED «AS IS», WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from random import randrange as rand
import pygame , sys
# The configuration
config =
‘cell_size’ : 20 ,
‘cols’ : 8 ,
‘rows’ : 16 ,
‘delay’ : 750 ,
‘maxfps’ : 30
>
colors = [
( 0 , 0 , 0 ),
( 255 , 0 , 0 ),
( 0 , 150 , 0 ),
( 0 , 0 , 255 ),
( 255 , 120 , 0 ),
( 255 , 255 , 0 ),
( 180 , 0 , 255 ),
( 0 , 220 , 220 )
]
# Define the shapes of the single parts
tetris_shapes = [
[[ 1 , 1 , 1 ],
[ 0 , 1 , 0 ]],
[[ 0 , 2 , 2 ],
[ 2 , 2 , 0 ]],
[[ 3 , 3 , 0 ],
[ 0 , 3 , 3 ]],
[[ 4 , 0 , 0 ],
[ 4 , 4 , 4 ]],
[[ 0 , 0 , 5 ],
[ 5 , 5 , 5 ]],
[[ 6 , 6 , 6 , 6 ]],
[[ 7 , 7 ],
[ 7 , 7 ]]
]
def rotate_clockwise ( shape ):
return [ [ shape [ y ][ x ]
for y in xrange ( len ( shape )) ]
for x in xrange ( len ( shape [ 0 ]) — 1 , — 1 , — 1 ) ]
def check_collision ( board , shape , offset ):
off_x , off_y = offset
for cy , row in enumerate ( shape ):
for cx , cell in enumerate ( row ):
try :
if cell and board [ cy + off_y ][ cx + off_x ]:
return True
except IndexError :
return True
return False
def remove_row ( board , row ):
del board [ row ]
return [[ 0 for i in xrange ( config [ ‘cols’ ])]] + board
def join_matrixes ( mat1 , mat2 , mat2_off ):
off_x , off_y = mat2_off
for cy , row in enumerate ( mat2 ):
for cx , val in enumerate ( row ):
mat1 [ cy + off_y — 1 ][ cx + off_x ] += val
return mat1
def new_board ():
board = [ [ 0 for x in xrange ( config [ ‘cols’ ]) ]
for y in xrange ( config [ ‘rows’ ]) ]
board += [[ 1 for x in xrange ( config [ ‘cols’ ])]]
return board
class TetrisApp ( object ):
def __init__ ( self ):
pygame . init ()
pygame . key . set_repeat ( 250 , 25 )
self . width = config [ ‘cell_size’ ] * config [ ‘cols’ ]
self . height = config [ ‘cell_size’ ] * config [ ‘rows’ ]
self . screen = pygame . display . set_mode (( self . width , self . height ))
pygame . event . set_blocked ( pygame . MOUSEMOTION ) # We do not need
# mouse movement
# events, so we
# block them.
self . init_game ()
def new_stone ( self ):
self . stone = tetris_shapes [ rand ( len ( tetris_shapes ))]
self . stone_x = int ( config [ ‘cols’ ] / 2 — len ( self . stone [ 0 ]) / 2 )
self . stone_y = 0
if check_collision ( self . board ,
self . stone ,
( self . stone_x , self . stone_y )):
self . gameover = True
def init_game ( self ):
self . board = new_board ()
self . new_stone ()
def center_msg ( self , msg ):
for i , line in enumerate ( msg . splitlines ()):
msg_image = pygame . font . Font (
pygame . font . get_default_font (), 12 ). render (
line , False , ( 255 , 255 , 255 ), ( 0 , 0 , 0 ))
msgim_center_x , msgim_center_y = msg_image . get_size ()
msgim_center_x //= 2
msgim_center_y //= 2
self . screen . blit ( msg_image , (
self . width // 2 — msgim_center_x ,
self . height // 2 — msgim_center_y + i * 22 ))
def draw_matrix ( self , matrix , offset ):
off_x , off_y = offset
for y , row in enumerate ( matrix ):
for x , val in enumerate ( row ):
if val :
pygame . draw . rect (
self . screen ,
colors [ val ],
pygame . Rect (
( off_x + x ) *
config [ ‘cell_size’ ],
( off_y + y ) *
config [ ‘cell_size’ ],
config [ ‘cell_size’ ],
config [ ‘cell_size’ ]), 0 )
def move ( self , delta_x ):
if not self . gameover and not self . paused :
new_x = self . stone_x + delta_x
if new_x < 0 :
new_x = 0
if new_x > config [ ‘cols’ ] — len ( self . stone [ 0 ]):
new_x = config [ ‘cols’ ] — len ( self . stone [ 0 ])
if not check_collision ( self . board ,
self . stone ,
( new_x , self . stone_y )):
self . stone_x = new_x
def quit ( self ):
self . center_msg ( «Exiting. » )
pygame . display . update ()
sys . exit ()
def drop ( self ):
if not self . gameover and not self . paused :
self . stone_y += 1
if check_collision ( self . board ,
self . stone ,
( self . stone_x , self . stone_y )):
self . board = join_matrixes (
self . board ,
self . stone ,
( self . stone_x , self . stone_y ))
self . new_stone ()
while True :
for i , row in enumerate ( self . board [: — 1 ]):
if 0 not in row :
self . board = remove_row (
self . board , i )
break
else :
break
def rotate_stone ( self ):
if not self . gameover and not self . paused :
new_stone = rotate_clockwise ( self . stone )
if not check_collision ( self . board ,
new_stone ,
( self . stone_x , self . stone_y )):
self . stone = new_stone
def toggle_pause ( self ):
self . paused = not self . paused
def start_game ( self ):
if self . gameover :
self . init_game ()
self . gameover = False
def run ( self ):
key_actions =
‘ESCAPE’ : self . quit ,
‘LEFT’ : lambda : self . move ( — 1 ),
‘RIGHT’ : lambda : self . move ( + 1 ),
‘DOWN’ : self . drop ,
‘UP’ : self . rotate_stone ,
‘p’ : self . toggle_pause ,
‘SPACE’ : self . start_game
>
self . gameover = False
self . paused = False
pygame . time . set_timer ( pygame . USEREVENT + 1 , config [ ‘delay’ ])
dont_burn_my_cpu = pygame . time . Clock ()
while 1 :
self . screen . fill (( 0 , 0 , 0 ))
if self . gameover :
self . center_msg ( «»»Game Over!
Press space to continue»»» )
else :
if self . paused :
self . center_msg ( «Paused» )
else :
self . draw_matrix ( self . board , ( 0 , 0 ))
self . draw_matrix ( self . stone ,
( self . stone_x ,
self . stone_y ))
pygame . display . update ()
for event in pygame . event . get ():
if event . type == pygame . USEREVENT + 1 :
self . drop ()
elif event . type == pygame . QUIT :
self . quit ()
elif event . type == pygame . KEYDOWN :
for key in key_actions :
if event . key == eval ( «pygame.K_»
+ key ):
key_actions [ key ]()
dont_burn_my_cpu . tick ( config [ ‘maxfps’ ])
if __name__ == ‘__main__’ :
App = TetrisApp ()
App . run ()

Источник

Программа для питона тетрис

Игровое поле представляет собой прямоугольный «стакан», в который сверху падают фигуры – стилизованные буквы L, S, Z, J, O, I и T.

Буквы-фигуры в Тетрисе

Каждая буква состоит из 4 блоков:

Фигуры и варианты поворотов описаны в 2D-списках 5 х 5

Игрок управляет движением фигур вниз – двигает их вправо и влево (но не вверх), поворачивает на 90 градусов, при желании ускоряет падение нажатием/удержанием клавиши ↓ или мгновенно сбрасывает фигуры на дно нажатием Enter.

Приземлением считается момент, когда фигура падает на дно стакана или на элемент предыдущих фигур. После этого программа проверяет, вызвало ли приземление полное (без пустот) заполнение ряда элементов. Заполненные ряды (их может быть от 1 до 4 включительно) удаляются; находящиеся над ними элементы перемещаются вниз на столько рядов, сколько было заполнено и удалено; вверху стакана добавляется соответствующее количество пустых рядов. После удаления 10 заполненных рядов происходит переход на следующий уровень, и падение фигур ускоряется.

Все экраны игры

Основные параметры игры

Прежде всего импортируем нужные модули:

Во время паузы экран заливается полупрозрачным синим цветом

Заливку сплошным цветом реализовать очень просто, но полупрозрачную заставку сделать сложнее – как ни странно, метод draw в Pygame до сих пор не поддерживает эту опцию. Есть несколько способов решения этой проблемы. Мы воспользуемся методом, который предусматривает создание дополнительной поверхности с попиксельным альфа-смешением, и последующую заливку экрана паузы цветом с наложением на поверхность окна игры:

Допустимое и недопустимое положение фигуры в стакане

Функция checkPos() следит за тем, чтобы падающая фигура оставалась в пределах игрового поля и не накладывалась на предыдущие. На примере слева фигура остается в допустимой области, на примере справа – ошибочно накладывается на предыдущую. Чтобы определить положение фигуры в стакане, нужно суммировать собственные координаты фигуры со «стаканными»:

Собственные координаты – (2, 1), (3, 1), (2, 2), (2, 3).

Стаканные координаты фигуры – (2, 3) на примере слева и (1, 11) на примере справа. Суммирование дает следующие результаты:

(2+2, 1+3), (3+2, 1+3), (2+2, 2+3), (2+2, 3+3) = (4, 4), (5, 4), (4, 5), (4, 6). Значит, фигура находится в пределах стакана и не наталкивается ни на один элемент предыдущих фигур.

На примере слева ситуация обратная:

(2+1, 2+11), (3+1, 2+11), (2+1, 3+11), (2+1, 4+11) = (3, 13), (4, 13), (3, 14), (3, 15) – две последние координаты в массиве cup уже заняты блоками предыдущих фигур. Именно такие ситуации и предотвращают checkPos() вместе с incup() :

Переменная указывает на удаленный ряд

Переменная y после удаления одного ряда продолжает указывать на его номер – это нужно для того, чтобы перейти к удалению других заполненных рядов, если они смещаются на место только что удаленного. В случае если других заполненных рядов пока нет, происходит уменьшение у .

Рисование блоков фигур

Каждая фигура состоит из 4 элементов – блоков. Блоки рисует функция drawBlock(), которая получает координаты из convertCoords() :

def drawBlock(block_x, block_y, color, pixelx=None, pixely=None): #отрисовка квадратных блоков, из которых состоят фигуры if color == empty: return if pixelx == None and pixely == 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) 

Для рисования блоков используются примитивы rect (прямоугольник) и circle (круг). При желании верхний квадрат можно конвертировать в поверхность ( Surface ), после чего наложить на эту поверхность изображение или текстовый символ. Функция drawBlock() также используется в drawnextFig() для вывода следующей фигуры справа от игрового поля.

Заключение

Напоминаем, что полный код игры можно скачать здесь . Это полностью функциональный Тетрис с простым интерфейсом. Pygame предоставляет немало дополнительных возможностей для дополнения программы: к примеру, в игру можно добавить звуковые эффекты, диалоговое окно для закрытия, фоновое изображение, запись рекордов в файл. Если какие-то моменты остались неясными – задавайте вопросы в комментариях.

Материалы по теме

Источник

Читайте также:  Перечисляемый тип данных python
Оцените статью