Tetris

Classic Tetris Game!


Introduction

This is classic Tetris-style block stacking game, and designed to use the st7789 display driver to render graphics, and features real-time sound effects with a music engine.The game board is a 12-column by 16-row grid where randomly shaped blocks fall from the top, and your goal is to rotate and position them to complete full rows, which are then cleared for points.

To play, press Button A to start the game. Once the blocks begin falling, you can tilt the device left or right (using the built-in accelerometer) to move the block horizontally. Tilt forward to move the block down faster. Press Button B to rotate the block clockwise. As the game progresses, blocks fall faster, and your score increases with each cleared row.

The game ends when the blocks stack up and reach the top of the screen. Your current score is always displayed on the side, and if you score over 1000, it caps at 999. After a game over, the screen prompts you to press Button A to restart.

Programming Design

Source Code

By default, your device comes with the necessary firmware and libraries preinstalled. If you have modified or replaced the firmware or libraries, make sure the following files are present (download if need by click the link)

  • Assets: board.py, button.py, buzzer_music.py, mma7660.py, st7789.py

  • Fonts: vga_16x32.py, vga2_8x8.py

Below is the main program file along with any additional files required for this specific app.

Github Code

Main.py
import machine
import test.st7789 as st7789
import time
from machine import Pin, ADC
import random
from test.fonts import vga2_8x8 as font1
from test.fonts import vga1_16x32 as font2
from buzzer_music import music
from time import sleep

st7789_res = 0
st7789_dc = 1
disp_width = 240
disp_height = 240
spi_sck=machine.Pin(2)
spi_tx=machine.Pin(3)
spi0=machine.SPI(0,baudrate=900000000, phase=1, polarity=1, sck=spi_sck, mosi=spi_tx)
display = st7789.ST7789(spi0, disp_width, disp_width,
    reset=machine.Pin(st7789_res, machine.Pin.OUT),
    dc=machine.Pin(st7789_dc, machine.Pin.OUT),
    xstart=0, ystart=0, rotation=0)
xAxis = ADC(Pin(28))
yAxis = ADC(Pin(29))
display.fill(st7789.BLACK)
buttonB = Pin(5,Pin.IN, Pin.PULL_UP)
buttonA = Pin(6,Pin.IN, Pin.PULL_UP)

g=[]
for i in range(16):
    g.append([0]*12)

song = '0 A#4 1 1;2 F5 1 1;4 D#5 1 1;8 D5 1 1;11 D5 1 1;6 A#4 1 1;14 D#5 1 1;18 A#4 1 1;20 D#5 1 1;22 A#4 1 1;24 D5 1 1;27 D5 1 1;30 D#5 1 1;32 A#4 1 1;34 F5 1 1;36 D#5 1 1;38 A#4 1 1;40 D5 1 1;43 D5 1 1;46 D#5 1 1;50 A#4 1 1;52 D#5 1 1;54 G5 1 1;56 F5 1 1;59 D#5 1 1;62 F5 1 1;64 A#4 1 1;66 F5 1 1;68 D#5 1 1;70 A#4 1 1;72 D5 1 1;75 D5 1 1;78 D#5 1 1;82 A#4 1 1;84 D#5 1 1;86 A#4 1 1;88 D5 1 1;91 D5 1 1;94 D#5 1 1;96 A#4 1 1;100 D#5 1 1;102 A#4 1 1;104 D5 1 1;107 D5 1 1;110 D#5 1 1;114 A#4 1 1;116 D#5 1 1;118 G5 1 1;120 F5 1 1;123 D#5 1 1;126 F5 1 1;98 F5 1 1'

boxO = [[1,1],[1,1]]
boxz_1 = [[1,1,0],[0,1,1],[0,0,0]]
boxz_2 = [[0,1,1],[1,1,0],[0,0,0]]
box7_1 = [[1,1,0],[0,1,0],[0,1,0]]
box7_2 = [[0,1,1],[0,1,0],[0,1,0]]
boxT = [[0,1,0],[1,1,1],[0,0,0]]
boxI = [[0,0,0,0,0],[0,0,0,0,0],[1,1,1,1,0],[0,0,0,0,0],[0,0,0,0,0]]
boxes = [boxO,boxz_1,boxz_2,box7_1,box7_2,boxT,boxI]
color = [0xFFE0,0x867f,0x7ef,0xfb08]
score = 0
box_column = 4
box_row = 0
global cell
global reachtop
reachtop = False
cell = 15
box_column = 4
box_row = 0
def newbox():
    box_id=random.randint(0,6)
    box_org = boxes[box_id]
    b = []
    for i in range(len(box_org)):
        b.append(box_org[i][:])
    return b
box=newbox()
def clockwise():
    N = len(box)
    a=[]
    for i in range(N):
        a.append(box[i][:])
    for i in range(N):
        for j in range(N):
            box[N-j-1][i]=a[i][j]

def counter_clockwise():
    N = len(box)
    a=[]
    for i in range(N):
        a.append(box[i][:])
    for i in range(N):
        for j in range(N):
            box[j][N-i-1] = a[i][j]

def leave():
    j=box_row
    for r in box:
        i=box_column
        for d in r:
            if d==1:
                g[j][i]=0
            i+=1
        j+=1
def enter():
    global box_row
    global box_column
    j=box_row
    for r in box:
        i=box_column
        for d in r:
            if d==1:
                g[j][i]=1
            i+=1
        j+=1
def checkvalid():
    global box_row
    global box_column
    j=box_row
    for r in box:
        i=box_column
        for d in r:
            if d==1:
                if i<0 or i>= 12:
                    return False
                if j<0 or j>= 16:
                    return False
                if g[j][i]==1:
                    return False
            i+=1
        j+=1
    return True
def turn():
    leave()
    clockwise()
    if checkvalid()==False:
        counter_clockwise()
    enter()

def down():
    global box_row
    leave()
    box_row+=1
    if checkvalid() == False:
        box_row-=1
    enter()

def left():
    global box_column
    leave()
    box_column-=1
    if checkvalid()==False:
        box_column+=1
    enter()

def right():
    global box_column
    leave()
    box_column+=1
    if checkvalid()==False:
        box_column-=1
    enter()

def clear():
    global score,reachtop
    i = 0
    c = 0
    while i<16:
        if 0 in g[i]:
            i+=1
        else:
            c+=1
            del g[i]
            g.insert(0,[0]*12)
    if c>0:
        score+=10*(2**(c-1))
        if score >1000:
            score=999
    if 1 in g[0]:
        reachtop = True
def autodrop():
    global box_row,box_column,box,box_id
    leave()
    box_row+=1
    if checkvalid() == False:
        box_row-=1
        enter()
        clear()
        box=newbox()
        box_column = 4
        box_row = 0
    enter()
def falldown():
    global color
    display.fill(0x0000)
    y=0
    for r in g:
        x=0
        for d in r:
            if d==1:
                display.rect(x,y,15,15,0x10)
                display.fill_rect(x+1,y+1,13,13, color[0])
            x+=cell
        y+=cell
def timeaxis (mySong, time):
    l = 0
    time0 = time/40
    while l<time0:
        l+=1
        mySong.tick()
        sleep(0.04)
def game():
    global reachtop,song
    mySong = music(song, pins=[Pin(23)])
    while True:
        timeaxis(mySong, 400)
        xValue = xAxis.read_u16()
        yValue = yAxis.read_u16()
        f=4
        if buttonB.value()==0:
            turn()
        elif xValue in range(50000, 70000):
            down()
        elif yValue in range(0, 10000):
            left()
        elif yValue in range(50000, 70000) :
            right()
        else:
            print("stop" )
        falldown()
        display.fill_rect(181,0,4,240,color[1])
        display.text(font1,"Tetris",185,25)
        display.text(font1,"Score",185,50)
        display.text(font2,str(score),185,80)
        autodrop()
        if reachtop==True:
            mySong.stop()
            display.fill(0x0000)
            display.text(font2,"   GAME   ",45,60)
            display.text(font2,"   OVER   ",45,130)
            time.sleep(1)
            Tetris()
def Tetris():
    display.fill(0x0000)
    display.text(font2,"Press A", 30, 40, color=0x7e0)
    display.text(font2,"To Start", 30, 80, color=0x7e0)
    buttonValueB = buttonB.value()
    while True:
        buttonValueA = buttonA.value()
        if buttonValueA==0:
            print("OK" )
            g=[]
            for i in range(16):
                g.append([0]*12)
            enter()
            game()
Tetris()

Demos

Last updated

Was this helpful?