Taller Práctico de IA y Lógica en Videojuegos Autor: Jesús Flores García Tenerife LanParty 2k9 Taller Práctico de IA y Lógica en Videojuegos
Objetivos Taller de iniciación Aclaración conceptos Introducción de técnicas básicas Resolución cuestiones y dudas Más ameno que riguroso
Temario Día 1: Entrando en la “Matrix” Día 2: Buscando el camino Día 3: Nuestro cajón de arena Día 4: Ahora te vas y ¿yo qué hago?
Día 1: Entrando en la “Matrix” Introducción de IA en videojuegos Principios básicos Objetos y Comportamientos Máquinas de estados (FSM)
Día 2: Buscando el camino Decisiones y Capas Caso de Estudio: Pathfinding Técnica de alto nivel: Nav Maps Técnica de bajo nivel: Perseguidor
Día 1: Entrando en la “Matrix”
Día 1: Entrando en la “Matrix” Introducción de IA en videojuegos Principios básicos Objetos y Comportamientos Máquinas de estados (FSM)
Breve Introducción de IA NIÑO: No intentes doblar la cuchara. Eso es imposible. En vez de eso, sólo procura comprender la verdad. NEO: ¿Qué verdad? NIÑO: Que no hay cuchara. NEO: ¿No hay cuchara?
Breve Introducción de IA Falsear la realidad Distraer la atención Cómputos ligeros Soluciones aceptables, no óptimas
¡Quieres empezar! Inicialización Bucle de Juego Fase de Update Fase de Render Update Render Cierre
¡Código Please! if ( SGame.Init( hWnd ) ) { _________ while( msg.message != WM_QUIT ) SGame.Update( seconds ); SGame.Render(); } SGame.Destroy();
Objetos y Sistema de Referencia
Objetos y Sistema de Referencia
Mates I: Vectores y Puntos XYZ D3DXVECTOR3 (X, Y, Z) (X, Y, Z)
Objetos y Comportamientos
Objetos y Comportamientos
Objetos y Comportamientos
Objetos y Comportamientos
Patrón Estrategia STRATEGY OBJECT STRATEGY 1 STRATEGY 2 STRATEGY 3 Strategy * strg; algorithm() STRATEGY 1 STRATEGY 2 STRATEGY 3 algorithm() algorithm() algorithm()
¡A Practicar!
¿Por qué necesitamos más? Tenemos un comportamiento simple Queremos: Secuencias Comportamientos más complejos Recordar pasos anteriores
Ejemplo: Enemigo Secuencial ESPERAR LANZAR BARRIL
Ejemplo: Más moderno
FSM – Máquinas de Estados Comportamiento Complejo Enemigo Usa Ascensor
FSM – Máquinas de Estados Comportamiento se descompone Enemigo Usa Ascensor Pulsar Botón Entrar Pulsar Botón Salir
FSM – Máquinas de Estados Transiciones Enemigo Usa Ascensor Pulsar Botón Entrar Pulsar Botón Salir
FSM – Máquinas de Estados Reglas de Transición Enemigo Usa Ascensor Pulsar Botón Entrar Pulsar Botón Salir Estar Dentro Esperar Esperar
FSM – Implementación Se debe guardar el estado actual Secuencia de IF´s if ( state == “AAA” ) … else if ( state == “BBB” ) else if ( state == “CCC” )
FSM – Implementación Mejor con números (eficiencia) Secuencia de IF´s if ( state == 0 ) … else if ( state == 1 ) else if ( state == 2 )
FSM – Implementación Mejor usar un switch: switch( state ) { … { … case 0: … break; case 1: … break; case 2: … break; }
FSM – Implementación Un enum es más claro: switch( state ) { … { … case AAA: … break; case BBB: … break; case CCC: … break; }
FSM – Implementación Válido para casos sencillos Problema del switch de las 5000 líneas switch( state ) { … case AAA: … break; case BBB: … break; case CCC: … break; }
FSM – Implementación Crear una función para cada estado switch( state ) { … case AAA: AAA(); break; case BBB: BBB(); break; case CCC: CCC(); break; }
FSM – Implementación Válido para máquinas medianas No tiene código en las transiciones switch( state ) { … case AAA: AAA(); break; case BBB: BBB(); break; case CCC: CCC(); break; }
FSM – Implementación STATE OnEnter() OnUpdate() OnExit() Los estados son clases: STATE OnEnter() OnUpdate() OnExit()
FSM – Implementación STATE 1 STATE 2 FSM STATE 3 State * actual; La FSM es otra clase: STATE 1 STATE 2 FSM STATE 3 State * actual; STATE 4 STATE … STATE N
FSM – Implementación Miles de implementaciones Miles de artículos Miles de extensiones Máquinas de Máquinas de estados Basadas en Eventos Máquinas de pila Máquinas multi-estados (No deterministas) Máquinas inerciales Máquinas Fuzzy (FuSM) ….
No Matar Moscas a Cañonazos Usa lo que te haga falta No hay soluciones generales
¡A Practicar!
Mates II: Entre 2 Puntos VDistancia = PtoDestino – PtoOrigen Distancia = Length(VDistancia) Dirección = Normalize(VDistancia)
Mates III: Ángulos Z X VDistancia = PtoDestino – PtoOrigen Ángulo = atan2( X, Z ); Z X
Día 2: Buscando el camino
Día 2: Buscando el camino Decisiones y Capas Caso de Estudio: Pathfinding Técnica de alto nivel: Nav Maps Técnica de bajo nivel: Perseguidor
Decisiones en el Juego Curarse Pulsar Botón Volver a la Base Múltiples decisiones que tomar Curarse Pulsar Botón Volver a la Base Perseguir J1 Esperar Usar Ascensor Cambiar Animación Subir Escaleras Pedir Refuerzos Disparar
Decisiones en el Juego Curarse Pulsar Botón Volver a la Base No es bueno que todo se resuelva a la vez Curarse Pulsar Botón Volver a la Base Perseguir J1 Esperar Usar Ascensor Cambiar Animación Subir Escaleras Pedir Refuerzos Disparar
Decisiones y Capas Diferentes niveles / Capas de decisión: Decisiones a largo plazo Decisiones a medio plazo Decisiones a corto plazo Decisiones a inmediatas
Decisiones Ejemplos de Decisiones: Atacar Base Enemiga Decisiones a largo plazo Atacar Base Enemiga Decisiones a medio plazo Buscar Ruta Segura Decisiones a corto plazo Disparar a vigilante Decisiones a inmediatas Ejecutar Animación
Decisiones Diferentes estrategias / técnicas: Decisiones a largo plazo Decisiones a medio plazo T3 Decisiones a corto plazo T4 Decisiones a inmediatas T5 T6
Decisiones y Capas 120 segs 10 segs 0.5 segs 0.0016 segs Distinta frecuencia de actualización: Decisiones a largo plazo 120 segs Decisiones a medio plazo 10 segs Decisiones a corto plazo 0.5 segs Decisiones a inmediatas 0.0016 segs
Decisiones y Capas Perseguir J1 Volver a la Base Subir Escaleras Distintos subsistemas: Perseguir J1 Volver a la Base Subir Escaleras Pedir Refuerzos Usar Ascensor Curarse Disparar Pulsar Botón Cambiar Animación
Caso de estudio Movimiento y Pathfinding Necesidad de Desplazarse por el Mundo Distintos niveles de decisión: Una capa superior: Ir al bosque de los elfos Pathfinding: Usar el camino del oeste Movimiento: Esquivar una roca
Representación del mundo Mundo continuo Difícil de trabajar con él Se necesita una representación
Representación del mundo Usar geometría para simplificar
Representación del mundo Usar geometría para simplificar Es un primer paso En general no es suficiente
Representación del mundo Rejilla Cuadrada
Representación del mundo Rejilla hexagonal
Representación del mundo Rejillas Buenas representaciones en 2D Espacios de búsqueda muy grandes
Representación del mundo Quad Trees y Octrees
Representación del mundo Grafos y Waypoints
Representación del mundo Grafos y Waypoints
Representación del mundo Grafos y Waypoints Muchos nodos por procesar Raíles y mucho zigzag
Representación del mundo Grafos y Waypoints Muchos nodos por procesar Raíles y mucho zigzag
Representación del mundo Grafos y Waypoints Muchos nodos por procesar Raíles y mucho zigzag
Representación del mundo Mapas de navegación: NavMaps
Representación del mundo NavMaps Grafo de areas caminables Menos nodos y más libertad de movimiento
Representación del mundo NavMaps Grafo de áreas caminables Menos nodos y más libertad de movimiento
Representación del mundo Muchas otras representaciones
Algoritmos de Búsquedas Algoritmos tradicionales: Anchura y profundidad A* y variantes Dijkstra Floyd-Warshall …
Caso práctico de NavMesh 1- Crear el Mapa de Navegación:
Caso práctico de NavMesh 1- Crear el Mapa de Navegación:
Caso práctico de NavMesh 2- Aplicamos Floyd-Warshall: 946 Nodos Maxscript Matriz Grafo
Caso práctico de NavMesh 3- Obtener el camino usando la matriz (0.0, 0, 28) (0.1, 0, 12) (3, 0, -5) (-1, 0, 28) (8, 0, 28.8) (8.2, 0, 21.8) (8.1, 0, 22.8) Matriz
Caso práctico de NavMesh 4- Pasar los Waypoints a la capa inferior Pathfinding (Alto nivel) (0.1, 0, 12) (3, 0, -5) (-1, 0, 28) (8, 0, 28.8) (8.2, 0, 21.8) (8.1, 0, 22.8) Movimiento (Bajo Nivel)
Vamos a verlo en ejecución:
Caso práctico de NavMesh Se mueve al medio de las aristas Lejos de estar acabado
Caso práctico de NavMesh 5- Heurística de refinamiento: String-Pulling
Caso práctico de NavMesh 5- Heurística de refinamiento: String-Pulling
Caso práctico de NavMesh 5- Heurística de refinamiento: String-Pulling
Caso práctico de NavMesh 5- Heurística de refinamiento: String-Pulling
Caso práctico de NavMesh 5- Heurística de refinamiento: String-Pulling
Caso práctico de NavMesh 5- Heurística de refinamiento: String-Pulling
Caso práctico de NavMesh 5- Heurística de refinamiento: String-Pulling
Caso práctico de NavMesh 5- Heurística de refinamiento: String-Pulling
Caso práctico de NavMesh 5- Heurística de refinamiento: String-Pulling
Vamos a verlo en ejecución:
¡Todavía no funciona bien! Continuar refinando la solución Probar otras heurísticas Mejorar el Grafo inicial ¡TIEMPO, TIEMPO, TIEMPO!
Estrategia Bajo Nivel: Perseguidor Velocidad Lineal Limitada Velocidad Angular Limitada Efecto del Cocodrilo
Mates IV: Ángulo entre vectores Producto escalar = Dot Product Dot(V, W) = Vx*Wx + Vy*Wy +Vz*Wz Dot(V, W) = |V| * |W| * cos(ang) Si |V| = |W| = 1 Dot(V, W) = cos(ang) V W
Mates V: Plano N P Plano = A * X + B * Y+ C * Z + D Plano = Nx * X + Ny * Y + Nz * Z + D D = – Nx * Px – Ny * Py – Nz * Pz N P
Mates VI: Test de Plano-Punto Plano = A * X + B * Y+ C * Z + D Punto P V = A * Px + B * Py + C * Pz + D V=0 En el plano V>0 Encima del plano(Donde Apunta N) V<0 Debajo del plano P
Algoritmo Perseguidor: vDist = TargetPos – CurrentPos
Algoritmo Perseguidor: vDist = TargetPos – CurrentPos angle = acos( Dot( vDist, CurrentFront ) )
Algoritmo Perseguidor: vDist = TargetPos – CurrentPos angle = acos( Dot( vDist, CurrentFront ) ) if ( angle > velAng * timestep ) angle = velAng * timestep
Algoritmo Perseguidor: vDist = TargetPos – CurrentPos angle = acos( Dot( vDist, CurrentFront ) ) if ( angle > velAng * timestep ) angle = velAng * timestep p = Plane( CurrentLeft, 0 ) if ( PlaneTest( vDist, p ) < 0) angle = -angle
Algoritmo Perseguidor: vDist = TargetPos – CurrentPos angle = acos( Dot( vDist, CurrentFront ) ) if ( angle > velAng * timestep ) angle = velAng * timestep p = Plane( CurrentLeft, 0 ) if ( PlaneTest( vDist, p ) < 0) angle = -angle Yaw += angle CurrentPos += |vDist | * NewCurrentFront
Vamos a verlo en ejecución:
Día 3: Nuestro cajón de arena
Día 3: Nuestro cajón de arena
Día 3: Nuestro cajón de arena Comunicación entre elementos Pizarra, Mensajes y Eventos Lenguajes de Scripting Introducción a Lua