-
[python] 파이썬으로 테트리스 게임카테고리 없음 2022. 1. 19. 16:49
나의 첫 티스토리는 내가 현재 만들고 있는 테트리스 게임을 소개할 것이다.
테트리스 게임은 대중적인 게임이고, 룰도 매우 간단하다. 그래서 나는 이 게임을 파이썬으로 구현해보고자 여러 자료들을 찾아보며 pygame 모듈을 사용한 게임을 만드는 방법을 공부하였다.
하지만 게임을 만들다 보니 룰은 간단하다고 생각했던 테트리스가 생각보다 복잡한 처리 과정이 필요하고, 버그는 어떤식으로 수정해야 할 지 막막하기만 했었다. 그래도 단순한 재미만으로 계속하여 생각해보고 고민해봤다. 결국, 게임을 실행할 수 있게 되었다.
아직 버그는 많이 존재하고, 완성된 것은 아니다.내가 만든 코드는 다음과 같다. 살짝 봐도 효율따위는 신경쓰지 않고 단지 열정만을 보이는 매우 긴 코드를 볼 수 있다. 초보 티를 팍팍 낸다...ㅎㅎ
대략 800줄....더 열심히 코딩을 공부하여 효율 및 처리속도 등을 따질 수 있는 날이 오도록 노력해야겠다!코드
import pygame import random def block_mod_set(): global block_blank_size, block_fill if block_mode == 1: block_blank_size = 1 block_fill = 0 elif block_mode == 2: block_blank_size = 1 block_fill = 2 elif block_mode == 3: block_blank_size = int(block_size * 1 / 2) block_fill = 0 elif block_mode == 4: block_blank_size = 0 block_fill = int(block_size * 1 / 3) def draw_screen(): global rows, columns, grid screen.fill((0, 0, 0)) for row in range(rows): for col in range(columns): draw_game(grid[row][col], (row, col)) draw_next() draw_hold() draw_score() draw_block_mode() draw_combo_text() draw_block() def draw_game(color_idx, pos): global block_size, block_blank_size, block_fill x_pos = pos[0] * block_size + block_size * 2 y_pos = pos[1] * block_size + block_size * 2 block = pygame.Rect(0, 0, block_size - block_blank_size, block_size - block_blank_size) block.center = (y_pos, x_pos) pygame.draw.rect(screen, color[color_idx], block, block_fill) def draw_next(): global block_size, blocks_data, next_block, block_fill x_size = block_size * 5 y_size = block_size * 10 pygame.draw.rect(screen, (255, 255, 255), (21 * block_size, 22 * block_size - y_size, x_size, y_size), 2) size = block_size / 4 * 3 for y in range(6): num = int(y / 2) k = y % 2 idx = next_block[num] x_start = 23.5 * block_size - (len(blocks_data[idx - 1][0][0]) / 2) * size y_start = 12 * block_size + (num + 1) * block_size + (num + 0.5) * size if idx == 1 and k == 1: k = 0 elif idx == 1 and k == 0: y += 1 for x in range(len(blocks_data[idx - 1][0][k])): if blocks_data[idx - 1][0][k][x] == 1: block = pygame.Rect(x_start + x * size, y_start + y * size, size - block_blank_size * 3 / 4, size - block_blank_size * 3 / 4) pygame.draw.rect(screen, color[idx], block, block_fill) text = small_font.render("Next Blocks", True, color[next_block[0]]) screen.blit(text, (21.15 * block_size, 11 * block_size)) def hold_block(): global hold, grid, curr_block_idx, hold_check, blocks_data, hold_now_turn_check if not hold_now_turn_check: # 이번 턴에 홀드 하지 않았더라면 홀드 가능 if hold == 0: # 홀드 한 것이 없다면 hold_block_idx = curr_block_idx hold_check = False else: # 있다면 hold_block_idx = curr_block_idx hold_check = True block_data = blocks_data[curr_block_idx - 1] last_block = block_data[last_block_shape_idx] last_block_size_x = len(last_block[0]) last_block_size_y = len(last_block) if last_block_x_pos > -1: for x in range(last_block_size_x): for y in range(last_block_size_y): if last_block[y][x] == 1: grid[y + last_block_y_pos][x + last_block_x_pos] = 0 block_pos_produce() hold = hold_block_idx hold_now_turn_check = True def draw_hold(): global hold, blocks_data, block_size size = block_size / 4 * 3 x_size = block_size * 5 y_size = block_size * 4 pygame.draw.rect(screen, (255, 255, 255), (15 * block_size, 12 * block_size, x_size, y_size), 2) for y in range(2): k = y x_start = 17.5 * block_size - (len(blocks_data[hold - 1][0][0]) / 2) * size y_start = 13 * block_size + 0.5 * size if hold == 1 and k == 1: k = 0 elif hold == 1 and k == 0: y += 1 for x in range(len(blocks_data[hold - 1][0][k])): if blocks_data[hold - 1][0][k][x] == 1: block = pygame.Rect(x_start + x * size, y_start + y * size, size - block_blank_size * 3 / 4, size - block_blank_size * 3 / 4) pygame.draw.rect(screen, color[hold], block, block_fill) if hold == 0: color_rbg = [255, 255, 255] else: color_rbg = color[hold] text = small_font.render("Hold Block", True, color_rbg) screen.blit(text, (15.35 * block_size, 11 * block_size)) def draw_score(): global score, score_title_font, score_font, block_size, color_idx, color x_size = block_size * 11 y_size = block_size * 5 pygame.draw.rect(screen, (255, 255, 255), (15 * block_size, 5 * block_size, x_size, y_size), 2) if color_idx >= 7: color_idx = 1 else: color_idx += 0.001 text = score_title_font.render("S C O R E", True, color[curr_block_idx]) screen.blit(text, (16.6 * block_size, 2.7 * block_size)) score_text = score_font.render(str(score).zfill(7), True, color[int(color_idx)]) score_text_rect = score_text.get_rect(center=(20.5 * block_size, 7.8 * block_size)) screen.blit(score_text, score_text_rect) def draw_block_mode(): global mode_1, mode_2, mode_3, mode_4, block_mode button_size = int(block_size * 3 / 2) x_size = block_size * 5 y_size = block_size * 4.5 pygame.draw.rect(screen, (255, 255, 255), (15 * block_size, 17.5 * block_size, x_size, y_size), 2) text = small_font.render("Block Mode", True, (255, 255, 255)) screen.blit(text, (15.15 * block_size, 16.4 * block_size)) mode_1 = pygame.Rect(block_size * 15.1 + button_size * 0.4, block_size * 17.1 + button_size * 0.6, button_size, button_size) mode_2 = pygame.Rect(block_size * 17.9, block_size * 17.1 + button_size * 0.6, button_size, button_size) mode_3 = pygame.Rect(block_size * 15.1 + button_size * 0.4, block_size * 20, button_size, button_size) mode_4 = pygame.Rect(block_size * 17.9, block_size * 20, button_size, button_size) pygame.draw.rect(screen, (0, 0, 0), mode_1) pygame.draw.rect(screen, (0, 0, 0), mode_2) pygame.draw.rect(screen, (0, 0, 0), mode_3) pygame.draw.rect(screen, (0, 0, 0), mode_4) mode_1_color = [100, 100, 100] mode_2_color = [100, 100, 100] mode_3_color = [100, 100, 100] mode_4_color = [100, 100, 100] if block_mode == 1: mode_1_color = color[8] elif block_mode == 2: mode_2_color = color[8] elif block_mode == 3: mode_3_color = color[8] elif block_mode == 4: mode_4_color = color[8] block = pygame.Rect(block_size * 15.1 + 1 + button_size * 0.4, block_size * 17.1 + 1 + button_size * 0.6, button_size - 2, button_size - 2) pygame.draw.rect(screen, mode_1_color, block, 0) block = pygame.Rect(block_size * 17.9 + 1, block_size * 17.1 + 1 + button_size * 0.6, button_size - 2, button_size - 2) pygame.draw.rect(screen, mode_2_color, block, 4) block = pygame.Rect(block_size * 15.1 + int(button_size * 1 / 2) / 2 + button_size * 0.4, block_size * 20 + int(button_size * 1 / 2) / 2, button_size - int(button_size * 1 / 2), button_size - int(button_size * 1 / 2)) pygame.draw.rect(screen, mode_3_color, block, 0) block = pygame.Rect(block_size * 17.9, block_size * 20, button_size, button_size) pygame.draw.rect(screen, mode_4_color, block, int(button_size * 1 / 3)) def block_pos_produce(): global curr_block_idx, next_block, block_count, fall_turn, max_fall_turn, curr_block_idx, blocks_data, block_x_pos, block_y_pos, produce_ticks, curr_block_x_size, curr_block_y_size, curr_block_shape_idx, last_block_shape_idx, last_block_x_pos, last_block_y_pos, hold_check, hold, hold_now_turn_check if hold_check: curr_block_idx = hold hold_check = False else: curr_block_idx = next_block[0] for i in range(len(next_block) - 1): next_block[i] = next_block[i + 1] next_block[2] = random.randint(1, 7) hold_now_turn_check = False fall_turn = max((0.5 - 1.2) / 100 * block_count + 1.2, (max_fall_turn - 0.5) / (300 - 100) * (block_count - 100) + 0.5, max_fall_turn) curr_block_shape_idx = 0 last_block_shape_idx = 0 block_data = blocks_data[curr_block_idx - 1] curr_block = block_data[curr_block_shape_idx] curr_block_x_size = len(curr_block[0]) curr_block_y_size = len(curr_block) block_x_pos = 5 + int(2.5 - curr_block_x_size) block_y_pos = 0 last_block_x_pos = -1 last_block_y_pos = -1 produce_ticks = pygame.time.get_ticks() def block_falling(): global produce_ticks, now_ticks, fall_turn, block_y_pos, can_under, straight now_ticks = pygame.time.get_ticks() if straight: falling_finish() straight = False if (now_ticks - produce_ticks) / 1000 > fall_turn: produce_ticks = now_ticks now_ticks = pygame.time.get_ticks() if can_under: block_y_pos += 1 can_under = False else: falling_finish() def falling_finish(): global curr_block_idx, block_y_pos, running, block_count, block_score, score block_clear_check() block_count += 1 if block_y_pos <= 0: cause_motion() running = False else: block_pos_produce() score += block_score def draw_block(): global curr_block_idx, curr_block_shape_idx, block_x_pos, block_y_pos, last_block_x_pos, last_block_y_pos, last_block_shape_idx, curr_block_x_size, curr_block_y_size, last_block_x_size, last_block_y_size block_data = blocks_data[curr_block_idx - 1] curr_block = block_data[curr_block_shape_idx] curr_block_x_size = len(curr_block[0]) curr_block_y_size = len(curr_block) last_block = block_data[last_block_shape_idx] last_block_size_x = len(last_block[0]) last_block_size_y = len(last_block) if last_block_x_pos > -1: for x in range(last_block_size_x): for y in range(last_block_size_y): if last_block[y][x] == 1: grid[y + last_block_y_pos][x + last_block_x_pos] = 0 for x in range(curr_block_x_size): for y in range(curr_block_y_size): if curr_block[y][x] == 1: grid[y + block_y_pos][x + block_x_pos] = curr_block_idx last_block_x_pos = block_x_pos last_block_y_pos = block_y_pos last_block_shape_idx = curr_block_shape_idx def block_right(): global block_x_pos, can_right if can_right: block_x_pos += 1 def block_left(): global block_x_pos, can_left if can_left: block_x_pos -= 1 def block_up(): global block_y_pos block_y_pos -= 1 def block_rotate(): global curr_block_shape_idx, blocks_data, block_x_pos, curr_block_x_size, curr_block_y_size, block_y_pos, can_under_size, can_up_size, can_right_size, can_left_size, can_rotate block_data = blocks_data[curr_block_idx - 1] can_horizontal_size = min(can_right_size) + min(can_left_size) + curr_block_x_size can_vertical_size = min(can_under_size) + min(can_up_size) + curr_block_y_size can_rotate = True if can_horizontal_size >= curr_block_y_size: # 회전 가능 if (min(can_up_size) == 100) and (min(can_under_size) + curr_block_y_size + block_y_pos > curr_block_x_size): # 회전 가능 can_rotate = True else: if can_vertical_size >= curr_block_x_size and (min(can_under_size) + curr_block_y_size + block_y_pos > curr_block_x_size): # 회전 가능 can_rotate = True else: can_rotate = False else: # 회전 불가능 can_rotate = False if can_rotate: if min(can_right_size) < curr_block_y_size: for i in range(curr_block_y_size - (curr_block_x_size + min(can_right_size))): block_left() if min(can_under_size) < curr_block_x_size: for i in range(curr_block_x_size - (curr_block_y_size + min(can_under_size))): block_up() if (curr_block_idx == 4) and (curr_block_shape_idx == 0): if can_under_size[0] == 0: if can_up_size[1] == 1: curr_block_shape_idx -= 1 else: block_up() if (curr_block_idx == 5) and (curr_block_shape_idx == 2): if can_under_size[1] == 0: block_up() if (curr_block_idx == 6) and (curr_block_shape_idx == 2): if (can_under_size[0] == 0) or (can_under_size[1] == 0): block_up() if (curr_block_idx == 6) and (curr_block_shape_idx == 1): if can_under_size[1] == 0: block_up() if curr_block_shape_idx < len(block_data) - 1: curr_block_shape_idx += 1 else: curr_block_shape_idx = 0 def block_down(): global block_y_pos, can_under if can_under: block_y_pos += 1 can_under = False def block_can_right_check(): global block_x_pos, block_y_pos, can_right, blocks_data, curr_block_idx, curr_block_shape_idx, curr_block_x_size, curr_block_y_size, grid, can_right_size can_right = False can_right_size = [] block_data = blocks_data[curr_block_idx - 1] curr_block = block_data[curr_block_shape_idx] block_margin_x = curr_block_x_size - 1 curr_block_x_size = len(curr_block[0]) curr_block_y_size = len(curr_block) for y in range(curr_block_y_size): for x in range(curr_block_x_size - 1, -1, -1): if curr_block[y][x] == 1: block_margin_x = x break for x in range(block_x_pos + block_margin_x + 1, 12, 1): if grid[y + block_y_pos][x] > 0: can_right_size.append(x - (block_x_pos + block_margin_x) - 1) break if min(can_right_size) == 0: can_right = False else: can_right = True def block_can_left_check(): global block_x_pos, block_y_pos, can_left, blocks_data, curr_block_idx, curr_block_shape_idx, curr_block_x_size, curr_block_y_size, grid, can_left_size can_left = False can_left_size = [] block_data = blocks_data[curr_block_idx - 1] curr_block = block_data[curr_block_shape_idx] block_margin_x = 0 curr_block_x_size = len(curr_block[0]) curr_block_y_size = len(curr_block) for y in range(curr_block_y_size): for x in range(curr_block_x_size): if curr_block[y][x] == 1: block_margin_x = x break for x in range(block_x_pos + block_margin_x - 1, -1, -1): if grid[y + block_y_pos][x] > 0: can_left_size.append((block_x_pos + block_margin_x) - x - 1) break if min(can_left_size) == 0: can_left = False else: can_left = True def block_can_under_check(): #한 칸 아래로 내려갈 수 있는지 확인 global block_x_pos, block_y_pos, can_under, blocks_data, curr_block_idx, curr_block_shape_idx, curr_block_x_size, curr_block_y_size, grid, can_under_size can_under = False can_under_size = [] block_data = blocks_data[curr_block_idx - 1] curr_block = block_data[curr_block_shape_idx] block_bottom_y = curr_block_y_size - 1 curr_block_x_size = len(curr_block[0]) curr_block_y_size = len(curr_block) for x in range(curr_block_x_size): for y in range(curr_block_y_size - 1, -1, -1): if curr_block[y][x] == 1: block_bottom_y = y break for y in range(block_y_pos + block_bottom_y + 1, 21, 1): if grid[y][x + block_x_pos] > 0: can_under_size.append(y - (block_y_pos + block_bottom_y) - 1) break if min(can_under_size) == 0: can_under = False else: can_under = True def block_can_up_check(): global block_x_pos, block_y_pos, blocks_data, curr_block_idx, curr_block_shape_idx, curr_block_x_size, curr_block_y_size, grid, can_up_size can_up_size = [] block_data = blocks_data[curr_block_idx - 1] curr_block = block_data[curr_block_shape_idx] block_top_y = 0 curr_block_x_size = len(curr_block[0]) curr_block_y_size = len(curr_block) for x in range(curr_block_x_size): for y in range(curr_block_y_size): if curr_block[y][x] == 1: block_top_y = y break for y in range(block_y_pos + block_top_y - 1, -1, -1): if grid[y][x + block_x_pos] > 0: can_up_size.append((block_y_pos + block_top_y) - y - 1) break if y == 0: can_up_size.append(100) if block_y_pos + block_top_y == 0: can_up_size.append(100) def block_straight(): global can_under_size, block_y_pos, straight, straight_score, score block_y_pos += min(can_under_size) straight = True score += straight_score * min(can_under_size) def block_clear_check(): global grid, columns, rows, clear_score, score, clear_combo, draw_combo, clear_row_y_pos now_clear_rows = 0 for row in range(0, rows - 1, 1): check = 1 for col in range(columns): check *= grid[row][col] if check > 0: clear(row) clear_row_y_pos = row * block_size + block_size * 2 now_clear_rows += 1 if not now_clear_rows == 0: clear_combo += 1 draw_combo = 1 else: clear_combo = 0 draw_combo = 0 score += clear_score * ((now_clear_rows) ** 2) * int(clear_combo ** (3 / 2)) def draw_combo_text(): global combo_ticks, now_ticks, draw_combo now_ticks = pygame.time.get_ticks() if clear_combo >= 2: if draw_combo == 1: if combo_ticks == None: combo_ticks = pygame.time.get_ticks() elif now_ticks - combo_ticks <= 1000: combo_text = combo_font.render("Combo X " + str(clear_combo), True, (255, 255, 255)) combo_text_rect = combo_text.get_rect(center=(20.5 * block_size, 6.1 * block_size)) screen.blit(combo_text, combo_text_rect) else: combo_ticks = None draw_combo = 0 def clear(clear_row): global grid, columns, rows list1 = [8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8] list2 = [i for i in grid[clear_row]] for i in range(6): if i % 2 == 0: grid[clear_row] = list1 else: grid[clear_row] = list2 for row in range(rows): for col in range(columns): draw_game(grid[row][col], (row, col)) pygame.display.update() pygame.time.delay(100) for row in range(clear_row, 0, -1): grid[row] = grid[row - 1] grid[0] = [8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8] def cause_motion(): global grid list1 = [8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8] list2 = [i for i in grid[0]] for i in range(8): if i % 2 == 0: grid[0] = list1 else: grid[0] = list2 for row in range(rows): for col in range(columns): draw_game(grid[row][col], (row, col)) pygame.display.update() pygame.time.delay(100) def game_over(): for y in range(21): for x in range(12): x_pos = x * block_size + block_size * 2 y_pos = y * block_size + block_size * 2 block = pygame.Rect(0, 0, block_size - block_blank_size, block_size - block_blank_size) block.center = (x_pos, y_pos) pygame.draw.rect(screen, color[8], block, block_fill) pygame.display.update() pygame.time.delay(100) def check_buttons(pos): global mode_1, mode_2, mode_3, mode_4, block_mode if mode_1.collidepoint(pos): block_mode = 1 elif mode_2.collidepoint(pos): block_mode = 2 elif mode_3.collidepoint(pos): block_mode = 3 elif mode_4.collidepoint(pos): block_mode = 4 pygame.init() block_size = 24 screen_width = block_size * 28 # 가로 크기 screen_height = block_size * 24 # 세로 크기 screen = pygame.display.set_mode((screen_width, screen_height)) pygame.display.set_caption("TETRIS") ############################################################## background_1 = [(0, i) for i in range(21)] background_2 = [(i, 20) for i in range(12)] background_3 = [(11, i) for i in range(21)] background = background_1 + background_2 + background_3 columns = 12 rows = 21 grid = [[0 for col in range(columns)] for row in range(rows)] miri_grid = [[0 for col in range(columns)] for row in range(rows)] for pos in background: grid[pos[1]][pos[0]] = 8 block_mode = 1 block_blank_size = 1 block_fill = 0 block_count = 1 score = 0 straight_score = 3 falling_score = 1 block_score = 15 clear_score = 100 clear_combo = 0 draw_combo = 0 clear_row_y_pos = 0 draw_increase_score = 0 small_font = pygame.font.Font(None, int(block_size * 5 / 4)) score_font = pygame.font.Font(None, int(block_size * 3.5)) score_title_font = pygame.font.Font(None, int(block_size * 2.5)) combo_font = pygame.font.Font(None, int(block_size)) color_idx = 1 block_x_pos = 0 block_y_pos = 0 curr_block_shape_idx = 0 curr_block_x_size = 0 curr_block_y_size = 0 last_block_x_pos = -1 last_block_y_pos = -1 last_block_shape_idx = 0 last_block_x_size = 0 last_block_y_size = 0 next_block = [random.randint(1, 7), random.randint(1, 7), random.randint(1, 7)] hold = 0 hold_check = False hold_now_turn_check = False curr_block_idx = 0 # 검은색, 하늘색, 노란색, 초록색, 빨간색, 주황색, 파란색, 보라색, 회색 color = [(0, 0, 0), (0, 255, 255), (255, 255, 0), (0, 255, 0), (255, 0, 0), (255, 127, 0), (0, 0, 255), (168, 64, 255), (195, 195, 195)] blocks_data = [ [ [[1, 1, 1, 1]], [[1], [1], [1], [1]] ], #하늘색 1 [ [[1, 1], [1, 1]] ], #노란색 2 [ [[0, 1, 1], [1, 1, 0]], [[1, 0], [1, 1], [0, 1]] ], #초록색 3 [ [[1, 1, 0], [0, 1, 1]], [[0, 1], [1, 1], [1, 0]] ], #빨간색 4 [ [[0, 0, 1], [1, 1, 1]], [[1, 0], [1, 0], [1, 1]], [[1, 1, 1], [1, 0, 0]], [[1, 1], [0, 1], [0, 1]] ], #주황색 5 [ [[1, 0, 0], [1, 1, 1]], [[1, 1], [1, 0], [1, 0]], [[1, 1, 1], [0, 0, 1]], [[0, 1], [0, 1], [1, 1]] ], #파란색 6 [ [[0, 1, 0], [1, 1, 1]], [[1, 0], [1, 1], [1, 0]], [[1, 1, 1], [0, 1, 0]], [[0, 1], [1, 1], [0, 1]] ], # 보라색 7 ] combo_ticks = None produce_ticks = None now_ticks = None fall_turn = 1 max_fall_turn = 0.15 can_under_size = [] can_under = True can_right_size = [] can_right = True can_left_size = [] can_left = True can_up_size = [] can_rotate = True straight = False mode_1 = pygame.Rect(0, 0, 0, 0) mode_2 = pygame.Rect(0, 0, 0, 0) mode_3 = pygame.Rect(0, 0, 0, 0) mode_4 = pygame.Rect(0, 0, 0, 0) click_pos = None block_pos_produce() running = True while running: block_mod_set() block_can_up_check() block_can_under_check() block_can_right_check() block_can_left_check() block_falling() for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_RIGHT: block_right() elif event.key == pygame.K_LEFT: block_left() elif event.key == pygame.K_UP: block_rotate() elif event.key == pygame.K_DOWN: block_down() score += falling_score elif event.key == pygame.K_SPACE: block_straight() elif event.key == pygame.K_c: hold_block() elif event.type == pygame.MOUSEBUTTONUP: click_pos = pygame.mouse.get_pos() check_buttons(click_pos) draw_screen() pygame.display.update() pygame.time.delay(500) game_over() pygame.quit()
게임 설명
게임 방법은 기존 게임과 비슷하다.
임의로 떨어지는 블럭을 좌우 이동 및 회전을 통해 쌓고 한 줄을 모두 채우면 그 줄이 사라진다. 꼭대기에 블럭이 닿지 않도록 하면서 최대한 빠르고 많은 블럭을 쌓을수록 점수가 높아진다. 점수를 많이 얻는 것이 목적인 게임이다.
이 게임의 키보드 설정은 다음과 같다.
방향키 오른쪽/왼쪽은 떨어지는 블럭을 좌/우로 움직여주고, 방향키 아래쪽은 블럭의 떨어지는 속도를 빠르게 해준다. 방향키 위쪽은 떨어지는 블럭을 회전시켜준다. 스페이스는 블럭을 현재 블럭이 내려갈 수 있는 만큼 내려가도록 해준다.
C는 현재 블럭을 홀드해준다.
코드 설명 및 실행
게임 실행 화면 처음 실행하게 되면 이와 같은 창이 실행이 된다.
창의 이름은 TETRIS로 설정하였다.
SCORE에서 점수를 보여준다.
SCORE 글씨의 색은 현재 블럭의 색이라는 이스터에그(?)도 있다.점수의 색은 반복적으로 변화하고, 콤보 시 "Combo X (콤보수)"라는 텍스트를 띄울 수 있다.
점수가 오르는 만큼 텍스트를 띄워주는 기능을 추가해볼 것이다.
홀드 기능 Hold Block에서는 현재 홀드한 블럭을 볼 수 있다.
한 번 홀드를 하면 현재 블럭을 쌓기 전까지는 다시 홀드를 하지 못한다. (기존 테트리스 규칙)
Hold Block 글씨 색은 홀드한 블럭의 색이라는 이스터에그(?)도 있다.Next Block에서는 다음으로 나올 블럭 3개를 볼 수 있다.
Next Block 글씨 색은 바로 다음 블럭의 색이라는 이스터에그(?)도 있다. (이쯤 되면 이스터에그가 아니라는 생각도 든다.)Block Mode의 네 개의 버튼을 클릭하면 현재 블럭의 모습을 다음과 같이 바꿀 수 있다.
블럭 모드 2 블럭 모드 3 블럭 모드 4 블럭 모드를 바꾸면 지금까지 쌓았던 블럭, 쌓을 블럭, 블럭 테투리, 홀드 블럭, 다음 블럭 등 모든 블럭의 모양이 바뀐다.
느낀점 및 개선 방향
<앞으로 더 추가하고 싶은 기능들>
1. 점수 증가 텍스트
2. 게임창 기본 그림 테트리스로 설정
<수정해야 할 버그들>
1. 아래 블럭 뚫림 현상(내려가는 시간과 블럭의 모양이 변화하는 시간이 겹칠 때 생기는 것으로 추정)
2. 떨어질 떄 회전 시 내려가는 시간 늘어남(처리 속도 및 시간으로 추정)
3. can_under_size에 아무 것도 들어가지 않는 현상(이유 모름)
아직 수정해야 할 버그도 있고, 추가해야 할 점도 많은 코드이다...
그래도 여러 자료를 찾아보면서 따라 만들던 이전과는 달리 처음으로 아무 자료도 찾아보지 않고 처음부터 알고리즘부터 코딩까지 모두 나 혼자 스스로 게임을 만들었다는 것이 뿌듯하고, 자랑스러웠다. 이를 계기로 코딩에 더 재미를 붙일 수 있게 된 것 같았다.
앞으로 수정하고, 보안하면서 더 나은 테트리스 게임을 만들어 볼 것이다. 또한 더 다양한 게임을 만들 것이고, 게임 뿐만 아니라 다른 분야의 코딩들도 해볼 것이다.