competitive_tetris.py 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. #!/usr/bin/python3
  2. """
  3. Competitive tetris server
  4. """
  5. import random
  6. import pygame
  7. pygame.font.init()
  8. # GLOBALS VARS
  9. S_WIDTH = 800
  10. S_HEIGHT = 700
  11. PLAY_WIDTH = 300 # meaning 300 // 10 = 30 width per block
  12. PLAY_HEIGHT = 600 # meaning 600 // 20 = 30 height per block
  13. BLOCK_SIZE = 30
  14. TOP_LEFT_X = (S_WIDTH - PLAY_WIDTH) // 2
  15. TOP_LEFT_Y = S_HEIGHT - PLAY_HEIGHT
  16. # SHAPE FORMATS
  17. S = [['.....',
  18. '.....',
  19. '..00.',
  20. '.00..',
  21. '.....'],
  22. ['.....',
  23. '..0..',
  24. '..00.',
  25. '...0.',
  26. '.....']]
  27. Z = [['.....',
  28. '.....',
  29. '.00..',
  30. '..00.',
  31. '.....'],
  32. ['.....',
  33. '..0..',
  34. '.00..',
  35. '.0...',
  36. '.....']]
  37. I = [['..0..',
  38. '..0..',
  39. '..0..',
  40. '..0..',
  41. '.....'],
  42. ['.....',
  43. '0000.',
  44. '.....',
  45. '.....',
  46. '.....']]
  47. O = [['.....',
  48. '.....',
  49. '.00..',
  50. '.00..',
  51. '.....']]
  52. J = [['.....',
  53. '.0...',
  54. '.000.',
  55. '.....',
  56. '.....'],
  57. ['.....',
  58. '..00.',
  59. '..0..',
  60. '..0..',
  61. '.....'],
  62. ['.....',
  63. '.....',
  64. '.000.',
  65. '...0.',
  66. '.....'],
  67. ['.....',
  68. '..0..',
  69. '..0..',
  70. '.00..',
  71. '.....']]
  72. L = [['.....',
  73. '...0.',
  74. '.000.',
  75. '.....',
  76. '.....'],
  77. ['.....',
  78. '..0..',
  79. '..0..',
  80. '..00.',
  81. '.....'],
  82. ['.....',
  83. '.....',
  84. '.000.',
  85. '.0...',
  86. '.....'],
  87. ['.....',
  88. '.00..',
  89. '..0..',
  90. '..0..',
  91. '.....']]
  92. T = [['.....',
  93. '..0..',
  94. '.000.',
  95. '.....',
  96. '.....'],
  97. ['.....',
  98. '..0..',
  99. '..00.',
  100. '..0..',
  101. '.....'],
  102. ['.....',
  103. '.....',
  104. '.000.',
  105. '..0..',
  106. '.....'],
  107. ['.....',
  108. '..0..',
  109. '.00..',
  110. '..0..',
  111. '.....']]
  112. SHAPES = [S, Z, I, O, J, L, T]
  113. SHAPE_COLORS = [(0, 255, 0), (255, 0, 0), (0, 255, 255), (255, 255, 0),
  114. (255, 165, 0), (0, 0, 255), (128, 0, 128)]
  115. # index 0 - 6 represent shape
  116. class Piece:
  117. def __init__(self, x, y, shape):
  118. self.x = x
  119. self.y = y
  120. self.shape = shape
  121. self.color = SHAPE_COLORS[SHAPES.index(shape)]
  122. self.rotation = 0
  123. def create_grid(locked_pos={}):
  124. grid = [[(0,0,0) for _ in range(10)] for _ in range(20)]
  125. for i in range(len(grid)):
  126. for j in range(len(grid[i])):
  127. if (j, i) in locked_pos:
  128. c = locked_pos[(j,i)]
  129. grid[i][j] = c
  130. return grid
  131. def convert_shape_format(shape):
  132. positions = []
  133. format = shape.shape[shape.rotation % len(shape.shape)]
  134. for i, line in enumerate(format):
  135. row = list(line)
  136. for j, column in enumerate(row):
  137. if column == '0':
  138. positions.append((shape.x + j, shape.y + i))
  139. for i, pos in enumerate(positions):
  140. positions[i] = (pos[0] - 2, pos[1] - 4)
  141. return positions
  142. def valid_space(shape, grid):
  143. accepted_pos = [[(j, i) for j in range(10) if grid[i][j] == (0,0,0)] for i in range(20)]
  144. accepted_pos = [j for sub in accepted_pos for j in sub]
  145. formatted = convert_shape_format(shape)
  146. for pos in formatted:
  147. if pos not in accepted_pos:
  148. if pos[1] > -1:
  149. return False
  150. return True
  151. def check_lost(positions):
  152. for pos in positions:
  153. x, y = pos
  154. if y < 1:
  155. return True
  156. return False
  157. def get_shape():
  158. return Piece(5, 0, random.choice(SHAPES))
  159. def draw_text_middle(surface, text, size, color):
  160. font = pygame.font.SysFont("comicsans", size, bold=True)
  161. label = font.render(text, 1, color)
  162. surface.blit(label, (TOP_LEFT_X + PLAY_WIDTH /2 - (label.get_width()/2), TOP_LEFT_Y + PLAY_HEIGHT/2 - label.get_height()/2))
  163. def draw_grid(surface, grid):
  164. sx = TOP_LEFT_X
  165. sy = TOP_LEFT_Y
  166. for i in range(len(grid)):
  167. pygame.draw.line(surface, (128,128,128), (sx, sy + i*BLOCK_SIZE), (sx+PLAY_WIDTH, sy+ i*BLOCK_SIZE))
  168. for j in range(len(grid[i])):
  169. pygame.draw.line(surface, (128, 128, 128), (sx + j*BLOCK_SIZE, sy),(sx + j*BLOCK_SIZE, sy + PLAY_HEIGHT))
  170. def clear_rows(grid, locked):
  171. inc = 0
  172. for i in range(len(grid)-1, -1, -1):
  173. row = grid[i]
  174. if (0,0,0) not in row:
  175. inc += 1
  176. ind = i
  177. for j in range(len(row)):
  178. try:
  179. del locked[(j,i)]
  180. except:
  181. continue
  182. if inc > 0:
  183. for key in sorted(list(locked), key=lambda x: x[1])[::-1]:
  184. x, y = key
  185. if y < ind:
  186. newKey = (x, y + inc)
  187. locked[newKey] = locked.pop(key)
  188. return inc
  189. def draw_next_shape(shape, surface):
  190. font = pygame.font.SysFont('comicsans', 30)
  191. label = font.render('Next Shape', 1, (255,255,255))
  192. sx = TOP_LEFT_X + PLAY_WIDTH + 50
  193. sy = TOP_LEFT_Y + PLAY_HEIGHT/2 - 100
  194. format = shape.shape[shape.rotation % len(shape.shape)]
  195. for i, line in enumerate(format):
  196. row = list(line)
  197. for j, column in enumerate(row):
  198. if column == '0':
  199. pygame.draw.rect(surface, shape.color, (sx + j*BLOCK_SIZE, sy + i*BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE), 0)
  200. surface.blit(label, (sx + 10, sy - 30))
  201. def update_score(nscore):
  202. score = max_score()
  203. with open('scores.txt', 'w') as f:
  204. if int(score) > nscore:
  205. f.write(str(score))
  206. else:
  207. f.write(str(nscore))
  208. def max_score():
  209. with open('scores.txt', 'r') as f:
  210. lines = f.readlines()
  211. score = lines[0].strip()
  212. return score
  213. def draw_window(surface, grid, score=0, last_score = 0):
  214. surface.fill((0, 0, 0))
  215. pygame.font.init()
  216. font = pygame.font.SysFont('comicsans', 60)
  217. label = font.render('Tetris', 1, (255, 255, 255))
  218. surface.blit(label, (TOP_LEFT_X + PLAY_WIDTH / 2 - (label.get_width() / 2), 30))
  219. # current score
  220. font = pygame.font.SysFont('comicsans', 30)
  221. label = font.render('Score: ' + str(score), 1, (255,255,255))
  222. sx = TOP_LEFT_X + PLAY_WIDTH + 50
  223. sy = TOP_LEFT_Y + PLAY_HEIGHT/2 - 100
  224. surface.blit(label, (sx + 20, sy + 160))
  225. # last score
  226. label = font.render('High Score: ' + last_score, 1, (255,255,255))
  227. sx = TOP_LEFT_X - 200
  228. sy = TOP_LEFT_Y + 200
  229. surface.blit(label, (sx + 20, sy + 160))
  230. for i in range(len(grid)):
  231. for j in range(len(grid[i])):
  232. pygame.draw.rect(surface, grid[i][j], (TOP_LEFT_X + j*BLOCK_SIZE, TOP_LEFT_Y + i*BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE), 0)
  233. pygame.draw.rect(surface, (255, 0, 0), (TOP_LEFT_X, TOP_LEFT_Y, PLAY_WIDTH, PLAY_HEIGHT), 5)
  234. draw_grid(surface, grid)
  235. #pygame.display.update()
  236. def main(win): # *
  237. last_score = max_score()
  238. locked_positions = {}
  239. grid = create_grid(locked_positions)
  240. change_piece = False
  241. run = True
  242. current_piece = get_shape()
  243. next_piece = get_shape()
  244. clock = pygame.time.Clock()
  245. fall_time = 0
  246. fall_speed = 0.27
  247. level_time = 0
  248. score = 0
  249. while run:
  250. grid = create_grid(locked_positions)
  251. fall_time += clock.get_rawtime()
  252. level_time += clock.get_rawtime()
  253. clock.tick()
  254. if level_time/1000 > 5:
  255. level_time = 0
  256. if level_time > 0.12:
  257. level_time -= 0.005
  258. if fall_time/1000 > fall_speed:
  259. fall_time = 0
  260. current_piece.y += 1
  261. if not(valid_space(current_piece, grid)) and current_piece.y > 0:
  262. current_piece.y -= 1
  263. change_piece = True
  264. for event in pygame.event.get():
  265. if event.type == pygame.QUIT:
  266. run = False
  267. pygame.display.quit()
  268. if event.type == pygame.KEYDOWN:
  269. if event.key == pygame.K_LEFT:
  270. current_piece.x -= 1
  271. if not(valid_space(current_piece, grid)):
  272. current_piece.x += 1
  273. if event.key == pygame.K_RIGHT:
  274. current_piece.x += 1
  275. if not(valid_space(current_piece, grid)):
  276. current_piece.x -= 1
  277. if event.key == pygame.K_DOWN:
  278. current_piece.y += 1
  279. if not(valid_space(current_piece, grid)):
  280. current_piece.y -= 1
  281. if event.key == pygame.K_UP:
  282. current_piece.rotation += 1
  283. if not(valid_space(current_piece, grid)):
  284. current_piece.rotation -= 1
  285. shape_pos = convert_shape_format(current_piece)
  286. for i in range(len(shape_pos)):
  287. x, y = shape_pos[i]
  288. if y > -1:
  289. grid[y][x] = current_piece.color
  290. if change_piece:
  291. for pos in shape_pos:
  292. p = (pos[0], pos[1])
  293. locked_positions[p] = current_piece.color
  294. current_piece = next_piece
  295. next_piece = get_shape()
  296. change_piece = False
  297. score += clear_rows(grid, locked_positions) * 10
  298. draw_window(win, grid, score, last_score)
  299. draw_next_shape(next_piece, win)
  300. pygame.display.update()
  301. if check_lost(locked_positions):
  302. draw_text_middle(win, "YOU LOST!", 80, (255,255,255))
  303. pygame.display.update()
  304. pygame.time.delay(1500)
  305. run = False
  306. update_score(score)
  307. def main_menu(win): # *
  308. run = True
  309. while run:
  310. win.fill((0,0,0))
  311. draw_text_middle(win, 'Press Any Key To Play', 60, (255,255,255))
  312. pygame.display.update()
  313. for event in pygame.event.get():
  314. if event.type == pygame.QUIT:
  315. run = False
  316. if event.type == pygame.KEYDOWN:
  317. main(win)
  318. pygame.display.quit()
  319. win = pygame.display.set_mode((S_WIDTH, S_HEIGHT))
  320. pygame.display.set_caption('Tetris')
  321. main_menu(win)