Introducció als Behavior Trees

Els Behavior Trees (BTs) són una estructura de dades utilitzada per modelar el comportament dels personatges no jugadors (NPCs) en els videojocs. Són una alternativa a les màquines d'estats finits (FSM) i ofereixen una manera més flexible i escalable de gestionar comportaments complexos.

Conceptes Bàsics

  1. Node: La unitat bàsica d'un BT. Cada node representa una acció o una decisió.
  2. Arrel (Root): El node inicial del BT, des d'on comença l'execució.
  3. Fulles (Leaves): Nodes terminals que representen accions concretes.
  4. Nodes Compositors: Nodes que poden tenir fills i determinen l'ordre d'execució dels seus fills.
  5. Nodes Decoradors: Nodes que modifiquen el comportament dels seus fills.

Tipus de Nodes

  1. Sequence (Seqüència): Executa els seus fills en ordre fins que un falla. Si un falla, la seqüència falla.
  2. Selector: Executa els seus fills en ordre fins que un té èxit. Si un té èxit, el selector té èxit.
  3. Parallel (Paral·lel): Executa tots els seus fills simultàniament.
  4. Decorator (Decorador): Modifica el comportament d'un altre node (per exemple, repeteix una acció fins que tingui èxit).

Exemple de Behavior Tree

Root
 ├── Sequence
 │   ├── CheckHealth
 │   ├── FindEnemy
 │   └── Attack
 └── Selector
     ├── Patrol
     └── Idle

En aquest exemple, el node arrel té dos fills: una seqüència i un selector. La seqüència comprova la salut, busca un enemic i ataca. Si qualsevol d'aquestes accions falla, la seqüència falla. El selector patrulla o es queda en mode idle si no hi ha enemics.

Implementació de Behavior Trees

Pas 1: Definir els Nodes

Primer, definim les classes per als diferents tipus de nodes.

class Node:
    def run(self):
        raise NotImplementedError("This method should be overridden by subclasses")

class Sequence(Node):
    def __init__(self, children):
        self.children = children

    def run(self):
        for child in self.children:
            if not child.run():
                return False
        return True

class Selector(Node):
    def __init__(self, children):
        self.children = children

    def run(self):
        for child in self.children:
            if child.run():
                return True
        return False

class Action(Node):
    def __init__(self, action):
        self.action = action

    def run(self):
        return self.action()

Pas 2: Definir les Accions

Definim les accions que els nodes fulla executaran.

def check_health():
    print("Checking health...")
    return True  # Simulació de la verificació de salut

def find_enemy():
    print("Finding enemy...")
    return True  # Simulació de la cerca d'enemics

def attack():
    print("Attacking enemy...")
    return True  # Simulació de l'atac a l'enemic

def patrol():
    print("Patrolling...")
    return False  # Simulació de la patrulla

def idle():
    print("Idling...")
    return True  # Simulació de l'estat idle

Pas 3: Construir el Behavior Tree

Construïm el BT utilitzant els nodes i les accions definides.

# Crear nodes fulla
check_health_node = Action(check_health)
find_enemy_node = Action(find_enemy)
attack_node = Action(attack)
patrol_node = Action(patrol)
idle_node = Action(idle)

# Crear nodes compositors
sequence_node = Sequence([check_health_node, find_enemy_node, attack_node])
selector_node = Selector([patrol_node, idle_node])

# Crear el node arrel
root = Selector([sequence_node, selector_node])

# Executar el Behavior Tree
root.run()

Exercici Pràctic

Exercici: Implementa un Behavior Tree que afegeixi una acció de "Recollir Objectes" abans de l'atac. Si no hi ha objectes per recollir, el personatge hauria de patrullar.

Solució:

def collect_items():
    print("Collecting items...")
    return True  # Simulació de la recollida d'objectes

# Crear nodes fulla addicionals
collect_items_node = Action(collect_items)

# Actualitzar nodes compositors
sequence_node = Sequence([check_health_node, find_enemy_node, collect_items_node, attack_node])
selector_node = Selector([patrol_node, idle_node])

# Actualitzar el node arrel
root = Selector([sequence_node, selector_node])

# Executar el Behavior Tree
root.run()

Conclusió

Els Behavior Trees són una eina poderosa per gestionar comportaments complexos en videojocs. Ofereixen una estructura clara i escalable que facilita la implementació i manteniment de comportaments d'NPCs. Amb la pràctica, es poden crear BTs molt sofisticats que millorin significativament la jugabilitat i la immersió en els videojocs.

© Copyright 2024. Tots els drets reservats