[FIS] Usando física no GM:S - Parte 3 (Oficial)
Enviado: Qui Mai 26, 2016 5:24 pm
USANDO FÍSICA NO GAMEMAKER: STUDIO - PARTE 3
Autor original: Mark Alexander
Nesta última parte da série sobre a física no GameMaker: Studio, vamos explorar os Joints (articulações), funções avançadas de física e como desenhar o debug (depuração) do sistema de física. Se você ainda não viu as partes anteriores desta série, você pode encontrá-las clicando nos seguintes links:
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:
As duas primeiras linhas são as mesmas opções que temos no editor de rooms para fixar quantos metros equivalem a 1 pixel e o vector de gravidade (que, neste caso é definido como 0 para tornar as coisas mais simples), mas as duas últimas são ligeiramente mais complexas e não aparecem no editor de rooms.
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:
Se você seguiu estes tutoriais desde o inicio, você deve reconhecer este código como sendo semelhante ao que foi utilizado para a definição de um fixture poligonal. A diferença desta vez é que estamos usando ele para criar um fixture estático, que é especialmente feita a partir de uma série de fixtures para representar as beiradas da room. Note que isso só vai funcionar porque a instância do "obj_Controlador" é posicionada em (0,0) na room. Se você colocá-lo em outro lugar, então não vai funcionar bem.
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):
Você pode encontrar uma lista completa das constantes disponíveis a partir do manual.
Para desenhar o debug da física precisamos adicionar agora um evento Draw com este código:
Agora, quando adicionarmos instâncias com fixtures para a nossa room, eles serão desenhados por esta função.
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:
Nós também precisamos adicionar o evento Mouse -> Global Mouse -> Left Mouse Pressed para criar um impulso e assim mover as instâncias, caso contrário você não será capaz de ver como os joints funcionam, portanto, acrescente este código:
Agora você pode adicionar uma instância de "obj_Control" na room e testar o seu jogo. Se tudo tiver corrido bem, você pode ricochetear algumas "bolas" clicando perto delas com o mouse.
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:
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:
Como antes, nós criamos duas fixtures (um círculo e uma caixa) e queremos juntar a caixa com a borda externa do círculo. Fazemos isso com a revolute joint, e nós também definimos um motor (isto é parte da função), para que ele comece a rodar.
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:
Mais uma vez, duas instâncias, cada uma com seus fixtures e posicionadas na room. Em seguida, é adicionado o polley joint, selecionando os fixtures, em seguida, definindo o primeiro e segundo pontos de ancoragem para a polia. Estes pontos de ancoragem podem estar em qualquer lugar no ambiente, e a distância entre o exemplo e cada ponto de ancoragem é a quantidade de "ganho" que cada uma das extremidades da polia terá. Você também pode definir um deslocamento local para x e y nesse conjunto, e isso vai fazer a ligação entre a polia e o deslocamento do fixture ancorado.
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
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