UI update

This commit is contained in:
dan63047 2021-05-24 22:56:33 +03:00
parent a0ce5c89cf
commit e291a01882
1 changed files with 243 additions and 271 deletions

View File

@ -4,8 +4,6 @@ import pygame, random, datetime
from string import Template from string import Template
BLOCK_SIZE = 30 BLOCK_SIZE = 30
FIELD_SIZE_X = 10
FIELD_SIZE_Y = 20
GUIDELINES = ["Current", "NES like"] GUIDELINES = ["Current", "NES like"]
@ -21,7 +19,39 @@ class Block:
return f"Block {self.color_str}" return f"Block {self.color_str}"
TETROMINOS = [ class DeltaTemplate(Template):
delimiter = "%"
def strfdelta(tdelta, fmt):
d = {"D": tdelta.days}
hours, rem = divmod(tdelta.seconds, 3600)
minutes, seconds = divmod(rem, 60)
hours += d["D"] * 24
d["S"] = '{:02d}'.format(seconds)
d["s"] = seconds
t = DeltaTemplate(fmt)
d["Z"] = '{:02d}'.format(int(tdelta.microseconds / 10000))
d["z"] = '{:1d}'.format(int(tdelta.microseconds / 100000))
d["H"] = hours
d["M"] = '{:02d}'.format(minutes)
d["m"] = minutes
return t.substitute(**d)
class TetrisGameplay:
def __init__(self, level=0, buffer_zone=20, srs=True, lock_delay=True, seven_bag=True, ghost_piece=True, hold=True, hard_drop=True, handling=(167, 33), nes_mechanics=False, next_len=3):
self.buffer_y = buffer_zone
self.FIELD = list(range(20 + buffer_zone))
y = 0
while y != len(self.FIELD):
self.FIELD[y] = list(range(10))
x = 0
while x != 10:
self.FIELD[y][x] = None
x += 1
y += 1
self.TETROMINOS = [
[ [
[ [
[None, None, Block((240, 160, 0)), None], [None, None, Block((240, 160, 0)), None],
@ -189,41 +219,7 @@ TETROMINOS = [
[None, None, None, None] [None, None, None, None]
] ]
] # 6, O ] # 6, O
] ]
class DeltaTemplate(Template):
delimiter = "%"
def strfdelta(tdelta, fmt):
d = {"D": tdelta.days}
hours, rem = divmod(tdelta.seconds, 3600)
minutes, seconds = divmod(rem, 60)
hours += d["D"] * 24
d["S"] = '{:02d}'.format(seconds)
d["s"] = seconds
t = DeltaTemplate(fmt)
d["Z"] = '{:02d}'.format(int(tdelta.microseconds / 10000))
d["z"] = '{:1d}'.format(int(tdelta.microseconds / 100000))
d["H"] = hours
d["M"] = '{:02d}'.format(minutes)
d["m"] = minutes
return t.substitute(**d)
class TetrisGameplay:
def __init__(self, size_x=FIELD_SIZE_X, size_y=FIELD_SIZE_Y, level=0, buffer_zone=20, srs=True, lock_delay=True, seven_bag=True, ghost_piece=True, hold=True, hard_drop=True, handling=(167, 33), nes_mechanics=False, next_len=3):
self.buffer_y = buffer_zone
self.FIELD = list(range(size_y + buffer_zone))
y = 0
while y != len(self.FIELD):
self.FIELD[y] = list(range(size_x))
x = 0
while x != size_x:
self.FIELD[y][x] = None
x += 1
y += 1
self.current_posx = 4 self.current_posx = 4
self.current_posy = self.buffer_y - 2 self.current_posy = self.buffer_y - 2
self.can_hard_drop = hard_drop self.can_hard_drop = hard_drop
@ -256,7 +252,7 @@ class TetrisGameplay:
] ]
self.score_up = 0 self.score_up = 0
self.for_what_id = 0 self.for_what_id = 0
self.for_what_score = ["SINGLE", "DOUBLE", "TRIPLE", "QUAD", "T-SPIN MINI 0L", "T-SPIN MINI 1L", "T-SPIN MINI 2L", "T-SPIN 0L", "T-SPIN 1L", "T-SPIN 2L", "T-SPIN 3L"] self.for_what_score = ["SINGLE", "DOUBLE", "TRIPLE", "QUAD", "T-SPIN MINI", "T-SPIN MINI SINGLE", "T-SPIN MINI DOUBLE", "T-SPIN", "T-SPIN SINGLE", "T-SPIN DOUBLE", "T-SPIN TRIPLE"]
self.for_what_delay = 0 self.for_what_delay = 0
self.cleared_lines = [ self.cleared_lines = [
0, # Single 0, # Single
@ -368,12 +364,12 @@ class TetrisGameplay:
for k in i: for k in i:
if k is not None: if k is not None:
ic += 1 ic += 1
if ic == FIELD_SIZE_X: if ic == 10:
cleared += 1 cleared += 1
self.FIELD.remove(i) self.FIELD.remove(i)
new = list(range(FIELD_SIZE_X)) new = list(range(10))
x = 0 x = 0
while x != FIELD_SIZE_X: while x != 10:
new[x] = None new[x] = None
x += 1 x += 1
self.FIELD.insert(0, new) self.FIELD.insert(0, new)
@ -458,7 +454,7 @@ class TetrisGameplay:
def collision(self, next_posx, next_posy, next_id, next_spin_id): def collision(self, next_posx, next_posy, next_id, next_spin_id):
i1 = next_posy i1 = next_posy
k1 = next_posx k1 = next_posx
for i in TETROMINOS[next_id][next_spin_id]: for i in self.TETROMINOS[next_id][next_spin_id]:
for k in i: for k in i:
if k and (i1 >= len(self.FIELD) or k1 >= len(self.FIELD[i1]) or i1 < 0 or k1 < 0 or self.FIELD[i1][k1]): if k and (i1 >= len(self.FIELD) or k1 >= len(self.FIELD[i1]) or i1 < 0 or k1 < 0 or self.FIELD[i1][k1]):
return True return True
@ -681,7 +677,7 @@ class TetrisGameplay:
i1 = self.current_posy i1 = self.current_posy
k1 = self.current_posx k1 = self.current_posx
if self.current_id is not None: if self.current_id is not None:
for i in TETROMINOS[self.current_id][self.current_spin_id]: for i in self.TETROMINOS[self.current_id][self.current_spin_id]:
for k in i: for k in i:
if k: if k:
self.FIELD[i1][k1] = k self.FIELD[i1][k1] = k
@ -721,12 +717,12 @@ class TetrisGameplay:
def draw_game(self): def draw_game(self):
win.fill((25, 25, 25)) win.fill((25, 25, 25))
pygame.draw.rect(win, (0, 0, 0), pygame.draw.rect(win, (0, 0, 0),
(5, (BLOCK_SIZE * 2 + 5), BLOCK_SIZE * FIELD_SIZE_X, BLOCK_SIZE * FIELD_SIZE_Y)) (130, (BLOCK_SIZE * 2 + 5), BLOCK_SIZE * 10, BLOCK_SIZE * 20))
x = 0 x = 0
y = -self.buffer_y y = -self.buffer_y
for i in self.FIELD: for i in self.FIELD:
for k in i: for k in i:
window_x = 5 + BLOCK_SIZE * x window_x = 130 + BLOCK_SIZE * x
window_y = (BLOCK_SIZE * 2 + 5) + BLOCK_SIZE * y window_y = (BLOCK_SIZE * 2 + 5) + BLOCK_SIZE * y
if k is not None: if k is not None:
pygame.draw.rect(win, k.color, (window_x, window_y, BLOCK_SIZE, BLOCK_SIZE)) pygame.draw.rect(win, k.color, (window_x, window_y, BLOCK_SIZE, BLOCK_SIZE))
@ -739,10 +735,10 @@ class TetrisGameplay:
i1 = self.current_posy - self.buffer_y i1 = self.current_posy - self.buffer_y
k1 = self.current_posx k1 = self.current_posx
if self.current_id is not None: if self.current_id is not None:
for i in TETROMINOS[self.current_id][self.current_spin_id]: for i in self.TETROMINOS[self.current_id][self.current_spin_id]:
for k in i: for k in i:
if k is not None: if k is not None:
window_x = 5 + BLOCK_SIZE * k1 window_x = 130 + BLOCK_SIZE * k1
window_y = (BLOCK_SIZE * 2 + 5) + BLOCK_SIZE * i1 window_y = (BLOCK_SIZE * 2 + 5) + BLOCK_SIZE * i1
pygame.draw.rect(win, (int(k.color[0]*self.lock_delay_frames/30), int(k.color[1]*self.lock_delay_frames/30), int(k.color[2]*self.lock_delay_frames/30)), (window_x, window_y, BLOCK_SIZE, BLOCK_SIZE)) pygame.draw.rect(win, (int(k.color[0]*self.lock_delay_frames/30), int(k.color[1]*self.lock_delay_frames/30), int(k.color[2]*self.lock_delay_frames/30)), (window_x, window_y, BLOCK_SIZE, BLOCK_SIZE))
pygame.draw.rect(win, (0, 0, 0), (window_x, window_y, BLOCK_SIZE, BLOCK_SIZE), width=2) pygame.draw.rect(win, (0, 0, 0), (window_x, window_y, BLOCK_SIZE, BLOCK_SIZE), width=2)
@ -752,10 +748,10 @@ class TetrisGameplay:
if self.support_ghost_piece: if self.support_ghost_piece:
i1 = self.ghost_piece_y() - self.buffer_y i1 = self.ghost_piece_y() - self.buffer_y
k1 = self.current_posx k1 = self.current_posx
for i in TETROMINOS[self.current_id][self.current_spin_id]: for i in self.TETROMINOS[self.current_id][self.current_spin_id]:
for k in i: for k in i:
if k is not None: if k is not None:
window_x = 5 + BLOCK_SIZE * k1 window_x = 130 + BLOCK_SIZE * k1
window_y = (BLOCK_SIZE * 2 + 5) + BLOCK_SIZE * i1 window_y = (BLOCK_SIZE * 2 + 5) + BLOCK_SIZE * i1
pygame.draw.rect(win, (k.color[0], k.color[1], k.color[2]), (window_x+5, window_y+5, BLOCK_SIZE-10, BLOCK_SIZE-10), width=10, border_radius=1) pygame.draw.rect(win, (k.color[0], k.color[1], k.color[2]), (window_x+5, window_y+5, BLOCK_SIZE-10, BLOCK_SIZE-10), width=10, border_radius=1)
k1 += 1 k1 += 1
@ -765,10 +761,10 @@ class TetrisGameplay:
for q in range(0, self.next_length): for q in range(0, self.next_length):
i1 = 0 i1 = 0
k1 = 0 k1 = 0
for i in TETROMINOS[self.next_queue[q]][0]: for i in self.TETROMINOS[self.next_queue[q]][0]:
for k in i: for k in i:
if k is not None: if k is not None:
window_x = 5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + 10 * k1 + x_offset window_x = 470 + 10 * k1 + x_offset
window_y = (BLOCK_SIZE * 2 + 30) + 10 * i1 window_y = (BLOCK_SIZE * 2 + 30) + 10 * i1
pygame.draw.rect(win, k.color, (window_x, window_y, 10, 10)) pygame.draw.rect(win, k.color, (window_x, window_y, 10, 10))
pygame.draw.rect(win, (0, 0, 0), (window_x, window_y, 10, 10), width=1) pygame.draw.rect(win, (0, 0, 0), (window_x, window_y, 10, 10), width=1)
@ -780,78 +776,53 @@ class TetrisGameplay:
if self.hold_id is not None: if self.hold_id is not None:
i1 = 0 i1 = 0
k1 = 0 k1 = 0
for i in TETROMINOS[self.hold_id][0]: for i in self.TETROMINOS[self.hold_id][0]:
for k in i: for k in i:
if k is not None: if k is not None:
window_x = 5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + 10 * k1 window_x = 90 + 10 * k1
window_y = (BLOCK_SIZE * 2 + 75) + 10 * i1 window_y = (BLOCK_SIZE * 2 + 30) + 10 * i1
pygame.draw.rect(win, k.color, (window_x, window_y, 10, 10)) pygame.draw.rect(win, k.color, (window_x, window_y, 10, 10))
pygame.draw.rect(win, (0, 0, 0), (window_x, window_y, 10, 10), width=1) pygame.draw.rect(win, (0, 0, 0), (window_x, window_y, 10, 10), width=1)
k1 += 1 k1 += 1
k1 = 0 k1 = 0
i1 += 1 i1 += 1
win.blit(FONT.render("SCORE", 1, (255, 255, 255)), win.blit(MEDIUM_FONT.render("SCORE", 1, (255, 255, 255)), (440, 562))
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 25 + BLOCK_SIZE * 7)) win.blit(MEDIUM_FONT.render(f"{sum(self.score):5d}", 1, (255, 255, 255)), (440, 582))
total_score = sum(self.score) win.blit(MEDIUM_FONT.render("LINES", 1, (255, 255, 255)), (440, 622))
win.blit(FONT.render(f"{total_score:06d}", 1, (255, 255, 255)), win.blit(MEDIUM_FONT.render(f"{sum(self.cleared_lines):5d}", 1, (255, 255, 255)), (440, 642))
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 50 + BLOCK_SIZE * 7)) win.blit(MEDIUM_FONT.render("LV", 1, (255, 255, 255)), (80, 502))
win.blit(FONT.render("LINES", 1, (255, 255, 255)), win.blit(MEDIUM_FONT.render(f"{self.level:02d}", 1, (255, 255, 255)), (80, 522))
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 90 + BLOCK_SIZE * 7)) win.blit(MEDIUM_FONT.render("PPS", 1, (255, 255, 255)), (60, 562))
total_lines = sum(self.cleared_lines)
win.blit(FONT.render(f"{total_lines:03d}", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 115 + BLOCK_SIZE * 7))
win.blit(FONT.render("LV", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 155 + BLOCK_SIZE * 7))
win.blit(FONT.render(f"{self.level:02d}", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 180 + BLOCK_SIZE * 7))
try: try:
pps = sum(self.pieces) / self.game_time pps = sum(self.pieces) / self.game_time
except ZeroDivisionError: except ZeroDivisionError:
pps = 0 pps = 0
win.blit(FONT.render("PPS", 1, (255, 255, 255)), win.blit(MEDIUM_FONT.render(f"{pps:6.2f}", 1, (255, 255, 255)), (0, 582))
(5 + BLOCK_SIZE * FIELD_SIZE_X + 120 + BLOCK_SIZE * k1, 155 + BLOCK_SIZE * 7)) win.blit(MEDIUM_FONT.render("TIME", 1, (255, 255, 255)), (40, 622))
if pps >= 1: win.blit(MEDIUM_FONT.render(f"{strfdelta(datetime.timedelta(seconds=self.game_time), '%m:%S'):>6s}", 1, (255, 255, 255)), (0, 642))
win.blit(FONT.render(f"{pps:1.1f}", 1, (255, 255, 255)), if self.for_what_delay > 0.1:
(5 + BLOCK_SIZE * FIELD_SIZE_X + 120 + BLOCK_SIZE * k1, 180 + BLOCK_SIZE * 7))
else:
win.blit(FONT.render(f".{int(pps*100):02d}", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 120 + BLOCK_SIZE * k1, 180 + BLOCK_SIZE * 7))
win.blit(FONT.render("TIME", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 220 + BLOCK_SIZE * 7))
if self.game_time < 10:
win.blit(FONT.render(strfdelta(datetime.timedelta(seconds=self.game_time), '%s.%Z'), 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 245 + BLOCK_SIZE * 7))
elif self.game_time < 60:
win.blit(FONT.render(strfdelta(datetime.timedelta(seconds=self.game_time), '%S.%z'), 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 245 + BLOCK_SIZE * 7))
elif self.game_time < 3600:
win.blit(FONT.render(strfdelta(datetime.timedelta(seconds=self.game_time), '%m:%S'), 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 245 + BLOCK_SIZE * 7))
else:
win.blit(FONT.render(strfdelta(datetime.timedelta(seconds=self.game_time), '%H:%M:%S'), 1, (255, 255, 255)), (5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 245 + BLOCK_SIZE * 7))
if self.score_up > 0:
win.blit(FONT.render(self.for_what_score[self.for_what_id], 1, (230*(min(self.for_what_delay, 1))+25, 230*(min(self.for_what_delay, 1))+25, 230*(min(self.for_what_delay, 1))+25)), win.blit(FONT.render(self.for_what_score[self.for_what_id], 1, (230*(min(self.for_what_delay, 1))+25, 230*(min(self.for_what_delay, 1))+25, 230*(min(self.for_what_delay, 1))+25)),
(5, 5 + BLOCK_SIZE * (FIELD_SIZE_Y+2) + 5)) (120, 670))
win.blit( win.blit(
FONT.render(f"+{self.score_up}", 1, (230*(min(self.for_what_delay, 1))+25, 230*(min(self.for_what_delay, 1))+25, 230*(min(self.for_what_delay, 1))+25)), FONT.render(f"+{self.score_up}", 1, (230*(min(self.for_what_delay, 1))+25, 230*(min(self.for_what_delay, 1))+25, 230*(min(self.for_what_delay, 1))+25)),
(5, 5 + BLOCK_SIZE * (FIELD_SIZE_Y+2) + 30)) (120, 695))
if self.combo > 0: if self.combo > 0:
win.blit( win.blit(
FONT.render(f"COMBO × {self.combo}", 1, ( FONT.render(f"COMBO × {self.combo}", 1, (
230 * (min(self.for_what_delay, 1)) + 25, 230 * (min(self.for_what_delay, 1)) + 25, 230 * (min(self.for_what_delay, 1)) + 25, 230 * (min(self.for_what_delay, 1)) + 25,
230 * (min(self.for_what_delay, 1)) + 25)), 230 * (min(self.for_what_delay, 1)) + 25)),
(5, 5 + BLOCK_SIZE * (FIELD_SIZE_Y + 2) + 55)) (120, 720))
if self.back_to_back > 0: if self.back_to_back > 0:
win.blit( win.blit(
FONT.render(f"BACK-TO-BACK × {self.back_to_back}", 1, ( FONT.render(f"BACK-TO-BACK × {self.back_to_back}", 1, (
230 * (min(self.for_what_delay, 1)) + 25, 230 * (min(self.for_what_delay, 1)) + 25, 230 * (min(self.for_what_delay, 1)) + 25, 230 * (min(self.for_what_delay, 1)) + 25,
230 * (min(self.for_what_delay, 1)) + 25)), 230 * (min(self.for_what_delay, 1)) + 25)),
(5, 5 + BLOCK_SIZE * (FIELD_SIZE_Y + 2) + 80)) (120, 745))
if self.game_over: if self.game_over:
text_size_x = FONT.size("GAME")[0] text_size_x = FONT.size("GAME")[0]
pygame.draw.rect(win, (0, 0, 0), (BLOCK_SIZE * (FIELD_SIZE_X / 2) - text_size_x, BLOCK_SIZE * FIELD_SIZE_Y / 2, text_size_x * 2 + 10, 60)) pygame.draw.rect(win, (0, 0, 0), (BLOCK_SIZE * (10 / 2) - text_size_x, BLOCK_SIZE * 20 / 2, text_size_x * 2 + 10, 60))
win.blit(FONT.render("GAME", 1, (255, 255, 255)), (5 + BLOCK_SIZE * FIELD_SIZE_X / 2 - text_size_x / 2, 5 + BLOCK_SIZE * FIELD_SIZE_Y / 2)) win.blit(FONT.render("GAME", 1, (255, 255, 255)), (5 + BLOCK_SIZE * 10 / 2 - text_size_x / 2, 5 + BLOCK_SIZE * 20 / 2))
win.blit(FONT.render("OVER", 1, (255, 255, 255)), (5 + BLOCK_SIZE * FIELD_SIZE_X / 2 - text_size_x / 2, 5 + BLOCK_SIZE * FIELD_SIZE_Y / 2 + 25)) win.blit(FONT.render("OVER", 1, (255, 255, 255)), (5 + BLOCK_SIZE * 10 / 2 - text_size_x / 2, 5 + BLOCK_SIZE * 20 / 2 + 25))
pygame.display.update() pygame.display.update()
def draw_game_stats(self, on_pause): def draw_game_stats(self, on_pause):
@ -886,7 +857,7 @@ class TetrisGameplay:
win.blit(SMALL_FONT.render(f"TRIPLE {triple_times:5d} {self.cleared_lines[2]:5d} T {self.pieces[4]:<4d} O {self.pieces[6]:<4d}", 1, (255, 255, 255)), win.blit(SMALL_FONT.render(f"TRIPLE {triple_times:5d} {self.cleared_lines[2]:5d} T {self.pieces[4]:<4d} O {self.pieces[6]:<4d}", 1, (255, 255, 255)),
(25, 340)) (25, 340))
tetris_times = int(self.cleared_lines[3] / 4) tetris_times = int(self.cleared_lines[3] / 4)
win.blit(SMALL_FONT.render(f"TETRIS {tetris_times:5d} {self.cleared_lines[3]:5d} I {self.pieces[5]:<10d}", 1, (255, 255, 255)), win.blit(SMALL_FONT.render(f"QUAD {tetris_times:7d} {self.cleared_lines[3]:5d} I {self.pieces[5]:<10d}", 1, (255, 255, 255)),
(25, 355)) (25, 355))
win.blit(SMALL_FONT.render(f"SCORE TABLE", 1, (255, 255, 255)), (25, 380)) win.blit(SMALL_FONT.render(f"SCORE TABLE", 1, (255, 255, 255)), (25, 380))
win.blit(SMALL_FONT.render(f"SOFT DROPS {self.score[0]:14d}", 1, (255, 255, 255)), (25, 400)) win.blit(SMALL_FONT.render(f"SOFT DROPS {self.score[0]:14d}", 1, (255, 255, 255)), (25, 400))
@ -894,7 +865,7 @@ class TetrisGameplay:
win.blit(SMALL_FONT.render(f"SINGLE {self.score[2]:18d}", 1, (255, 255, 255)), (25, 430)) win.blit(SMALL_FONT.render(f"SINGLE {self.score[2]:18d}", 1, (255, 255, 255)), (25, 430))
win.blit(SMALL_FONT.render(f"DOUBLE {self.score[3]:18d}", 1, (255, 255, 255)), (25, 445)) win.blit(SMALL_FONT.render(f"DOUBLE {self.score[3]:18d}", 1, (255, 255, 255)), (25, 445))
win.blit(SMALL_FONT.render(f"TRIPLE {self.score[4]:18d}", 1, (255, 255, 255)), (25, 460)) win.blit(SMALL_FONT.render(f"TRIPLE {self.score[4]:18d}", 1, (255, 255, 255)), (25, 460))
win.blit(SMALL_FONT.render(f"TETRIS {self.score[5]:18d}", 1, (255, 255, 255)), (25, 475)) win.blit(SMALL_FONT.render(f"QUAD {self.score[5]:20d}", 1, (255, 255, 255)), (25, 475))
win.blit(SMALL_FONT.render(f"T-SPIN MINI NO L. {self.score[6]:7d}", 1, (255, 255, 255)), (25, 490)) win.blit(SMALL_FONT.render(f"T-SPIN MINI NO L. {self.score[6]:7d}", 1, (255, 255, 255)), (25, 490))
win.blit(SMALL_FONT.render(f"T-SPIN MINI SINGLE {self.score[7]:6d}", 1, (255, 255, 255)), (25, 505)) win.blit(SMALL_FONT.render(f"T-SPIN MINI SINGLE {self.score[7]:6d}", 1, (255, 255, 255)), (25, 505))
win.blit(SMALL_FONT.render(f"T-SPIN MINI DOUBLE {self.score[8]:6d}", 1, (255, 255, 255)), (25, 520)) win.blit(SMALL_FONT.render(f"T-SPIN MINI DOUBLE {self.score[8]:6d}", 1, (255, 255, 255)), (25, 520))
@ -908,7 +879,7 @@ class TetrisGameplay:
class NesLikeTetris(TetrisGameplay): class NesLikeTetris(TetrisGameplay):
def __init__(self, size_x=FIELD_SIZE_X, size_y=FIELD_SIZE_Y, level=0): def __init__(self, size_x=10, size_y=20, level=0):
super().__init__(size_x, size_y, level, 2, False, False, False, False, False, False, (267, 100), True, 1) super().__init__(size_x, size_y, level, 2, False, False, False, False, False, False, (267, 100), True, 1)
def __str__(self): def __str__(self):
@ -975,12 +946,12 @@ class NesLikeTetris(TetrisGameplay):
for k in i: for k in i:
if k is not None: if k is not None:
ic += 1 ic += 1
if ic == FIELD_SIZE_X: if ic == 10:
cleared += 1 cleared += 1
self.FIELD.remove(i) self.FIELD.remove(i)
new = list(range(FIELD_SIZE_X)) new = list(range(10))
x = 0 x = 0
while x != FIELD_SIZE_X: while x != 10:
new[x] = None new[x] = None
x += 1 x += 1
self.FIELD.insert(0, new) self.FIELD.insert(0, new)
@ -1018,7 +989,7 @@ class NesLikeTetris(TetrisGameplay):
def draw_game(self): def draw_game(self):
win.fill((25, 25, 25)) win.fill((25, 25, 25))
pygame.draw.rect(win, (0, 0, 0), pygame.draw.rect(win, (0, 0, 0),
(5, (BLOCK_SIZE * 2 + 5), BLOCK_SIZE * FIELD_SIZE_X, BLOCK_SIZE * FIELD_SIZE_Y)) (5, (BLOCK_SIZE * 2 + 5), BLOCK_SIZE * 10, BLOCK_SIZE * 20))
x = 0 x = 0
y = -self.buffer_y y = -self.buffer_y
for i in self.FIELD: for i in self.FIELD:
@ -1034,7 +1005,7 @@ class NesLikeTetris(TetrisGameplay):
i1 = self.current_posy - self.buffer_y i1 = self.current_posy - self.buffer_y
k1 = self.current_posx k1 = self.current_posx
if self.current_id is not None: if self.current_id is not None:
for i in TETROMINOS[self.current_id][self.current_spin_id]: for i in self.TETROMINOS[self.current_id][self.current_spin_id]:
for k in i: for k in i:
if k is not None: if k is not None:
window_x = 5 + BLOCK_SIZE * k1 window_x = 5 + BLOCK_SIZE * k1
@ -1048,10 +1019,10 @@ class NesLikeTetris(TetrisGameplay):
for q in range(0, self.next_length): for q in range(0, self.next_length):
i1 = 0 i1 = 0
k1 = 0 k1 = 0
for i in TETROMINOS[self.next_queue[q]][0]: for i in self.TETROMINOS[self.next_queue[q]][0]:
for k in i: for k in i:
if k is not None: if k is not None:
window_x = 5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1 + x_offset window_x = 5 + BLOCK_SIZE * 10 + 20 + BLOCK_SIZE * k1 + x_offset
window_y = (BLOCK_SIZE * 2 + 30) + BLOCK_SIZE * i1 window_y = (BLOCK_SIZE * 2 + 30) + BLOCK_SIZE * i1
pygame.draw.rect(win, k.color, (window_x, window_y, BLOCK_SIZE, BLOCK_SIZE)) pygame.draw.rect(win, k.color, (window_x, window_y, BLOCK_SIZE, BLOCK_SIZE))
pygame.draw.rect(win, (0, 0, 0), (window_x, window_y, BLOCK_SIZE, BLOCK_SIZE), width=1) pygame.draw.rect(win, (0, 0, 0), (window_x, window_y, BLOCK_SIZE, BLOCK_SIZE), width=1)
@ -1063,70 +1034,70 @@ class NesLikeTetris(TetrisGameplay):
if self.hold_id is not None: if self.hold_id is not None:
i1 = 0 i1 = 0
k1 = 0 k1 = 0
for i in TETROMINOS[self.hold_id][0]: for i in self.TETROMINOS[self.hold_id][0]:
for k in i: for k in i:
if k is not None: if k is not None:
window_x = 5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + 10 * k1 window_x = 5 + BLOCK_SIZE * 10 + 20 + 10 * k1
window_y = (BLOCK_SIZE * 2 + 75) + 10 * i1 window_y = (BLOCK_SIZE * 2 + 75) + 10 * i1
pygame.draw.rect(win, k.color, (window_x, window_y, 10, 10)) pygame.draw.rect(win, k.color, (window_x, window_y, 10, 10))
pygame.draw.rect(win, (0, 0, 0), (window_x, window_y, 10, 10), width=1) pygame.draw.rect(win, (0, 0, 0), (window_x, window_y, 10, 10), width=1)
k1 += 1 k1 += 1
k1 = 0 k1 = 0
i1 += 1 i1 += 1
win.blit(FONT.render("SCORE", 1, (255, 255, 255)), win.blit(MEDIUM_FONT.render("SCORE", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 25 + BLOCK_SIZE * 7)) (5 + BLOCK_SIZE * 10 + 20 + BLOCK_SIZE * k1, 25 + BLOCK_SIZE * 7))
total_score = sum(self.score) total_score = sum(self.score)
win.blit(FONT.render(f"{total_score:06d}", 1, (255, 255, 255)), win.blit(FONT.render(f"{total_score:06d}", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 50 + BLOCK_SIZE * 7)) (5 + BLOCK_SIZE * 10 + 20 + BLOCK_SIZE * k1, 50 + BLOCK_SIZE * 7))
win.blit(FONT.render("LINES", 1, (255, 255, 255)), win.blit(FONT.render("LINES", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 90 + BLOCK_SIZE * 7)) (5 + BLOCK_SIZE * 10 + 20 + BLOCK_SIZE * k1, 90 + BLOCK_SIZE * 7))
total_lines = sum(self.cleared_lines) total_lines = sum(self.cleared_lines)
win.blit(FONT.render(f"{total_lines:03d}", 1, (255, 255, 255)), win.blit(FONT.render(f"{total_lines:03d}", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 115 + BLOCK_SIZE * 7)) (5 + BLOCK_SIZE * 10 + 20 + BLOCK_SIZE * k1, 115 + BLOCK_SIZE * 7))
win.blit(FONT.render("LV", 1, (255, 255, 255)), win.blit(FONT.render("LV", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 155 + BLOCK_SIZE * 7)) (5 + BLOCK_SIZE * 10 + 20 + BLOCK_SIZE * k1, 155 + BLOCK_SIZE * 7))
win.blit(FONT.render(f"{self.level:02d}", 1, (255, 255, 255)), win.blit(FONT.render(f"{self.level:02d}", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 180 + BLOCK_SIZE * 7)) (5 + BLOCK_SIZE * 10 + 20 + BLOCK_SIZE * k1, 180 + BLOCK_SIZE * 7))
try: try:
tetris_rate = int((self.cleared_lines[3] / total_lines) * 100) tetris_rate = int((self.cleared_lines[3] / total_lines) * 100)
except ZeroDivisionError: except ZeroDivisionError:
tetris_rate = 0 tetris_rate = 0
win.blit(FONT.render("TRT", 1, (255, 255, 255)), win.blit(FONT.render("TRT", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 120 + BLOCK_SIZE * k1, 155 + BLOCK_SIZE * 7)) (5 + BLOCK_SIZE * 10 + 120 + BLOCK_SIZE * k1, 155 + BLOCK_SIZE * 7))
if tetris_rate == 100: if tetris_rate == 100:
win.blit(FONT.render(f"{tetris_rate}", 1, (255, 255, 255)), win.blit(FONT.render(f"{tetris_rate}", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 120 + BLOCK_SIZE * k1, 180 + BLOCK_SIZE * 7)) (5 + BLOCK_SIZE * 10 + 120 + BLOCK_SIZE * k1, 180 + BLOCK_SIZE * 7))
else: else:
win.blit(FONT.render(f"{tetris_rate:02d}%", 1, (255, 255, 255)), win.blit(FONT.render(f"{tetris_rate:02d}%", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 120 + BLOCK_SIZE * k1, 180 + BLOCK_SIZE * 7)) (5 + BLOCK_SIZE * 10 + 120 + BLOCK_SIZE * k1, 180 + BLOCK_SIZE * 7))
win.blit(FONT.render("TIME", 1, (255, 255, 255)), win.blit(FONT.render("TIME", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 220 + BLOCK_SIZE * 7)) (5 + BLOCK_SIZE * 10 + 20 + BLOCK_SIZE * k1, 220 + BLOCK_SIZE * 7))
if self.game_time < 10: if self.game_time < 10:
win.blit(FONT.render(strfdelta(datetime.timedelta(seconds=self.game_time), '%s.%Z'), 1, (255, 255, 255)), win.blit(FONT.render(strfdelta(datetime.timedelta(seconds=self.game_time), '%s.%Z'), 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 245 + BLOCK_SIZE * 7)) (5 + BLOCK_SIZE * 10 + 20 + BLOCK_SIZE * k1, 245 + BLOCK_SIZE * 7))
elif self.game_time < 60: elif self.game_time < 60:
win.blit(FONT.render(strfdelta(datetime.timedelta(seconds=self.game_time), '%S.%z'), 1, (255, 255, 255)), win.blit(FONT.render(strfdelta(datetime.timedelta(seconds=self.game_time), '%S.%z'), 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 245 + BLOCK_SIZE * 7)) (5 + BLOCK_SIZE * 10 + 20 + BLOCK_SIZE * k1, 245 + BLOCK_SIZE * 7))
elif self.game_time < 3600: elif self.game_time < 3600:
win.blit(FONT.render(strfdelta(datetime.timedelta(seconds=self.game_time), '%m:%S'), 1, (255, 255, 255)), win.blit(FONT.render(strfdelta(datetime.timedelta(seconds=self.game_time), '%m:%S'), 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 245 + BLOCK_SIZE * 7)) (5 + BLOCK_SIZE * 10 + 20 + BLOCK_SIZE * k1, 245 + BLOCK_SIZE * 7))
else: else:
win.blit(FONT.render(strfdelta(datetime.timedelta(seconds=self.game_time), '%H:%M:%S'), 1, (255, 255, 255)), win.blit(FONT.render(strfdelta(datetime.timedelta(seconds=self.game_time), '%H:%M:%S'), 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X + 20 + BLOCK_SIZE * k1, 245 + BLOCK_SIZE * 7)) (5 + BLOCK_SIZE * 10 + 20 + BLOCK_SIZE * k1, 245 + BLOCK_SIZE * 7))
if self.score_up > 0: if self.score_up > 0:
win.blit(FONT.render(self.for_what_score[self.for_what_id], 1, (230*(min(self.for_what_delay, 1))+25, 230*(min(self.for_what_delay, 1))+25, 230*(min(self.for_what_delay, 1))+25)), win.blit(FONT.render(self.for_what_score[self.for_what_id], 1, (230*(min(self.for_what_delay, 1))+25, 230*(min(self.for_what_delay, 1))+25, 230*(min(self.for_what_delay, 1))+25)),
(5, 5 + BLOCK_SIZE * (FIELD_SIZE_Y+2) + 5)) (5, 5 + BLOCK_SIZE * (20+2) + 5))
win.blit( win.blit(
FONT.render(f"+{self.score_up}", 1, (230*(min(self.for_what_delay, 1))+25, 230*(min(self.for_what_delay, 1))+25, 230*(min(self.for_what_delay, 1))+25)), FONT.render(f"+{self.score_up}", 1, (230*(min(self.for_what_delay, 1))+25, 230*(min(self.for_what_delay, 1))+25, 230*(min(self.for_what_delay, 1))+25)),
(5, 5 + BLOCK_SIZE * (FIELD_SIZE_Y+2) + 30)) (5, 5 + BLOCK_SIZE * (20+2) + 30))
if self.game_over: if self.game_over:
text_size_x = FONT.size("GAME")[0] text_size_x = FONT.size("GAME")[0]
pygame.draw.rect(win, (0, 0, 0), ( pygame.draw.rect(win, (0, 0, 0), (
BLOCK_SIZE * (FIELD_SIZE_X / 2) - text_size_x, BLOCK_SIZE * FIELD_SIZE_Y / 2, text_size_x * 2 + 10, 60)) BLOCK_SIZE * (10 / 2) - text_size_x, BLOCK_SIZE * 20 / 2, text_size_x * 2 + 10, 60))
win.blit(FONT.render("GAME", 1, (255, 255, 255)), win.blit(FONT.render("GAME", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X / 2 - text_size_x / 2, 5 + BLOCK_SIZE * FIELD_SIZE_Y / 2)) (5 + BLOCK_SIZE * 10 / 2 - text_size_x / 2, 5 + BLOCK_SIZE * 20 / 2))
win.blit(FONT.render("OVER", 1, (255, 255, 255)), win.blit(FONT.render("OVER", 1, (255, 255, 255)),
(5 + BLOCK_SIZE * FIELD_SIZE_X / 2 - text_size_x / 2, 5 + BLOCK_SIZE * FIELD_SIZE_Y / 2 + 25)) (5 + BLOCK_SIZE * 10 / 2 - text_size_x / 2, 5 + BLOCK_SIZE * 20 / 2 + 25))
pygame.display.update() pygame.display.update()
def draw_game_stats(self, on_pause): def draw_game_stats(self, on_pause):
@ -1161,14 +1132,14 @@ class NesLikeTetris(TetrisGameplay):
win.blit(SMALL_FONT.render(f"TRIPLE {triple_times:5d} {self.cleared_lines[2]:5d} T {self.pieces[4]:<4d} O {self.pieces[6]:<4d}", 1, (255, 255, 255)), win.blit(SMALL_FONT.render(f"TRIPLE {triple_times:5d} {self.cleared_lines[2]:5d} T {self.pieces[4]:<4d} O {self.pieces[6]:<4d}", 1, (255, 255, 255)),
(25, 340)) (25, 340))
tetris_times = int(self.cleared_lines[3] / 4) tetris_times = int(self.cleared_lines[3] / 4)
win.blit(SMALL_FONT.render(f"TETRIS {tetris_times:5d} {self.cleared_lines[3]:5d} I {self.pieces[5]:<10d}", 1, (255, 255, 255)), win.blit(SMALL_FONT.render(f"QUAD {tetris_times:7d} {self.cleared_lines[3]:5d} I {self.pieces[5]:<10d}", 1, (255, 255, 255)),
(25, 355)) (25, 355))
win.blit(SMALL_FONT.render(f"SCORE TABLE", 1, (255, 255, 255)), (25, 380)) win.blit(SMALL_FONT.render(f"SCORE TABLE", 1, (255, 255, 255)), (25, 380))
win.blit(SMALL_FONT.render(f"DROPS {self.score[0]:7d}", 1, (255, 255, 255)), (25, 400)) win.blit(SMALL_FONT.render(f"DROPS {self.score[0]:7d}", 1, (255, 255, 255)), (25, 400))
win.blit(SMALL_FONT.render(f"SINGLE {self.score[2]:6d}", 1, (255, 255, 255)), (25, 415)) win.blit(SMALL_FONT.render(f"SINGLE {self.score[2]:6d}", 1, (255, 255, 255)), (25, 415))
win.blit(SMALL_FONT.render(f"DOUBLE {self.score[3]:6d}", 1, (255, 255, 255)), (25, 430)) win.blit(SMALL_FONT.render(f"DOUBLE {self.score[3]:6d}", 1, (255, 255, 255)), (25, 430))
win.blit(SMALL_FONT.render(f"TRIPLE {self.score[4]:6d}", 1, (255, 255, 255)), (25, 445)) win.blit(SMALL_FONT.render(f"TRIPLE {self.score[4]:6d}", 1, (255, 255, 255)), (25, 445))
win.blit(SMALL_FONT.render(f"TETRIS {self.score[5]:6d}", 1, (255, 255, 255)), (25, 460)) win.blit(SMALL_FONT.render(f"QUAD {self.score[5]:8d}", 1, (255, 255, 255)), (25, 460))
pygame.display.update() pygame.display.update()
@ -1307,6 +1278,7 @@ if __name__ == "__main__":
pygame.display.set_caption("dan63047 Tetris") pygame.display.set_caption("dan63047 Tetris")
pygame.font.init() pygame.font.init()
FONT = pygame.font.Font("PressStart2P-vaV7.ttf", 25) FONT = pygame.font.Font("PressStart2P-vaV7.ttf", 25)
MEDIUM_FONT = pygame.font.Font("PressStart2P-vaV7.ttf", 20)
SMALL_FONT = pygame.font.Font("PressStart2P-vaV7.ttf", 15) SMALL_FONT = pygame.font.Font("PressStart2P-vaV7.ttf", 15)
main() main()
pygame.quit() pygame.quit()