User prompt
Recheck the code
User prompt
Make code game tetris
User prompt
Fix Bug: 'Cannot read properties of undefined (reading 'length')' in this line: 'var type = nextTetrominoType != null ? nextTetrominoType : tetrominoTypes[Math.floor(Math.random() * tetrominoTypes.length)];' Line Number: 283
User prompt
Fix Bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'length')' in this line: 'var type = nextTetrominoType != null ? nextTetrominoType : tetrominoTypes[Math.floor(Math.random() * tetrominoTypes.length)];' Line Number: 283
User prompt
Organize the code
User prompt
Fix Bug: 'Uncaught TypeError: Cannot read properties of undefined (reading 'initialize')' in this line: 'GameState.initialize();' Line Number: 399
User prompt
Add everything you need for tetris
User prompt
fix bug
User prompt
Test the code and fix logic and value errors
User prompt
Add to the code what is missing for the game
User prompt
Optimize the code
User prompt
Optimize the engine
User prompt
Optimize the game engine
User prompt
fix bug
User prompt
The code should employ full 'classes' for game objects and avoid the direct creation of art assets. Check that all graphical assets are being retrieved using `LK.getAsset` and that no direct PIXI calls are being made
User prompt
Elements with unique behaviors should be categorized into separate asset classes. Review the code to ensure that there is a clear distinction between different types of game objects and that they are using distinct assets
User prompt
Instances should be created and destroyed within the core game logic. Check for any instances that are created outside of the game logic or that are not properly destroyed when no longer needed
User prompt
The game logic should be written at the bottom of the source file. To check if this guideline is followed, review the code structure and ensure that the game logic is not interspersed throughout the file but is instead consolidated at the bottom
User prompt
Game elements should be initialized with their starting position. Review the code to ensure that all game elements are placed correctly when the game starts.
User prompt
Game elements that should be centered must account for asset size. Check that elements like the game board are centered correctly on the screen.
User prompt
Custom event handlers should be designed for touch event positions using `obj.event.getLocalPosition`. Check that the code is not using `clientX` or `clientY` and that event positions are handled correctly
User prompt
For size calculations related to assets, `.width` and `.height` should be used instead of hardcoded values. Review the code to ensure that size calculations are dynamic and based on the actual asset dimensions.
User prompt
Graphics should be retrieved with `LK.getAsset`, specifying the anchor points. Check that all assets are loaded using this method and that anchor points are set correctly.
User prompt
The code should employ full 'classes' for game objects and avoid the direct creation of art assets. Check that all graphical assets are being retrieved using `LK.getAsset` and that no direct PIXI calls are being made.
User prompt
Elements with unique behaviors should be categorized into separate asset classes. Review the code to ensure that there is a clear distinction between different types of game objects and that they are using distinct assets.
/**** 
* Classes
****/
var TetrominoBlock = Container.expand(function (type, i, j, blockSize) {
  var self = Container.call(this);
  var blockGraphic = self.createAsset('tetromino_' + type, type + ' Tetromino block', 0.5, 0.5);
  self.x = j * blockSize;
  self.y = i * blockSize;
});
// Define Tetromino class
var Tetromino = Container.expand(function () {
  var self = Container.call(this);
  Tetromino.prototype.checkCollision = function (dx, dy, board) {
    for (var i = 0; i < this.blocks.length; i++) {
      var block = this.blocks[i];
      var newX = this.x + block.x + dx;
      var newY = this.y + block.y + dy;
      var gridX = Math.floor(newX / blockSize);
      var gridY = Math.floor(newY / blockSize);
      if (gridX < 0 || gridX >= boardWidth || gridY >= boardHeight) {
        return true; // Collision with board boundaries
      }
      if (gridY >= 0 && board.grid[gridY] && board.grid[gridY][gridX]) {
        return true; // Collision with another block
      }
    }
    return false;
  };
  this.blocks = [];
  this.type = '';
  this.rotationIndex = 0;
  this.initializeBlocks = function (layout) {
    this.initializeBlocks = function (layout, blockSize) {
      for (var i = 0; i < layout.length; i++) {
        for (var j = 0; j < layout[i].length; j++) {
          if (layout[i][j]) {
            var block = new TetrominoBlock(this.type, i, j, blockSize);
            this.blocks.push(this.addChild(block));
          }
        }
      }
    };
  };
  this.create = function (type, blockSize) {
    this.type = type;
    this.rotationIndex = 0;
    var layout = tetrominoLayouts[type][this.rotationIndex];
    this.initializeBlocks(layout, blockSize);
  };
  this.rotate = function () {
    var oldRotationIndex = this.rotationIndex;
    var newRotationIndex = (this.rotationIndex + 1) % tetrominoLayouts[this.type].length;
    this.rotationIndex = newRotationIndex;
    this.updateBlockPositions();
    if (this.checkCollision(0, 0, board)) {
      this.rotationIndex = oldRotationIndex;
      this.updateBlockPositions();
    }
  };
  this.updateBlockPositions = function () {
    var layout = tetrominoLayouts[this.type][this.rotationIndex];
    var k = 0;
    for (var i = 0; i < layout.length; i++) {
      for (var j = 0; j < layout[i].length; j++) {
        if (layout[i][j]) {
          this.blocks[k].x = j * this.blocks[k].width;
          this.blocks[k].y = i * this.blocks[k].height;
          k++;
        }
      }
    }
  };
  this.move = function (dx, dy) {
    if (!this.checkCollision(dx, dy, board)) {
      this.x += dx;
      this.y += dy;
    } else if (dy > 0) {
      board.fixTetromino(this);
      spawnTetromino();
    }
  };
});
// Define GameBoard class
var GameBoard = Container.expand(function () {
  var self = Container.call(this);
  this.grid = [];
  this.init = function () {
    for (var i = 0; i < boardHeight; i++) {
      this.grid[i] = [];
      for (var j = 0; j < boardWidth; j++) {
        this.grid[i][j] = null;
      }
    }
  };
  this.fixTetromino = function (tetromino) {
    var blocks = tetromino.blocks;
    for (var i = 0; i < blocks.length; i++) {
      var block = blocks[i];
      var x = Math.round((block.x + tetromino.x - this.x) / blockSize);
      var y = Math.round((block.y + tetromino.y - this.y) / blockSize);
      if (y < boardHeight && x < boardWidth) {
        this.grid[y][x] = block;
        block.x = x * blockSize;
        block.y = y * blockSize;
        this.addChild(block);
      } else if (y < 0) {
        LK.showGameOver();
        return false;
      }
    }
    this.checkLines();
    return true;
  };
  this.isGameOver = function () {
    for (var x = 0; x < boardWidth; x++) {
      if (this.grid[0][x] !== null) {
        return true;
      }
    }
    return false;
  };
  this.checkLines = function () {
    for (var y = 0; y < boardHeight; y++) {
      var lineComplete = true;
      for (var x = 0; x < boardWidth; x++) {
        if (this.grid[y][x] === null) {
          lineComplete = false;
          break;
        }
      }
      if (lineComplete) {
        for (var row = y; row > 0; row--) {
          for (var x = 0; x < boardWidth; x++) {
            this.grid[row][x] = this.grid[row - 1][x];
            if (this.grid[row][x]) {
              this.grid[row][x].y += blockSize;
            }
          }
        }
        for (var x = 0; x < boardWidth; x++) {
          this.grid[0][x] = null;
        }
        for (var x = 0; x < boardWidth; x++) {
          if (this.grid[y][x]) {
            this.grid[y][x].destroy();
            this.grid[y][x] = null;
          }
        }
        var linesCleared = 0;
        for (var y = 0; y < boardHeight; y++) {
          var lineComplete = true;
          for (var x = 0; x < boardWidth; x++) {
            if (this.grid[y][x] === null) {
              lineComplete = false;
              break;
            }
          }
          if (lineComplete) {
            linesCleared++;
            for (var row = y; row > 0; row--) {
              for (var x = 0; x < boardWidth; x++) {
                this.grid[row][x] = this.grid[row - 1][x];
                if (this.grid[row][x]) {
                  this.grid[row][x].y += blockSize;
                }
              }
            }
            for (var x = 0; x < boardWidth; x++) {
              this.grid[0][x] = null;
            }
            for (var x = 0; x < boardWidth; x++) {
              if (this.grid[y][x]) {
                this.grid[y][x].destroy();
                this.grid[y][x] = null;
              }
            }
          }
        }
        if (linesCleared > 0) {
          var scoreToAdd = linesCleared === 1 ? 100 : linesCleared === 2 ? 300 : linesCleared === 3 ? 500 : 800;
          LK.setScore(LK.getScore() + scoreToAdd);
          gameUI.updateScore(LK.getScore());
        }
      }
    }
  };
  this.init();
});
// Define LowerField class for collecting Tetrominoes
var LowerField = Container.expand(function () {
  var self = Container.call(this);
  this.init = function () {
    this.grid = [];
    for (var i = 0; i < boardHeight; i++) {
      this.grid[i] = [];
      for (var j = 0; j < boardWidth; j++) {
        this.grid[i][j] = null;
      }
    }
  };
  this.init();
  this.addBlock = function (block, x, y) {
    if (y < boardHeight && x < boardWidth) {
      this.grid[y][x] = block;
      block.x = x * blockSize;
      block.y = y * blockSize;
      this.addChild(block);
    }
  };
});
// Define GameMenu class
var GameMenu = Container.expand(function () {
  var self = Container.call(this);
  this.startButton = new Text2('Start', {
    size: 150,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0.5
    }
  });
  this.startButton.on('down', function () {
    GameState.initialize();
    self.visible = false;
  });
  this.pauseButton = new Text2('Pause', {
    size: 150,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0.5
    }
  });
  this.pauseButton.on('down', function () {
    GameState.state = 'paused';
  });
  this.resumeButton = new Text2('Resume', {
    size: 150,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0.5
    }
  });
  this.resumeButton.on('down', function () {
    GameState.state = 'active';
  });
  this.restartButton = new Text2('Restart', {
    size: 150,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0.5
    }
  });
  this.restartButton.on('down', function () {
    GameState.initialize();
  });
  LK.gui.bottom.addChild(this.startButton);
  LK.gui.bottom.addChild(this.pauseButton);
  LK.gui.bottom.addChild(this.resumeButton);
  LK.gui.bottom.addChild(this.restartButton);
  this.pauseButton.visible = false;
  this.resumeButton.visible = false;
  this.restartButton.visible = false;
});
// Create a new GameMenu instance
// Create score display
var ScoreDisplay = Container.expand(function () {
  var self = Container.call(this);
  this.scoreText = new Text2('Score: 0', {
    size: 100,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0
    }
  });
  this.levelText = new Text2('Level: 1', {
    size: 100,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0
    }
  });
  this.linesText = new Text2('Lines: 0', {
    size: 100,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0
    }
  });
  LK.gui.top.addChild(this.scoreText);
  LK.gui.top.addChild(this.levelText);
  LK.gui.top.addChild(this.linesText);
  this.levelText.y = this.scoreText.height;
  this.linesText.y = this.scoreText.height * 2;
  this.updateScore = function (score) {
    this.scoreText.setText('Score: ' + score.toString());
  };
  this.updateLevel = function (level) {
    this.levelText.setText('Level: ' + level.toString());
  };
  this.updateLinesCleared = function (lines) {
    this.linesText.setText('Lines: ' + lines.toString());
  };
});
// Create a new ScoreDisplay instance
var GameUI = Container.expand(function () {
  var self = Container.call(this);
  this.scoreText = new Text2('Score: 0', {
    size: 100,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0
    }
  });
  this.levelText = new Text2('Level: 1', {
    size: 100,
    fill: "#ffffff",
    anchor: {
      x: 0.5,
      y: 0
    }
  });
  this.nextTetrominoPreview = new Container();
  LK.gui.top.addChild(this.scoreText);
  LK.gui.top.addChild(this.levelText);
  LK.gui.topRight.addChild(this.nextTetrominoPreview);
  this.scoreText.y = 20;
  this.levelText.y = this.scoreText.height + 20;
  this.nextTetrominoPreview.y = 20;
  this.updateScore = function (score) {
    this.scoreText.setText('Score: ' + score.toString());
  };
  this.updateLevel = function (level) {
    this.levelText.setText('Level: ' + level.toString());
  };
  this.updateNextTetrominoPreview = function (type) {
    this.nextTetrominoPreview.removeChildren();
    var layout = GameState.tetrominoLayouts[type][0];
    for (var i = 0; i < layout.length; i++) {
      for (var j = 0; j < layout[i].length; j++) {
        if (layout[i][j]) {
          var block = LK.getAsset('tetromino_' + type + '_preview', 'Next Tetromino block', 0.5, 0.5);
          block.x = j * (blockSize * 0.5);
          block.y = i * (blockSize * 0.5);
          this.nextTetrominoPreview.addChild(block);
        }
      }
    }
  };
});
/**** 
* Initialize Game
****/
// Create a new GameUI instance
var game = new LK.Game({
  backgroundColor: 0x000000 // Init game with black background for better contrast
});
/**** 
* Game Code
****/
// Create a new GameMenu instance
var gameMenu = new GameMenu();
// Define game constants and variables
var GameState = {
  boardWidth: 10,
  boardHeight: 20,
  blockSize: 2048 / 10,
  // Calculate block size based on viewable area width
  fallRate: 1000,
  // Time in milliseconds between each Tetromino fall step
  score: 0,
  // Initialize current score
  level: 1,
  // Initialize game level
  state: 'active',
  // Game state can be 'paused', 'active', or 'gameOver'
  grid: [],
  initializeGrid: function () {
    for (var i = 0; i < this.boardHeight; i++) {
      this.grid[i] = [];
      for (var j = 0; j < this.boardWidth; j++) {
        this.grid[i][j] = null; // Each cell starts as null (empty)
      }
    }
  }
};
GameState.initializeGrid();
// GameBoard class is now encapsulated and instantiated separately
var board = new GameBoard();
board.init();
// Center the board on the screen
board.x = (2048 - boardWidth * blockSize) / 2;
board.y = (2732 - boardHeight * blockSize) / 2;
// Add the board to the game
game.addChild(board);
// Create a new ScoreDisplay instance
var gameUI = new GameUI();
// Initialize the first Tetromino
spawnTetromino();
// Define game constants and variables
var TetrominoMovement = {
  calculateMove: function calculateMove(tetromino, dx, dy, board) {
    var newX = tetromino.x + dx;
    var newY = tetromino.y + dy;
    var canMove = true;
    for (var i = 0; i < tetromino.blocks.length; i++) {
      var block = tetromino.blocks[i];
      var gridX = Math.round((block.x + newX - board.x) / blockSize);
      var gridY = Math.round((block.y + newY - board.y) / blockSize);
      if (gridX < 0 || gridX >= boardWidth || gridY < 0 || gridY >= boardHeight) {
        canMove = false;
        break;
      } else if (gridY >= 0 && board.grid[gridY] && board.grid[gridY][gridX]) {
        canMove = false;
        break;
      }
    }
    return {
      canMove: canMove,
      newX: newX,
      newY: newY
    };
  }
};
var boardWidth = 10;
var boardHeight = 20;
var blockSize = 2048 / boardWidth; // Calculate block size based on viewable area width
var fallRate = 1000; // Time in milliseconds between each Tetromino fall step
// GameBoard class is now encapsulated and instantiated separately
var board = new GameBoard();
game.addChild(board);
var GameState = {
  currentTetromino: null,
  nextTetrominoType: null,
  tetrominoTypes: ['I', 'J', 'L', 'O', 'S', 'T', 'Z'],
  tetrominoLayouts: {
    'I': [[[1, 1, 1, 1]]],
    'J': [[[1, 0, 0], [1, 1, 1]]],
    'L': [[[0, 0, 1], [1, 1, 1]]],
    'O': [[[1, 1], [1, 1]]],
    'S': [[[0, 1, 1], [1, 1, 0]]],
    'T': [[[0, 1, 0], [1, 1, 1]]],
    'Z': [[[1, 1, 0], [0, 1, 1]]]
  },
  scoreTxt: null,
  isGameOver: false,
  initialize: function () {
    this.currentTetromino = null;
    this.nextTetrominoType = this.tetrominoTypes[Math.floor(Math.random() * this.tetrominoTypes.length)];
    this.linesCleared = 0;
    this.score = 0;
    this.level = 1;
    this.state = 'active';
    this.spawnTetromino();
    gameUI.updateScore(this.score);
    gameUI.updateLevel(this.level);
    gameUI.updateLinesCleared(this.linesCleared);
    gameMenu.startButton.visible = false;
    gameMenu.pauseButton.visible = true;
    gameMenu.resumeButton.visible = false;
    gameMenu.restartButton.visible = true;
    board.init();
    game.addChild(board);
    board.x = (2048 - boardWidth * blockSize) / 2;
    board.y = (2732 - boardHeight * blockSize) / 2;
    game.addChild(gameUI);
  },
  spawnTetromino: function () {
    GameState.linesCleared = 0;
    gameUI.updateScore(GameState.score);
    gameUI.updateLevel(GameState.level);
    gameUI.updateNextTetrominoPreview(GameState.nextTetrominoType);
    var type = this.nextTetrominoType != null ? this.nextTetrominoType : this.tetrominoTypes[Math.floor(Math.random() * this.tetrominoTypes.length)];
    this.nextTetrominoType = this.tetrominoTypes[Math.floor(Math.random() * this.tetrominoTypes.length)];
    this.currentTetromino = new Tetromino();
    this.currentTetromino.create(type);
    this.currentTetromino.x = board.x + (boardWidth * blockSize - this.currentTetromino.width) / 2;
    this.currentTetromino.y = board.y - this.currentTetromino.height;
    game.addChild(this.currentTetromino);
  },
  gameOver: function () {
    this.isGameOver = true;
    LK.showGameOver();
  }
};
GameState.initialize();
// Initialize board
board.init();
// Center the board on the screen
board.x = (2048 - boardWidth * blockSize) / 2;
board.y = (2732 - boardHeight * blockSize) / 2;
// Create a new GameUI instance
var gameUI = new GameUI();
// Function to spawn a new tetromino
function spawnTetromino(blockSize) {
  var type = GameState.nextTetrominoType != null ? GameState.nextTetrominoType : GameState.tetrominoTypes[Math.floor(Math.random() * GameState.tetrominoTypes.length)];
  GameState.nextTetrominoType = GameState.tetrominoTypes[Math.floor(Math.random() * GameState.tetrominoTypes.length)];
  GameState.currentTetromino = new Tetromino();
  GameState.currentTetromino.create(type, blockSize);
  GameState.currentTetromino.x = board.x + boardWidth / 2 * blockSize - GameState.currentTetromino.width / 2;
  GameState.currentTetromino.y = board.y;
  game.addChild(GameState.currentTetromino);
}
// Start the game with a new tetromino
spawnTetromino();
// Implement automatic Tetromino descent
// Function to handle user input for moving and rotating the tetromino
function handleUserInput() {
  game.on('down', function (obj) {
    var touchPos = obj.event.getLocalPosition(game);
    // Define touch areas for control
    var leftArea = {
      x: board.x,
      width: boardWidth * blockSize / 3
    };
    var rightArea = {
      x: board.x + boardWidth * blockSize * 2 / 3,
      width: boardWidth * blockSize / 3
    };
    var rotateArea = {
      x: board.x + boardWidth * blockSize / 3,
      width: boardWidth * blockSize / 3
    };
    // Move tetromino left
    if (touchPos.x >= leftArea.x && touchPos.x < leftArea.x + leftArea.width) {
      currentTetromino.move(-blockSize, 0);
    }
    // Move tetromino right
    else if (touchPos.x >= rightArea.x && touchPos.x < rightArea.x + rightArea.width) {
      currentTetromino.move(blockSize, 0);
    }
    // Rotate tetromino
    else if (touchPos.x >= rotateArea.x && touchPos.x < rotateArea.x + rotateArea.width) {
      currentTetromino.rotate();
    }
  });
}
// Game loop
LK.on('tick', function () {
  if (GameState.state === 'paused') {
    return;
  }
  // Handle Tetromino descent
  if (GameState.currentTetromino && GameState.state === 'active') {
    if (LK.ticks % (fallRate / (1000 / 60)) === 0) {
      GameState.currentTetromino.move(0, blockSize);
    }
  }
  // Handle user input for moving and rotating the tetromino
  handleUserInput();
  // Check for completed lines
  board.checkLines();
  // Check for game over
  if (board.isGameOver()) {
    GameState.gameOver();
  }
});
// Function to handle user input for moving and rotating the tetromino
function handleUserInput() {
  game.on('down', function (obj) {
    var touchPos = obj.event.getLocalPosition(game);
    var leftArea = {
      x: 0,
      width: board.x
    };
    var rightArea = {
      x: board.x + boardWidth * blockSize,
      width: 2048 - (board.x + boardWidth * blockSize)
    };
    var rotateArea = {
      x: board.x,
      y: board.y,
      width: boardWidth * blockSize,
      height: boardHeight * blockSize
    };
    if (touchPos.x < leftArea.width) {
      GameState.currentTetromino.move(-blockSize, 0);
    } else if (touchPos.x > rightArea.x) {
      GameState.currentTetromino.move(blockSize, 0);
    } else if (touchPos.x >= rotateArea.x && touchPos.x < rotateArea.x + rotateArea.width && touchPos.y >= rotateArea.y && touchPos.y < rotateArea.y + rotateArea.height) {
      GameState.currentTetromino.rotate();
    }
  });
} ===================================================================
--- original.js
+++ change.js
@@ -1,348 +1,592 @@
 /**** 
 * Classes
 ****/
-// Repeat the above pattern for L, O, S, T, and Z Tetromino blocks
+var TetrominoBlock = Container.expand(function (type, i, j, blockSize) {
+  var self = Container.call(this);
+  var blockGraphic = self.createAsset('tetromino_' + type, type + ' Tetromino block', 0.5, 0.5);
+  self.x = j * blockSize;
+  self.y = i * blockSize;
+});
 // Define Tetromino class
 var Tetromino = Container.expand(function () {
-	var self = Container.call(this);
-	this.blocks = [];
-	this.type = '';
-	this.rotationIndex = 0;
-	this.initializeBlocks = function (layout) {
-		for (var i = 0; i < layout.length; i++) {
-			for (var j = 0; j < layout[i].length; j++) {
-				if (layout[i][j]) {
-					this.blocks.push(game.addChild(new TetrominoBlock(type, j, i)));
-				}
-			}
-		}
-	};
-	this.create = function (type) {
-		this.type = type;
-		this.rotationIndex = 0;
-		var layout = tetrominoLayouts[type][this.rotationIndex];
-		this.initializeBlocks(layout);
-	};
-	this.rotate = function () {
-		this.rotationIndex = (this.rotationIndex + 1) % tetrominoLayouts[this.type].length;
-		this.updateBlockPositions();
-	};
-	this.updateBlockPositions = function () {
-		var layout = tetrominoLayouts[this.type][this.rotationIndex];
-		var k = 0;
-		for (var i = 0; i < layout.length; i++) {
-			for (var j = 0; j < layout[i].length; j++) {
-				if (layout[i][j]) {
-					this.blocks[k].x = j * this.blocks[k].width;
-					this.blocks[k].y = i * this.blocks[k].height;
-					k++;
-				}
-			}
-		}
-	};
-	this.move = function (dx, dy) {
-		var movement = TetrominoMovement.calculateMove(this, dx, dy, board);
-		if (movement.canMove) {
-			this.x = movement.newX;
-			this.y = movement.newY;
-		} else if (dy > 0) {
-			board.fixTetromino(this);
-			spawnTetromino();
-		}
-	};
+  var self = Container.call(this);
+  Tetromino.prototype.checkCollision = function (dx, dy, board) {
+    for (var i = 0; i < this.blocks.length; i++) {
+      var block = this.blocks[i];
+      var newX = this.x + block.x + dx;
+      var newY = this.y + block.y + dy;
+      var gridX = Math.floor(newX / blockSize);
+      var gridY = Math.floor(newY / blockSize);
+      if (gridX < 0 || gridX >= boardWidth || gridY >= boardHeight) {
+        return true; // Collision with board boundaries
+      }
+      if (gridY >= 0 && board.grid[gridY] && board.grid[gridY][gridX]) {
+        return true; // Collision with another block
+      }
+    }
+    return false;
+  };
+  this.blocks = [];
+  this.type = '';
+  this.rotationIndex = 0;
+  this.initializeBlocks = function (layout) {
+    this.initializeBlocks = function (layout, blockSize) {
+      for (var i = 0; i < layout.length; i++) {
+        for (var j = 0; j < layout[i].length; j++) {
+          if (layout[i][j]) {
+            var block = new TetrominoBlock(this.type, i, j, blockSize);
+            this.blocks.push(this.addChild(block));
+          }
+        }
+      }
+    };
+  };
+  this.create = function (type, blockSize) {
+    this.type = type;
+    this.rotationIndex = 0;
+    var layout = tetrominoLayouts[type][this.rotationIndex];
+    this.initializeBlocks(layout, blockSize);
+  };
+  this.rotate = function () {
+    var oldRotationIndex = this.rotationIndex;
+    var newRotationIndex = (this.rotationIndex + 1) % tetrominoLayouts[this.type].length;
+    this.rotationIndex = newRotationIndex;
+    this.updateBlockPositions();
+    if (this.checkCollision(0, 0, board)) {
+      this.rotationIndex = oldRotationIndex;
+      this.updateBlockPositions();
+    }
+  };
+  this.updateBlockPositions = function () {
+    var layout = tetrominoLayouts[this.type][this.rotationIndex];
+    var k = 0;
+    for (var i = 0; i < layout.length; i++) {
+      for (var j = 0; j < layout[i].length; j++) {
+        if (layout[i][j]) {
+          this.blocks[k].x = j * this.blocks[k].width;
+          this.blocks[k].y = i * this.blocks[k].height;
+          k++;
+        }
+      }
+    }
+  };
+  this.move = function (dx, dy) {
+    if (!this.checkCollision(dx, dy, board)) {
+      this.x += dx;
+      this.y += dy;
+    } else if (dy > 0) {
+      board.fixTetromino(this);
+      spawnTetromino();
+    }
+  };
 });
-var TetrominoBlock = Container.expand(function (type, gridX, gridY) {
-	var self = Container.call(this);
-	this.block = LK.getAsset('tetromino_' + type, type + ' Tetromino block', 0, 0);
-	self.x = gridX * this.block.width;
-	self.y = gridY * this.block.height;
-	this.addChild(this.block);
-});
 // Define GameBoard class
 var GameBoard = Container.expand(function () {
-	var self = Container.call(this);
-	this.grid = [];
-	this.init = function () {
-		for (var i = 0; i < boardHeight; i++) {
-			this.grid[i] = [];
-			for (var j = 0; j < boardWidth; j++) {
-				this.grid[i][j] = null;
-			}
-		}
-	};
-	this.fixTetromino = function (tetromino) {
-		var blocks = tetromino.blocks;
-		for (var i = 0; i < blocks.length; i++) {
-			var block = blocks[i];
-			var x = Math.round((block.x + tetromino.x - this.x) / blockSize);
-			var y = Math.round((block.y + tetromino.y - this.y) / blockSize);
-			if (y < boardHeight && x < boardWidth) {
-				this.grid[y][x] = block;
-				block.x = x * blockSize;
-				block.y = y * blockSize;
-				this.addChild(block);
-			} else if (y < 0) {
-				LK.showGameOver();
-				return false;
-			}
-		}
-		this.checkLines();
-		return true;
-	};
-	this.isGameOver = function () {
-		for (var x = 0; x < boardWidth; x++) {
-			if (this.grid[0][x] !== null) {
-				return true;
-			}
-		}
-		return false;
-	};
-	this.checkLines = function () {
-		for (var y = 0; y < boardHeight; y++) {
-			var lineComplete = true;
-			for (var x = 0; x < boardWidth; x++) {
-				if (this.grid[y][x] === null) {
-					lineComplete = false;
-					break;
-				}
-			}
-			if (lineComplete) {
-				for (var row = y; row > 0; row--) {
-					for (var x = 0; x < boardWidth; x++) {
-						this.grid[row][x] = this.grid[row - 1][x];
-						if (this.grid[row][x]) {
-							this.grid[row][x].y += blockSize;
-						}
-					}
-				}
-				for (var x = 0; x < boardWidth; x++) {
-					this.grid[0][x] = null;
-				}
-				for (var x = 0; x < boardWidth; x++) {
-					if (this.grid[y][x]) {
-						this.grid[y][x].destroy();
-						this.grid[y][x] = null;
-					}
-				}
-				var linesCleared = 0;
-				for (var y = 0; y < boardHeight; y++) {
-					var lineComplete = true;
-					for (var x = 0; x < boardWidth; x++) {
-						if (this.grid[y][x] === null) {
-							lineComplete = false;
-							break;
-						}
-					}
-					if (lineComplete) {
-						linesCleared++;
-						for (var row = y; row > 0; row--) {
-							for (var x = 0; x < boardWidth; x++) {
-								this.grid[row][x] = this.grid[row - 1][x];
-								if (this.grid[row][x]) {
-									this.grid[row][x].y += blockSize;
-								}
-							}
-						}
-						for (var x = 0; x < boardWidth; x++) {
-							this.grid[0][x] = null;
-						}
-						for (var x = 0; x < boardWidth; x++) {
-							if (this.grid[y][x]) {
-								this.grid[y][x].destroy();
-								this.grid[y][x] = null;
-							}
-						}
-					}
-				}
-				if (linesCleared > 0) {
-					var scoreToAdd = linesCleared === 1 ? 100 : linesCleared === 2 ? 300 : linesCleared === 3 ? 500 : 800;
-					LK.setScore(LK.getScore() + scoreToAdd);
-					scoreTxt.setText(LK.getScore());
-				}
-			}
-		}
-	};
-	this.init();
+  var self = Container.call(this);
+  this.grid = [];
+  this.init = function () {
+    for (var i = 0; i < boardHeight; i++) {
+      this.grid[i] = [];
+      for (var j = 0; j < boardWidth; j++) {
+        this.grid[i][j] = null;
+      }
+    }
+  };
+  this.fixTetromino = function (tetromino) {
+    var blocks = tetromino.blocks;
+    for (var i = 0; i < blocks.length; i++) {
+      var block = blocks[i];
+      var x = Math.round((block.x + tetromino.x - this.x) / blockSize);
+      var y = Math.round((block.y + tetromino.y - this.y) / blockSize);
+      if (y < boardHeight && x < boardWidth) {
+        this.grid[y][x] = block;
+        block.x = x * blockSize;
+        block.y = y * blockSize;
+        this.addChild(block);
+      } else if (y < 0) {
+        LK.showGameOver();
+        return false;
+      }
+    }
+    this.checkLines();
+    return true;
+  };
+  this.isGameOver = function () {
+    for (var x = 0; x < boardWidth; x++) {
+      if (this.grid[0][x] !== null) {
+        return true;
+      }
+    }
+    return false;
+  };
+  this.checkLines = function () {
+    for (var y = 0; y < boardHeight; y++) {
+      var lineComplete = true;
+      for (var x = 0; x < boardWidth; x++) {
+        if (this.grid[y][x] === null) {
+          lineComplete = false;
+          break;
+        }
+      }
+      if (lineComplete) {
+        for (var row = y; row > 0; row--) {
+          for (var x = 0; x < boardWidth; x++) {
+            this.grid[row][x] = this.grid[row - 1][x];
+            if (this.grid[row][x]) {
+              this.grid[row][x].y += blockSize;
+            }
+          }
+        }
+        for (var x = 0; x < boardWidth; x++) {
+          this.grid[0][x] = null;
+        }
+        for (var x = 0; x < boardWidth; x++) {
+          if (this.grid[y][x]) {
+            this.grid[y][x].destroy();
+            this.grid[y][x] = null;
+          }
+        }
+        var linesCleared = 0;
+        for (var y = 0; y < boardHeight; y++) {
+          var lineComplete = true;
+          for (var x = 0; x < boardWidth; x++) {
+            if (this.grid[y][x] === null) {
+              lineComplete = false;
+              break;
+            }
+          }
+          if (lineComplete) {
+            linesCleared++;
+            for (var row = y; row > 0; row--) {
+              for (var x = 0; x < boardWidth; x++) {
+                this.grid[row][x] = this.grid[row - 1][x];
+                if (this.grid[row][x]) {
+                  this.grid[row][x].y += blockSize;
+                }
+              }
+            }
+            for (var x = 0; x < boardWidth; x++) {
+              this.grid[0][x] = null;
+            }
+            for (var x = 0; x < boardWidth; x++) {
+              if (this.grid[y][x]) {
+                this.grid[y][x].destroy();
+                this.grid[y][x] = null;
+              }
+            }
+          }
+        }
+        if (linesCleared > 0) {
+          var scoreToAdd = linesCleared === 1 ? 100 : linesCleared === 2 ? 300 : linesCleared === 3 ? 500 : 800;
+          LK.setScore(LK.getScore() + scoreToAdd);
+          gameUI.updateScore(LK.getScore());
+        }
+      }
+    }
+  };
+  this.init();
 });
 // Define LowerField class for collecting Tetrominoes
 var LowerField = Container.expand(function () {
-	var self = Container.call(this);
-	this.init = function () {
-		this.grid = [];
-		for (var i = 0; i < boardHeight; i++) {
-			this.grid[i] = [];
-			for (var j = 0; j < boardWidth; j++) {
-				this.grid[i][j] = null;
-			}
-		}
-	};
-	this.init();
-	this.addBlock = function (block, x, y) {
-		if (y < boardHeight && x < boardWidth) {
-			this.grid[y][x] = block;
-			block.x = x * blockSize;
-			block.y = y * blockSize;
-			this.addChild(block);
-		}
-	};
+  var self = Container.call(this);
+  this.init = function () {
+    this.grid = [];
+    for (var i = 0; i < boardHeight; i++) {
+      this.grid[i] = [];
+      for (var j = 0; j < boardWidth; j++) {
+        this.grid[i][j] = null;
+      }
+    }
+  };
+  this.init();
+  this.addBlock = function (block, x, y) {
+    if (y < boardHeight && x < boardWidth) {
+      this.grid[y][x] = block;
+      block.x = x * blockSize;
+      block.y = y * blockSize;
+      this.addChild(block);
+    }
+  };
 });
+// Define GameMenu class
+var GameMenu = Container.expand(function () {
+  var self = Container.call(this);
+  this.startButton = new Text2('Start', {
+    size: 150,
+    fill: "#ffffff",
+    anchor: {
+      x: 0.5,
+      y: 0.5
+    }
+  });
+  this.startButton.on('down', function () {
+    GameState.initialize();
+    self.visible = false;
+  });
+  this.pauseButton = new Text2('Pause', {
+    size: 150,
+    fill: "#ffffff",
+    anchor: {
+      x: 0.5,
+      y: 0.5
+    }
+  });
+  this.pauseButton.on('down', function () {
+    GameState.state = 'paused';
+  });
+  this.resumeButton = new Text2('Resume', {
+    size: 150,
+    fill: "#ffffff",
+    anchor: {
+      x: 0.5,
+      y: 0.5
+    }
+  });
+  this.resumeButton.on('down', function () {
+    GameState.state = 'active';
+  });
+  this.restartButton = new Text2('Restart', {
+    size: 150,
+    fill: "#ffffff",
+    anchor: {
+      x: 0.5,
+      y: 0.5
+    }
+  });
+  this.restartButton.on('down', function () {
+    GameState.initialize();
+  });
+  LK.gui.bottom.addChild(this.startButton);
+  LK.gui.bottom.addChild(this.pauseButton);
+  LK.gui.bottom.addChild(this.resumeButton);
+  LK.gui.bottom.addChild(this.restartButton);
+  this.pauseButton.visible = false;
+  this.resumeButton.visible = false;
+  this.restartButton.visible = false;
+});
+// Create a new GameMenu instance
+// Create score display
+var ScoreDisplay = Container.expand(function () {
+  var self = Container.call(this);
+  this.scoreText = new Text2('Score: 0', {
+    size: 100,
+    fill: "#ffffff",
+    anchor: {
+      x: 0.5,
+      y: 0
+    }
+  });
+  this.levelText = new Text2('Level: 1', {
+    size: 100,
+    fill: "#ffffff",
+    anchor: {
+      x: 0.5,
+      y: 0
+    }
+  });
+  this.linesText = new Text2('Lines: 0', {
+    size: 100,
+    fill: "#ffffff",
+    anchor: {
+      x: 0.5,
+      y: 0
+    }
+  });
+  LK.gui.top.addChild(this.scoreText);
+  LK.gui.top.addChild(this.levelText);
+  LK.gui.top.addChild(this.linesText);
+  this.levelText.y = this.scoreText.height;
+  this.linesText.y = this.scoreText.height * 2;
+  this.updateScore = function (score) {
+    this.scoreText.setText('Score: ' + score.toString());
+  };
+  this.updateLevel = function (level) {
+    this.levelText.setText('Level: ' + level.toString());
+  };
+  this.updateLinesCleared = function (lines) {
+    this.linesText.setText('Lines: ' + lines.toString());
+  };
+});
+// Create a new ScoreDisplay instance
+var GameUI = Container.expand(function () {
+  var self = Container.call(this);
+  this.scoreText = new Text2('Score: 0', {
+    size: 100,
+    fill: "#ffffff",
+    anchor: {
+      x: 0.5,
+      y: 0
+    }
+  });
+  this.levelText = new Text2('Level: 1', {
+    size: 100,
+    fill: "#ffffff",
+    anchor: {
+      x: 0.5,
+      y: 0
+    }
+  });
+  this.nextTetrominoPreview = new Container();
+  LK.gui.top.addChild(this.scoreText);
+  LK.gui.top.addChild(this.levelText);
+  LK.gui.topRight.addChild(this.nextTetrominoPreview);
+  this.scoreText.y = 20;
+  this.levelText.y = this.scoreText.height + 20;
+  this.nextTetrominoPreview.y = 20;
+  this.updateScore = function (score) {
+    this.scoreText.setText('Score: ' + score.toString());
+  };
+  this.updateLevel = function (level) {
+    this.levelText.setText('Level: ' + level.toString());
+  };
+  this.updateNextTetrominoPreview = function (type) {
+    this.nextTetrominoPreview.removeChildren();
+    var layout = GameState.tetrominoLayouts[type][0];
+    for (var i = 0; i < layout.length; i++) {
+      for (var j = 0; j < layout[i].length; j++) {
+        if (layout[i][j]) {
+          var block = LK.getAsset('tetromino_' + type + '_preview', 'Next Tetromino block', 0.5, 0.5);
+          block.x = j * (blockSize * 0.5);
+          block.y = i * (blockSize * 0.5);
+          this.nextTetrominoPreview.addChild(block);
+        }
+      }
+    }
+  };
+});
 
 /**** 
 * Initialize Game
 ****/
+// Create a new GameUI instance
 var game = new LK.Game({
-	backgroundColor: 0xFFFFFF // Init game with white background
+  backgroundColor: 0x000000 // Init game with black background for better contrast
 });
 
 /**** 
 * Game Code
 ****/
+// Create a new GameMenu instance
+var gameMenu = new GameMenu();
 // Define game constants and variables
-var boardWidth = 10;
-var boardHeight = 20;
-var blockSize = 2048 / boardWidth; // Calculate block size based on viewable area width
-var fallRate = 1000; // Time in milliseconds between each Tetromino fall step
+var GameState = {
+  boardWidth: 10,
+  boardHeight: 20,
+  blockSize: 2048 / 10,
+  // Calculate block size based on viewable area width
+  fallRate: 1000,
+  // Time in milliseconds between each Tetromino fall step
+  score: 0,
+  // Initialize current score
+  level: 1,
+  // Initialize game level
+  state: 'active',
+  // Game state can be 'paused', 'active', or 'gameOver'
+  grid: [],
+  initializeGrid: function () {
+    for (var i = 0; i < this.boardHeight; i++) {
+      this.grid[i] = [];
+      for (var j = 0; j < this.boardWidth; j++) {
+        this.grid[i][j] = null; // Each cell starts as null (empty)
+      }
+    }
+  }
+};
+GameState.initializeGrid();
 // GameBoard class is now encapsulated and instantiated separately
 var board = new GameBoard();
 board.init();
 // Center the board on the screen
 board.x = (2048 - boardWidth * blockSize) / 2;
 board.y = (2732 - boardHeight * blockSize) / 2;
 // Add the board to the game
 game.addChild(board);
-// Create score display
-scoreTxt = new Text2('0', {
-	size: 150,
-	fill: "#ffffff"
-});
-scoreTxt.anchor.set(.5, 0);
-LK.gui.top.addChild(scoreTxt);
+// Create a new ScoreDisplay instance
+var gameUI = new GameUI();
 // Initialize the first Tetromino
 spawnTetromino();
 // Define game constants and variables
 var TetrominoMovement = {
-	calculateMove: function calculateMove(tetromino, dx, dy, board) {
-		var newX = tetromino.x + dx;
-		var newY = tetromino.y + dy;
-		var canMove = true;
-		for (var i = 0; i < tetromino.blocks.length; i++) {
-			var block = tetromino.blocks[i];
-			var gridX = Math.round((block.x + newX - board.x) / blockSize);
-			var gridY = Math.round((block.y + newY - board.y) / blockSize);
-			if (gridX < 0 || gridX >= boardWidth || gridY < 0 || gridY >= boardHeight) {
-				canMove = false;
-				break;
-			} else if (gridY >= 0 && board.grid[gridY] && board.grid[gridY][gridX]) {
-				canMove = false;
-				break;
-			}
-		}
-		return {
-			canMove: canMove,
-			newX: newX,
-			newY: newY
-		};
-	}
+  calculateMove: function calculateMove(tetromino, dx, dy, board) {
+    var newX = tetromino.x + dx;
+    var newY = tetromino.y + dy;
+    var canMove = true;
+    for (var i = 0; i < tetromino.blocks.length; i++) {
+      var block = tetromino.blocks[i];
+      var gridX = Math.round((block.x + newX - board.x) / blockSize);
+      var gridY = Math.round((block.y + newY - board.y) / blockSize);
+      if (gridX < 0 || gridX >= boardWidth || gridY < 0 || gridY >= boardHeight) {
+        canMove = false;
+        break;
+      } else if (gridY >= 0 && board.grid[gridY] && board.grid[gridY][gridX]) {
+        canMove = false;
+        break;
+      }
+    }
+    return {
+      canMove: canMove,
+      newX: newX,
+      newY: newY
+    };
+  }
 };
 var boardWidth = 10;
 var boardHeight = 20;
 var blockSize = 2048 / boardWidth; // Calculate block size based on viewable area width
 var fallRate = 1000; // Time in milliseconds between each Tetromino fall step
 // GameBoard class is now encapsulated and instantiated separately
 var board = new GameBoard();
 game.addChild(board);
-var currentTetromino;
-var nextTetrominoType;
-var tetrominoTypes = ['I', 'J', 'L', 'O', 'S', 'T', 'Z'];
-var nextTetrominoType;
-var tetrominoTypes = ['I', 'J', 'L', 'O', 'S', 'T', 'Z'];
-var tetrominoLayouts = {
-	'I': [[[1, 1, 1, 1]]],
-	'J': [[[1, 0, 0], [1, 1, 1]]],
-	'L': [[[0, 0, 1], [1, 1, 1]]],
-	'O': [[[1, 1], [1, 1]]],
-	'S': [[[0, 1, 1], [1, 1, 0]]],
-	'T': [[[0, 1, 0], [1, 1, 1]]],
-	'Z': [[[1, 1, 0], [0, 1, 1]]]
+var GameState = {
+  currentTetromino: null,
+  nextTetrominoType: null,
+  tetrominoTypes: ['I', 'J', 'L', 'O', 'S', 'T', 'Z'],
+  tetrominoLayouts: {
+    'I': [[[1, 1, 1, 1]]],
+    'J': [[[1, 0, 0], [1, 1, 1]]],
+    'L': [[[0, 0, 1], [1, 1, 1]]],
+    'O': [[[1, 1], [1, 1]]],
+    'S': [[[0, 1, 1], [1, 1, 0]]],
+    'T': [[[0, 1, 0], [1, 1, 1]]],
+    'Z': [[[1, 1, 0], [0, 1, 1]]]
+  },
+  scoreTxt: null,
+  isGameOver: false,
+  initialize: function () {
+    this.currentTetromino = null;
+    this.nextTetrominoType = this.tetrominoTypes[Math.floor(Math.random() * this.tetrominoTypes.length)];
+    this.linesCleared = 0;
+    this.score = 0;
+    this.level = 1;
+    this.state = 'active';
+    this.spawnTetromino();
+    gameUI.updateScore(this.score);
+    gameUI.updateLevel(this.level);
+    gameUI.updateLinesCleared(this.linesCleared);
+    gameMenu.startButton.visible = false;
+    gameMenu.pauseButton.visible = true;
+    gameMenu.resumeButton.visible = false;
+    gameMenu.restartButton.visible = true;
+    board.init();
+    game.addChild(board);
+    board.x = (2048 - boardWidth * blockSize) / 2;
+    board.y = (2732 - boardHeight * blockSize) / 2;
+    game.addChild(gameUI);
+  },
+  spawnTetromino: function () {
+    GameState.linesCleared = 0;
+    gameUI.updateScore(GameState.score);
+    gameUI.updateLevel(GameState.level);
+    gameUI.updateNextTetrominoPreview(GameState.nextTetrominoType);
+    var type = this.nextTetrominoType != null ? this.nextTetrominoType : this.tetrominoTypes[Math.floor(Math.random() * this.tetrominoTypes.length)];
+    this.nextTetrominoType = this.tetrominoTypes[Math.floor(Math.random() * this.tetrominoTypes.length)];
+    this.currentTetromino = new Tetromino();
+    this.currentTetromino.create(type);
+    this.currentTetromino.x = board.x + (boardWidth * blockSize - this.currentTetromino.width) / 2;
+    this.currentTetromino.y = board.y - this.currentTetromino.height;
+    game.addChild(this.currentTetromino);
+  },
+  gameOver: function () {
+    this.isGameOver = true;
+    LK.showGameOver();
+  }
 };
-var scoreTxt;
-var isGameOver = false;
+GameState.initialize();
 // Initialize board
 board.init();
 // Center the board on the screen
 board.x = (2048 - boardWidth * blockSize) / 2;
 board.y = (2732 - boardHeight * blockSize) / 2;
-// Create score display
-scoreTxt = new Text2('0', {
-	size: 150,
-	fill: "#ffffff"
-});
-scoreTxt.anchor.set(.5, 0);
-LK.gui.top.addChild(scoreTxt);
+// Create a new GameUI instance
+var gameUI = new GameUI();
 // Function to spawn a new tetromino
-function spawnTetromino() {
-	var type = nextTetrominoType !== undefined ? nextTetrominoType : tetrominoTypes[Math.floor(Math.random() * tetrominoTypes.length)];
-	nextTetrominoType = null;
-	nextTetrominoType = null;
-	nextTetrominoType = tetrominoTypes[Math.floor(Math.random() * tetrominoTypes.length)];
-	currentTetromino = new Tetromino();
-	currentTetromino.create(type);
-	currentTetromino.x = board.x + boardWidth / 2 * blockSize - currentTetromino.width / 2;
-	currentTetromino.y = board.y;
-	game.addChild(currentTetromino);
+function spawnTetromino(blockSize) {
+  var type = GameState.nextTetrominoType != null ? GameState.nextTetrominoType : GameState.tetrominoTypes[Math.floor(Math.random() * GameState.tetrominoTypes.length)];
+  GameState.nextTetrominoType = GameState.tetrominoTypes[Math.floor(Math.random() * GameState.tetrominoTypes.length)];
+  GameState.currentTetromino = new Tetromino();
+  GameState.currentTetromino.create(type, blockSize);
+  GameState.currentTetromino.x = board.x + boardWidth / 2 * blockSize - GameState.currentTetromino.width / 2;
+  GameState.currentTetromino.y = board.y;
+  game.addChild(GameState.currentTetromino);
 }
 // Start the game with a new tetromino
 spawnTetromino();
-// Game tick event
+// Implement automatic Tetromino descent
+// Function to handle user input for moving and rotating the tetromino
+function handleUserInput() {
+  game.on('down', function (obj) {
+    var touchPos = obj.event.getLocalPosition(game);
+    // Define touch areas for control
+    var leftArea = {
+      x: board.x,
+      width: boardWidth * blockSize / 3
+    };
+    var rightArea = {
+      x: board.x + boardWidth * blockSize * 2 / 3,
+      width: boardWidth * blockSize / 3
+    };
+    var rotateArea = {
+      x: board.x + boardWidth * blockSize / 3,
+      width: boardWidth * blockSize / 3
+    };
+    // Move tetromino left
+    if (touchPos.x >= leftArea.x && touchPos.x < leftArea.x + leftArea.width) {
+      currentTetromino.move(-blockSize, 0);
+    }
+    // Move tetromino right
+    else if (touchPos.x >= rightArea.x && touchPos.x < rightArea.x + rightArea.width) {
+      currentTetromino.move(blockSize, 0);
+    }
+    // Rotate tetromino
+    else if (touchPos.x >= rotateArea.x && touchPos.x < rotateArea.x + rotateArea.width) {
+      currentTetromino.rotate();
+    }
+  });
+}
+// Game loop
 LK.on('tick', function () {
-	// Implement fall rate timer
-	if (LK.ticks % (fallRate / (1000 / 60)) === 0) {
-		// Attempt to move current tetromino down and check for collision
-		currentTetromino.move(0, blockSize);
-		if (currentTetromino.isFixed) {
-			// Collision occurred and Tetromino is fixed, spawn a new Tetromino
-			spawnTetromino();
-		}
-	}
-	// Check for completed lines
-	board.checkLines();
-	// Check for game over
-	if (board.isGameOver()) {
-		isGameOver = true;
-		LK.showGameOver();
-	}
-	// Handle user input for moving and rotating the tetromino
-	handleUserInput();
+  if (GameState.state === 'paused') {
+    return;
+  }
+  // Handle Tetromino descent
+  if (GameState.currentTetromino && GameState.state === 'active') {
+    if (LK.ticks % (fallRate / (1000 / 60)) === 0) {
+      GameState.currentTetromino.move(0, blockSize);
+    }
+  }
+  // Handle user input for moving and rotating the tetromino
+  handleUserInput();
+  // Check for completed lines
+  board.checkLines();
+  // Check for game over
+  if (board.isGameOver()) {
+    GameState.gameOver();
+  }
 });
 // Function to handle user input for moving and rotating the tetromino
 function handleUserInput() {
-	game.on('down', function (obj) {
-		var touchPos = obj.event.getLocalPosition(game);
-		// Define touch areas for control
-		var leftArea = {
-			x: board.x,
-			width: boardWidth * blockSize / 3
-		};
-		var rightArea = {
-			x: board.x + boardWidth * blockSize * 2 / 3,
-			width: boardWidth * blockSize / 3
-		};
-		var rotateArea = {
-			x: board.x + boardWidth * blockSize / 3,
-			width: boardWidth * blockSize / 3
-		};
-		// Move tetromino left
-		if (touchPos.x >= leftArea.x && touchPos.x < leftArea.x + leftArea.width) {
-			currentTetromino.move(-blockSize, 0);
-		}
-		// Move tetromino right
-		else if (touchPos.x >= rightArea.x && touchPos.x < rightArea.x + rightArea.width) {
-			currentTetromino.move(blockSize, 0);
-		}
-		// Rotate tetromino
-		else if (touchPos.x >= rotateArea.x && touchPos.x < rotateArea.x + rotateArea.width) {
-			currentTetromino.rotate();
-		}
-	});
-}
-// Touch event listeners for rotating and moving tetromino
\ No newline at end of file
+  game.on('down', function (obj) {
+    var touchPos = obj.event.getLocalPosition(game);
+    var leftArea = {
+      x: 0,
+      width: board.x
+    };
+    var rightArea = {
+      x: board.x + boardWidth * blockSize,
+      width: 2048 - (board.x + boardWidth * blockSize)
+    };
+    var rotateArea = {
+      x: board.x,
+      y: board.y,
+      width: boardWidth * blockSize,
+      height: boardHeight * blockSize
+    };
+    if (touchPos.x < leftArea.width) {
+      GameState.currentTetromino.move(-blockSize, 0);
+    } else if (touchPos.x > rightArea.x) {
+      GameState.currentTetromino.move(blockSize, 0);
+    } else if (touchPos.x >= rotateArea.x && touchPos.x < rotateArea.x + rotateArea.width && touchPos.y >= rotateArea.y && touchPos.y < rotateArea.y + rotateArea.height) {
+      GameState.currentTetromino.rotate();
+    }
+  });
+}
\ No newline at end of file