Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Tettris
#1
This is my first program for the QB64PE site.
Up to now, I have never written a falling-tiles program - the sort of thing one ought to write as a hobbyist.  As there are copyright and trademark issues with Tetris, I certainly would not write a Tetris program!  But I see that contributor vince has written a Tetris program, and mine is very very similar in behaviour.  And he says that Tetris is the ultimate test of a programmer.  So, it is with some satisfaction that I offer this program.  It has no unique features, but it was a pleasure to code using the QB64 graphics features.
The pieces fall and can be moved left and right (L-, R- arrow keys), rotated (Up Arrow key), dropped (Down Arrow key or Space Bar).  P to pause, Esc or Q to quit.
I noted that if you leave out the large number of code lines which I used to make the graphics images, I did not take up many more lines than vince's code.  Doing the same job, after all, though I have not taken the trouble to see if the methods used have any distinct similarities.
Unzip the contents into a QB64 sub-folder.
There are two versions of the code.  The main version is written for a full 1080 vertical resolution monitor.  The second version is for screens with lower resolution.


.zip   Tettris.zip (Size: 20.18 KB / Downloads: 41)

[Image: Tettris.jpg]


Unzip the attachment and place the sub-folder in the QB64 directory.


v1.0
Code: (Select All)
'Tettris Program v1 5/9/25 by Magdha QB64 v2.0
'Thanks to https://blog.alexrinehart.net for input images

'Program requires HD 1080 vertical resolution monitor.
'Similar to a well-known tile manipulation program
'Get higher scores if you drop the pieces and as the game speeds up

'Piece Movement:
'Left/Right Arrow Keys, move left or right
'Up Arrow Key, rotate piece counter-clockwise
'Down Arrow Key or Space Bar, drop the piece
'P, Pause/unpause
'Esc or Q, Quit

CONST False = 0, True = NOT False
RANDOMIZE (TIMER)

'Declare arrays
'Shared Arrays Grid%%(), Array%%(), Offsets%%() are used in main code and in Function
DIM SHARED Grid%%(11, 21), Array%%(7, 3, 3, 3), Offsets%%(7, 3, 1)
DIM Squares&(7), Pieces&(7, 3), InPiece%%(3)

_TITLE ("Tettris v1.0")

'Define the working grid (10x20)
'Columns 0 & 11 and row 21 need to have non-zero value so that piece in play recognises boundaries
FOR M%% = 0 TO 21
    Grid%%(0, M%%) = 8
    Grid%%(11, M%%) = 8
NEXT M%%
FOR N%% = 0 TO 11
    Grid%%(N%%, 21) = 8
NEXT N%%

'Define Arrays for the movement of pieces within the working grid
'Array%%() values will be used to populate Grid%%() when a piece is fixed to the grid
'Laborious manual input code required for all pieces, all orientations
'Array%%() dimensions are: Piece no., orientation, x-direction, y-direction
'O-Piece
Array%%(1, 0, 0, 0) = 1
Array%%(1, 0, 1, 0) = 1
Array%%(1, 0, 0, 1) = 1
Array%%(1, 0, 1, 1) = 1
'I-Piece
Array%%(2, 0, 0, 0) = 2
Array%%(2, 0, 1, 0) = 2
Array%%(2, 0, 2, 0) = 2
Array%%(2, 0, 3, 0) = 2
Array%%(2, 1, 0, 0) = 2
Array%%(2, 1, 0, 1) = 2
Array%%(2, 1, 0, 2) = 2
Array%%(2, 1, 0, 3) = 2
'T-piece
Array%%(3, 0, 0, 0) = 3
Array%%(3, 0, 1, 0) = 3
Array%%(3, 0, 2, 0) = 3
Array%%(3, 0, 1, 1) = 3
Array%%(3, 1, 0, 0) = 3
Array%%(3, 1, 0, 1) = 3
Array%%(3, 1, 0, 2) = 3
Array%%(3, 1, 1, 1) = 3
Array%%(3, 2, 0, 1) = 3
Array%%(3, 2, 1, 1) = 3
Array%%(3, 2, 2, 1) = 3
Array%%(3, 2, 1, 0) = 3
Array%%(3, 3, 1, 0) = 3
Array%%(3, 3, 1, 1) = 3
Array%%(3, 3, 1, 2) = 3
Array%%(3, 3, 0, 1) = 3
'S-Piece
Array%%(4, 0, 1, 0) = 4
Array%%(4, 0, 2, 0) = 4
Array%%(4, 0, 0, 1) = 4
Array%%(4, 0, 1, 1) = 4
Array%%(4, 1, 0, 0) = 4
Array%%(4, 1, 0, 1) = 4
Array%%(4, 1, 1, 1) = 4
Array%%(4, 1, 1, 2) = 4
'Z-Piece
Array%%(5, 0, 0, 0) = 5
Array%%(5, 0, 1, 0) = 5
Array%%(5, 0, 1, 1) = 5
Array%%(5, 0, 2, 1) = 5
Array%%(5, 1, 0, 1) = 5
Array%%(5, 1, 0, 2) = 5
Array%%(5, 1, 1, 0) = 5
Array%%(5, 1, 1, 1) = 5
'J-Piece
Array%%(6, 0, 0, 0) = 6
Array%%(6, 0, 1, 0) = 6
Array%%(6, 0, 2, 0) = 6
Array%%(6, 0, 2, 1) = 6
Array%%(6, 1, 0, 0) = 6
Array%%(6, 1, 1, 0) = 6
Array%%(6, 1, 0, 1) = 6
Array%%(6, 1, 0, 2) = 6
Array%%(6, 2, 0, 0) = 6
Array%%(6, 2, 0, 1) = 6
Array%%(6, 2, 1, 1) = 6
Array%%(6, 2, 2, 1) = 6
Array%%(6, 3, 1, 0) = 6
Array%%(6, 3, 1, 1) = 6
Array%%(6, 3, 1, 2) = 6
Array%%(6, 3, 0, 2) = 6
'L-Piece
Array%%(7, 0, 0, 0) = 7
Array%%(7, 0, 1, 0) = 7
Array%%(7, 0, 2, 0) = 7
Array%%(7, 0, 0, 1) = 7
Array%%(7, 1, 0, 0) = 7
Array%%(7, 1, 0, 1) = 7
Array%%(7, 1, 0, 2) = 7
Array%%(7, 1, 1, 2) = 7
Array%%(7, 2, 2, 0) = 7
Array%%(7, 2, 0, 1) = 7
Array%%(7, 2, 1, 1) = 7
Array%%(7, 2, 2, 1) = 7
Array%%(7, 3, 0, 0) = 7
Array%%(7, 3, 1, 0) = 7
Array%%(7, 3, 1, 1) = 7
Array%%(7, 3, 1, 2) = 7

'Define Position offsets
'These are the starting offset values, laboriously manually input code
'These offsets are used to centre the piece as close to column 5 as possible at start
'Offsets%%() dimensions are: Piece no., orientation, x- (0) or y- (1)
Offsets%%(2, 0, 0) = -1
Offsets%%(2, 1, 1) = -1
Offsets%%(3, 0, 0) = -1
Offsets%%(3, 1, 1) = -1
Offsets%%(3, 2, 0) = -1
Offsets%%(3, 2, 1) = -1
Offsets%%(3, 3, 0) = -1
Offsets%%(3, 3, 1) = -1
Offsets%%(4, 0, 0) = -1
Offsets%%(4, 1, 1) = -1
Offsets%%(5, 0, 0) = -1
Offsets%%(5, 1, 0) = -1
Offsets%%(6, 0, 0) = -1
Offsets%%(6, 1, 1) = -1
Offsets%%(6, 2, 0) = -1
Offsets%%(6, 2, 1) = -1
Offsets%%(6, 3, 0) = -1
Offsets%%(6, 3, 1) = -1
Offsets%%(7, 0, 0) = -1
Offsets%%(7, 1, 1) = -1
Offsets%%(7, 2, 0) = -1
Offsets%%(7, 2, 1) = -1
Offsets%%(7, 3, 0) = -1
Offsets%%(7, 3, 1) = -1

'Load Squares images and generate images for all pieces, all orientations
'These images are all hardware
TempImg& = _LOADIMAGE("O-Square.png", 32)
TempImg1& = _NEWIMAGE(100, 100, 32)
FOR N%% = 0 TO 1
    FOR M%% = 0 TO 1
        _PUTIMAGE (N%% * 50, M%% * 50)-(49 + N%% * 50, 49 + M%% * 50), TempImg&, TempImg1&
    NEXT M%%
NEXT N%%
Pieces&(1, 0) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(50, 50, 32)
_PUTIMAGE , TempImg&, TempImg1&
Squares&(1) = HardwareImage&(TempImg1&)
_FREEIMAGE TempImg&
TempImg& = _LOADIMAGE("I-Square.png", 32)
TempImg1& = _NEWIMAGE(200, 50, 32)
FOR N%% = 0 TO 3
    _PUTIMAGE (N%% * 50, 0)-(49 + N%% * 50, 49), TempImg&, TempImg1&
NEXT N%%
Pieces&(2, 0) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(50, 200, 32)
FOR M%% = 0 TO 3
    _PUTIMAGE (0, M%% * 50)-(49, 49 + M%% * 50), TempImg&, TempImg1&
NEXT M%%
Pieces&(2, 1) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(50, 50, 32)
_PUTIMAGE , TempImg&, TempImg1&
Squares&(2) = HardwareImage&(TempImg1&)
_FREEIMAGE TempImg&
TempImg& = _LOADIMAGE("T-Square.png", 32)
TempImg1& = _NEWIMAGE(150, 100, 32)
FOR N%% = 0 TO 2
    _PUTIMAGE (N%% * 50, 0)-(49 + N%% * 50, 49), TempImg&, TempImg1&
NEXT N%%
_PUTIMAGE (50, 50)-(99, 99), TempImg&, TempImg1&
Pieces&(3, 0) = HardwareImage&(TempImg1&) 'They rotate counter-clockwise
TempImg1& = _NEWIMAGE(150, 100, 32)
FOR N%% = 0 TO 2
    _PUTIMAGE (N%% * 50, 50)-(49 + N%% * 50, 99), TempImg&, TempImg1&
NEXT N%%
_PUTIMAGE (50, 0)-(99, 49), TempImg&, TempImg1&
Pieces&(3, 2) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(100, 150, 32)
FOR M%% = 0 TO 2
    _PUTIMAGE (0, M%% * 50)-(49, 49 + M%% * 50), TempImg&, TempImg1&
NEXT M%%
_PUTIMAGE (50, 50)-(99, 99), TempImg&, TempImg1&
Pieces&(3, 1) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(100, 150, 32)
FOR M%% = 0 TO 2
    _PUTIMAGE (50, M%% * 50)-(99, 49 + M%% * 50), TempImg&, TempImg1&
NEXT M%%
_PUTIMAGE (0, 50)-(49, 99), TempImg&, TempImg1&
Pieces&(3, 3) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(50, 50, 32)
_PUTIMAGE , TempImg&, TempImg1&
Squares&(3) = HardwareImage&(TempImg1&)
_FREEIMAGE TempImg&
TempImg& = _LOADIMAGE("S-Square.png", 32)
TempImg1& = _NEWIMAGE(150, 100, 32)
FOR N%% = 1 TO 2
    _PUTIMAGE (N%% * 50, 0)-(49 + N%% * 50, 49), TempImg&, TempImg1&
    _PUTIMAGE ((N%% - 1) * 50, 50)-(49 + (N%% - 1) * 50, 99), TempImg&, TempImg1&
NEXT N%%
Pieces&(4, 0) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(100, 150, 32)
FOR M%% = 1 TO 2
    _PUTIMAGE (0, (M%% - 1) * 50)-(49, 49 + (M%% - 1) * 50), TempImg&, TempImg1&
    _PUTIMAGE (50, M%% * 50)-(99, 49 + M%% * 50), TempImg&, TempImg1&
NEXT M%%
Pieces&(4, 1) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(50, 50, 32)
_PUTIMAGE , TempImg&, TempImg1&
Squares&(4) = HardwareImage&(TempImg1&)
_FREEIMAGE TempImg&
TempImg& = _LOADIMAGE("Z-Square.png", 32)
TempImg1& = _NEWIMAGE(150, 100, 32)
FOR N%% = 1 TO 2
    _PUTIMAGE (N%% * 50, 50)-(49 + N%% * 50, 99), TempImg&, TempImg1&
    _PUTIMAGE ((N%% - 1) * 50, 0)-(49 + (N%% - 1) * 50, 49), TempImg&, TempImg1&
NEXT N%%
Pieces&(5, 0) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(100, 150, 32)
FOR M%% = 1 TO 2
    _PUTIMAGE (50, (M%% - 1) * 50)-(99, 49 + (M%% - 1) * 50), TempImg&, TempImg1&
    _PUTIMAGE (0, M%% * 50)-(49, 49 + M%% * 50), TempImg&, TempImg1&
NEXT M%%
Pieces&(5, 1) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(50, 50, 32)
_PUTIMAGE , TempImg&, TempImg1&
Squares&(5) = HardwareImage&(TempImg1&)
_FREEIMAGE TempImg&
TempImg& = _LOADIMAGE("J-Square.png", 32)
TempImg1& = _NEWIMAGE(150, 100, 32)
FOR N%% = 0 TO 2
    _PUTIMAGE (N%% * 50, 0)-(49 + N%% * 50, 49), TempImg&, TempImg1&
NEXT N%%
_PUTIMAGE (100, 50)-(149, 99), TempImg&, TempImg1&
Pieces&(6, 0) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(100, 150, 32)
FOR M%% = 0 TO 2
    _PUTIMAGE (50, M%% * 50)-(99, 49 + M%% * 50), TempImg&, TempImg1&
NEXT M%%
_PUTIMAGE (0, 100)-(49, 149), TempImg&, TempImg1&
Pieces&(6, 3) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(150, 100, 32)
FOR N%% = 0 TO 2
    _PUTIMAGE (N%% * 50, 50)-(49 + N%% * 50, 99), TempImg&, TempImg1&
NEXT N%%
_PUTIMAGE (0, 0)-(49, 49), TempImg&, TempImg1&
Pieces&(6, 2) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(100, 150, 32)
FOR M%% = 0 TO 2
    _PUTIMAGE (0, M%% * 50)-(49, 49 + M%% * 50), TempImg&, TempImg1&
NEXT M%%
_PUTIMAGE (50, 0)-(99, 49), TempImg&, TempImg1&
Pieces&(6, 1) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(50, 50, 32)
_PUTIMAGE , TempImg&, TempImg1&
Squares&(6) = HardwareImage&(TempImg1&)
_FREEIMAGE TempImg&
TempImg& = _LOADIMAGE("L-Square.png", 32)
TempImg1& = _NEWIMAGE(150, 100, 32)
FOR N%% = 0 TO 2
    _PUTIMAGE (N%% * 50, 0)-(49 + N%% * 50, 49), TempImg&, TempImg1&
NEXT N%%
_PUTIMAGE (0, 50)-(49, 99), TempImg&, TempImg1&
Pieces&(7, 0) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(100, 150, 32)
FOR M%% = 0 TO 2
    _PUTIMAGE (50, M%% * 50)-(99, 49 + M%% * 50), TempImg&, TempImg1&
NEXT M%%
_PUTIMAGE (0, 0)-(49, 49), TempImg&, TempImg1&
Pieces&(7, 3) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(150, 100, 32)
FOR N%% = 0 TO 2
    _PUTIMAGE (N%% * 50, 50)-(49 + N%% * 50, 99), TempImg&, TempImg1&
NEXT N%%
_PUTIMAGE (100, 0)-(149, 49), TempImg&, TempImg1&
Pieces&(7, 2) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(100, 150, 32)
FOR M%% = 0 TO 2
    _PUTIMAGE (0, M%% * 50)-(49, 49 + M%% * 50), TempImg&, TempImg1&
NEXT M%%
_PUTIMAGE (50, 100)-(99, 149), TempImg&, TempImg1&
Pieces&(7, 1) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(50, 50, 32)
_PUTIMAGE , TempImg&, TempImg1&
Squares&(7) = HardwareImage&(TempImg1&)
_FREEIMAGE TempImg&

'Load High Score
IF _FILEEXISTS("HiScore.txt") THEN
    OPEN "HiScore.txt" FOR INPUT AS #1
    INPUT #1, HiScore%
    CLOSE #1
ELSE
    HiScore% = 0
END IF

'Screen
'HD 1080 vertical resolution monitor required.
SCREEN _NEWIMAGE(1010, 1000, 32)
_SCREENMOVE 300, 20
_DEST 0
COLOR _RGB32(0, 0, 0), _RGB32(0, 85, 0)
CLS
_FONT _LOADFONT(ENVIRON$("SYSTEMROOT") + "\Fonts\Arial.ttf", 80, "Bold")
'Software images:
_PRINTSTRING (570, 50), "Next Piece:"
_PRINTSTRING (650, 550), "Score"
IF HiScore% > 0 THEN
    _PRINTSTRING (560, 800), "High Score"
    H$ = LTRIM$(STR$(HiScore%))
    _PRINTSTRING (755 - LEN(H$) * 22, 890), H$
END IF
'Area Delineations
LINE (500, 0)-(510, 999), _RGB(180, 0, 0), BF
LINE (500, 400)-(1009, 410), _RGB(180, 0, 0), BF

'Initial Conditions
InPlay%% = True
Count%% = 0
SpeedCount& = 0
CountLimit%% = 30
SpeedBonus! = 1
DropBonus! = 1
Paused%% = False
AddPiece%% = False
GameOver%% = False
Score% = 0
'Set up first in-play piece and next piece
InPiece%%(0) = 1 + INT(7 * RND) 'Piece in play
InPiece%%(1) = 1 + INT(7 * RND) 'Next piece
InPiece%%(2) = 5 'Start column
InPiece%%(3) = 0 'Start row
Q%% = 0 'Orientation

'Loop for play
WHILE InPlay%%
    _LIMIT 60

    IF NOT GameOver%% THEN
        IF NOT Paused%% THEN
            Count%% = Count%% + 1
            SpeedCount& = SpeedCount& + 1
            IF SpeedCount& / 1800 = SpeedCount& \ 1800 AND CountLimit%% >= 2 THEN
                'Speed increases every 30s
                'As the vertical speed of the piece increases, the score for a complete row increases
                CountLimit%% = CountLimit%% - 2
                SpeedBonus! = 1 + (30 - CountLimit%%) / 20
            END IF
            IF Count%% >= CountLimit%% THEN 'CountLimit%% sets speed of fall
                IF NOT CanMove%%(InPiece%%(0), Q%%, InPiece%%(2), InPiece%%(3) + 1) THEN
                    'Add piece to grid
                    AddPiece%% = True
                    DropBonus! = 1
                ELSE
                    InPiece%%(3) = InPiece%%(3) + 1
                END IF
                Count%% = 0
            END IF
        END IF
        K$ = INKEY$
        'Use arrow keys & Spacebar to move piece.
        IF K$ <> "" THEN
            Drop%% = False
            IF UCASE$(K$) = "Q" OR ASC(K$) = 27 THEN
                InPlay%% = False
            ELSEIF UCASE$(K$) = "P" THEN
                'Pause
                Paused%% = NOT Paused%%
            ELSEIF K$ = " " AND NOT Paused%% THEN 'Space Bar
                'Drop the piece
                Drop%% = True
            ELSEIF ASC(K$) = 0 AND NOT Paused%% THEN
                SELECT CASE RIGHT$(K$, 1)
                    CASE "H" 'Up Arrow Key
                        'Rotate the piece
                        IF InPiece%%(0) > 1 THEN
                            Q1%% = Q%% + 1
                            SELECT CASE InPiece%%(0)
                                CASE 2, 4, 5
                                    IF Q1%% > 1 THEN Q1%% = 0
                                CASE 3, 6, 7
                                    IF Q1%% > 3 THEN Q1%% = 0
                            END SELECT
                            IF CanMove%%(InPiece%%(0), Q1%%, InPiece%%(2), InPiece%%(3)) THEN
                                Q%% = Q1%%
                            END IF
                        END IF
                    CASE "M" 'Right Arrow Key
                        'Move Right
                        IF CanMove%%(InPiece%%(0), Q%%, InPiece%%(2) + 1, InPiece%%(3)) THEN InPiece%%(2) = InPiece%%(2) + 1
                    CASE "K" 'Left Arrow Key
                        'Move Left
                        IF CanMove%%(InPiece%%(0), Q%%, InPiece%%(2) - 1, InPiece%%(3)) THEN InPiece%%(2) = InPiece%%(2) - 1
                    CASE "P" 'Down Arrow Key
                        'Drop the piece
                        Drop%% = True
                END SELECT
            END IF
            IF Drop%% THEN
                M%% = InPiece%%(3) + 1
                MStart%% = M%%
                WHILE Drop%% AND M%% <= 21
                    IF NOT CanMove%%(InPiece%%(0), Q%%, InPiece%%(2), M%%) THEN
                        InPiece%%(3) = M%% - 1
                        Drop%% = False
                        AddPiece%% = True
                        'The larger the distance of drop, the higher the score for a complete row
                        DropBonus! = 1 + (InPiece%%(3) + 1 - MStart%%) / 20
                    ELSE
                        M%% = M%% + 1
                    END IF
                WEND
            END IF
            K$ = ""
        END IF
        IF AddPiece%% THEN
            'Add the old piece to the grid
            FOR M%% = 0 TO 3
                FOR N%% = 0 TO 3
                    IF Array%%(InPiece%%(0), Q%%, N%%, M%%) <> 0 THEN Grid%%(InPiece%%(2) + Offsets%%(InPiece%%(0), Q%%, 0) + N%%, InPiece%%(3) + Offsets%%(InPiece%%(0), Q%%, 1) + M%%) = Array%%(InPiece%%(0), Q%%, N%%, M%%)
                NEXT N%%
            NEXT M%%
            'Start new piece
            InPiece%%(0) = InPiece%%(1)
            InPiece%%(1) = 1 + INT(7 * RND)
            InPiece%%(2) = 5
            InPiece%%(3) = 0
            Q%% = 0
            AddPiece%% = False
            Count%% = 0
            IF NOT CanMove%%(InPiece%%(0), Q%%, InPiece%%(2), InPiece%%(3)) THEN
                'New piece has nowhere to move
                GameOver%% = True
            ELSE
                'Remove all filled lines and drop down - the essence of this game
                ReDoFromStart%% = True
                MStart%% = 20
                WHILE ReDoFromStart%%
                    NoFull%% = 0
                    FOR N%% = 1 TO 10
                        IF Grid%%(N%%, MStart%%) <> 0 THEN NoFull%% = NoFull%% + 1
                    NEXT N%%
                    IF NoFull%% = 0 THEN
                        ReDoFromStart%% = False
                    ELSEIF NoFull%% = 10 THEN
                        Score% = Score% + CINT(10 * DropBonus! * SpeedBonus!)
                        Scan%% = True
                        M%% = MStart%%
                        WHILE Scan%%
                            NextLineFull%% = 0
                            FOR N%% = 1 TO 10
                                Grid%%(N%%, M%%) = Grid%%(N%%, M%% - 1)
                                NextLineFull%% = NextLineFull%% + Grid%%(N%%, M%% - 1)
                            NEXT N%%
                            IF NextLineFull%% = 0 THEN
                                Scan%% = False
                            ELSE
                                M%% = M%% - 1
                            END IF
                        WEND
                    ELSE
                        MStart%% = MStart%% - 1
                    END IF
                WEND
            END IF
        END IF
    END IF

    'Display the score
    COLOR _RGB32(0, 0, 0)
    S$ = LTRIM$(STR$(Score%))
    _PRINTSTRING (755 - LEN(S$) * 22, 640), S$ + "  "
    IF NOT GameOver%% THEN
        'Display squares existing in grid
        FOR M%% = 0 TO 20
            FOR N%% = 1 TO 10
                IF Grid%%(N%%, M%%) <> 0 THEN _PUTIMAGE ((N%% - 1) * 50, (M%% - 1) * 50), Squares&(Grid%%(N%%, M%%))
            NEXT N%%
        NEXT M%%
        'Display the piece in play
        _PUTIMAGE ((InPiece%%(2) - 1 + Offsets%%(InPiece%%(0), Q%%, 0)) * 50, (InPiece%%(3) - 1 + Offsets%%(InPiece%%(0), Q%%, 1)) * 50), Pieces&(InPiece%%(0), Q%%)
        'Display the next piece
        _PUTIMAGE (755 - 75 + Offsets%%(InPiece%%(1), 0, 0), 150), Pieces&(InPiece%%(1), 0)
    ELSE
        'Display Game Over Banner
        COLOR _RGB32(100, 0, 0)
        _PRINTSTRING (40, 200), "Game Over"
        _PRINTSTRING (64, 400), "Press Any"
        _PRINTSTRING (120, 500), "Key To"
        _PRINTSTRING (140, 600), "Finish"
        _PRINTSTRING (570, 50), "                  "
        IF INKEY$ <> "" THEN InPlay%% = False
    END IF
    _DISPLAY
WEND

CLS
IF Score% > HiScore% THEN
    HiScore% = Score%
    OPEN "HiScore.txt" FOR OUTPUT AS #2
    WRITE #2, HiScore%
    CLOSE #2
END IF

SYSTEM

FUNCTION HardwareImage& (ImageName&)
    HardwareImage& = _COPYIMAGE(ImageName&, 33)
    _FREEIMAGE ImageName&
END FUNCTION

FUNCTION CanMove%% (P%%, QA%%, IPos%%, JPos%%)
    'How this is used for Rotation, Sideways Movement & Downward Movement:
    'Make temporary translation & see if any non-zero cells co-incide.  If so, translation not allowed.
    'Movement down, as above then stop and add.
    'Drop, as above, trying each row intervening sequentially
    I%% = 0
    J%% = 0
    ItsOK%% = True
    WHILE ItsOK%% AND I%% <= 3
        A%% = IPos%% + Offsets%%(P%%, QA%%, 0) + I%%
        B%% = JPos%% + Offsets%%(P%%, QA%%, 1) + J%%
        IF A%% >= 0 AND A%% <= 11 AND B%% >= 0 AND B%% <= 21 THEN
            IF (Grid%%(A%%, B%%)) > 0 AND (Array%%(P%%, QA%%, I%%, J%%) > 0) THEN ItsOK%% = False
        END IF
        J%% = J%% + 1
        IF J%% > 3 THEN
            J%% = 0
            I%% = I%% + 1
        END IF
    WEND
    IF ItsOK%% THEN
        CanMove%% = True
    ELSE
        CanMove%% = False
    END IF
END FUNCTION

v1.1 (small)
Code: (Select All)
'Tettris Program v1 5/9/25 by Magdha QB64 v2.0
'Thanks to https://blog.alexrinehart.net for input images

'Smaller window version for non- HD 1080 vertical resolution monitor.
'Similar to a well-known tile manipulation program
'Get higher scores if you drop the pieces and as the game speeds up

'Piece Movement:
'Left/Right Arrow Keys, move left or right
'Up Arrow Key, rotate piece counter-clockwise
'Down Arrow Key or Space Bar, drop the piece
'P, Pause/unpause
'Esc or Q, Quit

CONST False = 0, True = NOT False
RANDOMIZE (TIMER)

'Declare arrays
'Shared Arrays Grid%%(), Array%%(), Offsets%%() are used in main code and in Function
DIM SHARED Grid%%(11, 21), Array%%(7, 3, 3, 3), Offsets%%(7, 3, 1)
DIM Squares&(7), Pieces&(7, 3), InPiece%%(3)

_TITLE ("Tettris v1.1")

'Define the working grid (10x20)
'Columns 0 & 11 and row 21 need to have non-zero value so that piece in play recognises boundaries
FOR M%% = 0 TO 21
    Grid%%(0, M%%) = 8
    Grid%%(11, M%%) = 8
NEXT M%%
FOR N%% = 0 TO 11
    Grid%%(N%%, 21) = 8
NEXT N%%

'Define Arrays for the movement of pieces within the working grid
'Array%%() values will be used to populate Grid%%() when a piece is fixed to the grid
'Laborious manual input code required for all pieces, all orientations
'Array%%() dimensions are: Piece no., orientation, x-direction, y-direction
'O-Piece
Array%%(1, 0, 0, 0) = 1
Array%%(1, 0, 1, 0) = 1
Array%%(1, 0, 0, 1) = 1
Array%%(1, 0, 1, 1) = 1
'I-Piece
Array%%(2, 0, 0, 0) = 2
Array%%(2, 0, 1, 0) = 2
Array%%(2, 0, 2, 0) = 2
Array%%(2, 0, 3, 0) = 2
Array%%(2, 1, 0, 0) = 2
Array%%(2, 1, 0, 1) = 2
Array%%(2, 1, 0, 2) = 2
Array%%(2, 1, 0, 3) = 2
'T-piece
Array%%(3, 0, 0, 0) = 3
Array%%(3, 0, 1, 0) = 3
Array%%(3, 0, 2, 0) = 3
Array%%(3, 0, 1, 1) = 3
Array%%(3, 1, 0, 0) = 3
Array%%(3, 1, 0, 1) = 3
Array%%(3, 1, 0, 2) = 3
Array%%(3, 1, 1, 1) = 3
Array%%(3, 2, 0, 1) = 3
Array%%(3, 2, 1, 1) = 3
Array%%(3, 2, 2, 1) = 3
Array%%(3, 2, 1, 0) = 3
Array%%(3, 3, 1, 0) = 3
Array%%(3, 3, 1, 1) = 3
Array%%(3, 3, 1, 2) = 3
Array%%(3, 3, 0, 1) = 3
'S-Piece
Array%%(4, 0, 1, 0) = 4
Array%%(4, 0, 2, 0) = 4
Array%%(4, 0, 0, 1) = 4
Array%%(4, 0, 1, 1) = 4
Array%%(4, 1, 0, 0) = 4
Array%%(4, 1, 0, 1) = 4
Array%%(4, 1, 1, 1) = 4
Array%%(4, 1, 1, 2) = 4
'Z-Piece
Array%%(5, 0, 0, 0) = 5
Array%%(5, 0, 1, 0) = 5
Array%%(5, 0, 1, 1) = 5
Array%%(5, 0, 2, 1) = 5
Array%%(5, 1, 0, 1) = 5
Array%%(5, 1, 0, 2) = 5
Array%%(5, 1, 1, 0) = 5
Array%%(5, 1, 1, 1) = 5
'J-Piece
Array%%(6, 0, 0, 0) = 6
Array%%(6, 0, 1, 0) = 6
Array%%(6, 0, 2, 0) = 6
Array%%(6, 0, 2, 1) = 6
Array%%(6, 1, 0, 0) = 6
Array%%(6, 1, 1, 0) = 6
Array%%(6, 1, 0, 1) = 6
Array%%(6, 1, 0, 2) = 6
Array%%(6, 2, 0, 0) = 6
Array%%(6, 2, 0, 1) = 6
Array%%(6, 2, 1, 1) = 6
Array%%(6, 2, 2, 1) = 6
Array%%(6, 3, 1, 0) = 6
Array%%(6, 3, 1, 1) = 6
Array%%(6, 3, 1, 2) = 6
Array%%(6, 3, 0, 2) = 6
'L-Piece
Array%%(7, 0, 0, 0) = 7
Array%%(7, 0, 1, 0) = 7
Array%%(7, 0, 2, 0) = 7
Array%%(7, 0, 0, 1) = 7
Array%%(7, 1, 0, 0) = 7
Array%%(7, 1, 0, 1) = 7
Array%%(7, 1, 0, 2) = 7
Array%%(7, 1, 1, 2) = 7
Array%%(7, 2, 2, 0) = 7
Array%%(7, 2, 0, 1) = 7
Array%%(7, 2, 1, 1) = 7
Array%%(7, 2, 2, 1) = 7
Array%%(7, 3, 0, 0) = 7
Array%%(7, 3, 1, 0) = 7
Array%%(7, 3, 1, 1) = 7
Array%%(7, 3, 1, 2) = 7

'Define Position offsets
'These are the starting offset values, laboriously manually input code
'These offsets are used to centre the piece as close to column 5 as possible at start
'Offsets%%() dimensions are: Piece no., orientation, x- (0) or y- (1)
Offsets%%(2, 0, 0) = -1
Offsets%%(2, 1, 1) = -1
Offsets%%(3, 0, 0) = -1
Offsets%%(3, 1, 1) = -1
Offsets%%(3, 2, 0) = -1
Offsets%%(3, 2, 1) = -1
Offsets%%(3, 3, 0) = -1
Offsets%%(3, 3, 1) = -1
Offsets%%(4, 0, 0) = -1
Offsets%%(4, 1, 1) = -1
Offsets%%(5, 0, 0) = -1
Offsets%%(5, 1, 0) = -1
Offsets%%(6, 0, 0) = -1
Offsets%%(6, 1, 1) = -1
Offsets%%(6, 2, 0) = -1
Offsets%%(6, 2, 1) = -1
Offsets%%(6, 3, 0) = -1
Offsets%%(6, 3, 1) = -1
Offsets%%(7, 0, 0) = -1
Offsets%%(7, 1, 1) = -1
Offsets%%(7, 2, 0) = -1
Offsets%%(7, 2, 1) = -1
Offsets%%(7, 3, 0) = -1
Offsets%%(7, 3, 1) = -1

'Load Squares images and generate images for all pieces, all orientations
'These images are all hardware
TempImg& = _LOADIMAGE("O-Square.png", 32)
TempImg1& = _NEWIMAGE(60, 60, 32)
FOR N%% = 0 TO 1
    FOR M%% = 0 TO 1
        _PUTIMAGE (N%% * 30, M%% * 30)-(29 + N%% * 30, 29 + M%% * 30), TempImg&, TempImg1&
    NEXT M%%
NEXT N%%
Pieces&(1, 0) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(30, 30, 32)
_PUTIMAGE , TempImg&, TempImg1&
Squares&(1) = HardwareImage&(TempImg1&)
_FREEIMAGE TempImg&
TempImg& = _LOADIMAGE("I-Square.png", 32)
TempImg1& = _NEWIMAGE(120, 30, 32)
FOR N%% = 0 TO 3
    _PUTIMAGE (N%% * 30, 0)-(29 + N%% * 30, 29), TempImg&, TempImg1&
NEXT N%%
Pieces&(2, 0) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(30, 120, 32)
FOR M%% = 0 TO 3
    _PUTIMAGE (0, M%% * 30)-(29, 29 + M%% * 30), TempImg&, TempImg1&
NEXT M%%
Pieces&(2, 1) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(30, 30, 32)
_PUTIMAGE , TempImg&, TempImg1&
Squares&(2) = HardwareImage&(TempImg1&)
_FREEIMAGE TempImg&
TempImg& = _LOADIMAGE("T-Square.png", 32)
TempImg1& = _NEWIMAGE(90, 60, 32)
FOR N%% = 0 TO 2
    _PUTIMAGE (N%% * 30, 0)-(29 + N%% * 30, 29), TempImg&, TempImg1&
NEXT N%%
_PUTIMAGE (30, 30)-(59, 59), TempImg&, TempImg1&
Pieces&(3, 0) = HardwareImage&(TempImg1&) 'They rotate counter-clockwise
TempImg1& = _NEWIMAGE(90, 60, 32)
FOR N%% = 0 TO 2
    _PUTIMAGE (N%% * 30, 30)-(29 + N%% * 30, 59), TempImg&, TempImg1&
NEXT N%%
_PUTIMAGE (30, 0)-(59, 29), TempImg&, TempImg1&
Pieces&(3, 2) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(60, 90, 32)
FOR M%% = 0 TO 2
    _PUTIMAGE (0, M%% * 30)-(29, 29 + M%% * 30), TempImg&, TempImg1&
NEXT M%%
_PUTIMAGE (30, 30)-(59, 59), TempImg&, TempImg1&
Pieces&(3, 1) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(60, 90, 32)
FOR M%% = 0 TO 2
    _PUTIMAGE (30, M%% * 30)-(59, 29 + M%% * 30), TempImg&, TempImg1&
NEXT M%%
_PUTIMAGE (0, 30)-(29, 59), TempImg&, TempImg1&
Pieces&(3, 3) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(30, 30, 32)
_PUTIMAGE , TempImg&, TempImg1&
Squares&(3) = HardwareImage&(TempImg1&)
_FREEIMAGE TempImg&
TempImg& = _LOADIMAGE("S-Square.png", 32)
TempImg1& = _NEWIMAGE(90, 60, 32)
FOR N%% = 1 TO 2
    _PUTIMAGE (N%% * 30, 0)-(29 + N%% * 30, 29), TempImg&, TempImg1&
    _PUTIMAGE ((N%% - 1) * 30, 30)-(29 + (N%% - 1) * 30, 59), TempImg&, TempImg1&
NEXT N%%
Pieces&(4, 0) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(60, 90, 32)
FOR M%% = 1 TO 2
    _PUTIMAGE (0, (M%% - 1) * 30)-(29, 29 + (M%% - 1) * 30), TempImg&, TempImg1&
    _PUTIMAGE (30, M%% * 30)-(59, 29 + M%% * 30), TempImg&, TempImg1&
NEXT M%%
Pieces&(4, 1) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(30, 30, 32)
_PUTIMAGE , TempImg&, TempImg1&
Squares&(4) = HardwareImage&(TempImg1&)
_FREEIMAGE TempImg&
TempImg& = _LOADIMAGE("Z-Square.png", 32)
TempImg1& = _NEWIMAGE(90, 60, 32)
FOR N%% = 1 TO 2
    _PUTIMAGE (N%% * 30, 30)-(29 + N%% * 30, 59), TempImg&, TempImg1&
    _PUTIMAGE ((N%% - 1) * 30, 0)-(29 + (N%% - 1) * 30, 29), TempImg&, TempImg1&
NEXT N%%
Pieces&(5, 0) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(60, 90, 32)
FOR M%% = 1 TO 2
    _PUTIMAGE (30, (M%% - 1) * 30)-(59, 29 + (M%% - 1) * 30), TempImg&, TempImg1&
    _PUTIMAGE (0, M%% * 30)-(29, 29 + M%% * 30), TempImg&, TempImg1&
NEXT M%%
Pieces&(5, 1) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(30, 30, 32)
_PUTIMAGE , TempImg&, TempImg1&
Squares&(5) = HardwareImage&(TempImg1&)
_FREEIMAGE TempImg&
TempImg& = _LOADIMAGE("J-Square.png", 32)
TempImg1& = _NEWIMAGE(90, 60, 32)
FOR N%% = 0 TO 2
    _PUTIMAGE (N%% * 30, 0)-(29 + N%% * 30, 29), TempImg&, TempImg1&
NEXT N%%
_PUTIMAGE (60, 30)-(129, 59), TempImg&, TempImg1&
Pieces&(6, 0) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(60, 90, 32)
FOR M%% = 0 TO 2
    _PUTIMAGE (30, M%% * 30)-(59, 29 + M%% * 30), TempImg&, TempImg1&
NEXT M%%
_PUTIMAGE (0, 60)-(29, 129), TempImg&, TempImg1&
Pieces&(6, 3) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(90, 60, 32)
FOR N%% = 0 TO 2
    _PUTIMAGE (N%% * 30, 30)-(29 + N%% * 30, 59), TempImg&, TempImg1&
NEXT N%%
_PUTIMAGE (0, 0)-(29, 29), TempImg&, TempImg1&
Pieces&(6, 2) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(60, 90, 32)
FOR M%% = 0 TO 2
    _PUTIMAGE (0, M%% * 30)-(29, 29 + M%% * 30), TempImg&, TempImg1&
NEXT M%%
_PUTIMAGE (30, 0)-(59, 29), TempImg&, TempImg1&
Pieces&(6, 1) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(30, 30, 32)
_PUTIMAGE , TempImg&, TempImg1&
Squares&(6) = HardwareImage&(TempImg1&)
_FREEIMAGE TempImg&
TempImg& = _LOADIMAGE("L-Square.png", 32)
TempImg1& = _NEWIMAGE(90, 60, 32)
FOR N%% = 0 TO 2
    _PUTIMAGE (N%% * 30, 0)-(29 + N%% * 30, 29), TempImg&, TempImg1&
NEXT N%%
_PUTIMAGE (0, 30)-(29, 59), TempImg&, TempImg1&
Pieces&(7, 0) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(60, 90, 32)
FOR M%% = 0 TO 2
    _PUTIMAGE (30, M%% * 30)-(59, 29 + M%% * 30), TempImg&, TempImg1&
NEXT M%%
_PUTIMAGE (0, 0)-(29, 29), TempImg&, TempImg1&
Pieces&(7, 3) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(90, 60, 32)
FOR N%% = 0 TO 2
    _PUTIMAGE (N%% * 30, 30)-(29 + N%% * 30, 59), TempImg&, TempImg1&
NEXT N%%
_PUTIMAGE (60, 0)-(129, 29), TempImg&, TempImg1&
Pieces&(7, 2) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(60, 90, 32)
FOR M%% = 0 TO 2
    _PUTIMAGE (0, M%% * 30)-(29, 29 + M%% * 30), TempImg&, TempImg1&
NEXT M%%
_PUTIMAGE (30, 60)-(59, 129), TempImg&, TempImg1&
Pieces&(7, 1) = HardwareImage&(TempImg1&)
TempImg1& = _NEWIMAGE(30, 30, 32)
_PUTIMAGE , TempImg&, TempImg1&
Squares&(7) = HardwareImage&(TempImg1&)
_FREEIMAGE TempImg&

'Load High Score
IF _FILEEXISTS("HiScore.txt") THEN
    OPEN "HiScore.txt" FOR INPUT AS #1
    INPUT #1, HiScore%
    CLOSE #1
ELSE
    HiScore% = 0
END IF

'Screen
'HD 1080 vertical resolution monitor required.
SCREEN _NEWIMAGE(606, 600, 32)
_SCREENMOVE 180, 20
_DEST 0
COLOR _RGB32(0, 0, 0), _RGB32(0, 85, 0)
CLS
_FONT _LOADFONT(ENVIRON$("SYSTEMROOT") + "\Fonts\Arial.ttf", 48, "Bold")
'Software images:
_PRINTSTRING (342, 30), "Next Piece:"
_PRINTSTRING (390, 330), "Score"
IF HiScore% > 0 THEN
    _PRINTSTRING (336, 480), "High Score"
    H$ = LTRIM$(STR$(HiScore%))
    _PRINTSTRING (453 - LEN(H$) * 13, 534), H$
END IF
'Area Delineations
LINE (300, 0)-(306, 599), _RGB(180, 0, 0), BF
LINE (300, 240)-(605, 246), _RGB(180, 0, 0), BF

'Initial Conditions
InPlay%% = True
Count%% = 0
SpeedCount& = 0
CountLimit%% = 30
SpeedBonus! = 1
DropBonus! = 1
Paused%% = False
AddPiece%% = False
GameOver%% = False
Score% = 0
'Set up first in-play piece and next piece
InPiece%%(0) = 1 + INT(7 * RND) 'Piece in play
InPiece%%(1) = 1 + INT(7 * RND) 'Next piece
InPiece%%(2) = 5 'Start column
InPiece%%(3) = 0 'Start row
Q%% = 0 'Orientation

'Loop for play
WHILE InPlay%%
    _LIMIT 60

    IF NOT GameOver%% THEN
        IF NOT Paused%% THEN
            Count%% = Count%% + 1
            SpeedCount& = SpeedCount& + 1
            IF SpeedCount& / 1800 = SpeedCount& \ 1800 AND CountLimit%% >= 2 THEN
                'Speed increases every 30s
                'As the vertical speed of the piece increases, the score for a complete row increases
                CountLimit%% = CountLimit%% - 2
                SpeedBonus! = 1 + (30 - CountLimit%%) / 20
            END IF
            IF Count%% >= CountLimit%% THEN 'CountLimit%% sets speed of fall
                IF NOT CanMove%%(InPiece%%(0), Q%%, InPiece%%(2), InPiece%%(3) + 1) THEN
                    'Add piece to grid
                    AddPiece%% = True
                    DropBonus! = 1
                ELSE
                    InPiece%%(3) = InPiece%%(3) + 1
                END IF
                Count%% = 0
            END IF
        END IF
        K$ = INKEY$
        'Use arrow keys & Spacebar to move piece.
        IF K$ <> "" THEN
            Drop%% = False
            IF UCASE$(K$) = "Q" OR ASC(K$) = 27 THEN
                InPlay%% = False
            ELSEIF UCASE$(K$) = "P" THEN
                'Pause
                Paused%% = NOT Paused%%
            ELSEIF K$ = " " AND NOT Paused%% THEN 'Space Bar
                'Drop the piece
                Drop%% = True
            ELSEIF ASC(K$) = 0 AND NOT Paused%% THEN
                SELECT CASE RIGHT$(K$, 1)
                    CASE "H" 'Up Arrow Key
                        'Rotate the piece
                        IF InPiece%%(0) > 1 THEN
                            Q1%% = Q%% + 1
                            SELECT CASE InPiece%%(0)
                                CASE 2, 4, 5
                                    IF Q1%% > 1 THEN Q1%% = 0
                                CASE 3, 6, 7
                                    IF Q1%% > 3 THEN Q1%% = 0
                            END SELECT
                            IF CanMove%%(InPiece%%(0), Q1%%, InPiece%%(2), InPiece%%(3)) THEN
                                Q%% = Q1%%
                            END IF
                        END IF
                    CASE "M" 'Right Arrow Key
                        'Move Right
                        IF CanMove%%(InPiece%%(0), Q%%, InPiece%%(2) + 1, InPiece%%(3)) THEN InPiece%%(2) = InPiece%%(2) + 1
                    CASE "K" 'Left Arrow Key
                        'Move Left
                        IF CanMove%%(InPiece%%(0), Q%%, InPiece%%(2) - 1, InPiece%%(3)) THEN InPiece%%(2) = InPiece%%(2) - 1
                    CASE "P" 'Down Arrow Key
                        'Drop the piece
                        Drop%% = True
                END SELECT
            END IF
            IF Drop%% THEN
                M%% = InPiece%%(3) + 1
                MStart%% = M%%
                WHILE Drop%% AND M%% <= 21
                    IF NOT CanMove%%(InPiece%%(0), Q%%, InPiece%%(2), M%%) THEN
                        InPiece%%(3) = M%% - 1
                        Drop%% = False
                        AddPiece%% = True
                        'The larger the distance of drop, the higher the score for a complete row
                        DropBonus! = 1 + (InPiece%%(3) + 1 - MStart%%) / 20
                    ELSE
                        M%% = M%% + 1
                    END IF
                WEND
            END IF
            K$ = ""
        END IF
        IF AddPiece%% THEN
            'Add the old piece to the grid
            FOR M%% = 0 TO 3
                FOR N%% = 0 TO 3
                    IF Array%%(InPiece%%(0), Q%%, N%%, M%%) <> 0 THEN Grid%%(InPiece%%(2) + Offsets%%(InPiece%%(0), Q%%, 0) + N%%, InPiece%%(3) + Offsets%%(InPiece%%(0), Q%%, 1) + M%%) = Array%%(InPiece%%(0), Q%%, N%%, M%%)
                NEXT N%%
            NEXT M%%
            'Start new piece
            InPiece%%(0) = InPiece%%(1)
            InPiece%%(1) = 1 + INT(7 * RND)
            InPiece%%(2) = 5
            InPiece%%(3) = 0
            Q%% = 0
            AddPiece%% = False
            Count%% = 0
            IF NOT CanMove%%(InPiece%%(0), Q%%, InPiece%%(2), InPiece%%(3)) THEN
                'New piece has nowhere to move
                GameOver%% = True
            ELSE
                'Remove all filled lines and drop down - the essence of this game
                ReDoFromStart%% = True
                MStart%% = 20
                WHILE ReDoFromStart%%
                    NoFull%% = 0
                    FOR N%% = 1 TO 10
                        IF Grid%%(N%%, MStart%%) <> 0 THEN NoFull%% = NoFull%% + 1
                    NEXT N%%
                    IF NoFull%% = 0 THEN
                        ReDoFromStart%% = False
                    ELSEIF NoFull%% = 10 THEN
                        Score% = Score% + CINT(10 * DropBonus! * SpeedBonus!)
                        Scan%% = True
                        M%% = MStart%%
                        WHILE Scan%%
                            NextLineFull%% = 0
                            FOR N%% = 1 TO 10
                                Grid%%(N%%, M%%) = Grid%%(N%%, M%% - 1)
                                NextLineFull%% = NextLineFull%% + Grid%%(N%%, M%% - 1)
                            NEXT N%%
                            IF NextLineFull%% = 0 THEN
                                Scan%% = False
                            ELSE
                                M%% = M%% - 1
                            END IF
                        WEND
                    ELSE
                        MStart%% = MStart%% - 1
                    END IF
                WEND
            END IF
        END IF
    END IF

    'Display the score
    COLOR _RGB32(0, 0, 0)
    S$ = LTRIM$(STR$(Score%))
    _PRINTSTRING (453 - LEN(S$) * 13, 384), S$ + "  "
    IF NOT GameOver%% THEN
        'Display squares existing in grid
        FOR M%% = 0 TO 20
            FOR N%% = 1 TO 10
                IF Grid%%(N%%, M%%) <> 0 THEN _PUTIMAGE ((N%% - 1) * 30, (M%% - 1) * 30), Squares&(Grid%%(N%%, M%%))
            NEXT N%%
        NEXT M%%
        'Display the piece in play
        _PUTIMAGE ((InPiece%%(2) - 1 + Offsets%%(InPiece%%(0), Q%%, 0)) * 30, (InPiece%%(3) - 1 + Offsets%%(InPiece%%(0), Q%%, 1)) * 30), Pieces&(InPiece%%(0), Q%%)
        'Display the next piece
        _PUTIMAGE (453 - 45 + Offsets%%(InPiece%%(1), 0, 0), 90), Pieces&(InPiece%%(1), 0)
    ELSE
        'Display Game Over Banner
        COLOR _RGB32(100, 0, 0)
        _PRINTSTRING (24, 120), "Game Over"
        _PRINTSTRING (38, 240), "Press Any"
        _PRINTSTRING (72, 300), "Key To"
        _PRINTSTRING (84, 360), "Finish"
        _PRINTSTRING (342, 30), "                  "
        IF INKEY$ <> "" THEN InPlay%% = False
    END IF
    _DISPLAY
WEND

CLS
IF Score% > HiScore% THEN
    HiScore% = Score%
    OPEN "HiScore.txt" FOR OUTPUT AS #2
    WRITE #2, HiScore%
    CLOSE #2
END IF

SYSTEM

FUNCTION HardwareImage& (ImageName&)
    HardwareImage& = _COPYIMAGE(ImageName&, 33)
    _FREEIMAGE ImageName&
END FUNCTION

FUNCTION CanMove%% (P%%, QA%%, IPos%%, JPos%%)
    'How this is used for Rotation, Sideways Movement & Downward Movement:
    'Make temporary translation & see if any non-zero cells co-incide.  If so, translation not allowed.
    'Movement down, as above then stop and add.
    'Drop, as above, trying each row intervening sequentially
    I%% = 0
    J%% = 0
    ItsOK%% = True
    WHILE ItsOK%% AND I%% <= 3
        A%% = IPos%% + Offsets%%(P%%, QA%%, 0) + I%%
        B%% = JPos%% + Offsets%%(P%%, QA%%, 1) + J%%
        IF A%% >= 0 AND A%% <= 11 AND B%% >= 0 AND B%% <= 21 THEN
            IF (Grid%%(A%%, B%%)) > 0 AND (Array%%(P%%, QA%%, I%%, J%%) > 0) THEN ItsOK%% = False
        END IF
        J%% = J%% + 1
        IF J%% > 3 THEN
            J%% = 0
            I%% = I%% + 1
        END IF
    WEND
    IF ItsOK%% THEN
        CanMove%% = True
    ELSE
        CanMove%% = False
    END IF
END FUNCTION
Reply
#2
Welcome @Magdha

vince says Tetris is "ULTIMATE" programmers challenge because he has that one under his belt. Where did that expression come from anyway? sounds kinda dirty like what vince named his Tetris clone, ha!

Anyway bplus says until you know everything, there infinitley many "ULTIMATE" challenges, like getting the flipper action right in a pinball sim or for bplus doing 3D stuff or knowing WTH? Unseen Machine is talking about with all his library stuff! Smile

I luv your signature Maghda, "Forever Newbie" Smile

PS +1 Thank you for your consideration of us smaller screened folks by providing an alternative code. I haven't had a regular computer and monitor since the 90's.
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)