Entrar
Últimos assuntos
» player não consegue andarpor lovn7 Qui 21 Nov 2024, 13:33
» É possível fazer istó no game maker
por William Lima Qui 21 Nov 2024, 10:56
» Rio Rise - novo launcher do Gta San Andreas SAMP Brasil
por Lua Sáb 16 Nov 2024, 20:22
» (Resolvido) Cenario longo x Texture Pages
por josuedemoraes Sáb 16 Nov 2024, 15:31
» Kids' band
por Adilson Lucindo Santos Sex 15 Nov 2024, 12:23
» (RESOLVIDO) Engasgos-Troca de Sprites/animações
por josuedemoraes Ter 12 Nov 2024, 01:49
» Block Room - DEMO
por Joton Qua 06 Nov 2024, 22:58
» Game Infinito vertical (subindo)
por macmilam Sáb 26 Out 2024, 12:36
» Retorno da GMBR!!!
por Dancity Ter 22 Out 2024, 16:36
» Máquina de estados
por aminaro Qui 10 Out 2024, 13:33
» como faço pra um objeto colidir com o outro e diminuir a vida do player ?
por josuedemoraes Qui 03 Out 2024, 16:51
» RESOLVIDO: Colisão com objetos moveis
por josuedemoraes Qua 02 Out 2024, 20:28
» Crypt of the Blood Moon
por divin sphere Qua 11 Set 2024, 18:18
» como fazer um objeto seguir?
por divin sphere Dom 18 Ago 2024, 18:08
» Procuro de alguém para Modelar/Texturizar/Animar objetos 3D
por un00brn Dom 11 Ago 2024, 11:10
» Destruição de cenário (estilo DD Tank)
por CoronelZeg Sex 09 Ago 2024, 17:16
» RESOLVIDO-Como destruir uma instancia especifica de um objeto
por josuedemoraes Ter 23 Jul 2024, 00:40
» Automatizar a coleta de id
por GabrielXavier Seg 22 Jul 2024, 18:01
» Preciso de ajuda para concluir um pequeno projeto
por lmoura Qui 27 Jun 2024, 15:45
» ANGULO ACOMPANHAR O OBJETO
por Klinton Rodrigues Qui 27 Jun 2024, 08:34
» Musica reinicia quando sala reinicia
por GabrielXavier Ter 18 Jun 2024, 07:28
» como fazer uma copia de gd
por generico_cube Sex 14 Jun 2024, 15:48
» Square Adventure
por guilherme551 Ter 11 Jun 2024, 09:54
» como posso definir limite de uma variavel
por GabrielXavier Sex 07 Jun 2024, 14:14
» [Resolvido] Dúvida, colisão única de objeto
por vdm842 Sex 24 maio 2024, 09:50
[Ajuda] Tiro seguir objeto dentro do alcance
3 participantes
Página 1 de 1
[Ajuda] Tiro seguir objeto dentro do alcance
Olá a todos!
Venho acompanhando o fórum há algum tempo e estou tentando aprender a usar o GM por conta, acompanhando os tutoriais e as dúvidas do pessoal.
Sou iniciante e ainda um pouco dependente de D&D.
Estou tentando criar um game no estilo tower defense e me deparei com o seguinte problema:
[img][/img][img][/img]
Preciso atender os seguintes aspectos:
- A torre começa a atacar quando um inimigo entra no alcance dela.
- Quando não tem inimigos dentro do alcance, a torre não ataca.
- No caso de dois ou mais inimigos dentro do alcance, a torre da preferência para atacar o que estiver mais próximo do final do caminho.
Para saber quando o inimigo está próximo eu uso o comando: if (distance_to_object (obj_enemy) < range)
Isso ativa um alarm que cria a instância do tiro.
No Step do tiro eu uso: move_towards_point(instance_nearest(x,y,obj_enemy).x,instance_nearest(x,y,obj_enemy).y, 8 )
O problema de usar esse comando é que ele ataca o inimigo mais próximo da torre, e não o mais próximo do final do caminho.
Tentei criar um objeto do final do caminho chamado de obj_end_line e trocar o Step do tiro pelo seguinte movimento:
move_towards_point(instance_nearest(obj_end_line.x,obj_end_line.y,obj_enemy).x,instance_nearest(obj_end_line.x,obj_end_line.y,obj_enemy).y, 8 );
Agora ele ataca o inimigo que está a frente, mas tem um problema crucial: O tiro não segue necessáriamente o inimigo que está dentro do alcance da torre, ele segue livremente pelo mapa o inimigo mais próximo do obj_end_line. Por exemplo, na imagem acima, como tem inimigos próximos da primeira torre, os tiros desta primeira torre estariam seguindo o primeiro inimigo lá da frente.
Eu preciso de um comando que escolha dentre os inimigos no alcance da torre, o que está mais próximo do final do caminho.
Não sei se fui bem claro, hehe.
Estou quebrando a cabeça aqui...
Desde já agradeço pela atenção;
Venho acompanhando o fórum há algum tempo e estou tentando aprender a usar o GM por conta, acompanhando os tutoriais e as dúvidas do pessoal.
Sou iniciante e ainda um pouco dependente de D&D.
Estou tentando criar um game no estilo tower defense e me deparei com o seguinte problema:
[img][/img][img][/img]
Preciso atender os seguintes aspectos:
- A torre começa a atacar quando um inimigo entra no alcance dela.
- Quando não tem inimigos dentro do alcance, a torre não ataca.
- No caso de dois ou mais inimigos dentro do alcance, a torre da preferência para atacar o que estiver mais próximo do final do caminho.
Para saber quando o inimigo está próximo eu uso o comando: if (distance_to_object (obj_enemy) < range)
Isso ativa um alarm que cria a instância do tiro.
No Step do tiro eu uso: move_towards_point(instance_nearest(x,y,obj_enemy).x,instance_nearest(x,y,obj_enemy).y, 8 )
O problema de usar esse comando é que ele ataca o inimigo mais próximo da torre, e não o mais próximo do final do caminho.
Tentei criar um objeto do final do caminho chamado de obj_end_line e trocar o Step do tiro pelo seguinte movimento:
move_towards_point(instance_nearest(obj_end_line.x,obj_end_line.y,obj_enemy).x,instance_nearest(obj_end_line.x,obj_end_line.y,obj_enemy).y, 8 );
Agora ele ataca o inimigo que está a frente, mas tem um problema crucial: O tiro não segue necessáriamente o inimigo que está dentro do alcance da torre, ele segue livremente pelo mapa o inimigo mais próximo do obj_end_line. Por exemplo, na imagem acima, como tem inimigos próximos da primeira torre, os tiros desta primeira torre estariam seguindo o primeiro inimigo lá da frente.
Eu preciso de um comando que escolha dentre os inimigos no alcance da torre, o que está mais próximo do final do caminho.
Não sei se fui bem claro, hehe.
Estou quebrando a cabeça aqui...
Desde já agradeço pela atenção;
Harus- Data de inscrição : 19/01/2013
Reputação : 0
Número de Mensagens : 2
Prêmios :
x 0 x 0 x 0
x 0 x 0 x 0
x 0 x 0 x 0
Re: [Ajuda] Tiro seguir objeto dentro do alcance
Você precisa de uma condição composta (dupla). O problema é um pouco complexo, mas podemos usar uma ds_priority...
Primeiro, vamos criar uma lista das instâncias ao alcance da torre, em ordem crescente de distância (prioridade). Esse código deve ser posto dentro do evento (ou código) que dispara o tiro da torre.
Espero que sirva, pois pesquisei bastante as funções.
Ver:
http://wiki.yoyogames.com/index.php/GML_Functions:_Priority_Queues
https://gmbr.forumeiros.com/t19975-tutorial-com-lasers#149793
Até mais!
Primeiro, vamos criar uma lista das instâncias ao alcance da torre, em ordem crescente de distância (prioridade). Esse código deve ser posto dentro do evento (ou código) que dispara o tiro da torre.
- Código:
ao_alcance = ds_priority_create();
with (OBJ_INIMIGO) {
if (distance_to_object(OBJ_TORRE)<other.alcance) {
ds_priority_add(other.ao_alcance, id, distance_to_object(other));
}
}
if (!ds_priority_empty(ao_alcance))
{
mais_proximo = ds_priority_find_min(ao_alcance);
while(mais_proximo != instance_nearest(obj_end_line.x, obj_end_line.y) && !ds_priority_empty(ao_alcance))
{
mais_proximo = ds_priority_delete_min(ao_alcance); //deleta, mas pega o valor também (embora o nome da função não indique isso)
}
}
ds_priority_destroy(ao_alcance);
move_towards_point(mais_proximo.x, mais_proximo.y, VELOCIDADE );
Espero que sirva, pois pesquisei bastante as funções.
Ver:
http://wiki.yoyogames.com/index.php/GML_Functions:_Priority_Queues
https://gmbr.forumeiros.com/t19975-tutorial-com-lasers#149793
Até mais!
Leia o Manual do Iniciante e a Lista de Tutoriais, para aprender bastante sobre o GM.
Recomendo o Manual completo das colisões, bem útil.
O exemplo Criar um chat (banir, kickar, etc) é interessante.
Para seu jogo ficar rápido e legal, aprenda a Aumentar o desempenho do seu jogo.
Aprenda a calcular a velocidade de suas animações
Entre para o Clube do Inglês:
Re: [Ajuda] Tiro seguir objeto dentro do alcance
Calma, PedroX, coisas simples primeiro. É o primeiro post do cara, ele ainda está usando DND.
MAS você não está errado em nada. Sua solução é ótima. Só que data structures são um tanto complexas pra um primeiro contato com a comunidade. Vou tentar uma aproximação mais simples. Embora você esteja certo também em afirmar que NÃO É um problema simples.
Primeiro, aquilo que não aparece na pergunta: como os inimigos fazem a curva? É um path? Se for, tem uma variável neles que você pode usar pra saber quem está mais à frente: path_position. Ela te armazena um número de 0 a 1 que representa o quanto do path o objeto já percorreu. Nem preciso dizer qual número representa um objeto mais perto do final, certo?
Agora, pra torre atirar, ela primeiro vai verificar se tem ALGUÉM ao alcance. Tendo, atira. Mas, se for atirar, que seja no que está mais adiantado. Certo?
Vou começar usando seu código:
Aí, dentro do código genérico que eu coloquei como comentário, você vai:
- escolher o inimigo com a maior path_position (e que esteja na linha de tiro)
- criar um tiro
- explicar pro tiro quem é a vítima
O maior problema é escolher a vítima, mas com um pouco de gml e geometria, fica mole. Com gml você vai aprender a usar a declaração "with" e as variáveis "var".
Variáveis "var" só existem dentro de um código. Elas não estão em nenhum objeto, estão naquele código e morrem no final dele. Além de serem leves na memória, você pode entrar numa declaração "with" com elas sem se preocupar com o objeto em que elas estão.
Uma declaração "with" é percorrida em todos os objetos que atendem pelo nome dado no argumento. Isso pode ficar bem complexo, mas por enquanto vamos considerar que "with(obj_inimigo)" vai rodar um código em todos os obj_inimigo.
Vamos melhorar um pouco nosso código, então.
A segunda parte do código já está explicada. Já verifiquei se é pra criar um tiro e já sei quem é a vítima. Falo pro tiro quem é o coitado que o tiro vai saber quem seguir.
A parte da geometria. Basicamente, o conceito envolvido é: se a sua distância até a mim é x, a minha distância até você é x. Bem básico.
É o seguinte, eu só usei o range da torre pra saber se é pra criar um tiro, ainda não expliquei que o tiro deve seguir um inimigo que está na linha de tiro.
Quem vai explicar isso é o inimigo. Não conta isso pro jogador, tá?
penúltima parte:
Tem esse "other". Ele não servia só pra colisão?
Não, ele é útil pra caramba. De fato, num evento de colisão, "other" significa "o objeto colidido". Mas dentro de um "with", significa "a instância que chamou o código". Eu gosto de chamar de "a instância original".
Mole? É, eu sei. Mas o difícil já ficou pra trás. De agora pra frente fica mole, mesmo.
Também, já está quase acabando.
seguinte... "dist" começa como zero. não tem como ser menor que isso. Qualquer inimigo que não esteja fora do alcance vai ter um path_position maior que esse. Aí, se ele atender aos requisitos do "if" (estar ao alcance da torre E ter um valor de path_position maior que "dist"), ele vai ser a próxima vítima. Antes de criar o tiro, eu vou correr esse código em todos os obj_enemy, garantindo que o valor de "vitima" vai ser a id da instância DENTRO da linha de tiro e que esteja mais perto do final.
UFA! E eu comecei a escrever porque achei a resposta do PedroX complexa... Foi mal, PedroX, eu acabei complicando a coisa, também. Mas agora já escrevi pra caramba, não vou jogar fora.
Espero que o código esteja bem explicado, de qualquer forma.
MAS você não está errado em nada. Sua solução é ótima. Só que data structures são um tanto complexas pra um primeiro contato com a comunidade. Vou tentar uma aproximação mais simples. Embora você esteja certo também em afirmar que NÃO É um problema simples.
Primeiro, aquilo que não aparece na pergunta: como os inimigos fazem a curva? É um path? Se for, tem uma variável neles que você pode usar pra saber quem está mais à frente: path_position. Ela te armazena um número de 0 a 1 que representa o quanto do path o objeto já percorreu. Nem preciso dizer qual número representa um objeto mais perto do final, certo?
Agora, pra torre atirar, ela primeiro vai verificar se tem ALGUÉM ao alcance. Tendo, atira. Mas, se for atirar, que seja no que está mais adiantado. Certo?
Vou começar usando seu código:
- Código:
if (distance_to_object (obj_enemy) < range){
// vai sair tiro
}
Aí, dentro do código genérico que eu coloquei como comentário, você vai:
- escolher o inimigo com a maior path_position (e que esteja na linha de tiro)
- criar um tiro
- explicar pro tiro quem é a vítima
O maior problema é escolher a vítima, mas com um pouco de gml e geometria, fica mole. Com gml você vai aprender a usar a declaração "with" e as variáveis "var".
Variáveis "var" só existem dentro de um código. Elas não estão em nenhum objeto, estão naquele código e morrem no final dele. Além de serem leves na memória, você pode entrar numa declaração "with" com elas sem se preocupar com o objeto em que elas estão.
Uma declaração "with" é percorrida em todos os objetos que atendem pelo nome dado no argumento. Isso pode ficar bem complexo, mas por enquanto vamos considerar que "with(obj_inimigo)" vai rodar um código em todos os obj_inimigo.
Vamos melhorar um pouco nosso código, então.
- Código:
if (distance_to_object (obj_enemy) < range){ // se é pra atirar
var vitima;
with(obj_enemy){ // aqui eu começo a rodar códigos dentro dos inimigos
// se está na linha de tiro e é o mais próximo do final
vitima = self; // note que "vitima" é uma variável "var".
} // aqui eu volto pra torre
with(instance_create(x, y, obj_tiro){ // aqui eu crio um tiro - e já começo a escrever nele
alvo = vitima;
} // aqui eu paro de escrever no tiro
}
A segunda parte do código já está explicada. Já verifiquei se é pra criar um tiro e já sei quem é a vítima. Falo pro tiro quem é o coitado que o tiro vai saber quem seguir.
A parte da geometria. Basicamente, o conceito envolvido é: se a sua distância até a mim é x, a minha distância até você é x. Bem básico.
É o seguinte, eu só usei o range da torre pra saber se é pra criar um tiro, ainda não expliquei que o tiro deve seguir um inimigo que está na linha de tiro.
Quem vai explicar isso é o inimigo. Não conta isso pro jogador, tá?
penúltima parte:
- Código:
if (distance_to_object (obj_enemy) < range){ // se é pra atirar
var vitima;
with(obj_enemy){ // aqui eu começo a rodar códigos dentro dos inimigos
if (distance_to_object(other) < other . range) // && tá mais perto do fim
vitima = self; // note que "vitima" é uma variável "var".
} // aqui eu volto pra torre
with(instance_create(x, y, obj_tiro){ // aqui eu crio um tiro - e já começo a escrever nele
alvo = vitima;
} // aqui eu paro de escrever no tiro
}
Tem esse "other". Ele não servia só pra colisão?
Não, ele é útil pra caramba. De fato, num evento de colisão, "other" significa "o objeto colidido". Mas dentro de um "with", significa "a instância que chamou o código". Eu gosto de chamar de "a instância original".
Mole? É, eu sei. Mas o difícil já ficou pra trás. De agora pra frente fica mole, mesmo.
Também, já está quase acabando.
- Código:
if (distance_to_object (obj_enemy) < range){ // se é pra atirar
var vitima, dist;
dist = 0; // o path_position da vitima (começa com 0)
with(obj_enemy){ // aqui eu começo a rodar códigos dentro dos inimigos
if (distance_to_object(other) < other . range && path_position > dist)
vitima = self; // note que "vitima" é uma variável "var".
dist = path_position; // pulo do gato
} // aqui eu volto pra torre
with(instance_create(x, y, obj_tiro){ // aqui eu crio um tiro - e já começo a escrever nele
alvo = vitima;
} // aqui eu paro de escrever no tiro
}
seguinte... "dist" começa como zero. não tem como ser menor que isso. Qualquer inimigo que não esteja fora do alcance vai ter um path_position maior que esse. Aí, se ele atender aos requisitos do "if" (estar ao alcance da torre E ter um valor de path_position maior que "dist"), ele vai ser a próxima vítima. Antes de criar o tiro, eu vou correr esse código em todos os obj_enemy, garantindo que o valor de "vitima" vai ser a id da instância DENTRO da linha de tiro e que esteja mais perto do final.
UFA! E eu comecei a escrever porque achei a resposta do PedroX complexa... Foi mal, PedroX, eu acabei complicando a coisa, também. Mas agora já escrevi pra caramba, não vou jogar fora.
Espero que o código esteja bem explicado, de qualquer forma.
saim- Games Ranking :
Notas recebidas : C-D-A-B
Data de inscrição : 14/01/2011
Reputação : 136
Número de Mensagens : 3033
Prêmios :
x 1 x 6 x 0
x 1 x 0 x 3
x 0 x 0 x 0
Re: [Ajuda] Tiro seguir objeto dentro do alcance
Gostei da sua solução. Na verdade, eu fiquei pensando um bom tempo antes de responder e só pensei em ds_priority. O motivo foi que um usuário me perguntou recentemente, por MP, qual era o tópico que você [saim] fez e que eu [Pedro] tinha postado uma solução com ds_priority. É o tutorial "Com lasers", do link que coloquei num post acima.
De qualquer forma, são 2 maneiras de chegar ao mesmo resultado. Ambas parecem funcionar sem bugs (não testei nenhuma). O que não faltou foi solução.
De qualquer forma, são 2 maneiras de chegar ao mesmo resultado. Ambas parecem funcionar sem bugs (não testei nenhuma). O que não faltou foi solução.
Leia o Manual do Iniciante e a Lista de Tutoriais, para aprender bastante sobre o GM.
Recomendo o Manual completo das colisões, bem útil.
O exemplo Criar um chat (banir, kickar, etc) é interessante.
Para seu jogo ficar rápido e legal, aprenda a Aumentar o desempenho do seu jogo.
Aprenda a calcular a velocidade de suas animações
Entre para o Clube do Inglês:
Re: [Ajuda] Tiro seguir objeto dentro do alcance
Primeiramente, agradeço pela ajuda!
Consegui adaptar no game o método do Saim. Aliás, está muito bem explicado. Já deu pra perceber que sou obrigado a desenvolver cada vez mais o gml, porque D&D é bem limitado, o que eu já esperava... O fato de conseguir manipular diferentes objetos, escrever neles, tomar ações com o other, e tudo isso dentro de um único script facilita demais a vida!
Só deu certo usando "id" ao invés de "self"... Não sei se tem a ver com o fato de estar usando GM Studio.
Também tentei o método do PedroX. Tentei, tentei mesmo fazer funcionar, mas não consigo...É bem provável que eu esteja fazendo algo errado, mas ele da erro quando um inimigo morre, ou o tiro se perde e fica indeciso em qual inimigo atacar, enfim, aconteceu variados problemas conforme eu tentava adaptar.
De qualquer modo foi tudo muito útil e aprendi mais um pouco.
Muito obrigado!
Consegui adaptar no game o método do Saim. Aliás, está muito bem explicado. Já deu pra perceber que sou obrigado a desenvolver cada vez mais o gml, porque D&D é bem limitado, o que eu já esperava... O fato de conseguir manipular diferentes objetos, escrever neles, tomar ações com o other, e tudo isso dentro de um único script facilita demais a vida!
Só deu certo usando "id" ao invés de "self"... Não sei se tem a ver com o fato de estar usando GM Studio.
Também tentei o método do PedroX. Tentei, tentei mesmo fazer funcionar, mas não consigo...É bem provável que eu esteja fazendo algo errado, mas ele da erro quando um inimigo morre, ou o tiro se perde e fica indeciso em qual inimigo atacar, enfim, aconteceu variados problemas conforme eu tentava adaptar.
De qualquer modo foi tudo muito útil e aprendi mais um pouco.
Muito obrigado!
Harus- Data de inscrição : 19/01/2013
Reputação : 0
Número de Mensagens : 2
Prêmios :
x 0 x 0 x 0
x 0 x 0 x 0
x 0 x 0 x 0
Re: [Ajuda] Tiro seguir objeto dentro do alcance
Não sei o que pode ser. Não acho que seja o GMS, nunca ouvi falar de eliminarem essa variável (que, de fato, não faria falta).Harus escreveu:Só deu certo usando "id" ao invés de "self"... Não sei se tem a ver com o fato de estar usando GM Studio.
Ehm... meu método também não prevê o que fazer quando o inimigo morre e o tiro já foi criado...Harus escreveu:da erro quando um inimigo morre, ou o tiro se perde e fica indeciso em qual inimigo atacar, enfim, aconteceu variados problemas conforme eu tentava adaptar.
Bom, eu presumi (corretamente) que você soubesse o que fazer com o tiro, uma vez que ele estivesse criado. Ele deve se mover towards alvo.x, alvo.y. Mas "alvo" é a id de uma instância que pode ser eliminada antes do tiro chegar lá. Por exemplo, duas torres podem atirar ao mesmo tempo e o tiro de uma pode matar o obj_enemy antes do tiro da outra chegar. Nesse caso, o tiro restante vai tentar se mover em direção a uma instância que não existe mais. O resultado é o erro "unknown variable 'x'".
Solução? Mover-se em direção a uma instância que exista. No step, mova-se apenas se a instância existir.
- Código:
if (instance_exists(alvo)){
move_towards(alvo.x, alvo.y, velocidade); // não sei se é desse jeito
}
else{
// elimina o tiro (o jogador não deve notar), escolhe outro alvo, sei lá
}
Você também pode gravar a posição que o alvo está e, se ele não existir mais, rumar pra essa posição e explodir quando a distância até ela for menor que a velocidade (dificilmente o tiro vai ficar EXATAMENTE na posição correta). Ou, dentro do inimigo, quando ele estiver morrendo, rodar um
- Código:
with(obj_tiro){ // roda em todos os tiros existentes
if (alvo == other){ // escolhe apenas aqueles que me acertariam
// fazer alguma coisa
}
}
// pronto, já pode morrer
saim- Games Ranking :
Notas recebidas : C-D-A-B
Data de inscrição : 14/01/2011
Reputação : 136
Número de Mensagens : 3033
Prêmios :
x 1 x 6 x 0
x 1 x 0 x 3
x 0 x 0 x 0
Tópicos semelhantes
» AJUDA: Seguir objeto sem parar
» [ajuda]como fazer objeto seguir com gravidade
» [RESOLVIDO]Preciso de ajuda com o tema relacionado a tiros. Que quando o objeto do tiro é criado, ao invés dele ir para a posição qe eu defini do objeto, ele fica em cima da tela. LEIA para mais detalhes.
» [ajuda] Objeto seguir player como se estivese fazendo parte dele.
» Objeto Seguir Outro Objeto
» [ajuda]como fazer objeto seguir com gravidade
» [RESOLVIDO]Preciso de ajuda com o tema relacionado a tiros. Que quando o objeto do tiro é criado, ao invés dele ir para a posição qe eu defini do objeto, ele fica em cima da tela. LEIA para mais detalhes.
» [ajuda] Objeto seguir player como se estivese fazendo parte dele.
» Objeto Seguir Outro Objeto
Página 1 de 1
Permissões neste sub-fórum
Não podes responder a tópicos