Detecção de colisão diminui o desenho da tela

8

Recentemente, tenho buscado o desenvolvimento de jogos como um hobby e decidi que, para aprender as vantagens e desvantagens do desenvolvimento de jogos, eu deveria criar um jogo e renderizar tudo sozinho (sem o uso de um mecanismo de jogo). Isso se mostrou um pouco complicado, mas estou fazendo um grande progresso. No entanto, eu me deparei com um problema que acho que pode estar relacionado à maneira como os telefones Android renderizam seus gráficos e precisará de alguns esclarecimentos sobre esse assunto.

O problema

Meu jogo contém uma série de bolas em um canhão; quando o usuário pressiona a tela, o canhão lança as bolas e o mecanismo (que estou implementando) lida com as atualizações das informações de localização e da detecção de colisão a partir daí. Agora, antes de implementar a detecção de colisão, meu jogo era executado de maneira muito suave e responsiva, no entanto, quando eu disse ao mecanismo para desenhar a conta apenas dentro dos limites e "rebatê-la" da parede, caso contrário, parece que o mecanismo O loop agora leva uma quantidade significativamente maior de tempo para ser executado.

Isso seria bom, se não fosse a latência que está fornecendo à experiência do usuário. Por exemplo, quando a tela é tocada agora , leva aproximadamente 2 segundos para que a bola seja exibida se movendo pela tela e, às vezes, ela não aparece . Anteriormente, a reação era instantânea.

Além disso, quando eu comento a parte de detecção de colisão do meu mecanismo de física, ele retoma seu comportamento responsivo usual.

O que eu acho que está causando esse comportamento

Nota: Recusei essa suposição (consulte 'Informações sobre depuração' abaixo)

Eu acho que, como não tenho um limitador de quadro implementado para o meu jogo, e ele está renderizando o mais rápido que o hardware permitir, está desenhando tantos quadros antigos (em algum buffer, talvez?) Na tela que ele está ocupado desenhando enquanto deveria estar atualizando a física. Embora minha depuração até o momento não tenha indicado que esse é o caso, não consigo chegar a nenhuma outra conclusão.

Some Code

Observe que esse código será um pouco confuso para entender sem saber o que tudo faz. Eu simplesmente o incluí no caso de alguém ser específico sobre ter algum código para trabalhar. As variáveis ​​são esclarecidas abaixo do trecho.

PhysicsEngine.updateBeadPositions (float) :

private void updateBeadPositions(float delta){

    //Update all of the beads currently on the board.
    beads = control.getBoard().getValues();

    temp_x = 0.0f;
    temp_y = 0.0f;

    //For each row...
    for(Bead[] row : beads){

        //For each bead...
        for(Bead bead : row){

            //If this bead exists...
            if(bead != null){

                temp_y = (float) (bead.getYCoordinate() * bead.getYVelocity() * delta);

                //If the coordinates are within the bounds of the game
                if(outwithVerticalBounds(temp_y, control.getBoard())){

                    //Set the X coordinate equal to the distance * the time differential (delta).
                    bead.setXCoordinate(temp_x);

                    //Set the X coordinate equal to the distance * the time differential (delta).
                    bead.setYCoordinate(temp_y);
                }
            }
        }
    }

    //If the cannon Bead has been set...
    if(control.getCannon().getReleased() != null){

        //Update the cannon bead
        if(control.getCannon().getReleased().getXVelocity() == PhysicsEngine.VELOCITY_STATIC && control.getCannon().getReleased().getYVelocity() == PhysicsEngine.VELOCITY_STATIC){

            control.getCannon().getReleased().setXCoordinate(control.getCannon().getX());
            control.getCannon().getReleased().setYCoordinate(control.getCannon().getY() - Cannon.PIVOT_Y_OFFSET);
        }
        else{

            temp_x = control.getCannon().getReleased().getXCoordinate() + (control.getCannon().getReleased().getXVelocity() * delta);
            temp_y = control.getCannon().getReleased().getYCoordinate() + (control.getCannon().getReleased().getYVelocity() * delta);

            //TODO: Commented out collision checkers!

            //If the horizontal coordinates are within the bounds of the game
            if(!outwithHorizontalBounds(temp_x, control.getBoard())){

                //If the vertical coordinates are within the bounds of game
                if(!outwithVerticalBounds(temp_y, control.getBoard())){

                    //Set the X coordinate equal to the distance * the time differential (delta).       
                    control.getCannon().getReleased().setXCoordinate(temp_x);

                    //Set the X coordinate equal to the distance * the time differential (delta).
                    control.getCannon().getReleased().setYCoordinate(temp_y);
                }
                //Otherwise...
                else{

                    //Bounds off the wall in the y direction
                    control.getCannon().getReleased().setYVelocity(-1.0f * control.getCannon().getReleased().getYVelocity());
                }
            }
            //Otherwise...
            else{

                //Bounce off the wall in the x direction (flip the x velocity)
                control.getCannon().getReleased().setXVelocity(-1.0f * control.getCannon().getReleased().getXVelocity());
            }
        }
    }
}

Aqui, as variáveis ​​são definidas como:

  • controlé uma referência ao meu controlador de jogo. Empacota a maioria do código do jogo.

  • beads é uma referência à matriz 2D que contém as contas no quadro atualmente (excluindo a que está em movimento)

  • delta é o diferencial de tempo entre as chamadas anteriores para o mecanismo de física e a chamada atual

Veja os comentários no código para outras explicações.

PhysicsEngine.outwithHorizontalBounds (float, Board) :

private boolean outwithHorizontalBounds(float x, Board board){

    //If the horizontal values are within the bounds...
    if(x > (board.getRight() - bead_radius)){

        return true;
    }

    if(x < (board.getLeft() + bead_radius)){

        return true;
    }

    //Otherwise, it is not.
    return false;
}

O método outwithVerticalBounds(float, Board)é de funcionalidade equivalente, mas na direção y.


Minha pergunta

E a detecção de colisão faria com que a renderização da tela fosse inibida de maneira tão drástica? Eu sei que é uma operação muito intensiva, mas minha depuração mostrou que as atualizações físicas estão sendo concluídas nos mesmos horários que os sorteios.

Informações de depuração

Última atualização: 29 de janeiro de 2013 16:27 EST

Aqui está uma agregação das informações de depuração que obtive até agora. Vou atualizar isso à medida que o tempo avança:

  • O update()método dentro do meu mecanismo leva, em média, apenas .018 mspara ser executado. Geralmente, o atraso aumenta 0.020 msquando toco na tela para liberar a conta.

  • Depois de comparar os horários dos sorteios e as atualizações do jogo, parece que eu estava correto: eles estão ocorrendo simultaneamente . Assim, este não poderia ser o problema, certo?

  • O FPSjogo é mais ou menos 87, ele dispara aleatoriamente para (na extremidade inferior) 60 FPS, no entanto, esse aumento não está relacionado à liberação do cordão. Não há FPSdesvantagens em fazer isso. Isso faz sentido, uma vez que a única parte que aumenta sua complexidade após o lançamento do cordão é a update()chamada, o desenho ainda acontece o mais rápido possível.

  • Após mais testes, tornou-se evidente que esse não é o caso de a tela estar atrasada em relação à física. Testei isso com uma bandeira booleana simples, na qual o fundo da tela ficaria branco quando o tocasse, e isso acontece imediatamente . Portanto, deve haver outra causa para o cordão não esticar. Vou atualizar em breve.

Informação complementar

Aqui estão algumas informações adicionais que devem ajudá-lo a entender minhas circunstâncias:

  • Estou testando isso no Google Nexus 7.

  • Existem algumas contas no mapa que estão sendo atualizadas de uma só vez (cerca de 30), mas apenas uma delas está em movimento.

  • Geralmente, depois que o cordão começa a se mover (após o atraso inicial e se ele realmente puxa), ele continua a se mover de maneira muito suave.

  • É importante observar que tenho outros elementos da interface do usuário na tela que são atualizados em reação ao evento de toque. Por exemplo, o cordão carregado no canhão se torna um cordão novo quando a tela é tocada (significando que foi liberada), mas o cordão móvel simplesmente não é desenhado.

Squagem
fonte
Acha que sua depuração que mostra as atualizações físicas alinhadas com os desenhos pode ser imprecisa? Você já fez outros perfis com esse código?
MichaelHouse
Fiz uma extensa depuração usando saídas para o console (LogCat), mas nada mais complicado que isso. Pode ser que minhas instruções de depuração estejam incorretas, vou analisá-las agora.
Squagem
Também é interessante se o FPS (quadros por segundo) muda ao adicionar o caso delimitador ou se o problema não está relacionado à rapidez com que o programa é executado.
Qqwy
Eu editei minha pergunta para responder aos pontos que você levantou.
Squagem

Respostas:

8

Sinceramente, tenho vergonha de anunciar a solução para o meu problema, pois passei muitas horas em busca dele, e era tão simples e poderia ter sido evitado tão facilmente com um pouco menos de negligência em meu nome. Pelo lado positivo, acabei encontrando alguns outros trechos de código que agora posso otimizar para obter um desempenho ainda melhor!

A solução

O canhão que estava lançando a conta estava abaixo do limite inferior da minha área jogável.

Isso foi enganoso, porque o limite inferior da minha área de jogo está um pouco acima da parte inferior da tela real do telefone. Então, basicamente, o mecanismo de física o estava devolvendo e o quarto levemente (invisível à inspeção humana) por cerca de 5 segundos antes de ser renderizado na tela.

Movi o canhão 50 pixels mais alto e ele funciona como pretendido agora.


Obrigado a todos pela ajuda! Eu não teria chegado aqui sem suas sugestões.

Squagem
fonte
3
+1 para uma pergunta bem formatado e +1 para responder it yourself
RoughPlace
Opa, esqueci essa pergunta! Thanks guys :)
Squagem