Usando Fisica no GMS Parte 1
Usando Fisica no GMS Parte 2
CONFIGURANDO O PHYSICS WORLD
Neste artigo, nós vamos começar tudo do zero, então crie um novo projeto chamado "physics_joints" ou algo similar. Agora adicione uma room, e deixe a cor de fundo como cinza escuro ou preto (você verá o porque mais tarde), em seguida, feche o editor de rooms. Nós não vamos usar a aba "Physics" no editor para configurar a física da room neste momento, mas em vez disso, vamos fazê-lo via código.
Crie um novo objeto agora e chame de " obj_Control ", em seguida, adicione o evento Create com o seguinte código:
Código: Selecionar todos
// Conversão - Pixels para metros
physics_world_create (0.1);
//Nenhuma gravidade
physics_world_gravity (0, 0);
// iterações por step
physics_world_update_iterations (20);
// Velocidade de atualização
physics_world_update_speed (60);
A primeira lida com as iterações de atualização. Este valor é o número de vezes que a física irá percorrer as colisões e movimento etc a cada step. Então, aqui estamos afirmando que a simulação de física deve percorrer tudo 20 vezes por step. Esta é uma função muito poderosa, pois significa que você pode fazer a simulação mais ou menos precisa, definindo isso para um valor maior ou menor.
O segundo é a velocidade de atualização. Este é o número de steps de atualização por segundo que a simulação física irá rodar. Normalmente, este valor é igual ao da velocidade da room, mas você pode configurá-lo para um valor superior ou inferior para aumentar ou diminuir a precisão da física. Por exemplo, uma room tem velocidade de trinta steps por segundo e uma atualização de física sendo de 60 forçará a simulação de física para executar uma atualização duas vezes para cada etapa do jogo. Note que isto é independente da velocidade de iteração, e irá ser acumulado com ele, ou seja, uma velocidade iteração de 20 e uma velocidade de atualização de 60 em uma sala de 30 fps vai dar 40 iterações por etapa.
Em geral, você não vai querer usar essas funções (e elas estão aqui apenas para mostrar como funcionam, mas elas não são estritamente necessárias para esta demonstração), mas se você tiver um jogo que requer movimento muito rápido, então você pode querer mais iterações, ou se você tiver um jogo que tem um vários corpos físicos, não vai requerer tanta precisão, você pode diminuir a velocidade de atualização e reduzir a sobrecarga na CPU.
Nossa próxima tarefa é criar limites na nossa room (Criar uma reação ao sair da room), ou seja, vamos fazer com que os objetos rebatam caso saiam dos limites da room, para isso adicione o código:
Código: Selecionar todos
var edge_fix physics_fixture_create = ();
physics_fixture_set_chain_shape (edge_fix, true);
physics_fixture_add_point (edge_fix, 0, 0);
physics_fixture_add_point (edge_fix, room_width, 0);
physics_fixture_add_point (edge_fix, room_width, room_height);
physics_fixture_add_point (edge_fix, 0, room_height);
physics_fixture_set_density (edge_fix, 0);
physics_fixture_set_restitution (edge_fix, 0.5);
physics_fixture_bind (edge_fix, id);
physics_fixture_delete (edge_fix);
USANDO O MODO DE DEPURAÇÃO
Outra coisa que vamos usar neste exemplo é a depuração (debug mode) do nosso sistema de física. Você pode chamar a função physics_world_draw_debug () para fazer o GM:S desenhar valores físicos, como o shape do fixture os ângulos de rotação, joints, etc ... e nesta demonstração vamos usar esta função para desenhar os shapes dos fixtures em vez usar sprites sprites (Tecnicamente, você pode codificar um jogo inteiro sem sprites e desenhá-la usando esta função! No entanto, isso não vai ficar tão bonito xD ...).
Esta função tem um argumento único que é uma máscara de bits. Coisas diferentes podem ser processadas, definindo o sinalizador apropriado para mascarar ou desmascará-los, por isso precisamos definir esse valor no Evento Create do objeto de controlador (DICA: Veja o tutorial sobre algebra boolena do Carlos L):
Código: Selecionar todos
render_flags = phy_debug_render_shapes | phy_debug_render_joints | phy_debug_render_coms | phy_debug_render_obb;
Para desenhar o debug da física precisamos adicionar agora um evento Draw com este código:
Código: Selecionar todos
physics_world_draw_debug (render_flags);
CRIAÇÃO DE INSTÂNCIAS
Estamos quase prontos para começar a adicionar instâncias com fixtures na nossa room, mas antes disso, temos de fazer um objeto "base". Nós vamos criar todas as instâncias e fixtures usando códigos, mas precisamos de um objeto para criar instâncias já anexadas com os fixtures, então crie um novo objeto agora e chame de "obj_Base". Você precisará adicionar um evento de colisão com ele mesmo contendo um único comentário para garantir que as colisões vão acontecer.
Podemos agora volte ao nosso objeto controlador e atribua o "obj_Base" como seu parent (Aquele evento de colisão será herdado e as instâncias irão interagir com aquele fixture que limita a saida da room), em seguida, abra o evento Create . Nós precisamos criar duas instâncias de nosso objeto de base e vincular um fixture a eles antes que possamos criar um joint, então vamos fazer isso adicionando o seguinte código:
Código: Selecionar todos
var instA = instance_create (100, 100, obj_Base);
var instB = instance_create (100, 300, obj_Base);
var fixA = physics_fixture_create ();
physics_fixture_set_circle_shape (fixA, 20);
physics_fixture_set_density (fixA, 0.5);
physics_fixture_set_restitution (fixA, 0.8);
physics_fixture_bind (fixA, instA);
physics_fixture_bind (fixA, instB);
physics_fixture_delete (fixA);
Código: Selecionar todos
with(obj_Base)
{
var dist = point_distance (x, y, mouse_x, mouse_y);
if dist <100
{
var pd = point_direction (x, y, mouse_x, mouse_y) - 180;
physics_apply_impulse (mouse_x, mouse_y, lengthdir_x (100, pd), lengthdir_y (100, pd));
}
}
ADICIONANDO UM DISTANCE JOINT
Vamos ligar esses dois fixtures de círculo com um joint. Joints são definidos no espaço da room e não no espaço local, assim que você deve criar as instâncias e colocar os joints com base nas coordenadas da sua room. Neste caso (ainda no evento Create do "obj_Control") vamos fazer assim, e colocar o código abaixo logo após a crição das instancias e fixtures:
Código: Selecionar todos
physics_joint_distance_create (instA, instB, instA.x, instA.y, instB.x, instB.y, true);
Você fornece as duas instâncias que irão se "juntar", onde na room isso vai acontecer, e, em seguida, se eles podem colidir entre (true ou false). Tudo muito simples! Execute novamente agora e veja como você tem uma "barra" como fixture que rebate em torno da room.
NOTA: Você só pode ver as juntas quando depurar desenho! Em um jogo normal eles não devem aparecer, portanto, você precisará desenhar alguns gráficos a si mesmo se você quer mostra-los.
ADICIONANDO UM REVOLUTE JOINT
Agora que você já viu como é fácil 'juntar' fixtures, vamos adicionar mais um par, mas com um tipo diferente de joint ... revolute joint (Articulação de revolução, algo assim). Este é um conjunto que é criado numa posição na room e que se junta a instâncias em torno desse ponto. Pense em um pino que segura duas argolas. então você pode girar as duas argolas ao redor do pino. Bem, nossa joint revolute vai fazer a mesma coisa.
Ainda no evento Create do "obj_Control", adicione o seguinte:
Código: Selecionar todos
var instA = instance_create (room_width - 300, 200, obj_Base);
var instB = instance_create (room_width - 300, 400, obj_Base);
var fixA = physics_fixture_create ();
var fixB physics_fixture_create = ();
physics_fixture_set_circle_shape (fixA, 100);
physics_fixture_set_density (fixA, 0);
physics_fixture_bind (fixA, instA);
physics_fixture_set_box_shape (fixB, 25, 100);
physics_fixture_set_density (fixB, 0.5);
physics_fixture_bind (fixB, instB);
physics_fixture_delete (fixA);
physics_fixture_delete (fixB);
physics_joint_revolute_create (instA, instB, room_width - 300, 300, 0, 0, falsa, 100, 50, true, false);
A maioria das joints tem alguns parâmetros extras, como este que lhe permite limitar o ângulo de rotação e adicionar um motor, por isso certifique-se de ler a referência de cada função no manual para ter certeza do que cada argumento faz.
ADICIONANDO UM PULLEY JOINT
O último joint que vamos adicionar é um polley joint (Articulação de polia). Isto irá ligar duas instâncias em duas posições no espaço da room, mas permitindo que aja moviemnto dentro dos limites da polia, ou seja: se alguém se move para a direita, então ele vai "puxar" sobre a polley joint e fazer a outra instância se mover bastante. Isto pode parecer um pouco complicado, mas como você verá, é semelhante aos joints anteriores:
Código: Selecionar todos
var instA = instance_create (300, room_height - 100, obj_Base);
var instB = instance_create (room_width - 300, room_height - 100, obj_Base);
var fixA = physics_fixture_create ();
physics_fixture_set_circle_shape (fixA, 20);
physics_fixture_set_density (fixA, 0.5);
physics_fixture_set_restitution (fixA, 0.8);
physics_fixture_bind (fixA, instA);
physics_fixture_bind (fixA, instB);
physics_fixture_delete (fixA);
physics_joint_pulley_create (instA, instB, 300, room_height - 180, room_width - 300, room_height - 180, 0, -2, 0, -2, 1, false);
Finalmente é possível adicionar uma proporção (neste caso, 1: 1), o que fará com que uma extremidade da polia tenha uma proporção de comprimento maior ou menor em comparação com a outra extremidade da polia.
RESUMO
Esta é a parte final dos nossos tutoriais sobre física e espero que eu tenha te ajudado a colocar a peça final desse quebra-cabeça. Com a capacidade de criar joints, e as técnicas mostradas para depuração, você deve agora ser capaz de fazer algum jogo de física simples, e tem uma base firme para a criação de jogos mais complexos, com uma pequena ajuda do manual!
Você pode baixar um arquivo de exemplo com o código deste tutorial:
Baixe o exemplo