{"id":2191,"date":"2019-06-28T20:52:54","date_gmt":"2019-06-28T18:52:54","guid":{"rendered":"https:\/\/pythonprogramming.altervista.org\/?p=2191"},"modified":"2019-06-30T21:13:29","modified_gmt":"2019-06-30T19:13:29","slug":"tetris-clone","status":"publish","type":"post","link":"https:\/\/pythonprogramming.altervista.org\/tetris-clone\/","title":{"rendered":"Tetris clone"},"content":{"rendered":"<p><a href=\"https:\/\/pythonprogramming.altervista.org\/wp-content\/uploads\/2019\/06\/cover.png\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-2192 aligncenter\" src=\"https:\/\/pythonprogramming.altervista.org\/wp-content\/uploads\/2019\/06\/cover.png\" alt=\"\" width=\"209\" height=\"200\" srcset=\"https:\/\/pythonprogramming.altervista.org\/wp-content\/uploads\/2019\/06\/cover.png 675w, https:\/\/pythonprogramming.altervista.org\/wp-content\/uploads\/2019\/06\/cover-320x307.png 320w\" sizes=\"auto, (max-width: 209px) 100vw, 209px\" \/><\/a><\/p>\n<p>I made some changes to this code about tetris game.<\/p>\n<p><iframe loading=\"lazy\" title=\"Tetris clone in Tetris\" width=\"747\" height=\"420\" src=\"https:\/\/www.youtube.com\/embed\/s2mrlSNwd1g?feature=oembed&amp;enablejsapi=1\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/p>\n<p>The original video with the tutorial<\/p>\n<p><iframe loading=\"lazy\" title=\"Python and Pygame Tutorial - Build Tetris! Full GameDev Course\" width=\"747\" height=\"420\" src=\"https:\/\/www.youtube.com\/embed\/zfvxp7PgQ6c?feature=oembed&amp;enablejsapi=1\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/p>\n<pre class=\"lang:default decode:true \">import pygame\r\nimport random\r\n \r\n\"\"\"\r\n10 x 20 square grid\r\nshapes: S, Z, I, O, J, L, T\r\nrepresented in order by 0 - 6\r\n\"\"\"\r\n \r\npygame.font.init()\r\n \r\n# GLOBALS VARS\r\ns_width = 800\r\ns_height = 700\r\nplay_width = 300  # meaning 300 \/\/ 10 = 30 width per block\r\nplay_height = 600  # meaning 600 \/\/ 20 = 20 height per blo ck\r\nblock_size = 20\r\n \r\ntop_left_x = (s_width - play_width) \/\/ 2\r\ntop_left_y = s_height - play_height - 50\r\n \r\n \r\n# SHAPE FORMATS\r\n \r\nshape = [ # redesigned\r\n[[\".....\",\r\n      \".....\",\r\n      \".000.\",\r\n      \".000.\",\r\n      \".....\"],\r\n     \r\n     [\".....\",\r\n      \"..00.\",\r\n      \"..00.\",\r\n      \"..00.\",\r\n      \".....\"]],\r\n \r\n[     [\".....\",\r\n      \".....\",\r\n      \".00..\",\r\n      \"..0..\",\r\n      \".....\"],\r\n\r\n     [\".....\",\r\n     \".....\",\r\n      \"..0..\",\r\n      \".00..\",\r\n      \".....\"],\r\n\r\n      [\".....\",\r\n      \".....\",\r\n      \".0...\",\r\n      \".00..\",\r\n      \".....\"],\r\n\r\n      [\".....\",\r\n      \".....\",\r\n      \".00..\",\r\n      \".0...\",\r\n      \".....\"]],\r\n\r\n      [[\".....\",\r\n      \".....\",\r\n      \"..00.\",\r\n      \"..0..\",\r\n      \".....\"],\r\n\r\n     [\".....\",\r\n     \".....\",\r\n      \"..00.\",\r\n      \"...0.\",\r\n      \".....\"],\r\n\r\n      [\".....\",\r\n      \".....\",\r\n      \"...0.\",\r\n      \"..00.\",\r\n      \".....\"],\r\n\r\n      [\".....\",\r\n      \".....\",\r\n      \"..0..\",\r\n      \"..00.\",\r\n      \".....\"],\r\n\r\n      ],\r\n \r\n [\t [\"..0..\",\r\n      \"..0..\",\r\n      \"..0..\",\r\n      \"..0..\",\r\n      \".....\"],\r\n     [\".....\",\r\n      \"0000.\",\r\n      \".....\",\r\n      \".....\",\r\n      \".....\"]],\r\n \r\n [\t [\".....\",\r\n      \"..0..\",\r\n      \"..0..\",\r\n      \"..0..\",\r\n      \".....\"],\r\n     [\".....\",\r\n      \".000.\",\r\n      \".....\",\r\n      \".....\",\r\n      \".....\"]],\r\n\r\n[\t [\".....\",      \r\n      \".00..\",\r\n      \".00..\",\r\n      \".....\"]],\r\n\r\n[\t [\".....\",      \r\n      \".....\",\r\n      \"..00.\",\r\n      \".....\",\r\n      \".....\"],\r\n      [\".....\",      \r\n      \"...0.\",\r\n      \"...0.\",\r\n      \".....\",\r\n      \".....\"],\r\n      ],\r\n[[\".....\",\r\n      \".0...\",\r\n      \".000.\",\r\n      \".....\",\r\n      \".....\"],\r\n     [\".....\",\r\n      \"..00.\",\r\n      \"..0..\",\r\n      \"..0..\",\r\n      \".....\"],\r\n     [\".....\",\r\n      \".....\",\r\n      \".000.\",\r\n      \"...0.\",\r\n      \".....\"],\r\n     [\".....\",\r\n      \"..0..\",\r\n      \"..0..\",\r\n      \".00..\",\r\n      \".....\"]],\r\n \r\n[[\".....\",\r\n      \"...0.\",\r\n      \".000.\",\r\n      \".....\",\r\n      \".....\"],\r\n     [\".....\",\r\n      \"..0..\",\r\n      \"..0..\",\r\n      \"..00.\",\r\n      \".....\"],\r\n     [\".....\",\r\n      \".....\",\r\n      \".000.\",\r\n      \".0...\",\r\n      \".....\"],\r\n     [\".....\",\r\n      \".00..\",\r\n      \"..0..\",\r\n      \"..0..\",\r\n      \".....\"]],\r\n \r\n[[\".....\",\r\n      \"..0..\",\r\n      \".000.\",\r\n      \"..0..\",\r\n      \".....\"]],\r\n\r\n[[\".....\",\r\n      \"..0..\",\r\n      \".000.\",\r\n      \".....\",\r\n      \".....\"],\r\n     [\".....\",\r\n      \"..0..\",\r\n      \"..00.\",\r\n      \"..0..\",\r\n      \".....\"],\r\n     [\".....\",\r\n      \".....\",\r\n      \".000.\",\r\n      \"..0..\",\r\n      \".....\"],\r\n     [\".....\",\r\n      \"..0..\",\r\n      \".00..\",\r\n      \"..0..\",\r\n      \".....\"]]\r\n     ]\r\n \r\nshapes = [x for x in shape]\r\n \r\nclass Piece(object):\r\n    rows = 20\r\n    columns = 10\r\n    def __init__(self, column, row, shape):\r\n        self.x = column\r\n        self.y = row\r\n        self.shape = shape\r\n        self.color = (129,200,128)\r\n        self.rotation = 0  # number from 0-3\r\n \r\n \r\ndef create_grid(locked_positions={}):\r\n    grid = [[(0,0,0) for x in range(10)] for x in range(20)]\r\n \r\n    for i in range(len(grid)):\r\n        for j in range(len(grid[i])):\r\n            if (j,i) in locked_positions:\r\n                c = locked_positions[(j,i)]\r\n                grid[i][j] = c\r\n    return grid\r\n \r\n \r\ndef convert_shape_format(shape):\r\n    positions = []\r\n    format = shape.shape[shape.rotation % len(shape.shape)]\r\n \r\n    for i, line in enumerate(format):\r\n        row = list(line)\r\n        for j, column in enumerate(row):\r\n            if column == \"0\":\r\n                positions.append((shape.x + j, shape.y + i))\r\n \r\n    for i, pos in enumerate(positions):\r\n        positions[i] = (pos[0] - 2, pos[1] - 4)\r\n \r\n    return positions\r\n \r\n \r\ndef valid_space(shape, grid):\r\n    accepted_positions = [[(j, i) for j in range(10) if grid[i][j] == (0,0,0)] for i in range(20)]\r\n    accepted_positions = [j for sub in accepted_positions for j in sub]\r\n    formatted = convert_shape_format(shape)\r\n \r\n    for pos in formatted:\r\n        if pos not in accepted_positions:\r\n            if pos[1] &gt; -1:\r\n                return False\r\n \r\n    return True\r\n \r\n \r\ndef check_lost(positions):\r\n    for pos in positions:\r\n        x, y = pos\r\n        if y &lt; 1:\r\n            return True\r\n    return False\r\n \r\n \r\ndef get_shape():\r\n    global shapes, shape_colors\r\n \r\n    return Piece(5, 0, random.choice(shapes))\r\n \r\n \r\ndef draw_text_middle(text, size, color, surface):\r\n    font = pygame.font.SysFont(\"comicsans\", size, bold=True)\r\n    label = font.render(text, 1, color)\r\n \r\n    surface.blit(label, (top_left_x + play_width\/2 - (label.get_width() \/ 2), top_left_y + play_height\/2 - label.get_height()\/2))\r\n \r\n \r\ndef draw_grid(surface, row, col):\r\n    sx = top_left_x\r\n    sy = top_left_y\r\n    for i in range(row):\r\n        pygame.draw.line(surface, (128,128,128), (sx, sy+ i*30), (sx + play_width, sy + i * 30))  # horizontal lines\r\n        for j in range(col):\r\n            pygame.draw.line(surface, (128,128,128), (sx + j * 30, sy), (sx + j * 30, sy + play_height))  # vertical lines\r\n \r\n \r\ndef clear_rows(grid, locked):\r\n    # need to see if row is clear the shift every other row above down one\r\n \r\n    inc = 0\r\n    for i in range(len(grid)-1,-1,-1):\r\n        row = grid[i]\r\n        if (0, 0, 0) not in row:\r\n            inc += 1\r\n            # add positions to remove from locked\r\n            ind = i\r\n            for j in range(len(row)):\r\n                try: \r\n                    del locked[(j, i)]\r\n                except:\r\n                    continue\r\n    if inc &gt; 0:\r\n        for key in sorted(list(locked), key=lambda x: x[1])[::-1]:\r\n            x, y = key\r\n            if y &lt; ind:\r\n                newKey = (x, y + inc)\r\n                locked[newKey] = locked.pop(key)\r\n \r\n \r\ndef draw_next_shape(shape, surface):\r\n    font = pygame.font.SysFont(\"comicsans\", 30)\r\n    label = font.render(\"Next Shape\", 1, (128,128,128))\r\n \r\n    sx = top_left_x + play_width + 50\r\n    sy = top_left_y + play_height\/2 - 100\r\n    format = shape.shape[shape.rotation % len(shape.shape)]\r\n \r\n    for i, line in enumerate(format):\r\n        row = list(line)\r\n        for j, column in enumerate(row):\r\n            if column == \"0\":\r\n                pygame.draw.rect(surface, shape.color, (sx + j*30, sy + i*30, 30, 30), 0)\r\n \r\n    surface.blit(label, (sx + 10, sy- 30))\r\n \r\n \r\ndef draw_window(surface):\r\n    surface.fill((0,0,32))\r\n    # Tetris Title\r\n    #font = pygame.font.SysFont(\"comicsans\", 48)\r\n    #label = font.render(\"TETRIS\", 1, (255,255,255))\r\n \r\n    #surface.blit(label, (top_left_x + play_width \/ 2 - (label.get_width() \/ 2), 30))\r\n \r\n    for i in range(len(grid)):\r\n        for j in range(len(grid[i])):\r\n            pygame.draw.rect(surface, grid[i][j], (top_left_x + j* 30, top_left_y + i * 30, 30, 30), 0)\r\n \r\n    # draw grid and border\r\n    draw_grid(surface, 27, 10)\r\n    pygame.draw.rect(surface, (128, 128, 128), (top_left_x, top_left_y, play_width, play_height), 5)\r\n    #pygame.display.update()\r\n \r\n\r\ndef main():\r\n    global grid\r\n \r\n    locked_positions = {}  # (x,y):(255,0,0)\r\n    grid = create_grid(locked_positions)\r\n \r\n    change_piece = False\r\n    run = True\r\n    current_piece = get_shape()\r\n    next_piece = get_shape()\r\n    clock = pygame.time.Clock()\r\n    fall_time = 0\r\n \r\n    while run:\r\n        fall_speed = 0.27\r\n \r\n        grid = create_grid(locked_positions)\r\n        fall_time += clock.get_rawtime()\r\n        clock.tick()\r\n \r\n        # PIECE FALLING CODE\r\n        if fall_time\/1000 &gt;= fall_speed:\r\n            fall_time = 0\r\n            current_piece.y += 1\r\n            if not (valid_space(current_piece, grid)) and current_piece.y &gt; 0:\r\n                current_piece.y -= 1\r\n                change_piece = True\r\n \r\n        for event in pygame.event.get():\r\n            if event.type == pygame.QUIT:\r\n                run = False\r\n                pygame.display.quit()\r\n                quit()\r\n \r\n            if event.type == pygame.KEYDOWN:\r\n\r\n                if event.key == pygame.K_LEFT:\r\n                    current_piece.x -= 1\r\n                    if not valid_space(current_piece, grid):\r\n                        current_piece.x += 1\r\n \r\n                elif event.key == pygame.K_RIGHT:\r\n                    current_piece.x += 1\r\n                    if not valid_space(current_piece, grid):\r\n                        current_piece.x -= 1\r\n                elif event.key == pygame.K_UP:\r\n                    # rotate shape\r\n                    current_piece.rotation = current_piece.rotation + 1 % len(current_piece.shape)\r\n                    if not valid_space(current_piece, grid):\r\n                        current_piece.rotation = current_piece.rotation - 1 % len(current_piece.shape)\r\n \r\n                if event.key == pygame.K_DOWN:\r\n                    # move shape down\r\n                    current_piece.y += 1\r\n                    if not valid_space(current_piece, grid):\r\n                        current_piece.y -= 1\r\n \r\n                if event.key == pygame.K_SPACE:\r\n                   while valid_space(current_piece, grid):\r\n                       current_piece.y += 1\r\n                   current_piece.y -= 1\r\n                   #print(convert_shape_format(current_piece))\"\"\"  # todo fix\r\n\r\n\r\n        shape_pos = convert_shape_format(current_piece)\r\n \r\n        # add piece to the grid for drawing\r\n        for i in range(len(shape_pos)):\r\n            x, y = shape_pos[i]\r\n            if y &gt; -1:\r\n                grid[y][x] = current_piece.color\r\n \r\n        # IF PIECE HIT GROUND\r\n        if change_piece:\r\n            for pos in shape_pos:\r\n                p = (pos[0], pos[1])\r\n                locked_positions[p] = current_piece.color\r\n            current_piece = next_piece\r\n            next_piece = get_shape()\r\n            change_piece = False\r\n \r\n            # call four times to check for multiple clear rows\r\n            clear_rows(grid, locked_positions)\r\n \r\n        draw_window(win)\r\n        draw_next_shape(next_piece, win)\r\n        pygame.display.update()\r\n \r\n        # Check if user lost\r\n        if check_lost(locked_positions):\r\n            run = False\r\n \r\n    draw_text_middle(\"You Lost\", 40, (255,255,255), win)\r\n    pygame.display.update()\r\n    pygame.time.delay(2000)\r\n \r\n \r\ndef main_menu():\r\n    run = True\r\n    while run:\r\n        win.fill((0,0,0))\r\n        draw_text_middle(\"Press any key to begin.\", 60, (255, 255, 255), win)\r\n        pygame.display.update()\r\n        for event in pygame.event.get():\r\n            if event.type == pygame.QUIT:\r\n                run = False\r\n \r\n            if event.type == pygame.KEYDOWN:\r\n                main()\r\n    pygame.quit()\r\n \r\n\r\nwin = pygame.display.set_mode((s_width, s_height))\r\n#win = pygame.display.set_mode((0, 0), pygame.FULLSCREEN)\r\npygame.display.set_caption(\"Tetris\")\r\nmain_menu()  # start game<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"Tetris clone\n<a class=\"moretag\" href=\"https:\/\/pythonprogramming.altervista.org\/tetris-clone\/\"> [...]<\/a>","protected":false},"author":1,"featured_media":2192,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","footnotes":""},"categories":[154],"tags":[137,194,4,425],"class_list":["post-2191","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-games","tag-game","tag-pygame","tag-python","tag-tetris"],"avopt_banners_inside_post":true,"avopt_banners_on_page":true,"av_copy_from":"","av_sharing_message":"","av_sharing_allowed":false,"av_sharing_on":{"fb":[],"tw":[]},"av_allow_affiliate_banner":false,"av_allow_affiliate_multi_banner":false,"av_show_affiliation_buy_button":false,"av_post_rating":true,"av_have_post_rating_value":false,"av_is_artificial_intelligence_content":false,"_links":{"self":[{"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/posts\/2191","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/comments?post=2191"}],"version-history":[{"count":3,"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/posts\/2191\/revisions"}],"predecessor-version":[{"id":2204,"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/posts\/2191\/revisions\/2204"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/media\/2192"}],"wp:attachment":[{"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/media?parent=2191"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/categories?post=2191"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/tags?post=2191"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}