# Artigos de Programação

# Técnicas usadas no Gadget - Ars Bellica

Experiências adquiridas durante o desenvolvimento do Gadget - Ars Bellica (https://gitlab.com/uspgamedev/gadget-ars-bellica-2).

# Injeção de dependência na Godot - Como fazer um nó achar outro?

Precisar que um nó de uma cena encontre outro nó de outra cena é um problema que sempre aparece quando eu vou fazer algum jogo na Godot.

## Exemplo 1

Uma aranha precisa perseguir o jogador.

[![spider.gif](https://usp.game.dev.br/wiki2/uploads/images/gallery/2023-12/AELspider.gif)](https://usp.game.dev.br/wiki2/uploads/images/gallery/2023-12/AELspider.gif)[ ![player.gif](https://usp.game.dev.br/wiki2/uploads/images/gallery/2023-12/player.gif)](https://usp.game.dev.br/wiki2/uploads/images/gallery/2023-12/player.gif)

Portanto, o nó de perseguição da aranha (`chase.gd`) da aranha precisa encontrar o nó do jogador (`player.gd`) de alguma forma.

### Solução 1  - Grupos


```Go
# chase.gd

# O nó do jogador está no grupo "PLAYER"
@export var target_group := "PLAYER"

var current_target: Node

func chase():
    # 
    current_target = get_tree().get_first_node_in_group(target_group)

    # Então pegamos a posição do jogador para que possamos
    # mover a aranha em sua direção 
    var target_position = current_target.get_position()
    move_toward(target_position)

```
Porém 

## Exemplo 2
Agora, veja a seguinte situação:
 1. O jogador persegue o slime mais próximo;
 2. A aranha ataca o slime mais próximo

![player.gif](https://usp.game.dev.br/wiki2/uploads/images/gallery/2023-12/player.gif) 
![slime.gif](https://usp.game.dev.br/wiki2/uploads/images/gallery/2023-12/image-1702215851332.gif)
![slime.gif](https://usp.game.dev.br/wiki2/uploads/images/gallery/2023-12/image-1702215851332.gif)
[![spider.gif](https://usp.game.dev.br/wiki2/uploads/images/gallery/2023-12/AELspider.gif)](https://usp.game.dev.br/wiki2/uploads/images/gallery/2023-12/AELspider.gif) 
![slime.gif](https://usp.game.dev.br/wiki2/uploads/images/gallery/2023-12/image-1702215851332.gif)

Nesse caso, apenas pegar o primeiro nó de um grupo já não é mais suficiente, será necesário achar todos os nós no grupo `SLIME` e iterar para descobrir o slime que estiver mais perto. Porém, aonde se deve colocar o código que faz isso?  No `Chase.gd`? 

Há pelo menos dois problemas em colocar esse código no `Chase.gd`:
- Seria necessário repetir esse código no `Attack.gd` para satisfazer a condição 2 e portanto haveria duplicação de código, o que é ruim.
- Não necessariamente todas as criaturas que perseguem irão perseguir o ser mais próximo de determinado grupo, por exemplo, a aranha poderia perseguir o slime com menos pontos de vida.

Vejamos agora uma solução que tenta resolver esses problemas:

### Solução 2  - Solicitador


O que devemos fazer aqui é extrair essa busca para um nó para próprio. Para isso, iremos primeiro criar a interface `Solicitador`:

```Go
# solicitador.gd
class_name Solicitador

# Método virtual que devolve o nó procurado.
func solicita() -> Node:
    push_error("Método virtual!")
    return null

# Método abstrato que devolve vários nós.
# Por padrão devolve apenas o nó retornado por solicita()
func solicita_varios() -> Array[Node]:
    if solicita():
        return [solicita()]
	return []


```
Agora, vamos criar um solicitador que pega nós de um grupo:

```Go
# solicitador_de_grupo.gd

class_name SolicitadorDeGrupo
extends Solicitador

@export var grupo = ""

func solicita() -> Node:
    return get_tree().get_first_node_in_group(grupo)

func solicita_varios() -> Array[Node]:
    return get_tree().get_nodes_in_group(grupo)
```

Agora, um solitador que acha o nó mais perto
```
# tile_requester

class_name SimpleTileRequester
extends TileRequester

@export var tile: Tile

func request() -> Tile:
	return tile


# chase.gd

@export var requester: Requester 

func persegue():
    # World é um autoload que representa um mundo ECS
    # Player é o nome da classe de player.gd
    var presa = World.get_first_entity_with_component(Player)
	
	# Resto do código

```

# Ação e interação - Como implementar comportamentos complexos

Nesse texto vou mostrar como combinei os padrões <span style="color:red">*Unlimited Rulebook*</span> e *[Composite](https://pt.wikipedia.org/wiki/Composite)* para gerar comportamentos complexos no Gadget - Ars Bellica.

### Interações
O conceito de interação é bastante comum em jogos, por exemplo:
 - O jogador interage com uma alavanca para ativá-la
 -
 
 
 #### Exemplo 1
 1.