Ir ao conteúdo

Posts recomendados

Postado

Fiz esse código aqui em C para verificar se a peça colidiu nesse caso somente uma peça, essa peça aqui (l) e também estou verificando na posição deitada, ela está colidindo quando está verticalmente e horizontalmente mas ocorre essa colisão quando está na última linha e a peça vertical colide uma linha acima, já quando a peça está deitada ela colide na última linha, fora isso quando aparece uma nova peça as mesmas que já estão na matriz não colidem com as novas peças nem na vertical e nem na horizontal. 

Segue o código abaixo

int collisionDetect(char matrix[ROWS][COLUMNS], Bloco barra){
    int retorno = 0;

    //Colisão com a base
    if((barra.i + barra.height/2) >= (ROWS-1))
        retorno = 1;
    return retorno;
}

 

  • Amei 1
Postado

@devair1010A peça é um código ASCII 219 ele possui tamanho deitada 1 de altura e 5 de largura, e os valores de invertem quando ele está na vertical, ficando 5 de altura 1 e largura, elas são compostas por mais de um caractere ASCII, mas são do mesmo caractere ASCII

  • Obrigado 1
Postado

Anos atrás, eu traduzi um tutorial justamente de um tetris em C com SDL.

Vou procurar aqui, se eu achar eu posto o link pra você baixar.

adicionado 5 minutos depois

Ops, me enganei na linguagem. No tutorial é usado C++, você vai precisar adaptar, ver abaixo:

http://bit.ly/tetristutorial

Postado

Acho que pode usar teoria de conjuntos mesmo: uma peça é um conjunto de partes e tem então um conjunto de pontos. Elas colidem quando ao menos um desses pontos é compartilhado. Só isso. Escolha uma estrutura de dados e implemente assim. C++ ou java tem classes de conjuntos mesmo. Em C por exemplo usando listas e vetores estaria coberto.

 

Sugestão: Pense assim:

  • cada peça é um conjunto de pontos, pixels, bloco, o diabo.
  • Defina um máximo de coordenadas para uma peça na matriz, como sua peça do exemplo tem cinco. Cada peça terá então um vetor desse tamanho com pares (x,y)
  • Seu universo terá um número finito de peças, representadas cada uma por um vetor desses. Então sua matriz terá num dado momento um certo número de peças, correspondendo cada uma a um vetor desses.
  • Defina a posição de cada peça como sendo por exemplo a coordenada com o menor (x,y)
  • Crie uma função de comparação que vai definir a colisão
  • Note que isso funcionam mesmo que as peças tenham "buracos"

Só isso

  • Curtir 2
Postado

Olá fiquei curioso por esse algoritmo e pensei em algo mínimo que desse pra testar rápido. Tive sucesso com uma estrutura assim --- sem preocupação com performance:


#define			MAX_PINOS		10
#define			MAX_X			20
#define			MAX_Y			20
#define			_LIVRE			'*'
#define			_PONTO			'O'

struct ponto
{
    uint8_t        X;
    uint8_t        Y;
};
typedef            struct ponto Ponto;

struct peca
{
    uint8_t        id;
    uint8_t        H;
    uint8_t        n_blocos;
    char*          nome;
    Ponto          pino[MAX_PINOS];
    uint8_t        W;
};
typedef            struct peca Peca;

struct mapa
{
    short          total;
    Peca*          peca[30];
    Ponto*         posicao[30];
    short          status[30];
};
typedef            struct mapa Mapa;

struct grade
{
    uint8_t        grade[MAX_X][MAX_Y];
    Mapa*          mapa;
};
typedef            struct grade Grade;

Bem simples.

 

  • A grade é o tabuleiro ou sei o nome.
  •  
    struct grade
    {
        uint8_t     grade[MAX_X][MAX_Y];
        Mapa*       mapa;
    };
    typedef         struct grade Grade;

     

  • tem um mapa associado à grade com as peças
  •  
    struct mapa
    {
        short        total;
        Peca*        peca[30];
        Ponto*       posicao[30];
        short        status[30];
    };
    typedef          struct mapa Mapa;
  • confesso uma certa preguiça ou ansiedade pra testar... o mapa tem uma lista de peças. As com status 0 terão posição definida na tela. as outras já tem. Os significados aqui são os óbvios: no mapa de total peças elas tem um vetor de posições e um de status
  • as pecas tem um id único gerado na criação e um nome que pode ser repetido
struct peca
{
    uint8_t      id;
    uint8_t      H;
    uint8_t      n_blocos;
    char*        nome;
    Ponto        pino[MAX_PINOS];
    uint8_t      W;
};
typedef          struct peca Peca;
  • as peças tem um número máximo de pontos, definido em tempo de compilação
  • uma pequena matriz na struct tem as coordenadas dos pontos todos,
    em relação ao ponto mais a esquerda e acima da peça
  • cada peça tem uma largura e altura especificadas assim se pode posicionar aleatoriamente na tela
  • cada ponto tem as coordenadas
  •  
    struct ponto
    {
        uint8_t        X;
        uint8_t        Y;
    };
    typedef            struct ponto Ponto;

    E é isso...

  • Eis o header todo

  • #pragma once
    #define            _CRT_SECURE_NO_WARNINGS
    #define            MAX_PINOS        10
    #define            MAX_X            20
    #define            MAX_Y            20
    #define            _LIVRE            '*'
    #define            _PONTO            'O'
    
    #include "stdint.h"
    #include "stdio.h"
    
    struct ponto
    {
        uint8_t        X;
        uint8_t        Y;
    };
    typedef            struct ponto Ponto;
    
    struct peca
    {
        uint8_t        id;
        uint8_t        H;
        uint8_t        n_blocos;
        char*        nome;
        Ponto        pino[MAX_PINOS];
        uint8_t        W;
    };
    typedef            struct peca Peca;
    
    struct mapa
    {
        short        total;
        Peca*        peca[30];
        Ponto*        posicao[30];
        short        status[30];
    };
    typedef            struct mapa Mapa;
    
    struct grade
    {
        uint8_t        grade[MAX_X][MAX_Y];
        Mapa*        mapa;
    };
    typedef            struct grade Grade;
    
    
    Peca*    cria_1_5(Grade*, char*);
    Peca*    cria_5_1(Grade*, char*);
    Peca*    fabrica_de_pecas(Grade*, Peca*);
    int        inicia_grade(Grade*);
    int        mostra_grade(Grade*);
    int        mostra_peca(Peca*);
    int        posiciona_pecas(Grade*);
    int        posiciona_um(Grade*,uint8_t);

    Eis um exemplo para uma coluna de 1x5 pontos vertical

  • {    // horizontal
        Peca* p = (Peca*)malloc(sizeof(Peca));
        if (p == NULL) return NULL;
        p->H = 5;
        p->n_blocos = 5; p->nome = nome;
        p->W = 1;
    
        p->pino[0].X = 0;
        p->pino[1].X = 0;
        p->pino[2].X = 0;
        p->pino[3].X = 0;
        p->pino[4].X = 0;
    
        p->pino[0].Y = 0;
        p->pino[1].Y = 1;
        p->pino[2].Y = 2;
        p->pino[3].Y = 3;
        p->pino[4].Y = 4;
        // preenchido. Falta so o id pra garantir que nao duplique
        return fabrica_de_pecas(g, p);
    } 

    Assim quando se encontra a posição em que ela vai ficar é só aplicar as coordenadas da estrutura a partir da posição final na tela e verificar se há colisão...

  • Curtir 1
  • Obrigado 1
Postado

Mais sobre os desenhos das peças

 

Esse programa --- abaixo --- roda até ter uma colisão, colocando peças [ ] [ ] [ ] [ ] [ ]  alternadamente na horizontal e vertical até ter uma colisão.

Eis a última tela de um teste.  @Irwing Seiji Ato Se sabe que houve colisão com uma certa peça em uma certa posição e temos o ID da peça em questão. Dependendo das "regras" é trivial ir até a estrutura da peça em questão e pegar o nome e mais informações para por exemplo 

  • apagar as duas
  • simular uma explosão
  • juntar as duas
Peca 'vertical 5' id=10
Largura 1, Altura 5, 5 blocos
origem para a peca=(7,7)
COLISAO: peca com id=7 ja ocupa a posicao (7,9)
Grade:
  X     0    1    2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19
  0     *    *    *    *    *    2    *    *    *    *    *    *    *    *    *    *    *    *    *    *     0
  1     *    *    *    *    *    2    *    *    *    *    *    *    *    *    *    *    *    *    *    *     1
  2     *    *    *    *    *    2    *    *    *    *    *    *    *    *    *    *    *    *    *    *     2
  3     *    *    *    *    *    2    *    *    *    *    *    *    *    *    *    *    *    *    *    *     3
  4     *    *    *    *    *    2    *    *    *    *    *    *    *    *    *    *    *    *    *    *     4
  5     *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *     5
  6     *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *     6
  7     *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *     7
  8     *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    6    *     8
  9     *    *    *    *    *    *    *    7    7    7    7    7    *    *    *    *    *    *    6    *     9
 10     *    *    8    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    6    *    10
 11     *    *    8    3    3    3    3    3    *    *    *    *    *    *    *    *    *    *    6    *    11
 12     *    *    8    *    *    *    9    9    9    9    9    5    5    5    5    5    *    *    6    *    12
 13     *    *    8    *    *    *    *    4    *    *    *    *    *    *    *    *    *    *    *    *    13
 14     *    *    8    *    *    *    *    4    *    *    *    *    *    *    *    *    *    *    *    *    14
 15     *    *    *    *    *    *    *    4    *    *    *    *    *    *    *    *    *    *    *    *    15
 16     *    *    *    *    *    *    *    4    *    1    1    1    1    1    *    *    *    *    *    *    16
 17     *    *    *    *    *    *    *    4    *    *    *    *    *    *    *    *    *    *    *    *    17
 18     *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    18
 19     *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    *    19
  X     0    1    2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19
Teste: encerra na primeira colisao

Esse código

int main(int argc, char** argv)
{
    char* coluna_h = "horizontal 5";
    char* coluna_v = "vertical 5";
    int ciclo = 0;
    int i;
    Grade    grid;
    inicia_grade(&grid);
    printf("Grade:\n");
    mostra_grade(&grid);
    do
    {
        if (ciclo%2)
        {
            // peca 1x5
            cria_1_5(&grid, coluna_v);
            i = posiciona_pecas(&grid);
            ciclo += 1;
        }
        else
        {
            // peca 5x1
            cria_5_1(&grid, coluna_h);
            i = posiciona_pecas(&grid);
            ciclo += 1;
        }
        printf("Grade:\n");
        mostra_grade(&grid);
    } while (i>=0);
    printf("Teste: encerra na primeira colisao\n");
    return 0;
};    // end main()

Simples: alterna usando o valor de ciclo e mostra a grade até posiciona_pecas() reportar uma colisão. É só um teste para as estruturas afinal.

tela.png.1b2795ca08ae11cda9fa2f52bdf489cf.png

 

Não, eu não queria escrever na tela. O interesse é só no mecanismo.

 

Como cada peça tem dentro de si as coordenadas de cada ponto dela, ao identificar onde ela vai ficar na tela fica trivial identificar se tem uma colisão:

Esse é um trecho possível de código para quando ela vai ficar em uma posição aleatória

    Peca*        p = g->mapa->peca[pos];        // simplifica
    uint8_t      outra = 0;                    // em quem bateu
    Ponto        colisao;
    // a peca tem suas coordenadas ja armazenadas a partir do canto 
    // superior esquerdo. a partir da largura maxima e altura maxima
    // e ja esta gravado na descricao da peca
    // calcula onde ela pode ficar na tela
    mostra_peca(p);
    uint8_t     x = rand() % (MAX_X - p->W);
    uint8_t     y = rand() % (MAX_Y - p->H);
    printf("origem para a peca=(%d,%d)\n", x, y);
    /*
    a nova peca tem n_blocos e a origem (x,y). Para ver se ela pode ser
    colocada na grade basta um loop, mapeando os blocos na peca a partir 
    da origem (x,y) e ve se esta marcado como livre na grade
    */
    uint8_t    blocos = p->n_blocos;
    int        ok = 1;                    // livre na tela
    for (int i = 0; i < blocos; i += 1)
    {
        // vamos definir X,Y como a posicao na grade para esse bloco
        uint8_t X = x + p->pino[i].X;
        uint8_t Y = y + p->pino[i].Y;
        if ( g->grade[X][Y] == 0) continue;
        ok = 0;
        outra = (uint8_t)g->grade[X][Y];
        colisao.X = X;
        colisao.Y = Y;
        break;
    }

 

 

 

 

 

 

adicionado 17 minutos depois
[][][]  Uma peça assim teria então 11 "pinos" como
[]      descrito na estrutura de Peça
[][][]
[]      claro, cada par [] significa um ponto
[][][]  podia ser um pixel ou dois caracteres
        ou qualquer outra representação

Uma peça em formato de E ficaria assim então no código

int main(int argc, char** argv)
{
    char* nome = "em formato de E";
    int ciclo = 0;
    int i;
    Grade    grid;
    inicia_grade(&grid);
    printf("Grade:\n");
    mostra_grade(&grid);

    Peca* p = (Peca*)malloc(sizeof(Peca));
    if (p == NULL) return NULL;
    /* peca em formato de 'E' */
    p->H = 5;
    p->n_blocos = 11;
    p->nome = nome;
    p->W = 3;

    p->pino[0].X = 0;
    p->pino[0].Y = 0;    // linha 0
    p->pino[1].X = 1;
    p->pino[1].Y = 0;
    p->pino[2].X = 2;
    p->pino[2].Y = 0;

    p->pino[3].X = 0;
    p->pino[3].Y = 1;    // linha 1

    p->pino[4].X = 0;
    p->pino[4].Y = 2;    // linha 2
    p->pino[5].X = 1;
    p->pino[5].Y = 2;
    p->pino[6].X = 2;
    p->pino[6].Y = 2;

    p->pino[7].X = 0;
    p->pino[7].Y = 3;    // linha 3

    p->pino[8].X = 0;
    p->pino[8].Y = 4;    // linha 4
    p->pino[9].X = 1;
    p->pino[9].Y = 4;
    p->pino[10].X = 2;
    p->pino[10].Y = 4;

    // preenchido. Falta so o id pra garantir que nao duplique
    fabrica_de_pecas(&grid, p);

    i = posiciona_pecas(&grid);
    printf("Grade depois:\n");
    mostra_grade(&grid);
    printf("Teste: posiciona uma unica peca\n");
    return 0;
};    // end main()

E mostraria por exemplo

1734500772_umE.thumb.png.8d8c085e38046f6b044241e238e9a4dd.png

 

Aí você pensa que já tem como compilar as peças e se cada uma tivesse nxn pixels e aí tem as regras e podia... ok parei.

  • Obrigado 1

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...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!