Skip to content

Instantly share code, notes, and snippets.

@villares
Created October 6, 2024 14:16
Show Gist options
  • Save villares/321c087b517cffee026ab828aabc35f0 to your computer and use it in GitHub Desktop.
Save villares/321c087b517cffee026ab828aabc35f0 to your computer and use it in GitHub Desktop.
Porting my tetris from py5 to pyp5js
"""
This is quick adaptation from my py5 imported mode sketch at:
https://abav.lugaralgum.com/sketch-a-day/#sketch_2024_07_09
Use arrows to play - up to rotate, space bar to restart.
What changed: py5pjs didn't have random_choice, so I had to import it, and
in pyp5js the arrow key constants are different ARROW_LEFT and not LEFT, etc.
"""
from random import choice as random_choice
well = {} # a dictionary for the walls and already fallen pieces
falling_piece = [] # will contain ((x,y), color) tuples, the component blocks of a piece
pieces = (
[((x, y), color(0, 200, 0)) for x, y in ((6, 0), (7, 0), (6, 1), (7, 1))], # O
[((x, y), color(0, 0, 200)) for x, y in ((4, 0), (5, 0), (6, 0), (6, 1))], # J
[((x, y), color(200, 200, 0)) for x, y in ((4, 1), (5, 1), (6, 1), (6, 0))], # L
[((x, y), color(200, 0, 0)) for x, y in ((4, 0), (5, 0), (6, 0), (7, 0))], # I
[((x, y), color(0, 200, 200)) for x, y in ((5, 0), (5, 1), (6, 1), (6, 2))], # S
[((x, y), color(200, 0, 200)) for x, y in ((6, 0), (6, 1), (5, 1), (5, 2))], # N
[((x, y), color(200)) for x, y in ((4, 0), (5, 0), (6, 0), (5, 1))], # T
)
W, H, s = 11, 20, 25 # Well Width, Well Height, single block size
frame_sample = 12 # a smaller number makes it faster, a bigger number makes it slower
def setup():
size(525, 525)
text_align(CENTER, CENTER)
text_size(80)
start()
def start():
global game_over, score
game_over, score = False, 0
well.clear()
for y in range(H): # Set vertical well walls
well[0, y] = color(128)
well[W, y] = color(128)
for x in range(W + 1): # Set bottom of well
well[x, H] = color(128)
new_falling_piece()
loop() # reactivates draw if it is paused
def draw():
global score
background(0)
for (x, y), block_color in list(well.items()) + falling_piece:
fill(block_color)
square(x * s, y * s, s)
fill(200)
text(score, W * s + (width - W * s) / 2, s * 2)
if game_over:
fill(255)
text('GAME OVER',
width / 2, height / 2)
no_loop() # pause draw
elif frame_count % frame_sample == 0:
if check_move(falling_piece, 0, 1):
move_falling_piece(0, 1)
else:
add_to_well()
new_falling_piece()
r = check_filled_row()
if r != -1:
collapse_on_row(r)
score += 1
def new_falling_piece():
global game_over
falling_piece[:] = random_choice(pieces)
if not check_move(falling_piece):
game_over = True
def add_to_well():
for (x, y), b in falling_piece:
well[x, y] = b
def check_move(p, h=0, v=0):
for (x, y), _ in p:
if well.get((x + h, y + v)):
return False
return True
def move_falling_piece(h, v):
falling_piece[:] = (((x + h, y + v), b) for (x, y), b in falling_piece)
def check_filled_row():
for r in range(H):
filled_blocks = 0
for c in range(W):
if well.get((c, r)):
filled_blocks += 1
if filled_blocks == W:
return r # return first filled row found
return -1 # no filled row
def clear_row(r):
for c in range(1, W):
if (c, r) in well:
del well[c, r]
def collapse_on_row(row):
# clear passed row and move blocks down to it
for r in range(row, -1, -1): # moving upwards, starting from passed row
clear_row(r)
for c in range(1, W):
if b := well.get((c, r - 1)): # get block from 1 row up
well[c, r] = b
def rounded_falling_piece_centroid():
positions = ((x, y) for (x, y), _ in falling_piece)
coords = tuple(zip(*positions))
max_x, max_y = map(max, coords)
min_x, min_y = map(min, coords)
return (max_x + min_x) // 2, (max_y + min_y) // 2
def rotated_falling_piece():
cx, cy = rounded_falling_piece_centroid() # causes y displacement of -1 offset later...
# translated to origin falling piece copy
ttofpc = (((x - cx, y - cy), b) for (x, y), b in falling_piece)
return tuple(((y + cx, -x + cy + 1), b) for (x, y), b in ttofpc) # note y + 1 offset
def key_pressed():
if key == ' ':
start()
elif key_code == LEFT_ARROW and check_move(falling_piece, -1, 0):
move_falling_piece(-1, 0)
elif key_code == RIGHT_ARROW and check_move(falling_piece, 1, 0):
move_falling_piece(1, 0);
elif key_code == DOWN_ARROW and check_move(falling_piece, 0, 1):
move_falling_piece(0, 1);
elif key_code == UP_ARROW and check_move(rp := rotated_falling_piece()):
falling_piece[:] = rp
@villares
Copy link
Author

villares commented Oct 6, 2024

Versão minified: https://abav.lugaralgum.com/pyp5js/py5mode/?sketch=TiUzREZhbHNlJTBBTSUzRHR1cGxlJTBBRCUzRHJhbmdlJTBBZnJvbSUyMHJhbmRvbSUyMGltcG9ydCUyMGNob2ljZSUyMGFzJTIwTyUwQUIlM0QlN0IlN0QlMEFBJTNEJTVCJTVEJTBBUCUzRCU1QigoQSUyQ0IpJTJDY29sb3IoMCUyQzIwMCUyQzApKWZvcihBJTJDQilpbigoNiUyQzApJTJDKDclMkMwKSUyQyg2JTJDMSklMkMoNyUyQzEpKSU1RCUyQyU1QigoQSUyQ0IpJTJDY29sb3IoMCUyQzAlMkMyMDApKWZvcihBJTJDQilpbigoNCUyQzApJTJDKDUlMkMwKSUyQyg2JTJDMCklMkMoNiUyQzEpKSU1RCUyQyU1QigoQSUyQ0IpJTJDY29sb3IoMjAwJTJDMjAwJTJDMCkpZm9yKEElMkNCKWluKCg0JTJDMSklMkMoNSUyQzEpJTJDKDYlMkMxKSUyQyg2JTJDMCkpJTVEJTJDJTVCKChBJTJDQiklMkNjb2xvcigyMDAlMkMwJTJDMCkpZm9yKEElMkNCKWluKCg0JTJDMCklMkMoNSUyQzApJTJDKDYlMkMwKSUyQyg3JTJDMCkpJTVEJTJDJTVCKChBJTJDQiklMkNjb2xvcigwJTJDMjAwJTJDMjAwKSlmb3IoQSUyQ0IpaW4oKDUlMkMwKSUyQyg1JTJDMSklMkMoNiUyQzEpJTJDKDYlMkMyKSklNUQlMkMlNUIoKEElMkNCKSUyQ2NvbG9yKDIwMCUyQzAlMkMyMDApKWZvcihBJTJDQilpbigoNiUyQzApJTJDKDYlMkMxKSUyQyg1JTJDMSklMkMoNSUyQzIpKSU1RCUyQyU1QigoQSUyQ0IpJTJDY29sb3IoMjAwKSlmb3IoQSUyQ0IpaW4oKDQlMkMwKSUyQyg1JTJDMCklMkMoNiUyQzApJTJDKDUlMkMxKSklNUQlMEFDJTJDSiUyQ0UlM0QxMSUyQzIwJTJDMjUlMEFRJTNEMTIlMEFkZWYlMjBzZXR1cCgpJTNBc2l6ZSg1MjUlMkM1MjUpJTNCdGV4dF9hbGlnbihDRU5URVIlMkNDRU5URVIpJTNCdGV4dF9zaXplKDgwKSUzQksoKSUwQWRlZiUyMEsoKSUzQSUwQSUwOWdsb2JhbCUyMEclMkNIJTNCRyUyQ0glM0ROJTJDMCUzQkIuY2xlYXIoKSUwQSUwOWZvciUyMEElMjBpbiUyMEQoSiklM0FCJTVCMCUyQ0ElNUQlM0Rjb2xvcigxMjgpJTNCQiU1QkMlMkNBJTVEJTNEY29sb3IoMTI4KSUwQSUwOWZvciUyMEUlMjBpbiUyMEQoQyUyQjEpJTNBQiU1QkUlMkNKJTVEJTNEY29sb3IoMTI4KSUwQSUwOUwoKSUzQmxvb3AoKSUwQWRlZiUyMGRyYXcoKSUzQSUwQSUwOWdsb2JhbCUyMEglM0JiYWNrZ3JvdW5kKDApJTBBJTA5Zm9yKChKJTJDSyklMkNNKWluJTIwbGlzdChCLml0ZW1zKCkpJTJCQSUzQWZpbGwoTSklM0JzcXVhcmUoSipFJTJDSypFJTJDRSklMEElMDlmaWxsKDIwMCklM0J0ZXh0KEglMkNDKkUlMkIod2lkdGgtQypFKSUyRjIlMkNFKjIpJTBBJTA5aWYlMjBHJTNBZmlsbCgyNTUpJTNCdGV4dCgnR0FNRSUyME9WRVInJTJDd2lkdGglMkYyJTJDaGVpZ2h0JTJGMiklM0Jub19sb29wKCklMEElMDllbGlmJTIwZnJhbWVfY291bnQlMjVRJTNEJTNEMCUzQSUwQSUwOSUwOWlmJTIwRihBJTJDMCUyQzEpJTNBSSgwJTJDMSklMEElMDklMDllbHNlJTNBUigpJTNCTCgpJTBBJTA5JTA5RCUzRFMoKSUwQSUwOSUwOWlmJTIwRCElM0QtMSUzQVUoRCklM0JIJTJCJTNEMSUwQWRlZiUyMEwoKSUzQSUwQSUwOWdsb2JhbCUyMEclM0JBJTVCJTNBJTVEJTNETyhQKSUwQSUwOWlmJTIwbm90JTIwRihBKSUzQUclM0RUcnVlJTBBZGVmJTIwUigpJTNBJTBBJTA5Zm9yKChDJTJDRCklMkNFKWluJTIwQSUzQUIlNUJDJTJDRCU1RCUzREUlMEFkZWYlMjBGKHAlMkNoJTNEMCUyQ3YlM0QwKSUzQSUwQSUwOWZvcigoQSUyQ0MpJTJDRClpbiUyMHAlM0ElMEElMDklMDlpZiUyMEIuZ2V0KChBJTJCaCUyQ0MlMkJ2KSklM0FyZXR1cm4lMjBOJTBBJTA5cmV0dXJuJTIwVHJ1ZSUwQWRlZiUyMEkoaCUyQ3YpJTNBQSU1QiUzQSU1RCUzRCgoKEElMkJoJTJDQiUyQnYpJTJDQylmb3IoKEElMkNCKSUyQ0MpaW4lMjBBKSUwQWRlZiUyMFMoKSUzQSUwQSUwOWZvciUyMEElMjBpbiUyMEQoSiklM0ElMEElMDklMDlFJTNEMCUwQSUwOSUwOWZvciUyMEYlMjBpbiUyMEQoQyklM0ElMEElMDklMDklMDlpZiUyMEIuZ2V0KChGJTJDQSkpJTNBRSUyQiUzRDElMEElMDklMDlpZiUyMEUlM0QlM0RDJTNBcmV0dXJuJTIwQSUwQSUwOXJldHVybi0xJTBBZGVmJTIwVChyKSUzQSUwQSUwOWZvciUyMEElMjBpbiUyMEQoMSUyQ0MpJTNBJTBBJTA5JTA5aWYoQSUyQ3IpaW4lMjBCJTNBZGVsJTIwQiU1QkElMkNyJTVEJTBBZGVmJTIwVShyb3cpJTNBJTBBJTA5Zm9yJTIwQSUyMGluJTIwRChyb3clMkMtMSUyQy0xKSUzQSUwQSUwOSUwOVQoQSklMEElMDklMDlmb3IlMjBFJTIwaW4lMjBEKDElMkNDKSUzQSUwQSUwOSUwOSUwOWlmKEYlM0ElM0RCLmdldCgoRSUyQ0EtMSkpKSUzQUIlNUJFJTJDQSU1RCUzREYlMEFkZWYlMjBWKCklM0FDJTNEKChBJTJDQilmb3IoKEElMkNCKSUyQ0MpaW4lMjBBKSUzQkIlM0RNKHppcCgqQykpJTNCRCUyQ0UlM0RtYXAobWF4JTJDQiklM0JGJTJDRyUzRG1hcChtaW4lMkNCKSUzQnJldHVybihEJTJCRiklMkYlMkYyJTJDKEUlMkJHKSUyRiUyRjIlMEFkZWYlMjBXKCklM0FCJTJDQyUzRFYoKSUzQkQlM0QoKChBLUIlMkNELUMpJTJDRSlmb3IoKEElMkNEKSUyQ0UpaW4lMjBBKSUzQnJldHVybiUyME0oKChEJTJCQiUyQy1BJTJCQyUyQjEpJTJDRSlmb3IoKEElMkNEKSUyQ0UpaW4lMjBEKSUwQWRlZiUyMGtleV9wcmVzc2VkKCklM0ElMEElMDlpZiUyMGtleSUzRCUzRCclMjAnJTNBSygpJTBBJTA5ZWxpZiUyMGtleV9jb2RlJTNEJTNETEVGVF9BUlJPVyUyMGFuZCUyMEYoQSUyQy0xJTJDMCklM0FJKC0xJTJDMCklMEElMDllbGlmJTIwa2V5X2NvZGUlM0QlM0RSSUdIVF9BUlJPVyUyMGFuZCUyMEYoQSUyQzElMkMwKSUzQUkoMSUyQzApJTBBJTA5ZWxpZiUyMGtleV9jb2RlJTNEJTNERE9XTl9BUlJPVyUyMGFuZCUyMEYoQSUyQzAlMkMxKSUzQUkoMCUyQzEpJTBBJTA5ZWxpZiUyMGtleV9jb2RlJTNEJTNEVVBfQVJST1clMjBhbmQlMjBGKChCJTNBJTNEVygpKSklM0FBJTVCJTNBJTVEJTNEQg%3D%3D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment