Página em português - Andre-LA/baixada-game-jam-game GitHub Wiki

Observações:

  • Vetor pode se referir à estrutura de dados vector do Nelua quanto Vector2 do Raylib. Observe o contexto para entender a qual vetor se refere, sendo vector uma estrutura similar as listas de outras linguagens e Vector2 uma dupla de números representando um ponto no espaço.

Estruturas de dados

Globals

Variável global que guarda em seu registro diversas "sub variáveis":

  • player_input
    • Vetor de direção, representando pra onde o jogador quer ir.
    • booliana de ação, representando a entrada do jogador.
  • engaged_slots
    • vetor de boolianas, cada índice se refere a um encaixe de engrenagem, o valor indica se o encaixe está com uma engrenagem encaixada.
  • camera
    • vetor de posição da câmera.
    • camera do Raylib
  • game_window
    • tamanho horizontal da tela
    • tamanho vertical da tela
    • título da janela

Esses valores são atualizados diretamente no game loop.

Enumerações

EntityTag

Informa qual entidade está presente, isso é, se é um mapa de ladrilhos, um colisor de parede, p personagem do jogador, etc. O valor do enésimo membro da enumeração é equivalente a 2ⁿ

CollisionState

Informa o estado de colisão com outro objeto, pode ser Enter ou Stay.

Componentes

Player

Indica que a entidade é o jogador

Gear

Indica que a entidade é uma engrenagem. Contém:

  • Vetor de direção.
  • Booliana que descreve se está encaixado ou não.

GearSlot

Indica que a entidade é um encaixe pra engrenagem.
Contém:

  • inteiro sem sinal, se refere a um índice do Globals.engaged_slots.

Brigde

Indica que a entidade é uma passagem de ponte.
Contém:

  • inteiro sem sinal, se refere a um índice do Globals.engaged_slots.

Box

Indica que a entidade é uma caixa

Position

Contém:

  • Vetor da posição da entidade.

Velocity

Contém:

  • Vetor normalizado de direção.
  • Número da velocidade escalar.

Collider

Contém:

  • Retângulo do colisor local, relativo à posição da entidade
  • Retângulo do colisor global, relativo ao seu espaço em jogo
  • ID da própria entidade (índice geracional)
  • Etiqueta EntityTag que informa qual objeto ele pertence.

Collisions

Contém:

  • Vetor de colisões sendo cada entrada contendo uma tripla:
    • Collider, colisor externo intersectado;
    • Rectangle que descreve o retângulo de interseção;
    • CollisionState que descreve se é Enter ou Stay.

Sprite

Contém:

  • Folha de sprites, com todos os sprites possíveis da entidade
  • inteiro indicando qual sprite será pintado
  • retângulo do sprite do quadro de animação dentro da folha de sprites
  • vetor de deslocamento

Animations

Contém:

  • vetor de uma dupla, contendo um vetor de inteiros, onde cada inteiro corresponderá a um quadro de animação; e um real com o intervalo de duração de cada quadro. Cada elemento do vetor de duplas correspondente a uma animação diferente.
  • inteiro indicando qual a animação atual
  • inteiro indicando qual quadro de animação atual
  • real indicando qual tempo percorrido desde a última mudança de quadro.
  • booliana indicando se a animação está pausada.

Obstacles

Contém

  • máscara de bits que guarda múltiplos EntityTags

Sistemas

CollidersSync

Leitura: Position, Velocity
Escrita: Collider
Procedimento:

Atualiza o retângulo global do Collideriterado de acordo com a posição do Position.

Nada é feito com o componente Velocity, sua função como componente de leitura serve de filtro, assim, esse sistema só será executado em entidades com movimento.

CollisionDetection

Leitura: Collider
Escrita: Collisions
Procedimento:

Num laço i será iterado os Colliders e Collisionss de uma entidade.

Dentro existirá um laço j que iterará sobre todos os Colliders do jogo, exceto o Collider iterado no laço i, essa verificação será feita graças a comparação de ID da entidade que está contida dentro do registro Collider.

Sendo ambos os Colliders pertencentes à entidades diferentes, é primeiramente detectada se há interseção entre os retângulos globais de ambos os Colliders através da função Raylib.CheckCollisionRecs, passando ambos os retângulos como argumentos e recebendo como retorno uma booliana indicado se há ou não interseção.

Também é verificado se o Collider do laço J já estava cadastrado antes.

Se houver interseção, é obtido o retângulo de interseção pelo retorno da função Raylib.GetCollisionRec passando ambos os retângulos globais como argumentos, depois é verificado se aquela interseção é a mesma que alguma das já identificadas em ciclos de jogo anteriores.

Se é uma interseção já identificada, então o seu estado é modificado para Stay e seu retângulo de interseção atualizado.

Caso contrário, então será adicionado ao vetor de interseções do Collisions uma nova entrada contendo o Collider do laço j, o retângulo de interseção obtido anteriormente e o estado Enter no estado de colisões.

Entretanto, se não há interseção, mas é um colisor já cadastrado nas interseções, então a entrada identificada nas interseções é removida.


PlayerController

Leitura: Player
Escrita: Velocity
Procedimento:

Manipula o vetor de direção do Velocity de acordo com os valores guardados em Globals.player_input.

BoxController

Leitura: Box, Collisions
Escrita: Velocity
Procedimento:

É similar ao PlayerController, ele manipula o vetor de direção do Velocity de acordo com o Globals.player_input, entretanto, ele só o faz se:

  • Valor de ação do Globals.player_input for verdadeira;
  • houver interseção com o jogador

GearController

Leitura: Gear, Collisions
Escrita: Velocity, Position, Animations
Procedimento:

O procedimento abaixo só ocorrerá se o valor de encaixe de Gear estiver como falsa.

Ao estar em interseção com o jogador e o valor de ação do Globals.player_input for verdadeira, é definida a direção do Velocity como a direção da interseção, entretanto o eixo de direção com menor valor é zerada.

Se houver interseção com a entidade de encaixe, então o valor de encaixe é definida como verdadeira.

Caso o valor de encaixe seja verdadeiro, então a posição da entidade deverá ser a posição do retângulo global do colisor da entidade de encaixe (obtido via interseção).

No final, pausa ou resume a animação analisando o tamanho da direção de Velocity (estará pausado se não estiver em movimento) e define a animação de acordo com o eixo com maior valor da direção de Velocity.

Obs: o valor da direção de Velocity nunca será zerada por esse sistema (a parada da engrenagem se dá pelo sistema de obstáculos).


VelocitySystem

Leitura: Velocity
Escrita: Position
Procedimento:

Apenas incrementa a posição do Position pela multiplicação da velocidade escalar do Velocitycom a direção do mesmo.

ObstaclesSystem

Leitura: Obstacles, Collisions
Escrita: Velocity
Procedimento:

Obtém as interseções da colisão da entidade iterada e os itera num laço j.

Se a interseção iterada contém algum dos bits da máscara de bits definido em Obstacles, haverá seguintes verificações para cada eixo:

  • se a direção do eixo da velocidade e a direção do eixo da interseção forem opostas;
  • se a proporção do tamanho do eixo do retângulo de interseção em relação ao tamanho do outro eixo do retângulo for menor que 1.

Se ambas as verificações forem avaliadas como verdadeiras, a velocidade será zerada.

EngageSystem

Leitura: Collisions
Escrita: GearSlot
Procedimento:

Se houver interseção com uma engrenagem, o valor de Globals.engaged_slots é definida como verdadeira.

BridgeSystem

Leitura: Brigde,
Escrita: Collider
Procedimento:

Verifica se o índice (guardado em Bridge) de Globals.engaged_slots está verdadeiro.

Se estiver, modifica a etiqueta do Collider pra de uma ponte liberada.

Animation

Leitura:
Escrita: Animations, Sprite
Procedimento:

Primeiro, se a booliana de pausa é avaliada como falsa, é então incrementado dentro do real de tempo percorrido o intervalo em relação ao quadro anterior.

Depois é obtido o vetor da dupla de animação em curso, se o intervalo percorrido for maior que o intervalo dessa animação, então o intervalo percorrido será zerado e o quadro atual incrementado (voltando pra 0 se ultrapassar o tamanho do vetor de quadros).

Após isso, é obtido o valor do vetor de inteiros (que representa os quadros de animação da animação) no índice do quadro atual, e esse valor é copiado para o valor inteiro de quadro de animação do Sprite.


SpritePainter

Leitura: Sprite, Position
Procedimento:

Esse sistema contém dois procedimentos, o 1º com o intuito de gerar a ordem de pintura e a segunda com a pintura em si, obedecendo a ordem de pintura.

Antes de tudo, é criado dois vetores de tamanho igual ao da quantidade de entidades que serão iteradas nos procedimentos. O primeiro vetor é de inteiros e o segundo vetor é do mesmo tipo do membro y do Vector2

O 1º procedimento itera sobre os índices geracionais das entidades do sistema. Analisando o eixo Y da posição do Position, sprites que estão com valor maior de altura deverá ser pintado antes.

Para isso, é guardado o índice do laço dentro do primeiro vetor anteriormente criado e a posição correspondente no segundo vetor, de forma que sprites com posição Y maior ficarão no inicio do vetor de inteiros.

Após isso, se inicia o 2º procedimento, que é a pintura dos sprites. Esse procedimento obedece a ordem dos índices guardados no vetor ao invés de iterar normalmente como nos outros procedimentos.

Pra cada Sprite iterado no 2º procedimento, é atualizado seu retângulo do quadro de animação e então pintado seu sprite via Raylib.DrawTextureRec na posição de Position somado ao deslocamento do Sprite.


ShowCollisions

(Utilidade de desenvolvimento)
Leitura: Collisions, Collider
Escrita:
Procedimento:

Pinta o retângulo global do colisor da entidade iterada de verde. Pra cada interseção, pinta o retângulo de interseção de azul ou vermelho se o estado de interseção for Enter ou Stay respectivamente.

A pintura dos retângulos é um retângulo sem preenchimento.