Git hub에는 많은 오픈 소스코드가 있다. 그래서 이 소스코드들을 잘 활용하는 것도 중요하다. 나는 예전에는 아무것도 없는 상태에서 내가 전부 창조해야겠다고 생각을 했었는데, 그렇게 하니까 걱정과 부담만 늘어나고 아무것도 되지 않더라. 특히 프로그래밍 분야에 있어서는 다른 사람이 만든 라이브러리나 모듈, 코드들을 잘 갖다가 쓰는게 중요하다고 한다.
내 주변에는 정말 뛰어난 사람들이 많다. 이름만 대면 알만한 대학에서 석박사를 하는 사람이 주변에 널렸고 (심지어 편의점에서 만나는 사람도 박사님이라는) 대학생 때 SCI급 논문을 쓰는 사람도 있고, 자신만의 게임을 개발해서 펀드도 받고 스팀에 출시하고 회사랑 계약한 친구도 있다.
이번에 포공 석사에 들어간 친구에게, "어떻게 잘해?"라고 물어봤을 때, 자기는 프로젝트를 할 때 먼저 기존에 있던 자료들을 가져와서 분석하는 작업부터 한다고 했다. 소스코드를 이해하고, 이것을 어떻게 발전시켜갈지에 대해 생각해본다고.. 그러자 옆에 있던 다른 박사 선배가 연구도 똑같다면서 대답을 했다. 연구도, 먼저 맨땅에 하는게 아니라 그 분야의 논문을 읽으면서 현재 어디까지 발전이 되었는지 파악한다고 한다. 그리고나서, 앞으로 어떻게 발전시킬 수 있을지 아이디어를 떠올리고 실행해보는 것이라고..
창조는 모방으로부터 시작한다는 것. (물론 항상 그런건 아니지만) 세상에 완전 새로운 것부터 시작하는 사람은 흔치 않다는 것을 생각해보았다. 심지어 AI도 뭔가 성과를 내려면, 학습 데이터 자료가 필요하지 않나. 또, 그러라고 객체지향 프로그래밍을 만든 것 같기도 하고. 천재들이 이미 잘 짜놓은 함수와 라이브러리를 잘 조합해서 결과물을 만들 수 있으니까. 예를 들어, 테이블을 만든다고 가정할때, 다른 사람들이 잘 만들어놓은 합판과 다리를 조합해서 잇기만 하면 되니까.
결론은 ㅋㅋ 먼저 다른 사람이 어떻게 코드를 작성했나. 구경해보자는 것이다 !
파이썬 테트리스 오픈소스 코드를 가져와봤다. (공유해주신 분 넘나 감사합니다)
1. 우선 아래 소스코드를 복사해줍니다
silvasur님 코드
https://gist.github.com/silvasur/565419/45a3ded61b993d1dd195a8a8688e7dc196b08de8
#!/usr/bin/env python3
#-*- 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
# Return - Instant drop
#
# Have fun!
# NOTE: If you're looking for the old python2 version, see
# <https://gist.github.com/silvasur/565419/45a3ded61b993d1dd195a8a8688e7dc196b08de8>
# Copyright (c) 2010 "Laria Carolin Chabowski"<me@laria.me>
#
# 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
cell_size = 18
cols = 10
rows = 22
maxfps = 30
colors = [
(0, 0, 0 ),
(255, 85, 85),
(100, 200, 115),
(120, 108, 245),
(255, 140, 50 ),
(50, 120, 52 ),
(146, 202, 73 ),
(150, 161, 218 ),
(35, 35, 35) # Helper color for background grid
]
# 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 range(len(shape)) ]
for x in range(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 range(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 range(cols) ]
for y in range(rows)
]
board += [[ 1 for x in range(cols)]]
return board
class TetrisApp(object):
def __init__(self):
pygame.init()
pygame.key.set_repeat(250,25)
self.width = cell_size*(cols+6)
self.height = cell_size*rows
self.rlim = cell_size*cols
self.bground_grid = [[ 8 if x%2==y%2 else 0 for x in range(cols)] for y in range(rows)]
self.default_font = pygame.font.Font(
pygame.font.get_default_font(), 12)
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.next_stone = tetris_shapes[rand(len(tetris_shapes))]
self.init_game()
def new_stone(self):
self.stone = self.next_stone[:]
self.next_stone = tetris_shapes[rand(len(tetris_shapes))]
self.stone_x = int(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()
self.level = 1
self.score = 0
self.lines = 0
pygame.time.set_timer(pygame.USEREVENT+1, 1000)
def disp_msg(self, msg, topleft):
x,y = topleft
for line in msg.splitlines():
self.screen.blit(
self.default_font.render(
line,
False,
(255,255,255),
(0,0,0)),
(x,y))
y+=14
def center_msg(self, msg):
for i, line in enumerate(msg.splitlines()):
msg_image = self.default_font.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) *
cell_size,
(off_y+y) *
cell_size,
cell_size,
cell_size),0)
def add_cl_lines(self, n):
linescores = [0, 40, 100, 300, 1200]
self.lines += n
self.score += linescores[n] * self.level
if self.lines >= self.level*6:
self.level += 1
newdelay = 1000-50*(self.level-1)
newdelay = 100 if newdelay < 100 else newdelay
pygame.time.set_timer(pygame.USEREVENT+1, newdelay)
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 > cols - len(self.stone[0]):
new_x = 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, manual):
if not self.gameover and not self.paused:
self.score += 1 if manual else 0
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()
cleared_rows = 0
while True:
for i, row in enumerate(self.board[:-1]):
if 0 not in row:
self.board = remove_row(
self.board, i)
cleared_rows += 1
break
else:
break
self.add_cl_lines(cleared_rows)
return True
return False
def insta_drop(self):
if not self.gameover and not self.paused:
while(not self.drop(True)):
pass
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': lambda:self.drop(True),
'UP': self.rotate_stone,
'p': self.toggle_pause,
'SPACE': self.start_game,
'RETURN': self.insta_drop
}
self.gameover = False
self.paused = False
dont_burn_my_cpu = pygame.time.Clock()
while 1:
self.screen.fill((0,0,0))
if self.gameover:
self.center_msg("""Game Over!\nYour score: %d
Press space to continue""" % self.score)
else:
if self.paused:
self.center_msg("Paused")
else:
pygame.draw.line(self.screen,
(255,255,255),
(self.rlim+1, 0),
(self.rlim+1, self.height-1))
self.disp_msg("Next:", (
self.rlim+cell_size,
2))
self.disp_msg("Score: %d\n\nLevel: %d\
\nLines: %d" % (self.score, self.level, self.lines),
(self.rlim+cell_size, cell_size*5))
self.draw_matrix(self.bground_grid, (0,0))
self.draw_matrix(self.board, (0,0))
self.draw_matrix(self.stone,
(self.stone_x, self.stone_y))
self.draw_matrix(self.next_stone,
(cols+1,2))
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.USEREVENT+1:
self.drop(False)
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(maxfps)
if __name__ == '__main__':
App = TetrisApp()
App.run()
2. 주피터 노트북에 복붙
그리고 실행 버튼을 누르면 왼쪽에 *이 뜨면서 실행이 됩니다.
3. 실행결과 아래와 같이 게임 플레이가 가능합니다.
키보드 ↑ 버튼을 누르면, 모양을 바꿀 수 있답니다.
'python으로 게임 만들기 > 테트리스' 카테고리의 다른 글
[테트리스] 5. 스켈레톤 코드 다운 및 실행 (0) | 2024.02.22 |
---|---|
[테트리스] 4. 참고할 자료 선정 _ 게임으로 배우는 파이썬 (0) | 2024.02.22 |
[테트리스] 3. 게임 설계 (0) | 2024.02.22 |
[테트리스] 1. 개발 환경 준비하기 (0) | 2024.02.22 |
[테트리스] 0. 동기 (0) | 2024.02.22 |