Obrigado por visitar a The Game Makers Brasil 😁 Use o fórum de Dúvidas para fazer perguntas. Se está em busca de aprender dê uma olhada nos tutoriais.

Como executar bloco de código por vez?

Perguntas? A comunidade te ajuda a resolver.
Avatar do usuário
Mysterious Stranger
Artista
Artista
Reações: 0
Mensagens: 62
Localização: BH

Contato:

Como executar bloco de código por vez?

Mensagem por Mysterious Stranger » Qua Abr 26, 2017 2:09 pm

Boa tarde, pessoal. Quanto tempo.
Estou envolvido em um projeto por hobby e faz parte desse hobby aparecem dúvidas cabeludas.

Seguinte: tenho um objeto que tem a instrução de escolher duas ações entre 5 possíveis. Uma variável ajuda ele nessa tarefa. Assim que as ações são escolhidas, o jogo executa um segundo script onde estão todas as tarefas separadas por IFs (ex: if (var_action[0] = "andar"){ ... } else if(var_action[0] = "atacar" { ... }, enfim). Alguns desses objetos podem executar até duas ações de uma vez UMA POR VEZ. E é aqui que o problema aparece!

Se o objeto escolhe andar aleatoriamente antes de executar a segunda ação, ele precisa terminar sua caminhada aleatória. O código precisa ficar nessa ação até ela terminar e só depois seguir o codigo. Então pensei em incluir essa ação em uma while, por exemplo. O problema é que tarefas de SPEED ficam paradas e começa um loop infinito. Fiz assim:

while (point_distance(argumentos) != 0){speed = 2} e também fiz: while (point_distance(argumentos) != 0){move_towards(valor de x, valor de y, 2)}. Enfim, nada disso faz sair do lugar.

No fim do dia que eu conseguir com a função mp_alguma coisa_step, só que a movimentação do personagem fica instantânea, ou seja, ele vira o The Flash e não da pra ver ele se deslocando.

Então o que preciso é de uma lógica ou estrutura que me permita executar blocos de código de cada vez. Algum mestre no código aí pra me auxiliar?
Valeus!

Avatar do usuário
Golden Bunny
Membro
Membro
Reações: 0
Mensagens: 44

Re: Como executar bloco de código por vez?

Mensagem por Golden Bunny » Qua Abr 26, 2017 2:29 pm

Não entendi direito.. Mas acho que usar State Machine deve ajudar.
https://www.youtube.com/watch?v=-0bckaBj__M
"Nunca morra virgem, os unicórnios morreram virgens, por isso não existem mais" < Gonzo, o eterno filósofo.

Avatar do usuário
Markito
Colaborador
Colaborador
Reações: 0
Mensagens: 50

Re: Como executar bloco de código por vez?

Mensagem por Markito » Qua Abr 26, 2017 3:13 pm

Acho que ele está se referindo a uma fila de ações, comum em jogos RTS. Você pode usar uma Queue, contendo uma string com o nome da ação que você quer executar. Tem ainda as Priority Queues que possuem um atributo de prioridade (número inteiro), que automaticamente ordena o conteúdo da fila baseada nos itens que tiverem prioridade maior. Caso a ação precise de parâmetros, você poderia usar uma List ao invés de uma string pra enfileirar na queue - com o primeiro item da lista o nome da ação e a seguir seus parâmetros.

Quando adicionar uma ação, você dá um ds_queue_enqueue. E quando o objeto ver que está sem ações pra fazer, ele verifica se tem ações na lista com ds_queue_empty (se for false) e retorna-os com ds_queue_dequeue.

Código: Selecionar todos

// Adicionar ação
ds_queue_enqueue(fila_acoes, "atacar")

Código: Selecionar todos

// Executar ação
if not ds_queue_empty(fila_acoes) {
    acao = ds_queue_dequeue(fila_acoes)
    executar_acao(acao)
}

Código: Selecionar todos

// Executar ação, mas com 2 ao mesmo tempo
// Usando listas pra ficar mais prático

// Processar a fila
if not ds_queue_empty(fila_acoes) {
    while ds_list_size(acoes) < 2 and not ds_queue_empty(fila_acoes) {
        acao = ds_list_dequeue(fila_acoes)
        ds_list_add(acoes, acao)
    }
}

// Executar as ações
tamanho_lista = ds_list_size(acoes)
if tamanho_lista > 0 {
    for (i=0;i<tamanho_lista;i+=1) {
        acao = ds_list_find_index(acoes, i)
        executar_acao(acao)
    }

    ds_list_clear(acoes) // Limpa a lista
}
Não se esqueça de criar as filas e/ou listas no Create, e destruí-las no Destroy, conforme descrito nas páginas do manual que linkei acima. Máquinas de estados finitos são um outro componente interessante pra você utilizar na execução das ações. Tem também um tutorial bacana (em texto) na forumeiros que explica sobre.

Abraços o/

Avatar do usuário
Mysterious Stranger
Artista
Artista
Reações: 0
Mensagens: 62
Localização: BH

Contato:

Re: Como executar bloco de código por vez?

Mensagem por Mysterious Stranger » Qua Abr 26, 2017 3:41 pm

Vc diz q não entendeu, mas entendeu Golden heheh. Acho q declarar esse degrau me ajudaria... não tinha pensado nisso.
Markito é isso mesmo. Vc matou o problema. Com certeza vou tentar isso. Obrigado mesmo!

Avatar do usuário
Markito
Colaborador
Colaborador
Reações: 0
Mensagens: 50

Re: Como executar bloco de código por vez?

Mensagem por Markito » Qua Abr 26, 2017 6:50 pm

Errata: falhei um pouco na minha lógica ao não considerar que as ações ainda poderiam estar sendo executadas e durar vários steps. Você tem que bolar um jeito pra determinar quando uma ação for completada e aí sim liberar espaço pra acrescentar na ds_list de ações ao invés de simplesmente dar clear. Bom desenvolvimento :)

Avatar do usuário
Mysterious Stranger
Artista
Artista
Reações: 0
Mensagens: 62
Localização: BH

Contato:

Re: Como executar bloco de código por vez?

Mensagem por Mysterious Stranger » Seg Mai 01, 2017 4:46 pm

Galera, seguinte.
Eu usei mais ou menos a lógica do artigo q o Markito passou. Eu executo o script e só depois da condição cumprida, uma variável libera permisao pra outra ação ou passar o turno em um script Mestre que controla a fila. Digo assim justamente pq as ações duram mais q 1 step. Tava funcionando bem até a ação d ataque. Algumas vezes randômicos a função sprite_index ignora a sprite q mando executar e a animação de ataque não acontece.
Já vi c era erro de variáveis, mas elas funcionam perfeitamente. Será q a questão de entrar e sair dos scripts da bugando a função?

Avatar do usuário
Thiago Silva Thiago
Membro
Membro
Reações: 0
Mensagens: 25

Re: Como executar bloco de código por vez?

Mensagem por Thiago Silva Thiago » Ter Mai 02, 2017 3:53 pm

Eu tentei fazer um esqueminha que pode ser mais simples e ajuda-lo.
Pra iniciar

Código: Selecionar todos

fila_acoes = ds_queue_create();
acao = "nenhuma";
pronto_proxima_acao = true;
adicione as ações normalmente com

Código: Selecionar todos

ds_queue_enqueue(fila_acoes,"acao a ser adicionada a lista de prioridade");
E esse código pra controlar as ações, e avançar pra próxima

Código: Selecionar todos

if (pronto_proxima_acao == true)
{
    if (ds_queue_size(fila_acoes) > 0)
    {
        acao = ds_queue_dequeue(fila_acoes);
        pronto_proxima_acao = false;
    }
}

//algums exemplos de como eu faria
switch acao
{
    case "mover_para_ponto":
    {
        //nessa acao, vamos move-lo ao ponto.
        if ((point_distance(x,y,parax,paray) < 5))
        {
            sprite_index = parado;
            image_speed = 0;
            speed = 0;
            
            pronto_proxima_acao = true;
        }
        else
        {
            direction = point_direction(x,y,parax,paray);
            speed = 3;
            sprite_index = andando;
            image_speed = 0.3;
        }
    }
    break;
    case "atacar_o_jogador":
    {
        //nessa acao, vamos seguir e atacar o jogador
        if (distance_to_object(jogador) < 5)
        {
            sprite_index = atacando;
            image_speed = 0.5;
            speed = 0;
        }
        else
        {
            direction = point_direction(x,y,jogador.x,jogador.y);
            speed = 3;
            sprite_index = andando;
            image_speed = 0.3;
        }
        //essa acao, pelo que pode perceber, nao tem fim, mas caso voce queira dar um fim nela use -
        //pronto_proxima_acao = true;
    }
    break;
}
20 anos, estudante de linguagens de programação.
Uso Godot Engine.

Avatar do usuário
Mysterious Stranger
Artista
Artista
Reações: 0
Mensagens: 62
Localização: BH

Contato:

Re: Como executar bloco de código por vez?

Mensagem por Mysterious Stranger » Seg Mai 15, 2017 1:07 pm

Thiago Silva Thiago escreveu:Eu tentei fazer um esqueminha que pode ser mais simples e ajuda-lo.
Pra iniciar

Código: Selecionar todos

fila_acoes = ds_queue_create();
acao = "nenhuma";
pronto_proxima_acao = true;
adicione as ações normalmente com

Código: Selecionar todos

ds_queue_enqueue(fila_acoes,"acao a ser adicionada a lista de prioridade");
E esse código pra controlar as ações, e avançar pra próxima

Código: Selecionar todos

if (pronto_proxima_acao == true)
{
    if (ds_queue_size(fila_acoes) > 0)
    {
        acao = ds_queue_dequeue(fila_acoes);
        pronto_proxima_acao = false;
    }
}

//algums exemplos de como eu faria
switch acao
{
    case "mover_para_ponto":
    {
        //nessa acao, vamos move-lo ao ponto.
        if ((point_distance(x,y,parax,paray) < 5))
        {
            sprite_index = parado;
            image_speed = 0;
            speed = 0;
            
            pronto_proxima_acao = true;
        }
        else
        {
            direction = point_direction(x,y,parax,paray);
            speed = 3;
            sprite_index = andando;
            image_speed = 0.3;
        }
    }
    break;
    case "atacar_o_jogador":
    {
        //nessa acao, vamos seguir e atacar o jogador
        if (distance_to_object(jogador) < 5)
        {
            sprite_index = atacando;
            image_speed = 0.5;
            speed = 0;
        }
        else
        {
            direction = point_direction(x,y,jogador.x,jogador.y);
            speed = 3;
            sprite_index = andando;
            image_speed = 0.3;
        }
        //essa acao, pelo que pode perceber, nao tem fim, mas caso voce queira dar um fim nela use -
        //pronto_proxima_acao = true;
    }
    break;
}
Eu acabei não precisando usar a função queue, Thiago. Usei a lógica de scripts que o Makito passou e funcionou. As sprites eu fiz mais ou menos isso que vc fez usando uma switch e funcionou perfeitamente. Valeu todo mundo a ajuda!

Responder

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 0 visitante