tetris2.py

Created by cent20

Created on January 11, 2025

11.1 KB

𝗧𝗲𝘁𝗿𝗶𝘀 𝟮


Python Game for Numworks, Epsilon 20+
By Kevin FEDYNA, Ilyas RAHMOUN & Vincent ROBERT. April 2020, december 2024
https://nsi.xyz/tetris (FR) Un Tetris en flat design, ludique et prenant. A tester rapidement ! 😍

Changelog
Tetris v1.0 - 28/04/2020:
- Initial game

Tetris v2.0 - 25/12/2024:
- Fixed the game on Epsilon 20+
- The interface has been updated
- The [var] key is now used to pause and resume the game


from kandinsky import draw_string as txt, fill_rect as rec, get_pixel
from ion import keydown
from random import randint
from math import sqrt,log
from time import monotonic, sleep

# Tetris 2.0 NumWorks, 25.12.2024
# Par Kevin FEDYNA, Ilyas RAHMOUN, & Vincent ROBERT
# https://nsi.xyz/tetris <3

dark_c=(42,)*3
light_c=(142,)*3
bright_c=(242,)*3
game_c=(148,113,222)
void_c=(255,)*3

color = ((128,192,224),(224,128,192),(192,224,128),(192,192,192),(224,192,128),(192,128,224),(128,224,192))
formes = ([(1,1,2,1)],[(1,2,1),(0,0,1)],[(0,2,1),(1,1,0)],[(2,2),(2,2)],[(1,2,1),(0,1,0)],[(1,2,1),(1,0,0)],[(1,2,0),(0,1,1)])
os = (148,113,222)

scoreboard=[["Level",1],["Lines",0],["Score",0], [None]]

game_config=(["Level",1],["Vision",3],["Grid", 0])
config_limits=((1,9),(1,4),(0,1))
state="IN_MENU"
ks=0


def reset():
    global scoreboard
    rec(0,0,320,222,void_c)
    scoreboard=[["Level",game_config[0][1]],["Lines",0],["Score",0], [None]]


def gui(e=0):
    rec(74,0,2,222,light_c)
    rec(246,0,2,222,light_c)
    rec(0,200,320,22,game_c)
    txt("Developed by nsi.xyz/tetris",25,202,bright_c,game_c)
    for i in range(len(game_config)):
        txt(game_config[i][0],37 -5*len(game_config[i][0]),200//(len(game_config)+1)*(i + 1)-18,light_c)
        rec((74-18)//2,200//(len(game_config)+1)*(i+1),18,18,light_c)
        txt(str(game_config[i][1]),(74-18)//2+4,200//(len(game_config)+1)*(i+1),bright_c,light_c)
    config_displayer(0,1)
    arrows_displayer(0,1*(e!=0))
    txt("TETRIS",254,155,light_c)
    if game_config[2][1]:
        grid(1)
    for i in range(7):
        rec(250+10*i,178,8,8,color[i])
    if e:
        rec(0, 0, 74, 200, void_c)


def grid(e):
    for i in range(13):
        rec(76+i*14,0,2,200,bright_c*(e==1)+void_c*(e==0))

def config_displayer(conf,stt):
    c=game_c if stt else light_c
    txt(game_config[conf][0],37-5*len(game_config[conf][0]),200//(len(game_config)+1)*(conf+1)-18,c)
    rec((74-18)//2,200//(len(game_config)+1)*(conf+1),18,18,c)
    txt(str(game_config[conf][1]),(74-18)//2+4,200//(len(game_config)+1)*(conf+1),bright_c,c)


def config_updater(conf,incr,f=0):
    global game_config
    c=light_c if f else game_c
    game_config[conf][1]+=incr
    txt(str(game_config[conf][1]),(74-18)//2+4,200//(len(game_config)+1)*(conf+1),bright_c,c)
    arrows_displayer(conf)
    if conf==2:
        grid(game_config[2][1])
    elif conf==0:
        scoreboard[0][1] = game_config[0][1]
        scoreboard_displayer()


def arrows_displayer(conf,leave=0):
    if leave:
        for i in range(len(game_config)):
            for j in range(2):
                rec((74-18)//2+(25 if j else -17),200//(len(game_config)+1)*(i+1)+3,10,10,void_c)
    else:
        if game_config[conf][1]>config_limits[conf][0]:
            txt("<",(74-18)//2-17,200//(len(game_config)+1)*(conf+1),game_c)
        else:
            txt("<",(74-18)//2-17,200//(len(game_config)+1)*(conf+1),void_c)
        if game_config[conf][1]<config_limits[conf][1]:
            txt(">",(74-18)//2+25,200//(len(game_config)+1)*(conf+1),game_c)
        else:
            txt(">",(74-18)//2+25,200//(len(game_config)+1)*(conf+1),void_c)


def arrow(x,y,d=0,c=game_c):
    for i in range(6):
        rec(x+(23+i)*(d==3)-(5+i)*(d==0)+(3+i)*(d%3!=0),y+(3+i)*(d%3==0)-(7+i)*(d==1)+(22+i)*(d==2),1,2,c)
        rec(x+(23+i)*(d==3)-(5+i)*(d==0)+(13-i)*(d%3!=0),y+(13-i)*(d%3==0)-(7+i)*(d==1)+(22+i)*(d==2),1,2,c)


def config_manager(conf,i):
    config_displayer(conf,0)
    arrows_displayer(conf,1)
    conf+=i
    config_displayer(conf,1)
    arrows_displayer(conf)


def menu():
    global game,ks
    config=0
    last_key=None
    while not (keydown(4) or keydown(52)) or not ks:
        if keydown(1) and config>0 and last_key!=1:
            config_manager(config,-1)
            config-=1
            last_key=1
        if keydown(2) and config<len(game_config)-1 and last_key!=2:
            config_manager(config,1)
            config+=1
            last_key=2
        if keydown(0) and game_config[config][1]>config_limits[config][0] and last_key!=0:
            config_updater(config,-1)
            last_key = 0
        if keydown(3) and game_config[config][1]<config_limits[config][1] and last_key!=3:
            config_updater(config,1)
            last_key=3
        if not (keydown(0) or keydown(1) or keydown(2) or keydown(3) or keydown(4) or keydown(52)):
            last_key,ks = None,1
    gui(1)


def scoreboard_displayer():
    for i in range(len(scoreboard)-1):
        txt(scoreboard[i][0],284-5*len(scoreboard[i][0]),200//(len(scoreboard)+1)*(i+1)-18,dark_c)
        rec(250,200//(len(scoreboard)+1)*(i+1),60,18,void_c)
        txt(str(scoreboard[i][1]),284-5*len(str(scoreboard[i][1])),200//(len(scoreboard)+1)*(i+1),light_c)

def score(li=0, i=0):
    scoreboard[1][1] += li
    scoreboard[2][1] += scoreboard[0][1]*(25*li+25*2**max(li-1,0))*(li!=0)+scoreboard[0][1]*i
    scoreboard[0][1] = max(round(sqrt(scoreboard[2][1] + (10 * game_config[0][1]) ** 2 ) / 10), game_config[0][1])
    scoreboard_displayer()

def rlen(l):
    return range(len(l))

def ancr(piece):
    for i in rlen(piece[1]):
        for j in rlen(piece[1][i]):
            if piece[1][i][j] == 2:
                return piece[0][0]-14*j, piece[0][1]-14*i

def draw_tetro(piece,clr=-1):
    if clr == -1:
        clr = piece[2]
    x,y = ancr(piece)
    for i in rlen(piece[1]):
        for j in rlen(piece[1][i]):
            if piece[1][i][j]:
                rec(x+14*j+1,y+14*i+1,12,12,clr)

def tourner(piece,s,t=0):
    if not t:
        draw_tetro(piece,(255,255,255))
    if s == "h":
        piece[1] = list(zip(*piece[1][::-1]))
    if s == "a":
        piece[1] = list(zip(*(list(i)[::-1] for i in piece[1])))
    if not t:
        draw_tetro(piece)

def move(piece,x=0,y=0):
    draw_tetro(piece, (248, 252, 248))
    piece[0][0] += x*14
    piece[0][1] += y*14
    draw_tetro(piece)

def test_rot(piece,s):
    x,y = ancr(piece)
    blocs = []
    for i in rlen(piece[1]):
        for j in rlen(piece[1][i]):
            if piece[1][i][j]:
                blocs += [[x+14*j,y+14*i]]
    tourner(piece,s,1)
    x,y = ancr(piece)
    for i in rlen(piece[1]):
        for j in rlen(piece[1][i]):
            if not [j*14+x,i*14+y] in blocs:
                if not(77<=x+14*j<=231) or not(3<=y+14*i<=207) or get_pixel(x+7+14*j,y+7+14*i) != (255,255,255):
                    tourner(piece,"a"*(s=="h")+"h"*(s=="a"),1)
                    return 1
    tourner(piece,"a"*(s=="h")+"h"*(s=="a"),1)
    return 0


def collision(d,piece):
    x,y = ancr(piece)
    for i in rlen(piece[1]):
        for j in rlen(piece[1][i]):
            if piece[1][i][j]:
                if d in (0,3) and ((0<=j+(d==3)-(d==0)<=len(piece[1][i])-1 and not piece[1][i][j+(d==3)-(d==0)]) or (j,d) in ((0,0),(len(piece[1][i])-1,3))):
                    if get_pixel(x+7+14*(j+(d==3)-(d==0)),y+7+14*i) != (255,255,255) or x+((j+1)*14)*(d!=0) in [77,245]:
                        return 1
                if d == 2 and ((i != len(piece[1])-1 and not piece[1][i+1][j]) or (i == len(piece[1])-1 and piece[1][i][j])):
                    if get_pixel(x+7+14*j,y+7+14*(i+1)) != (255,255,255) or y+i*14 == 207:
                        return 1
    return 0


def engine():
    global state
    x_n,y_n=17,200//(game_config[1][1]+1)-32
    if game_config[1][1]:
        tetrominos = []
        for i in range(game_config[1][1]):
            chx = randint(0,6)
            tetrominos += [[[37-14*(chx == 3)-6*(chx in (1,2,4,5,6)), 200//(len(tetrominos)+1)*(i)], formes[chx], color[chx]]]
    while get_pixel(154,10) == (255,255,255):
        chx = randint(0,6)
        if game_config[1][1]:
            for tet in tetrominos:
                draw_tetro(tet,(255,255,255))
            tetromino = [[147, 3],tetrominos[0][1],tetrominos[0][2]]
            tetrominos = [tetrominos[i+1] for i in range(game_config[1][1]-1)] + [[[0, 0], formes[chx], color[chx]]]
            for i in range(game_config[1][1]):
                tetrominos[i][0] = [37-14*(tetrominos[i][1] == formes[3])-6*(tetrominos[i][1] in (formes[1],formes[2],formes[4],formes[5],formes[6])), 200//(len(tetrominos)+1)*(i+1)]
            for tet in tetrominos:
                draw_tetro(tet)
        else:
            tetromino = [[147, 3], formes[chx], color[chx]]
        draw_tetro(tetromino)
        chute = 0.120
        while 1:
            txt("Next", x_n, y_n)
            depart = monotonic()
            while monotonic() < depart+round(-0.1945871*log(scoreboard[0][1])+1.01122,3):
                if keydown(0) and not collision(0, tetromino):
                    move(tetromino, x=-1)
                    sleep(0.120)
                if keydown(3) and not collision(3,tetromino):
                    move(tetromino,x=1)
                    sleep(0.120)
                if keydown(2):
                    sleep(chute)
                    chute /= 2
                    score(i=1)
                    break
                chute = 0.120
                if keydown(16) and not test_rot(tetromino,"h"):
                    sleep(0.160)
                    tourner(tetromino,"h")
                if (keydown(17) or keydown(1)) and not test_rot(tetromino,"a"):
                    sleep(0.160)
                    tourner(tetromino,"a")
                if (keydown(15) or keydown(52)) and state != "IN_PAUSE":
                    state = "IN_PAUSE"
                    rec(x_n-10,y_n-6,60,30,game_c)
                    txt("PAUSE",x_n-5,y_n,bright_c,game_c)
                    sleep(0.160)
                if state == "IN_PAUSE":
                    while not (keydown(15) or keydown(52)):
                        pass
                    state = "IN_GAME"
                    rec(x_n-10,y_n-6,60,30,void_c)
                    txt("Next", x_n, y_n)
                    sleep(0.160)
            if collision(2,tetromino):
                break
            score(i=1)
            move(tetromino,y=1)
        lignes = []
        for i in range(192,4,-14):
            verif = 0
            for j in range(84,252,14):
                verif += (get_pixel(j,i) != (255,255,255)) + 2*(get_pixel(j,i) == (255,255,255))
            if verif == 12:
                lignes += [i-7]
            if verif == 24:
                stop = i-7
                break
        if lignes:
            score(li=len(lignes))
            for c in range(7):
                for i in lignes:
                    for j in range(77,245,14):
                        rec(j+1,i+1,12,12,not c%2 and (255,255,255) or os)
                sleep(0.2*round(-0.1945871*log(scoreboard[0][1])+1.01122,3))
            lignes = [lignes[i]+i*14 for i in rlen(lignes)]
            for i in lignes:
                for y in range(i,stop-14,-14):
                    for x in range(77,245,14):
                        rec(x+1,y+1,12,12,get_pixel(x+7,y-7))
    rec(130,94,60,34,game_c)
    txt("LOST",140,102,bright_c,game_c)
    state = "END"

def start():
    global state
    gui()
    scoreboard_displayer()
    menu()
    state = "IN_GAME"
    sleep(0.160)
    engine()


def tetris():
    global ks
    while not keydown(51):
        if state == "IN_MENU":
            start()
        if state == "END" and (keydown(4) or keydown(52)) and not ks:
            reset()
            start()
        if not (keydown(4) or keydown(52)):
            ks = 0

tetris()

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.