B4J Tutorial [B4X] [BitmapCreator] Creating a cross platform Tetris game

Discussion in 'B4J Tutorials' started by Erel, Jun 17, 2018.

  1. Erel

    Erel Administrator Staff Member Licensed User

    Edit: XUI2D version of Tetris: https://www.b4x.com/android/forum/threads/xui2d-tetris.107698/



    This example shows how BitmapCreator can be used to create a cross platform Tetris game.
    The code is an evolution of the code introduced in the "walking character" example.

    There are three types of modules in these projects:
    • Main module which is mostly empty and is different in each of the projects.
    • The game framework classes, shared by all three projects, and not specific to this game.
      The following classes are included:
      • GameUtils - Manages the main loop and also includes various utility methods.
      • Sprite - Each custom sprite object holds a Sprite object. The Sprite object implements all the sprite common features.
      • DummySprite - Useful for simple sprites that do not need special implementation.
      • ScoreLabel - A custom view that shows the score
    • Game specific classes, shared by all three projects:
      • Game - The main game class. GameUtils calls all kinds of methods of this class.
      • Background - The background sprite. Note that the moving pieces start as sprites and once they stop moving they are drawn onto the background sprite.
      • Piece - Represents a moving piece
    If you are interested in cross platform development then it is most important to understand how to add modules as linked modules:


    This way, changes in one project will be updated automatically in other projects.

    I will not go over all the code. If you are interested then download it, play with it and feel free to ask any question you have.

    Some interesting points:

    - The pieces structure is loaded from a text file. It defines all the pieces. For example:

    Each piece is defined with a 4x4 grid. The Pattern field defines the blocks in this grid where block (0,0) position is defined by the Center field.

    - The Rows list stores the state of all blocks. There are 20 rows and 10 blocks in each row. Each item in the Rows list is an array of booleans. Each boolean represents the state of the column in that row.
    - When a piece stops moving we check for full rows. Full rows are removed from the list and new empty rows are inserted at position 0.
    - When one or more rows are removed, the existing graphical rows are copied to a temporary BC and after the moving animation completes, back to the background bc.
    - The B4A game uses Immersive Mode: https://www.b4x.com/android/forum/threads/90882/#content
    - The B4i game uses full screen: https://www.b4x.com/android/forum/threads/full-screen-apps.47866/#content
    - The clickable labels in B4A and B4i provide haptic feedback. It is done with NativeObject / JavaObject.
    - The blocks graphics are made from this greyscale image:
    - GameUtils.GreyscaleToColor sub is used to create copies of this image with different colors.
    - All the layout handling is done with two layout files. The first sets the main layout and the second uses designer script to set the ImageView width/height ratio:
    GameRatio = 2
    ScreenRatio = 
    100%y / 100%x
    If ScreenRatio > GameRatio Then
     Pane1.Height = Pane1.Width * GameRatio
     Pane1.VerticalCenter = 
     Pane1.Width = Pane1.Height / GameRatio
     Pane1.HorizontalCenter = 
    End If
    2dip, Pane1.Width - 2dip)
    2dip, Pane1.Height - 2dip)
    The ImageView is inside a Panel named Pane1.
    - All the game logic was developed and tested with B4J. Once the main things worked I ported it to B4A and B4i.

    Credits: Font and inspiration: https://github.com/spypunk/tetris
    - Tetris itself is a trademark of The Tetris Company. It is used here for educational purposes only.

    Edit: This game was created before XUI2D and the X2 framework were available. It is recommended to use XUI2D for new games.

    Attached Files:

    Last edited: Jul 16, 2019
    giga, Mark Turney, koaunglay and 22 others like this.
  2. Kancane

    Kancane New Member Licensed User

    Great !
    This is my favorite game !
    A big thank you for the source code...
  3. narek adonts

    narek adonts Well-Known Member Licensed User

    error in b4i.

    XUI.scale missing method
  4. stevel05

    stevel05 Expert Licensed User

    Thanks Erel, it's my favourite game.

    I have noticed a bug if you try to rotate a piece as soon as it is displayed, the row number calculated in the CanMove Sub can be -1 resulting in the error in the Game IsTaken sub:

    java.lang.RuntimeException: java.lang.RuntimeException: java.lang.ArrayIndexOutOfBoundsException: -1

    It doesn't do it every time, but often enough to be repeatable.

    Tested with the B4j implementation
    Erel likes this.
  5. Erel

    Erel Administrator Staff Member Licensed User

    Note that there is a bug that causes the game to crash if you rotate some of the pieces when they are at the top position. Will be fixed.

    You should use iXUI v1.70+. It was included in B4i v5.00.
    narek adonts likes this.
  6. Erel

    Erel Administrator Staff Member Licensed User

    Just noticed it as well while playing on my phone :)

    Will be fixed.
    Johan Hormaza and stevel05 like this.
  7. jamal

    jamal New Member

    Public Sub ToDrawTask As DrawTask unknwon
    problem solved! thanks Erel
    Last edited: Jun 20, 2018
  8. Erel

    Erel Administrator Staff Member Licensed User

    See the dependencies section at the end of the first post.
  9. Erel

    Erel Administrator Staff Member Licensed User

    An updated version was uploaded. It fixes the crash discussed above.
    Beja and stevel05 like this.
  10. stevel05

    stevel05 Expert Licensed User

    Thanks Erel, the problem I see now is that the pieces do not rotate if they are in the first row. I've changed the 3 Row number calculations to

    Dim RowNumber As Int = Max(0,b(1) + CenterPositionY + dy)
    Dim RowNumber As Int = Max(0,b(1) + CenterPositionY)
    Which seems to work and allows rotation in the first row. I can't see that it will cause any other problems, but I wanted to ask you just in case I missed something. I haven't been through all of the code yet.
  11. Erel

    Erel Administrator Staff Member Licensed User

    I'm not sure that it is a problem. There are some edge cases where it is not possible to rotate the piece.

    If you do want to allow it then the best solution is to allow blocks to be located in negative rows. It will require a few changes.
  12. stevel05

    stevel05 Expert Licensed User

    Yes of course, I hadn't considered that. It's best left as it is then :)
  13. Erel

    Erel Administrator Staff Member Licensed User

    Projects updated to be compatible with latest version of BitmapCreator.
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice