Ir ao conteúdo
  • Cadastre-se

Java Recriação do jogo Tetris com LibGDX


Posts recomendados

olá galera, estou com um problema o qual não consigo resolver de forma alguma no meu código!
as colisões o grid tudo está funcionando, más tem um problema na hora de retirar a linha completa do tetris! os métodos criados não estão respondendo corretamente, já pedi auxilio até para a porquera do ChatGPT  e nem ele conseguiu ajudar só piorou kkkkk
eu não sei em qual aula eu faltei de java, mas o problema é o seguinte. Quando a ultima peça que o jogador coloca no grid fecha uma linha ou mais, a peça em si que fechou a linha não tem tem a parte correspondente a linha fechada removida, a peça continua e as peças próximas também não são removidas! este projeto de recriar o jogo tetris é para uma implementação de uma IA, que eu também irei bater a cabeça para fazer kkk, mas primeiro preciso ter o jogo completo jogavel.

se alguém puder me ajudar com esse problema eu agradeceria muito. irei compactar o projeto inteiro com todas as classes e assets para que possam analisar onde eu errei!

caso queiram analisar a classe que manipula os tetrominos irei mostrar aqui!

 

package com.mygdx.iadojogo;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;


public class TetrominoManager {
    private int score;
    private Tetromino currentTetromino;
    private Tetromino nextTetromino;
    private static final int GRID_WIDTH = 10;
    private static final int GRID_HEIGHT = 20;
    private int[][] grid;

    private Texture spriteSheet;
    private int blockSize;
    private int xOffset;
    private int gridFirstScreenX = 60;
    private int gridFirstScreenY = 50;
    private float moveDelay = 1f; // Ajuste o valor conforme desejado (maior valor -> movimento mais lento)
    private float moveTimer = 0f;
    private boolean isPieceFalling = true;
    private boolean isMovingHorizontally = false; // Verifica se a peça está se movendo lateralmente
    private float horizontalMoveTimer = 0f;
    private float horizontalMoveDelay = 2f;
    private boolean gameOver = false;
    private int[][] gridSprites;


    public TetrominoManager(final Texture spriteSheet, final int blockSize, final int xOffset) {
        this.spriteSheet = spriteSheet;
        this.blockSize = blockSize;
        this.xOffset = xOffset;
        this.score = 0;
        currentTetromino = new Tetromino(getRandomShape());
        nextTetromino = new Tetromino(getRandomShape());
        gridSprites = new int[GRID_HEIGHT][GRID_WIDTH]; // Inicialize a matriz gridSprites
        grid = new int[GRID_HEIGHT][GRID_WIDTH];
        currentTetromino.setPosX(GRID_WIDTH / 2 - currentTetromino.getShape()[0].length / 2);
        currentTetromino.setPosY(GRID_HEIGHT - currentTetromino.getShape().length);
        int spriteWidth = 32;
        int spriteHeight = 32;

    }

    public void update(float delta) {

        if (gameOver) {
            return; // Se o jogo acabou, não atualize mais nada
        }
        // Verificar o movimento lateral esquerdo
        if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
            horizontalMoveTimer += delta;
            if (horizontalMoveTimer >= horizontalMoveDelay) {
                moveLeft();
                horizontalMoveTimer = 0f;
            }
        }
        // Verificar o movimento lateral direito
        if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
            horizontalMoveTimer += delta;
            if (horizontalMoveTimer >= horizontalMoveDelay) {
                moveRight();
                horizontalMoveTimer = 0f;
            }
        }
        // Atualização da queda da peça
        if (isPieceFalling) {
            moveTimer += delta;
            if (moveTimer >= moveDelay) {
                moveTimer = 0f;
                if (!moveDown()) {
                    placeTetromino();
                    isPieceFalling = false;
                    if (currentTetromino.getPosY() >= GRID_HEIGHT - currentTetromino.getShape().length) {
                        gameOver = true; // Peça chegou ao topo do grid, indicação de Game Over
                    }
                }
            }
        } else {
            currentTetromino = new Tetromino(getRandomShape());
            currentTetromino.setPosX(GRID_WIDTH / 2 - currentTetromino.getShape()[0].length / 2);
            currentTetromino.setPosY(GRID_HEIGHT - currentTetromino.getShape().length);
            isPieceFalling = true;
        }
        if (!isPieceFalling) {
            currentTetromino = nextTetromino;
            generateNextTetromino();
            currentTetromino.setPosX(GRID_WIDTH / 2 - currentTetromino.getShape()[0].length / 2);
            currentTetromino.setPosY(GRID_HEIGHT - currentTetromino.getShape().length);
            isPieceFalling = true;
        }
    }

    public void draw(SpriteBatch batch) {
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //primeira parte
        // Desenhar o contorno branco de cada bloco do grid
        for (int y = 0; y < GRID_HEIGHT; y++) {
            for (int x = 0; x < GRID_WIDTH; x++) {
                int xDraw = x * blockSize + gridFirstScreenX;
                int yDraw = y * blockSize + gridFirstScreenY;

                // Desenhar o contorno branco em volta do bloco
                batch.setColor(Color.WHITE);
                batch.draw(spriteSheet, xDraw - 1, yDraw - 1, blockSize + 2, 1);
                batch.draw(spriteSheet, xDraw - 1, yDraw + blockSize - 1, blockSize + 2, 1);
                batch.draw(spriteSheet, xDraw - 1, yDraw, 1, blockSize);
                batch.draw(spriteSheet, xDraw + blockSize - 1, yDraw, 1, blockSize);
            }
        }
        //fim primeira parte
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //segunda parte
        // Desenhar as peças que estão caindo
        int[][] shape = currentTetromino.getShape();
        int pieceIndex = currentTetromino.getSpriteIndex() ; // Índice 0 representa o primeiro sprite da folha de sprite (32x32)


        for (int i = 0; i < shape.length; i++) {
            for (int j = 0; j < shape[i].length; j++) {
                int index = shape[i][j];
                if (index == 1) {
                    // Calcule a posição na folha de sprite com base no pieceIndex
                    int xSheet = (pieceIndex % 4) * blockSize; // O módulo 4 garante que fique dentro da primeira linha (0 a 3)
                    int ySheet = (pieceIndex / 4) * blockSize; // A divisão inteira por 4 obtém a posição da linha correta (0 a 9)

                    // Calcule a posição de desenho no grid
                    int xDraw = (currentTetromino.getPosX() + j) * blockSize + gridFirstScreenX;
                    int yDraw = (currentTetromino.getPosY() + i) * blockSize + gridFirstScreenY;

                    // Desenhe o sprite de 32x32 na posição do Tetromino
                    batch.draw(spriteSheet, xDraw, yDraw, blockSize, blockSize,
                            xSheet, ySheet, blockSize, blockSize, false, false);
                }
            }
        }
        //fim segunda parte
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //terceira parte
        // Desenhar as peças que já estão no grid
        for (int y = 0; y < GRID_HEIGHT; y++) {
            for (int x = 0; x < GRID_WIDTH; x++) {
                if (grid[y][x] != 0) { // Verificar se a posição do grid está ocupada
                    int pieceIndex1 = grid[y][x] - 1; // Obtém o índice do sprite da peça (subtrai 1 pois os índices são incrementados na matriz grid)
                    int xDraw = x * blockSize + gridFirstScreenX;
                    int yDraw = y * blockSize + gridFirstScreenY;

                    // Desenhe o sprite de 32x32 na posição do grid
                    batch.draw(spriteSheet, xDraw, yDraw, blockSize, blockSize,
                            pieceIndex1 * blockSize, 0, blockSize, blockSize, false, false);
                }
            }
        }
        //fim terceira parte
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        //quarta parte
        // Desenha a próxima peça
        int[][] nextShape = nextTetromino.getShape();
        int nextBlockSize = blockSize / 2; // Tamanho reduzido para a próxima peça
        int nextGridFirstScreenX = gridFirstScreenX + GRID_WIDTH * blockSize + 50; // Posição x da próxima peça
        int nextGridFirstScreenY = gridFirstScreenY + GRID_HEIGHT * blockSize - nextShape.length * nextBlockSize; // Posição y da próxima peça

        for (int i = 0; i < nextShape.length; i++) {
            for (int j = 0; j < nextShape[i].length; j++) {
                int index = nextShape[i][j];
                if (index == 1) {
                    int nextPieceIndex = nextTetromino.getSpriteIndex() + 2; // Índice na folha de sprites para a próxima peça
                    int xSheet = (nextPieceIndex % 4 ) * blockSize; // O módulo 4 garante que fique dentro da primeira linha (0 a 3)
                    int ySheet = (nextPieceIndex / 4 ) * blockSize; // A divisão inteira por 4 obtém a posição da linha correta (0 a 9)

                    int xDraw = (j + nextGridFirstScreenX / nextBlockSize) * nextBlockSize;
                    int yDraw = (i + nextGridFirstScreenY / nextBlockSize) * nextBlockSize;

                    batch.draw(spriteSheet , xDraw, yDraw, nextBlockSize, nextBlockSize,
                            xSheet, ySheet, blockSize, blockSize, false, false);
                }
            }
        }
        //fim quarta parte
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    }

    public void setTetrominoShape(int[][] shape) {
        currentTetromino.setShape(shape);
    }
    private void generateNextTetromino() {
        nextTetromino = new Tetromino(getRandomShape());
    }

    private void startHorizontalMovement() {
        isMovingHorizontally = true;
    }


    public boolean moveLeft() {
        if (canMoveTo(currentTetromino.getPosX() - 1, currentTetromino.getPosY())) {
            currentTetromino.moveLeft();
            startHorizontalMovement();
            return true;
        }
        return false;
    }

    public boolean moveRight() {
        if (canMoveTo(currentTetromino.getPosX() + 1, currentTetromino.getPosY())) {
            currentTetromino.moveRight();
            startHorizontalMovement();
            return true;
        }
        return false;
    }

    public boolean moveDown() {
        if (canMoveTo(currentTetromino.getPosX(), currentTetromino.getPosY() - 1)) {
            currentTetromino.moveDown();
            return true;
        } else {
            // Se a peça não puder se mover para baixo, ela atinge a parte inferior do grid.
            // Neste ponto, podemos definir a peça no grid e definir a variável isPieceFalling como false.
            placeTetromino();
            isPieceFalling = false;
            return false;
        }
    }

    private boolean canMoveTo(int newX, int newY) {
        return canMoveTo(newX, newY, currentTetromino.getShape());
    }

    private boolean canMoveTo(int newX, int newY, int[][] newShape) {
        for (int i = 0; i < newShape.length; i++) {
            for (int j = 0; j < newShape[i].length; j++) {
                if (newShape[i][j] == 1) {
                    int x = newX + j;
                    int y = newY + i;
                    // Verifique se a posição (x, y) está dentro dos limites do grid
                    if (x < 0 || x >= GRID_WIDTH || y < 0 || y >= GRID_HEIGHT ) {
                        return false;
                    }
                    // Verifique se a posição (x, y) está vazia no grid
                    if (y >= 0 && grid[y][x] != 0) {
                        return false;
                    }
                }
            }
        }
        return true;
    }
    private boolean isLineComplete(int line) {
        for (int x = 0; x < GRID_WIDTH; x++) {
            if (grid[line][x] == 0) {
                return false; // Encontrou um bloco vazio na linha, não está completa
            }
        }
        return true;
    }

    private void removeLine(int line) {
        for (int y = line + 1; y < GRID_HEIGHT; y++) {
            for (int x = 0; x < GRID_WIDTH; x++) {
                grid[y - 1][x] = grid[y][x]; // Move cada linha acima para baixo em um passo
                gridSprites[y - 1][x] = gridSprites[y][x];
            }
        }

        for (int x = 0; x < GRID_WIDTH; x++) {
            grid[GRID_HEIGHT - 1][x] = 0; // Define a linha superior como vazia
            gridSprites[GRID_HEIGHT - 1][x] = 0;
        }
    }


    private void placeTetromino() {
        // Colocar o tetromino no grid
        int[][] shape = currentTetromino.getShape();
        int pieceIndex = currentTetromino.getSpriteIndex();

        int posX = currentTetromino.getPosX();
        int posY = currentTetromino.getPosY();

        for (int i = 0; i < shape.length; i++) {
            for (int j = 0; j < shape[i].length; j++) {
                if (shape[i][j] == 1) {
                    int x = posX + j;
                    int y = posY + i;

                    // Verificar se a posição (x, y) está dentro dos limites do grid
                    if (x >= 0 && x < GRID_WIDTH && y >= 0 && y < GRID_HEIGHT) {
                        // Verificar se a posição (x, y) está vazia no grid
                        if (grid[y][x] != 0) {
                            // Parte da peça está na linha completa, limpar essa célula do gridSprites e grid
                            gridSprites[y][x] = 0;
                            grid[y][x] = 0;
                        }

                        // Marque a posição no grid como ocupada pela peça
                        grid[y][x] = 1;
                        gridSprites[y][x] = pieceIndex + 1;
                    }
                }
            }
        }

        // Verificar se há linhas completas e removê-las, inclusive as peças adjacentes
        int linesCleared = 0;
        for (int y = 0; y < GRID_HEIGHT; y++) {
            if (isLineComplete(y)) {
                removeLine(y);
                linesCleared++;
                y--; // Após remover uma linha, precisamos verificar a linha atual novamente, pois a próxima linha desceu uma posição.
            }
        }


        if (linesCleared > 0) {
            score += calculateScore(linesCleared);
        }

        // Verifique se houve um Tetris (4 linhas eliminadas) e adicione pontos adicionais
        if (linesCleared == 4) {
            score += 800; // Valor padrão para Tetris
        }

    }


    private int calculateScore(int linesCleared) {
        // Implemente a lógica de pontuação aqui, você pode ajustar os valores conforme desejado
        switch (linesCleared) {
            case 1:
                return 100; // Pontuação para uma linha eliminada
            case 2:
                return 300; // Pontuação para duas linhas eliminadas simultaneamente
            case 3:
                return 500; // Pontuação para três linhas eliminadas simultaneamente
            default:
                return 0; // Por padrão, não há pontuação extra para eliminar mais de 3 linhas
        }
    }
    public void rotate() {
        currentTetromino.rotate();
    }

    private int[][] getRandomShape() {
        // Array que contém todas as formas possíveis de tetromino
        int[][][] allShapes = {
                Shape.getShapeI(),
                Shape.getShapeJ(),
                Shape.getShapeL(),
                Shape.getShapeO(),
                Shape.getShapeS(),
                Shape.getShapeT(),
                Shape.getShapeZ()
        };

        // Gerar um número aleatório para selecionar uma forma aleatória
        int randomIndex = (int) (Math.random() * allShapes.length);

        // Retornar a forma selecionada aleatoriamente
        return allShapes[randomIndex];
    }

    public Tetromino getCurrentTetromino() {
        return currentTetromino;
    }

    public void setCurrentTetromino(Tetromino currentTetromino) {
        this.currentTetromino = currentTetromino;
    }

    public int[][] getGrid() {
        return grid;
    }

    public void setGrid(int[][] grid) {
        this.grid = grid;
    }

    public Texture getSpriteSheet() {
        return spriteSheet;
    }

    public void setSpriteSheet(Texture spriteSheet) {
        this.spriteSheet = spriteSheet;
    }

    public int getBlockSize() {
        return blockSize;
    }

    public void setBlockSize(int blockSize) {
        this.blockSize = blockSize;
    }

    public int getxOffset() {
        return xOffset;
    }

    public void setxOffset(int xOffset) {
        this.xOffset = xOffset;
    }

    public int getGridFirstScreenX() {
        return gridFirstScreenX;
    }

    public void setGridFirstScreenX(int gridFirstScreenX) {
        this.gridFirstScreenX = gridFirstScreenX;
    }

    public int getGridFirstScreenY() {
        return gridFirstScreenY;
    }

    public void setGridFirstScreenY(int gridFirstScreenY) {
        this.gridFirstScreenY = gridFirstScreenY;
    }

    public float getMoveDelay() {
        return moveDelay;
    }

    public void setMoveDelay(float moveDelay) {
        this.moveDelay = moveDelay;
    }

    public float getMoveTimer() {
        return moveTimer;
    }

    public void setMoveTimer(float moveTimer) {
        this.moveTimer = moveTimer;
    }

    public boolean isPieceFalling() {
        return isPieceFalling;
    }

    public void setPieceFalling(boolean pieceFalling) {
        isPieceFalling = pieceFalling;
    }

    public boolean isMovingHorizontally() {
        return isMovingHorizontally;
    }

    public void setMovingHorizontally(boolean movingHorizontally) {
        isMovingHorizontally = movingHorizontally;
    }

    public float getHorizontalMoveTimer() {
        return horizontalMoveTimer;
    }

    public void setHorizontalMoveTimer(float horizontalMoveTimer) {
        this.horizontalMoveTimer = horizontalMoveTimer;
    }

    public float getHorizontalMoveDelay() {
        return horizontalMoveDelay;
    }

    public void setHorizontalMoveDelay(float horizontalMoveDelay) {
        this.horizontalMoveDelay = horizontalMoveDelay;
    }

    public boolean isGameOver() {
        return gameOver;
    }

    public void setGameOver(boolean gameOver) {
        this.gameOver = gameOver;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }
}

 

 

 

 

desde já agradeço a todos!

 

TetrisIA.zip

  • Amei 1
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!