Simulação e Física
Movimento Retilíneo Uniforme
Vamos supor, em um primeiro momento, que o jogo não possui aceleração da gravidade. Assim, o personagem vai cair em velocidade constante até chegar no chão.
Um primeiro problema é que, sem aceleração da gravidade o personagem não vai cair, pois sua velocidade vertical é zero. Vamos então supor que o personagem já começa caindo, com velocidade constante.
Exercício 1
Resposta
Nós sabemos a distância e o tempo. Usando a fórmula do Movimento Retilíneo Uniforme, nós poderíamos calcular a velocidade em pixels por segundo:
Entretanto, como não temos nenhuma maneira de relacionar o tempo em segundos com a quantidade de frames. Ainda nos falta informação!
Relacionando frames e tempo#
O problema é que nós não sabemos quanto tempo se passa de um frame para o outro. Em um computador antigo e lento, pode ser que o tempo entre os frames seja 200 ms. Em um computador mais rápido, pode ser que o tempo entre os mesmos frames seja 2 ms. Pior ainda, o tempo pode ser diferente de um frame para o outro!
Isso pode ocorrer devido a fatores internos ou externos. Um exemplo de fator interno é se em um determinado frame você precisar realizar um cálculo muito pesado. Isso pode fazer com que o tempo entre os frames aumente temporariamente. Um exemplo de fator externo é se o seu navegador começar a usar todo o processamento do computador. Nesse caso, o jogo pode acabar ficando mais lento por precisar esperar a liberação de recursos computacionais.
Então a resposta para a pergunta "quanto tempo se passa de um frame para outro" é depende! Não temos como saber de antemão. Precisamos medir isso de alguma forma. Felizmente, o Pygame já possui uma função que faz isso: pygame.time.get_ticks()
Exercício 2
Resposta
A função devolve quanto tempo se passou, em milissegundos, desde que a função pygame.init()
foi chamada.
Exercício 3
Resposta
Como a função pygame.time.get_ticks()
devolve o tempo em milissegundos desde a chamada ao pygame.init()
, precisamos guardar o resultado de pygame.time.get_ticks()
em um frame e subtraí-lo do resultado dessa mesma função no frame seguinte. O resultado seria mais ou menos assim:
No exercício acima, calculamos quanto tempo se passou entre dois frames. Uma outra forma de interpretar essa informação é o seu inverso, ou seja, quantos frames foram mostrados em 1 segundo. Para gamers, essa é uma medida bastante conhecida: o FPS (frames por segundo).
Exercício 4
Resposta
FPS é Frames Por Segundo, mas o nosso tempo está em milissegundos. Para transformar milissegundos em segundos, dividimos o valor por 1000. Assim:
Exercício 5
Voltando ao MRU#
Agora sim temos todos os dados que precisamos para saber quantos pixels o personagem deve se mover para o personagem chegar no chão em 0,5 segundos.
Exercício 6
Resposta
dy = vy * dt / 1000
Implementando o MRU#
Agora vamos desenvolver nosso primeiro programa usando física. Abra o exercício Bola Bate Rebate no VS Code e volte para este handout para seguir as instruções.
Vamos começar entendendo o código que recebemos.
Exercício 7
Resposta
O dicionário state
contém a chave ball_pos
, que representa a posição inicial da bola como uma lista em que o primeiro elemento é a coordenada x
e o segundo a coordenada y
.
Exercício 8
Agora vamos implementar o Movimento Retilíneo Uniforme em uma simulação simples. Seu jogo deverá ter o comportamento abaixo no fim deste guia.
Um ponto importante desse nosso primeiro jogo com física é que decompomos o movimento da bola em dois MRUs: um na horizontal e um na vertical. Assim usamos sempre o caso mais simples 1D mesmo com movimentos em 2D.
Exercício 9
Agora precisamos calcular quanto tempo se passou entre frames no nosso programa.
Exercício 10
Exercício 11
Estamos quase acabando nossa simulação. Execute o programa e veja o que está faltando para sua simulação ter os resultados esperados.
A bola não rebate nas bordas!
Exercício 12
Resposta
Para que a bola rebata nas bordas precisamos alterar sua velocidade!
A colisão com a borda será feita da mesma forma que o movimento: 1 dimensão por vez. Ou seja, primeiro vemos se a bola está saindo da tela na vertical e tratamos esse caso. Depois fazemos o mesmo para a horizontal.
Exercício 13
Resposta
A bola sai da tela se sua extremidade esquerda tiver coordenada x menor que 0 ou se sua extremidade direita tiver coordenada x maior que a largura da tela (640
). A posição que guardamos é a do centro da bola, logo, obtemos as extremidades adicionando/subtraindo o valor do raio do centro.
Sabendo disso, implemente a bola rebatendo em seu jogo. Leve em conta as seguintes dicas:
- Se você detectar que a bola está fora da tela em uma componente, deve inverter a velocidade da bola nesta componente
- A bola nunca pode sair da tela, se ela sair coloque-a de volta na tela no ponto da colisão
Agora você é capaz de implementar o Movimento Retilíneo Uniforme em seus jogos! O próximo passo é adicionar a possibilidade de aceleração.
CHECK 4
Agora você já pode fazer o check 4. Depois de concluir, faça um commit (não se esqueça de sincronizar/dar push) com a mensagem "Check 4".
Não se esqueça de mostrar para algum professor para ganhar o check!
CHECK 5
Agora você também já pode fazer o check 5. Depois de concluir, faça um commit (não se esqueça de sincronizar/dar push) com a mensagem "Check 5".
Não se esqueça de mostrar para algum professor para ganhar o check!