Tetris game blocks only spawn partially and behave weirdly when they collide with the bottom

66 Views Asked by At

I am trying to do a tetris game for a task in an apprentice ship we were provided with the html background and so on but the logic we have to write ourselfes in js i choose to do a class based approach by coding the shapes as a class and the blocks that they are made out of as a class aswell the gameboard which i call gameLogicState is a 10 by 20 array in which i move the blocks my error is that when the shape spawns in only the lower half is created and i have no idea why

I was guessing the function which translates the shapes into the block class is broken but it seems to work fine i am going to paste the important code here when i move the cube to the left it displays the cube very briefly before it is just a two block line when i move it to the right it only displays the upper right and lower right block of the cube very briefly

const horizontalCells = 10;

    let grid = generateGridArray();


    function colorCell(cell, color) {
        cell.style.background = color;
    }

    function generateGridArray() {
        let cells = document.querySelectorAll('.cell');
        let grid = [];

        for (let i = 0; i < cells.length; i++) {
            let cell = cells[i];
            let x = (i % horizontalCells);
            let y = Math.floor(i / horizontalCells);

            // Wenn noch kein Array in grid[x] initialisiert wurde, tun wir das.
            if (!grid[x]) {
                grid[x] = [];
            }
            grid[x][y] = cell;
        }
        return grid;
    }

    document.addEventListener("keydown", function (event) {
        let joystick = document.querySelector('.joystick');
        if (event.code === "ArrowLeft") {
            joystick.classList.remove('right');
            joystick.classList.add('left');
        } else if (event.code === "ArrowRight") {
            joystick.classList.remove('left');
            joystick.classList.add('right');
        }
        // Weitere Tasten-Abfragen hier einfügen...
    });

    document.addEventListener("keyup", function (event) {
        let joystick = document.querySelector('.joystick');
        if (event.code === "ArrowLeft") {
            joystick.classList.remove('left');
        } else if (event.code === "ArrowRight") {
            joystick.classList.remove('right');
        }
        // Weitere Tasten-Abfragen hier einfügen...
    });


    function gravity(currentItem, gameLogicState) {
        let gameData = currentItem.move(gameLogicState, 'down')
        return gameData;
    }

    function generateArrayForTheGame() {
        gameBoard = [];
        for (let i = 0; i < 10; i++) {
            const row = [];
            for (let j = 0; j < 20; j++) {
                row.push(null);
            }
            gameBoard.push(row);
        }
        return gameBoard;

    }

    const tetrinoShapes = {
        'Line': [
            [1, 1, 1, 1],
            [0, 0, 0, 0]
        ],
        'L': [
            [1, 0, 0, 0],
            [1, 1, 1, 0]
        ],
        'Cube': [
            [1, 1, 0, 0],
            [1, 1, 0, 0]
        ],
        'T': [
            [0, 1, 0, 0],
            [1, 1, 1, 0]
        ],
        'Z': [
            [1, 1, 0, 0],
            [0, 1, 1, 0]
        ],
    }


    class shape {
        constructor(spawnPoint, shapeForm) {
            //todo tetrino hsapes const setzen
            let form = tetrinoShapes[shapeForm];
            this.blocks = [];
            this.spawnPoint = spawnPoint
            let position = this.spawnPoint
            this.shapeName = shapeForm
            // Translate the shape into a list of blocks
            //todo vertical and horizontal are switched
            for (let vertical = 0; vertical < form.length; vertical++) {
                for (let horizontal = 0; horizontal < form[vertical].length; horizontal++) {
                    if (form[vertical][horizontal] === 1) {
                        const blockPosition = [spawnPoint[0] + horizontal, spawnPoint[1] + vertical];
                        console.log(`Erstelle Block an Position ${blockPosition}`);
                        this.blocks.push(new block(blockPosition, this));
                    }
                }
            }
        }
        move(gameLogicState, direction) {
            for (let block = 0; block < this.blocks.length; block++) {
                let location = this.blocks[block].location
                let selectedBlock = this.blocks[block]
                let x = location[0]
                let y = location [1]
                switch (direction) {
                    case 'left':
                        //if (this.blocks[block].collisionCheck(gameLogicState, 'left') === false) {
                            gameLogicState[x][y] = null
                            x -= 1
                            gameLogicState[x][y] = selectedBlock
                            selectedBlock.location[1] = y
                            selectedBlock.location[0] = x
                        //}

                        break;
                    case 'right':
                        //if (this.blocks[block].collisionCheck(gameLogicState, 'right') === false) {
                            gameLogicState[x][y] = null
                            x += 1
                            gameLogicState[x][y] = selectedBlock
                            selectedBlock.location[1] = y
                            selectedBlock.location[0] = x
                        //}
                        break;
                    case 'down':
                        gameLogicState[x][y] = null
                        y += 1
                        gameLogicState[x][y] = selectedBlock
                        selectedBlock.location[1] = y
                        selectedBlock.location[0] = x
                        break;
                }
            }
            return [this, gameLogicState]
        }

        collision(gameLogicState, direction) {
            for (let each = 0; each < 4; each++) {
                if (this.blocks[each].collisionCheck(gameLogicState, direction)) {
                    return true
                } else {
                    return false
                }
            }
        }
    }

    class block {
        constructor(location, shape) {
            this.location = location
            this.shape = shape
        }

        collisionCheck(gameLogicState, direction) {
            let x = this.location[0];
            let y = this.location[1];

            // Calculate the new coordinates based on the direction
            let newX = x;
            let newY = y;
            switch (direction) {
                case 'left':
                    newX = x - 1;
                    break;
                case 'right':
                    newX = x + 1;
                    break;
                case 'down':
                    newY = y + 1;
                    break;
            }

            // Check if the new coordinates are within the bounds of the gameLogicState
            if (newX < 0 || newX >= gameLogicState.length || newY < 0 || newY >= gameLogicState[0].length) {
                return true; // The block cannot move because it's out of bounds
            }

            // Check if the new location is null or occupied by the same block
            if (gameLogicState[newX][newY] !== null && gameLogicState[newX][newY] === "block") {
                return true; // The block cannot move because of a collision
            }

            // Update the block's location
            return false; // The block can move in the specified direction
        }
    }

    function createItem(array, item) {
        randomformlist = ["Cube", "T", "Z", "Line"]
        randomint = Math.floor(Math.random() * 4);
        let currentItem = new shape([4, 1], "Cube")
        for (let each = 0; each < currentItem.blocks.length; each++) {
            let x = currentItem.blocks[each].location[0]
            let y = currentItem.blocks[each].location[1]
            gameLogicState[x][y] = currentItem.blocks[each]
        }
        console.log(gameLogicState)
        return [currentItem, gameLogicState];
    }

    function render(gameLogicState, gameRenderState) {
        try {
            for (let i = 0; i < gameLogicState.length; i++) {
                for (let j = 0; j < gameLogicState[i].length; j++) {
                    if (gameLogicState[i][j] !== null) {
                        colorCell(gameRenderState[i][j], '#1e90ff');
                    } else if (gameLogicState[i][j] == null) {
                        colorCell(gameRenderState[i][j], 'transparent')
                    }
                }
            }

        } catch (TypeError) {
        }
    }

    //todo test move function maybe its a reason for the infinte array bug
    function store(gameLogicState, currentItem) {
        for (let each = 0; each < 4; each++) {
            y = currentItem.blocks[each].location[1]
            x = currentItem.blocks[each].location[0]
            gameLogicState[x][y] = "block"
        }
        return gameLogicState
    }

    function checkIfLineIsFull() {
        let row = 0
        let line = 19
        let counter = 0
        let lineFull = false
        for (line; line > 0; line--) {
            for (row; row < 10; row++) {
                if (gameLogicState[row][line] != null) {
                    counter++
                    if (counter == 10) {
                        lineFull = true
                        return {lineFull: lineFull, line: line}
                    }
                } else {
                    counter = 0
                }
            }
            return {lineFull: lineFull}
        }
    }

    function removeLine(line) {
        buffer = undefined
        for (horiontal = 0; horiontal < 10; horiontal++) {
            for (vertical = line; vertical > 0; vertical--) {
                if (vertical == 0) {
                    buffer = gameLogicState[horiontal][vertical]
                    gameLogicState[horiontal][vertical] = null
                } else {
                    gameLogicState[horiontal][vertical] = gameLogicState[horiontal][vertical - 1]
                }
            }
        }
        return gameLogicState
    }

    var gameLogicState = generateArrayForTheGame()
    currentItem = null
    wingame = true;
    var itemList = [];
    document.addEventListener('keydown', function (event) {
        if (event.key === 'ArrowLeft') {
            // Left arrow key pressed
            gameData = currentItem.move(gameLogicState, "left")
        } else if (event.key === 'ArrowRight') {
            // Right arrow key pressed
            gameData = currentItem.move(gameLogicState, "right")
        }
        gameLogicState = gameData[1]
        currentItem = gameData[0]
        render(gameLogicState, grid)
    });
//todo gameloop neu schreiben
    function gameLoop() {
        if (currentItem == null) {
            gameData = createItem(gameLogicState, currentItem);
            currentItem = gameData[0]
            gameLogicState = gameData[1]
        }
        if (currentItem.collision(gameLogicState, 'down')) {
            gameLogicState = store(gameLogicState, currentItem);
            if (checkIfLineIsFull().lineFull) {
                line = checkIfLineIsFull().line
                gameLogicState = removeLine(checkIfLineIsFull().line)
                console.log("removed line number", line)
            }
            gameData = createItem(gameLogicState, currentItem);
            currentItem = gameData[0];
            gameLogicState = gameData[1];
        } else {
            gameData = gravity(currentItem, gameLogicState);
            currentItem = gameData[0];
            gameLogicState = gameData[1];
        }

        render(gameLogicState, grid);
        setTimeout(gameLoop, 150);
    }

    gameLoop()

Image_1 Image_2 Image_3

0

There are 0 best solutions below