1. Curso de Programacion de Juegos 2D – Modulo II
Por: Ricardo D. Quiroga -> L2Radamanthys – l2radamanthys@gmail.com
Programación de Juegos
2D - Modulo II
Capitulo I: Inteligencia Artificial (IA)
1
2. Curso de Programacion de Juegos 2D – Modulo II
Por: Ricardo D. Quiroga -> L2Radamanthys – l2radamanthys@gmail.com
Inteligencia Artificial
Introducion
Bueno este capitulo tratara de introducirlos en los conceptos sobre la Inteligencia
Artificial desde ahora IA o AI para la variante de su nombre en Ingles, mas explicitamente
aplicados al tema que nos interesa en este caso programacion de juegos, aun asi el tema es
bastante amplio por si solo por lo que solo podremos cubrir una minima parte del tema. Otra
cosa omitire es toda la trama de historia que normalmente acarrea cualquier curso que toque el
tema IA, aunque la historia es importante en cierto sentido, este curso se enfoca o al menos es
lo que yo pretendo que aprendan algunos conceptos y puedan implementarlos rapidamente.
Que es la IA?
Dijimos que ibamos a ablar sobre IA, blabla.. pero en realidad no definimos que es, a lo
largo del tiempo se siguieron varios enfoques los mas comunes son los centrado en el
comportamiento humano y los de racionalidad, un sistema es racional, si hace 'lo correcto' en
funcion de sus conocimientos. El enfoque humano es mas algo enpirico.
Agentes Inteligentes
En la IA, el principal tema que junta todo lo conceptos es el de los Agentes Inteligentes.
La IA se define como el estudio de los agentes que reciben percepciones de un entorno y llevan
a cabo aciones. Los diferentes agentes se pueden clasificar en: Reactivos, Planificadores
condicionales, redes neuronales y sistemas teoricos de decicion.
¿Qué es un agente?
Al igual que ocurre con la propia definición de la IA, se pueden encontrar propuestas en
la literatura un gran número de definiciones del concepto de agente, sin que ninguna de ellas
haya sido plenamente aceptada por la comunidad científica, siendo quizás la más simple la de
Russell [Russell1996], que considera un agente como una entidad que percibe y actúa sobre un
entorno (ver figura 1). Basándose en esta definición, se pueden caracterizar distintos agentes
de acuerdo a los atributos que posean (y que van a definir su comportamiento) [Botti1999]
para resolver un determinado problema.
2
3. Curso de Programacion de Juegos 2D – Modulo II
Por: Ricardo D. Quiroga -> L2Radamanthys – l2radamanthys@gmail.com
Hay que indicar que el término «agente» está de moda y mucha gente se ha «subido al
carro» indicando que las aplicaciones que desarrollan son agentes. No es momento de entrar
en discusión, pero si que es necesario remarcar el origen por el que se planteó esta tecnología
y es el hecho de que debe ser aplicada a sistemas complejos, sistemas donde la aplicación
de las técnicas existentes hoy en día han fracasado o son sumamente difíciles de comprender
y/o mantener.
En la mayoría de las ocasiones, los agentes no son desarrollados de forma independiente
sino como entidades que constituyen un sistema. A este sistema se le denomina multi-agente
[Huhns1998]. En este caso los agentes deben o pueden interactuar entre ellos. Las
interacciones más habituales como son informar o consultar a otros agentes permiten a los
agentes «hablar» entre ellos, tener en cuenta lo que realiza cada uno de ellos y razonar acerca
del papel jugado por los diferentes agentes que constituyen el sistema.
La comunicación entre agentes se realiza por medio de un lenguaje de comunicación de
agentes (ACL --Agent Communication Language) por razones varias este tema esta mas alla de
este curso.
Actuar Racionalmente
Un agente es algo que razona. Pero en la informatica se pide algo mas, que esten
dotados de controles autonomos, que puedan persistir durante un periodo de tiempo
prolongado, que se adapten a los cambios y que sean capaces de alcanzar objetivos diferentes.
El enfoque del diseño de agentes racionales ofrece al menos 2 ventajas, la primera
proporciona un enfoque mas general que el de las leyes del pensamiento (orientada al
comportamiento de los humanos), el segundo es mas afin por que la norma de racionalidad
esta claramente definida y es de aplicacion general, por el contrario la conducta humana se
adapta bien a un entorno especifico y en parte es resultado de un proceso evolutivo muy
complejo.
Agentes y sus Entornos
Resumiendo, un agente es cualquier cosa capaz de persivir su medio ambiente (Entorno
en el que comvive), con la ayuda de sensores (si lo comparamos con una persona, los sensores
serian por ejemplo los ojos, oido ,tacto, etc) y actuadores (acciones que el agente puede
realizar en el medio ambiente).
3
4. Curso de Programacion de Juegos 2D – Modulo II
Por: Ricardo D. Quiroga -> L2Radamanthys – l2radamanthys@gmail.com
Maquinas de Estados
Las Maquinas de Estados son un caso particular de los Agentes Inteligentes, en realidad
no tienen nada de inteligentes si se comparan con una persona ya que no poseen la capacidad
de discriminar los eventos que persiven y no poseen memoria, solo actuan en base a las
entradas (informacion o eventos que persiven).
Se denomina máquina de estados a un modelo de comportamiento de un sistema con
entradas y salidas, en donde las salidas dependen no sólo de las señales de entradas actuales
sino también de las anteriores. Las máquinas de estados se definen como un conjunto de
estados que sirve de intermediario en esta relación de entradas y salidas, haciendo que el
historial de señales de entrada determine, para cada instante, un estado para la máquina, de
forma tal que la salida depende únicamente del estado y las entradas actuales.
Una máquina de estados se denomina máquina de estados finitos (FSM por finite state
machine) si el conjunto de estados de la máquina es finito, este es el único tipo de máquinas de
estados que podemos modelar en un computador en la actualidad; debido a esto se suelen
utilizar los terminos máquina de estados y máquina de estados finitos de forma intercambiable.
¿Por que usar Maquinas de estado?
Y esta respuesta es simple: hay varias maneras de programar una maquina de Estados,
y casi todas ellas son bastante sencillas a la hora de implementar. Son faciles de extender,
4
5. Curso de Programacion de Juegos 2D – Modulo II
Por: Ricardo D. Quiroga -> L2Radamanthys – l2radamanthys@gmail.com
adaptar, poner a punto segun nuestros requerimientos. tienen un costo computacional muy
pequeño ya que en realidad no tiene casi ningun costo de procesamiento real asignado.
Permiten determinar facilmente el comportamiento de un agente y como dato es lo que mas se
ha tendido a utilizar en materia de video Juegos.
¿Qué es exactamente una máquina de estados finitos?
Históricamente, una máquina de estados finitos es un dispositivo rígidamente
formalizado utilizada por los matemáticos para resolver problemas. La máquina de estados
finitos más famoso es probablemente dispositivo hipotético de Alan Turing: la máquina de
Turing, que él escribió en 1936 su estudio "Sobre números computables". Esta era una máquina
programable presagiando ordenadores de hoy en día y que podría realizar cualquier operación
lógica mediante la lectura, escritura y borrado de los símbolos en una tira de cinta infinitamente
larga. Afortunadamente, como programadores de IA, podemos renunciar a la definición formal
matemático de una máquina de estados finitos, uno descriptivo será suficiente:
Una máquina de estados finitos es un dispositivo, o un modelo de un dispositivo, que
tiene un número finito de estados que puede ser en un momento dado y puede funcionar en la
entrada para hacer bien las transiciones de un estado a otro o para provocar una salida o
acción a tomar su lugar. Una máquina de estados finitos sólo puede ser en un Estado en
cualquier momento en el tiempo.
La idea detrás de una máquina de estados finitos, por lo tanto, es descomponer el
comportamiento de un objeto en fácilmente manejable "trozos" o estados. El interruptor de luz
en la pared, por ejemplo, es una máquina de estados finitos muy simple. Tiene dos estados:
encendido y apagado. Las transiciones entre los estados son realizados por la entrada de su
dedo. Por chasqueando el interruptor hacia arriba que hace que la transición de apagado a
encendido, y accionando el interruptor hacia abajo se hace la transición de encendido a
apagado. No hay salida o acción asociada con el estado de apagado (a menos que se tiene en
cuenta la bombilla está apagado como una acción), pero cuando está en la electricidad en el
estado se permite que el flujo a través del interruptor y la luz hasta su habitación a través del
filamento en una bombilla.
5
6. Curso de Programacion de Juegos 2D – Modulo II
Por: Ricardo D. Quiroga -> L2Radamanthys – l2radamanthys@gmail.com
Por supuesto, el comportamiento de un agente de juego suele ser mucho más complejo
que una bombilla (gracias a Dios (Google :P)!). Éstos son algunos ejemplos de cómo las
máquinas de estado finito se han utilizado en los juegos.
El comportamiento de los fantasmas en Pac-Man se implementa como una máquina de
estados finitos. Hay un estado de evasión, que es el mismo para todos los fantasmas, y luego
cada fantasma tiene su propio estado Chase, cuyas acciones se implementan de forma
diferente para cada fantasma. La entrada del jugador de comer una de las pastillas de poder es
la condición para la transición de Chase para evadir. La entrada de un temporizador
derramándose es la condición para la transición de evadir a Chase.
Tambien los robots de estilo Quake, se implementan como máquinas de estados finitos.
Tienen estados como FindArmor, FindHealth, SeekCover, y salir corriendo. Incluso las armas en
Quake aplicar su propia mini máquinas de estados finitos. Por ejemplo, un cohete puede llevar
a cabo los estados, como Mover, TouchObject, y Die.
Jugadores en simulaciones de deportes como el FIFA2002 partido de fútbol se
implementan como máquinas de estado. Tienen estados como Huelga, Bote, ChaseBall y
MarkPlayer. Además, los equipos se suelen aplicarse como FSMs y puede tener estados como
Kickoff, defender o WalkOutOnField.
El NPC (personajes no jugadores) en los RPG (juegos de estrategia en tiempo real),
como Warcraft hacer uso de máquinas de estados finitos. Tienen estados como MoveToPosition,
patrullaje y FollowPath.
6
7. Curso de Programacion de Juegos 2D – Modulo II
Por: Ricardo D. Quiroga -> L2Radamanthys – l2radamanthys@gmail.com
Implementación de una máquina de estados finitos
Hay varias maneras de implementar máquinas de estado finito. Un enfoque ingenuo es
utilizar una serie de declaraciones si-entonces o el mecanismo de poco más ordenado de una
sentencia switch. El uso de un interruptor con un tipo enumerado para representar los estados
se ve algo como esto:
#estados del agente
RUNAWAY = 0
PATROL = 1
ATTACK = 2
class Agente:
… #omitido el codigo
def update_estado(self):
if self.estado_actual == RUNAWAY:
if self.evadir_enemigo():
self.estado_actual = PATROL
elif self.estado_actual == PATROL:
if self.localizo_un_enemigo():
if self.mas_fuerte_que_el_enemigo():
self.estado_actual = ATTACK
else:
self.estado_actual = RUNAWAY
elif self.estado_actual == ATTACK:
if self.mas_debil_que_el_enemigo():
self.estado_actual = RUNAWAY
else:
self.dispararle_a_la_cabeza()
Nota: supongo que entenderan que significa cada estado, aun asi hago una pequeña
descripcion (mas bien diria traducion) por si las dudas:
• RUNAWAY: escapar, huir del enemigo, este estado se supone que se dara cuando el
nivel de vida del bot es muy bajo, le es imposible atacar, o tiene las de perder... (Bueno
conste que si no se dieron cuenta, el ejemplo de un bot de este tipo esta pensado para
juegos de estrategias tales como StartCraft, Age of Empires, etc).
• PATROL: patrullar, vigilar... la zona alrededor del bot.
• ATTACK: si tiene un enemigo al alcance atacar con lo que tenga a mano
7
8. Curso de Programacion de Juegos 2D – Modulo II
Por: Ricardo D. Quiroga -> L2Radamanthys – l2radamanthys@gmail.com
Aunque a primera vista este enfoque parece razonable, cuando se aplica prácticamente
algo más complicado que en el más simple de los objetos del juego, el modificarlo se convierte
en algo monstruoso y con unas cuantas modificaciones esto termina pareciendo un spagueti
haciendose demasiado engorroso y dificil de entender, ademas es inflexible.
Además, como un codificador de AI, a menudo requieren que el Estado realice una
acción específica (o acciones), cuando inicialmente inscritos o cuando el estado se sale. Por
ejemplo, cuando un agente entra en el estado RunAway es posible que desee gritar
"Arghhhhhhh!" Cuando finalmente se escapa y cambia el estado de la Patrulla, puede que emita
un suspiro, pasarse la mano por la frente, y decir "¡Uf!" Se trata de acciones que sólo se
producen cuando el estado es RunAway entrado o salido y no durante la etapa de actualización
habitual. En consecuencia, esta funcionalidad adicional idealmente debe ser incorporado en la
arquitectura de su máquina de estados. Para ello en el marco de un interruptor o si entonces la
arquitectura estaría acompañado por un montón de rechinamiento de los dientes y las olas de
las náuseas, y producen un código muy feo por cierto.
Tablas de Transiciones de Estados
Un mejor mecanismo para la organización de los estados y que afectan a las transiciones
de estado es una tabla de transición de estados. Esto es exactamente lo que dice es: una tabla
de condiciones y los estados llevan a esas condiciones.
Estado Actual Condicion Estado Trancision
RUNAWAY Escapa del Enemigo PATROL
ATTACK Mas devil que el enemigo RUNAWAY
PATROL Localiza enemigo y mas fuerte que el ATTACK
PATROL Localiza enemigo y mas devil que el RUNAWAY
Esta tabla se puede consultar por un agente a intervalos regulares, lo que le permite
hacer cualquier transiciones de estado necesarias basadas en el estímulo que recibe del entorno
del juego. Cada estado puede ser modelado como un objeto independiente o función externa
existente para el agente, proporcionando una arquitectura limpia y flexible. Uno que es mucho
menos propenso a la spaghettificacion que el enfoque if-then/switch discutidos en la sección
anterior.
Alguien me dijo una vez una visualización vívida y tonta puede ayudar mas a la gente a
entender un concepto abstracto. Vamos a ver si funciona...
8
9. Curso de Programacion de Juegos 2D – Modulo II
Por: Ricardo D. Quiroga -> L2Radamanthys – l2radamanthys@gmail.com
Imaginemos un robot gatito. Es brillante y bonito, y tiene alambre para bigotes y una
ranura en su estómago, donde cartuchos - análogo a sus estados - pueden ser enchufado Cada
uno de estos cartuchos está programado con la lógica, lo que permite que el gatito para realizar
un conjunto específico de acciones. Cada conjunto de acciones que codifica un comportamiento
diferente, por ejemplo, "jugar con la cuerda", "comer pescado", o "caca en la alfombra." Sin un
cartucho de relleno dentro de su vientre el gatito es una escultura metálica inanimados, sólo es
capaz de estar sentado allí con una mirada linda (esto esta pareciendo algo muy cursi...)... en
fin es una especie de Metal Mickey el cual sin los cartuchos no se si serviria como pisa papeles.
El gatito es muy hábil y tiene la capacidad para intercambiar de manera autónoma su
cartucho por otro si así se le ordena. Al proporcionar las normas que dictan cuando un cartucho
debe ser cambiado, es posible encadenar secuencias de inserciones de cartucho que permite la
creación de todo tipo de comportamiento interesante y complicado. Estas normas están
programados en un pequeño chip situado en el interior del gatito cabeza, que es análoga a la
mesa de transición de estado que hemos debatido antes. El chip se comunica con las funciones
internas del gatito para recuperar la información necesaria para procesar las reglas (por
ejemplo, cómo 'hambre Kitty' o de la manera lúdica que se siente).
Como resultado, el chip de transición de estados se puede programar con reglas como la
siguiente por ejemplo:
IF Kitty_Hungry AND NOT Kitty_Playful
SWITCH_CARTRIDGE eat_fish
Todas las reglas en el cuadro se analizan cada paso de tiempo y las instrucciones se
envían a Kitty para cambiar los cartuchos en consecuencia. Bueno creo que con esto queda
entendida la Idea (la forma en la que trabajara la IA). Ahora prosigamos. Este tipo de
arquitectura es muy flexible, lo que facilita la expansión del repertorio del gatito mediante la
adición de nuevos cartuchos. Cada vez que un cartucho nuevo, se añade, el propietario sólo
está obligado a tener un destornillador a la cabeza del gatito con el fin de quitar y volver a
programar la transición de las regla de estados del chip. No es necesario interferir con cualquier
otro circuito interno.
Reglas incrustadas
Un enfoque alternativo es incorporar las normas de las transiciones de estado dentro de
los propios estados. Aplicando este concepto a Robo-Kitty, el chip de transición de estados se
puede prescindir de las normas y se trasladó directamente a los cartuchos. Por ejemplo, el
cartucho de "jugar con cadena" puede controlar el nivel del gatito de hambre y le instruimos
para cambiar los cartuchos para que los peces se "comen" el cartucho cuando se detecta un
aumento del hambre. A su vez el cartucho 'comer peces' puede supervisar el intestino del gatito
e instruirle para cambiar al cartucho hacer sus necesidades (caca en la alfombra) cuando sea
9
10. Curso de Programacion de Juegos 2D – Modulo II
Por: Ricardo D. Quiroga -> L2Radamanthys – l2radamanthys@gmail.com
detectado un nivel de desechos en sus intestino peligrosamente alto.
Este enfoque implica que aunque cada cartucho puede ser consciente de la existencia de
de los otros cartuchos, cada cartucho es considerado una unidad autónoma y no dependiente
de una lógica externa para decidir si debe o no permitirse ser canjeado por una alternativa.
Como consecuencia de ello, es un asunto sencillo para agregar estados o incluso para cambiar
el conjunto de cartuchos por un conjunto completamente nuevo (tal vez el nuevo kit que hace
que Kitty se comporta como un ave de rapiña o la version Kitty Hidraulico, que trae el cartucho
'cambiar rueda del auto' :P). No hay necesidad de tener un destornillador para el modificar el
chip de la cabeza del gatito, sólo hacen falta los propios cartuchos.
Echemos un vistazo a cómo este enfoque se aplica en el contexto de un videojuego. Al
igual que los cartuchos de Kitty, los estados están encapsulados como objetos y contienen la
lógica necesaria para facilitar las transiciones de estado. Además, todos los objetos del tipo
Estado comparten una interfaz común: una clase Estado. Aquí hay una versión que proporciona
una interfaz sencilla pero completa:
class Estado:
def init(self, sprite):
pass
def execute(self, sprite):
pass
def exit(self, sprite):
pass
Tenemos la clase base para definir los estados, la cual cuenta con tres métodos init(),
execute() y exit().
Init() es lanzado cuando el personaje canbia a ese estado, execute() es el método que
se llamara durante una ejecución normar y exit será llamado cuando el personaje avandone
dicho estado. No todos los estados tendran que tener necesariamente implementados los 3
metodos para la mayoria de ellos bastara con implementar solamente el metodo execute().
Para aclarar un poco la idea del uso de esta ide veamos un sencillo ejemplo:
Ahora imagine una clase de Troll que tiene variables miembro de atributos tales como la
salud, ira, resistencia, etc, y una interfaz que permita a un cliente consultar y ajustar esos
valores. Un troll puede tener la funcionalidad de una máquina de estados finitos mediante la
adición de un puntero a una instancia de un objeto derivado de la clase del Estado, y un
10
11. Curso de Programacion de Juegos 2D – Modulo II
Por: Ricardo D. Quiroga -> L2Radamanthys – l2radamanthys@gmail.com
método que permita a un cliente para cambiar la instancia es el puntero señalando.
class Troll:
#atributos omitidos
def cambia_estado(self, nuevo_estado):
self.estado_actual.exit(self)
self.estado_actual = nuevo_estado
self.estado_actual.init(self)
def update(self):
self.estado_actual.execute(self)
Cuando el método Update de un troll es llamada, a su vez llama al método Execute del
tipo de estado actual con el puntero self. El estado actual podrán utilizar la interfaz de Troll
para consultar su propietario, para ajustar los atributos de su propietario o para realizar una
transición de estado. En otras palabras, ¿cómo se comporta un Troll cuando se actualicen se
puedan hacer totalmente dependiente de la lógica en su estado actual. Esto se ilustra mejor
con un ejemplo, así que vamos a crear un par de estados para permitir que un troll de huir de
los enemigos cuando se siente amenazado y dormir cuando se siente seguro.
class EstadoHuir(Estado):
def execute(self, troll):
if troll.esta_seguro():
troll.cambiar_estado(EstadoDormir())
else:
troll.alejarse_del_enemigo()
class EstadoDormir(Estado):
def init(self, troll):
troll.echarse_una_siesta()
def execute(self, troll):
if not(troll.esta_seguro()):
troll.cambiar_estado(EstadoHuir())
else:
troll.despertar()
Nota: Aquí el mostrar la implementacion de los metodos porpios del troll no es la idea, sino el
principal objectivo fue mostrar la simplicidad con la cual trabaja esta arquitetura, y ademas
evitar posibles confuciones que podrian succeder al mostrar todo el codigo.
11
12. Curso de Programacion de Juegos 2D – Modulo II
Por: Ricardo D. Quiroga -> L2Radamanthys – l2radamanthys@gmail.com
Esta arquitectura se conoce como el patrón de diseño del estado y proporciona una
manera elegante de la aplicación de un comportamiento impulsado por los Estados. Aunque se
trata de una salida de la formalización matemática de un FSM(Maquina de Estados Finita), el
codigo aquí mostrado es intuitivo, fácil de códificar, y fácilmente extensible. También hace que
sea extremadamente fácil el agregar acciones para cada estado.
El único problema que se le podría encontrar a esta arquitectura es que utiliza un
acoplamiento Fuerte ya que se pasan estructuras de datos completas (referencias a objectos) y
no solamente valores atomicos, pero esto es cuanto al enfoque de la metodologia Orientada a
Objectos, pero esto es solo un cartel que dice 'Tener Cuidado si no manejas bien el concepto
de POO'.
Estados globales y Estados BLIPS
Con mucha frecuencia, la hora de diseñar máquinas de estado finito puede acabar con el
código que se repite en todos los estados. Por ejemplo, en el popular juego de Los Sims de
Maxis, un Sim puede sentir el impulso de la naturaleza vendrá sobre ella y tienen que ir al baño
para librarse. Este impulso puede ocurrir en cualquier estado del Sim puede ser y en cualquier
momento. Teniendo en cuenta el diseño actual, para otorgar el minero de oro con este tipo de
comportamiento, duplicar la lógica condicional habría que añadir a cada uno de sus estados, o,
alternativamente, colocado en el Miner:: La función de actualización. Aunque esta última
solución es aceptable, es mejor crear un estado global que se llama cada vez que se actualizó
la FSM. De esta manera, toda la lógica para el FSM se encuentra dentro de los estados y no en
la clase de agente que posee el FSM.
Además de comportamiento global, en ocasiones será conveniente que un agente para
entrar en un estado con la condición de que cuando el estado se sale, que el agente regrese a
su estado anterior. Yo llamo a esto el comportamiento de un blip estado. Por ejemplo, como en
Los Sims, usted puede insistir en que su agente puede ir al baño en cualquier momento, sin
embargo, asegúrese de que siempre vuelve a su estado anterior. Para dar un FSM este tipo de
funcionalidad que debe llevar un registro del estado anterior de modo que el bache Estado
puede volver a él.
Esto se puede lograr fácilmente agregando 2 variables adicionales una para el estado
global y otra para el estado Anterior, mas abajo puede ver el código de una maquina de
estados completa.
Creación de una máquina de Estados
El diseño se puede hacer mucho más limpio al encapsular todos los datos de estado y
12
13. Curso de Programacion de Juegos 2D – Modulo II
Por: Ricardo D. Quiroga -> L2Radamanthys – l2radamanthys@gmail.com
métodos en una clase de máquina de estados. De esta manera un agente puede ser dueño de
una instancia de una máquina de estados y delegar la gestión de los actuales estados, los
estados globales, y los estados anteriores a él.
class MaquinadeEstados:
def __init__(self):
#referencia al agente (Personaje) que posee la instancia actual
#de la maquina
self.agente = None
self.estado_actual = None #estado actual en ejecucion
self.estado_anterior = None #almacena un estado anterior
#esta logica se llama cada vez que la logica se actualiza
self.estado_global = None
def set_estado_actual(self, estado):
self.estado_actual = estado
def set_estado_amterior(self, estado):
self.estado_anterior = estado
def set_estado_global(self, estado):
self.estado_global = estado
def update(self):
#si hay un estado global lo ejecuto
if self.estado_global:
self.estado_global.execute(self.agente)
if self.estado_actual:
self.estado_actual.execute(self.agente)
def cambia_estado(self, nuevo_estado):
self.estado_anterior = self.estado_actual
self.estado_actual.exit(self)
self.estado_actual = nuevo_estado
self.estado_actual.init(self)
def volver_al_estado_anterior(self):
self.cambia_estado(self.estado_anterior)
13
14. Curso de Programacion de Juegos 2D – Modulo II
Por: Ricardo D. Quiroga -> L2Radamanthys – l2radamanthys@gmail.com
Comentarios Finales sobre el Tema
Supongo que sabran muy bien que esto es solo la punta del isber, pero al menos con
esto creo que tienen suficiente como para empezar, he dejado a su disposición una sencilla
pero potente herramienta que les permitirá construir IA para los Juegos que programen de aquí
en adelante ahora bien, este capitulo no contemplo el desarrollo de modelos de IA mas
sencillos, pero a mi parecer no tenia sentido explicar cosas que aparte de ser tan simples, se
pueden encontrar en casi cualquier tutorial basico, que ande dando vueltas y que solo pueden
ser aplicadas a un numero finitos de juegos (en su mayoria es la IA que veran en los primero
juegos de tipo Arcade)… O acaso me equiboco y por ejemplo ubiesen preferido que por ejemplo
gastase 2 hojas explicando como funcionaba la IA de los personajes del primer MarioBros…
bueno resumo la IA de ese juego: “si choca con un elemento del juego invertir
direcion...” ven lo simple que es (si no lo notan es mas o menos el mismo comportamiento
que tiene la pelota en un Pong) y pensar que un momento estuve dudando si agregar o no
dicho ejemplo.. :P.
Por ultimo... se me olvido decirlo pero las IA puramente de tipo aleatoria no suelen dar
un buen aspecto al juego (volviendo al tema planteado casi a principio de este capitulo se dice
que tiende a tener un comportamiento irracional) y son una muy mala idea (en cuestiones tales
que haran que el juego se vuelva aburrido, ya que a nivel de codificacion tirar un randon para
cada acion es super sencillo) a la hora de implementarla. Esto para nada quiere decir que este
mal usar un poco de aleatoriedad en algunas parte de las IA, por ejemplo se me ocurre un caso
sencillo, suponer que el bot tiene que elegir entre ir hacia la derecha o la izquierda y a nosotros
por cosas de la vida se nos ocurre que el bot tendra mas tendencia de ir hacia un determinado
lado (le definimos algo de personalidad), mediante una sencilla aplicación de probabilidad,
tiramos un nro al azar entre 0 y 1 si el valor es menor igual que 0,7 el bot se dirigira hacia la
derecha caso contrario ira hacia la izquierda.
14