Dúvida com uso de ds_list

Ver o tópico anterior Ver o tópico seguinte Ir em baixo

Dúvida com uso de ds_list

Mensagem por vitor_liminha123 em Dom 08 Jun 2014, 15:59

Oi pessoal, eu estou ainda fazendo meu tower defense aqui, e queria fazer uma I.A. para os turrets, que seguissem o inimigo com mais vida, ou o mais próximo do fim do path, etc. Dei uma procurada na net e vi um pessoal falando pra usar listas(ds_list_create), mas não entendi absolutamente nada desse recurso, e queria saber se alguém consegue me explicar direitinho como usar, e como colocar na I.A. dos meus turrets.
Agradecido desde já!  Happy 

vitor_liminha123

Número de Mensagens : 510
Idade : 18
Data de inscrição : 16/08/2010
Reputação : 12
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

http://www.newgrounds.com/tanber

Voltar ao Topo Ir em baixo

Re: Dúvida com uso de ds_list

Mensagem por saim em Dom 08 Jun 2014, 18:25

ds_lists são como arrays turbinadas. Pense na list como uma longa longa linha de caixinhas onde você coloca alguma coisa em cada uma. Depois, você pode pegar alguma coisa de uma das caixinhas.
No caso, você coloca o valor a ser considerado dos inimigos e pega um deles pra turret mirar.
O que te vai ser útil é o comando ds_list_sort, que organiza a list em ordem crescente ou decrescente. Daí, você pode pegar o maior/menor e associar o resultado com o inimigo. O inimigo que estiver no raio de tiro e o valor da variável coincidir com o maior/menor da list é o que vai ser mirado.

Um pouco de código? Em geral eu deixaria você quebrar a cabeça, mas tenho entrado tão pouco no fórum que o código só apareceria ano que vem, então vamos de uma vez.
Código:
/// scr_escolhe_mais_forte(raio, parent_dos_inimigos);
// escolhe o inimigo (entre os childs daquele dado como argumento) cuja variavel "forza" é a maior
// considera apenas aqueles que estiverem ao alcance do raio, que também entra como argumento

// o script deve ser chamado do pela turret, porque usa variáveis dela (x e y).

var raio, inimigo, ds_list_inimigos, ds_list_forza, maior_forza, i, inimigo_checa, inimigo_return;
raio := argument0; // raio de alcance do turret
inimigo := argument2; // nome do parent ou do objeto que corresponde aos inimigos

ds_list_forza := ds_list_create(); // cria a lista, vazia por enquanto, pra colocar as forças
ds_list_inimigos := ds_list_create();  // cria a lista, vazia por enquanto, pra colocar os inimigos
with(inimigo){ // todos os inimigos childs daquele dado como argumento entram no loop
    if (point_distance(x, y, other . x, other . y) <= raio){ // se está perto o suficiente
        ds_list_add(ds_list_forza, forza); // coloca o valor da variável "forza" na list
        ds_list_add(ds_list_inimigos, id); // coloca o valor da id na list
        }
    }
// agora tem uma list cheia de valores de "forza" e outra cheia de ids. Note que a list não associa, ainda, os valores de "forza" aos objetos de onde eles vieram. Isso não vai ter problema em breve, porque nós não eliminamos nem alteramos o valor NO OBJETO, então podemos usar a comparação pra saber qual objeto corresponde àquele valor.
// a lista com as ids não era realmente necessária, mas vai economizar um segundo loop por TODOS os inimigos. Nós vamos verificar só os que estiverem na lista, ou seja, só os que estiverem dentro do raio de alcance.

ds_list_sort(ds_list_forza, false); // organiza a lista em ordem decrescente. Assim, o maior valor será o primeiro valor.
maior_forza := ds_list_find_value(ds_list_forza, 0); // pega o primeiro valor da lista e joga numa variável

// agora, escolhe o primeiro inimigo cuja "forza" for igual àquela que escolhemos
for(i := 0; i < ds_list_size(ds_list_inimigos); i += 1){ // do começo ao final da lista
    inimigo_checa := ds_list_find_value(ds_list_inimigos, i); // coloca o valor da list numa variável (puramente didático, dá pra eliminar essa parte)
    if (inimigo_checa . forza == maior_forza){ // se é quem estávamos procurando (se a forza dele é igual à maior das forzas)
        inimigo_return := inimigo_checa; // agora sim, é importante colocar o bicho numa variável
        break; // já achou, não tem motivo pra continuar o loop
        }
    }
// já temos a resposta, eliminamos as ds_lists
ds_list_destroy(ds_list_forza);
ds_list_destroy(ds_list_inimigos);
return(inimigo_return); // retorna a id do inimigo

saim

Ranking : Nota B
Número de Mensagens : 2964
Idade : 38
Data de inscrição : 14/01/2011
Notas recebidas : C-D-A-B
Reputação : 121
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 1
   : 0
   : 3

Voltar ao Topo Ir em baixo

Re: Dúvida com uso de ds_list

Mensagem por vitor_liminha123 em Dom 08 Jun 2014, 19:54

Muito bom Saim, me ajudou muito! Valeu pela ajuda!  sorrindo 

vitor_liminha123

Número de Mensagens : 510
Idade : 18
Data de inscrição : 16/08/2010
Reputação : 12
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

http://www.newgrounds.com/tanber

Voltar ao Topo Ir em baixo

Re: Dúvida com uso de ds_list

Mensagem por vitor_liminha123 em Ter 10 Jun 2014, 19:59

Desculpa estar revivendo este post, mas Saim, eu tentei aqui no meu jogo e o turret simplesmente ignora todos os inimigos. Se você puder, peço que faça outro código, mas dessa vez, utilizando as vars do meu jogo, só pra eu entender melhor, por favor:
obj_enemy - nome do inimigo;
range - raio do turret; (já estabelecido no turret)
Ao invés de usar "forza", peço que faça um script com path_position;
list_path - lista com os 'path_position's;
list_id - lista com id's.

vitor_liminha123

Número de Mensagens : 510
Idade : 18
Data de inscrição : 16/08/2010
Reputação : 12
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

http://www.newgrounds.com/tanber

Voltar ao Topo Ir em baixo

Re: Dúvida com uso de ds_list

Mensagem por PedroX em Dom 15 Jun 2014, 11:03

Se não deu erro de variável inexistente, é porque você já substituiu todas (acho que fez corretamente).

Crie o script feito pelo saim. Depois coloque no evento Create:
Código:
show_message(object_get_name(scr_escolhe_mais_forte(800, objeto_inimigo).object_index));

Se ele mostrar o nome do objeto inimigo, é porque o código funciona.

PedroX

Ranking : Nota C
Número de Mensagens : 6034
Idade : 21
Data de inscrição : 26/07/2008
Notas recebidas : C+B
Reputação : 286
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   :
   :
   :

Voltar ao Topo Ir em baixo

Re: Dúvida com uso de ds_list

Mensagem por vitor_liminha123 em Dom 15 Jun 2014, 12:46

Uma dúvida que eu tive no final do script do Saim:
Esse "return" que ele usa, ele vai retornar aonde, em uma var? Então eu tenho que chamar o script assim:
Código:
alvo = script(script_do_Saim);
?

vitor_liminha123

Número de Mensagens : 510
Idade : 18
Data de inscrição : 16/08/2010
Reputação : 12
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

http://www.newgrounds.com/tanber

Voltar ao Topo Ir em baixo

Re: Dúvida com uso de ds_list

Mensagem por PedroX em Dom 15 Jun 2014, 13:06

Sim. Daí, por exemplo, você pode usar:
Código:
move_towards_point(alvo.x, alvo.y, 5);

PedroX

Ranking : Nota C
Número de Mensagens : 6034
Idade : 21
Data de inscrição : 26/07/2008
Notas recebidas : C+B
Reputação : 286
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   :
   :
   :

Voltar ao Topo Ir em baixo

Re: Dúvida com uso de ds_list

Mensagem por vitor_liminha123 em Dom 15 Jun 2014, 14:20

Olha Pedro, eu fiz assim:
Script do turret:
Código:
if mode=1 {
    if instance_exists(obj_enemy) {
        if target<=range*32 {
            target=instance_nearest(x,y,obj_enemy);
        }
        else {
            target=noone;
        }
    }
    else {
        target=noone;
    }
}
if mode=2 {
    target=script_target2_enemy();
}
E deixei a variável mode como 2, que abre o novo script, o do Saim, mas eu modifiquei com vars melhores pra mim:
Script (script_target2_enemy)
Código:
var range, list_enemy, list_path, last_path, i, enemy_check, enemy_return;

list_path := ds_list_create();
list_enemy := ds_list_create();
with(obj_enemy){
    if (point_distance(x, y, other . x, other . y) <= range*32){
        ds_list_add(list_path, path_position);
        ds_list_add(list_enemy, id);
        }
    }

ds_list_sort(list_path, false);
last_path := ds_list_find_value(list_path, 0);

for(i := 0; i < ds_list_size(list_enemy); i += 1){
    enemy_check := ds_list_find_value(list_enemy, i);
    if (enemy_check . path_position  == last_path){
        obj_enemy_return := enemy_check;
        break;
        }
    }

ds_list_destroy(list_path);
ds_list_destroy(list_enemy);
return(enemy_return);
Ele deu erro de não achar a var enemy_return, mesmo que eu tenha declarado lá no começo do script. :s

vitor_liminha123

Número de Mensagens : 510
Idade : 18
Data de inscrição : 16/08/2010
Reputação : 12
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

http://www.newgrounds.com/tanber

Voltar ao Topo Ir em baixo

Re: Dúvida com uso de ds_list

Mensagem por PedroX em Dom 15 Jun 2014, 19:40

Você criou a variável mas não definiu o valor dela. Você colocou "obj_" antes... Sempre use o mesmo nome.

PedroX

Ranking : Nota C
Número de Mensagens : 6034
Idade : 21
Data de inscrição : 26/07/2008
Notas recebidas : C+B
Reputação : 286
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   :
   :
   :

Voltar ao Topo Ir em baixo

Re: Dúvida com uso de ds_list

Mensagem por vitor_liminha123 em Dom 15 Jun 2014, 21:55

Certo, tirei o "obj_" antes da var. Engraçado que o script roda tranquilo em um turret, mas nos outros ele dá o mesmo erro de não ter definido a var 'enemy_return', mesmo que todos os turrets usem o mesmo script! #buguei  computador
-EDIT-
Parece que quando eu coloco o turret depois da wave, ele funciona o script perfeitamente, mas se eu coloco antes de aparecer algum inimigo, ele dá o erro da variável, e continua dando mesmo depois do inimigo aparecer! o.o

vitor_liminha123

Número de Mensagens : 510
Idade : 18
Data de inscrição : 16/08/2010
Reputação : 12
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

http://www.newgrounds.com/tanber

Voltar ao Topo Ir em baixo

Re: Dúvida com uso de ds_list

Mensagem por PedroX em Seg 16 Jun 2014, 16:51

Coloque uma condição:

Código:
if (instance_exists(alvo)){
move_towards_point(alvo.x, alvo.y, 1000);
}

PedroX

Ranking : Nota C
Número de Mensagens : 6034
Idade : 21
Data de inscrição : 26/07/2008
Notas recebidas : C+B
Reputação : 286
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   :
   :
   :

Voltar ao Topo Ir em baixo

Re: Dúvida com uso de ds_list

Mensagem por vitor_liminha123 em Seg 16 Jun 2014, 19:31

Então Pedro, eu testei algumas coisas, coloquei também o código, mas parece que dá o erro da variável quando não há monstros no raio do turret, então estava pensando nesse código:
Código:
with(obj_enemy) {
    if (point_distance(x, y, other . x, other . y) <= other.range*32){
        ds_list_add(list_path, path_position);
        ds_list_add(list_enemy, id);
        }
    else {
        ///o que fazer?
    }
}
Tenho que colocar algo ali no else pra que a variável exista, mas se eu ponho exit ali, o turret targeta o 1º e quando sai do raio ele não pega mais ninguém. Sinceramente não sei o que fazer.  bravo 
PS: Obrigado por estar sendo super paciente comigo e ainda estar tentando me ajudar!  blz 
 flw
-EDIT-
Aí Pedro, eu tentei fazer uma coisinha aqui, e parece que funcionou... o.o
Código:
with(obj_enemy) {
    if (point_distance(x, y, other . x, other . y) <= other.range*32){
        ds_list_add(list_path, path_position);
        ds_list_add(list_enemy, id);
        }
}

if ds_list_empty(list_path) {
    exit;
}
Ele vê se a lista tá vazia (ngm no raio do turret), e se tiver, sai do script. Só me verifica se tá tudo certo, por favor? Não queria que bugasse depois.
  

vitor_liminha123

Número de Mensagens : 510
Idade : 18
Data de inscrição : 16/08/2010
Reputação : 12
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 0
   : 0
   : 0

http://www.newgrounds.com/tanber

Voltar ao Topo Ir em baixo

Re: Dúvida com uso de ds_list

Mensagem por Conteúdo patrocinado Hoje à(s) 20:54


Conteúdo patrocinado


Voltar ao Topo Ir em baixo

Ver o tópico anterior Ver o tópico seguinte Voltar ao Topo

- Tópicos similares

 
Permissão deste fórum:
Você não pode responder aos tópicos neste fórum