Sistema de opciones generales

Ha pasado bastante tiempo desde el último post en el blog, pero eso no significa que no haya trabajado algo a lo largo de este tiempo. Bueno vale, he trabajado poco, pero lo suficiente como para haber mantenido el proyecto en una vía lenta pero funcional.

En esta “actualización” he añadido un sistema general de opciones al juego. De momento, la única forma de cambiar las opciones del juego es por medio de un fichero de texto plano llamado auto.config, en el que se recogen varias líneas con su valor al lado. Un ejemplo del fichero puede ser el siguiente:

pelota_color fa0ba6
pelota_alto 15
pad_alto 100
pad_ancho 15

Primero, el programa carga por defecto las opciones del programa. Luego, comprueba dicho fichero y carga las opciones introducidas. De esta forma, si no se reconoce una opción o si no se incluyen todas las opciones en el fichero, el programa no cargará “basura” en cualquier variable.

Otro detalle interesante ha sido pasar de un campo de Pong hecho a partir de una imagen a un tablero generado por el programa, con lo que incluimos las 2 opciones siguientes:

pantalla_ancho 1200
pantalla_alto 660

La forma de construir el tablero se puede apreciar bastante bien en la siguiente imagen:

proporciones

Por último, para el caso multijugador, he añadido un sistema de datos que guarda las opciones imprescindibles para “sincronizar” las opciones del cliente y el servidor, con lo que ambos juegan con el mismo tamaño del tablero. Una cuestión interesante sería poder escalar los elementos del juego para jugar a distintas resoluciones, pero de momento lo dejaré como una ventana modificable para dar más libertad a la hora de cambiar las opciones de la misma.

Intentaré subir esta tarde un vídeo mostrando el funcionamiento de todos estos detalles mencionados. Aquí un vídeo que muestra el funcionamiento de todo lo mencionado anteriormente:

 

Un saludo.

Publicado en Uncategorized | Deja un comentario

Encapsulado de instancias.

Después de unas maravillosas vacaciones de navidad en Asturias y una larga secuencia de no-tan-difíciles exámenes de enero, tenemos tiempo para seguir con este proyecto. Antes de empezar con cosas nuevas, hemos querido re-estructurar el proyecto para que quedase como un verdadero software orientado a objectos (usando el concepto de clases y objetos hasta el punto en el que lo conocemos). Para ello, hemos encapsulado diversas funciones “main_#modo_de_juego#” en clases “CInstance_#modo_de_juego#”. Dicha clase maneja de forma ordenada la ejecución de la mismísima estancia. Dicho esto, todas las estancias son gestionadas bajo la interfaz de una clase llamada “CEngine”. Su función principal es ejecutar única y exclusivamente una cada vez, con lo cual no será necesario cargar fuentes o imágenes que no van a ser usadas ni por estancias lejanas ni anteriores (no se genera recursividad).

 

engine

 

Lo próximo imagino que será mejorar algunos modos de juegos y meternos de lleno con el modo “1Jugador Aventura”.

Publicado en Uncategorized | 1 Comentario

Sistema de jugo online

Habiendo mejorado algunos aspectos, el modo de juego online parece bastante funcional y estable (siendo bastante generosos, claro). Falta por añadir algunos detalles, como asegurar la conexión entrante y asegurar que no se produzcan fallos drásticos en medio de la partida (como aceptar conexiones de desconocidos o cosas así). Pero bueno, centrándonos en el tema, voy a explicar como hemos realizado esta hercúlea tarea:

Nos hemos centrado en un sistema muy simple de juego. Un jugador hace de servidor o “host” y otro de cliente.  El bucle de ejecución del cliente es el siguiente:

  • Conectar a servidor
  • Empezar bucle
    • Gestionar eventos (teclado).
    • Enviar datos al servidor.
    • Recibir datos procesados del servidor.
    • Gestionar datos recibidos.
    • Mostrar objetos por pantalla.
  • Repetir hasta cerrar aplicación.

Y el bucle de ejecución del servidor es el siguiente:

  • Esperar al cliente
  • Empezar bucle
    • Gestionar eventos (teclado).
    • Recibir datos del cliente.
    • Procesar datos.
    • Enviar datos procesados al cliente.
    • Mostrar objetos por pantalla.
  • Repetir hasta cerrar aplicación.

Visto de una manera más sencilla, el usuario lo único que manda al servidor es un byte diciéndole si se está moviendo hacia arriba (1), hacia abajo (-1) o si no se está moviendo (0) (en este último caso, no se envía y se da por sentado que no hay movimiento). El servidor, recibe este dato, calcula la posición del pad del cliente, la posición del propio pad del servidor y la posición de la pelota, y por último, envía todos estos datos al cliente, además de las puntuaciones del marcador y una serie de flags (sonidos, etc…). Con lo cual, toda la gestión se realiza en el servidor, evitando cualquier trampa desde el cliente remoto, que recibe datos a ciegas y los coloca sobre pantalla. La pega es que el servidor tiene un control total sobre esos datos, que podrían ser modificados en casos de cambiar valores en memoria (complicado, pero no imposible).

Para finalizar, también hemos añadido un pequeño sistema para reconocer si la conexión se ha interrumpido. Aquí un pequeño vídeo con 2 partes: una primera mostrando una partida online (entre 2 ordenadores a través de internet) y otra con 2 procesos en un mismo pc.

Publicado en Uncategorized | Deja un comentario

Sistema online

Después de rompernos la cabeza con los protocolos online y demás (dios maldiga los protocolos TCP y UDP), hemos conseguido hacer funcionar un sistema cliente-cliente en el que uno hace de host. De momento, no voy a explicar nada ni a subir vídeos, ya que está bastante verde (no tiene interfaz ni nada por el estilo). Cuando pase navidad, acabaré lo empezado y subiré un vídeo.

Hasta entonces, ¡Feliz Navidad!

Publicado en Uncategorized | Deja un comentario

Menú de navegación

Aprovechando que tenemos 2 modos de juego muy básicos, me he tomado la molestia de programar un pequeño y simple menú para movernos por el juego de manera fácil y visual. Básicamente, el menú lo único que hace es redirigir funciones dada la elección del menú (en este caso, el menú consta de una función por estancia o submenú). Por ejemplo, si tenemos 1 menú que redirige a 1 submenú (multijugador), y a su vez ese submenú puede dirigirnos a 2 modos de juego (local y local CPU), tendremos un total de 1+1+2 = 4 funciones que representan la estancia de esos 2 modos de juego. Dicho de otra forma, cada “pantalla” cargada es una función. La forma en la que se muestra por pantalla es bastante cutre. Ya añadire cosas como alpha blending o algo por el estilo, para darle más vida. De momento, usaré esto para navegar por los distintos modos sin tener que cambiar cada 2×3 la función principal en función de que modo quiero probar.

Saludos.

Minientrada | Publicado el por | Deja un comentario

IAI (Inteligencia Artificial Invencible)

Bueno, después de una buena semana devanándome los sesos, he conseguido hacer que la pequeña inteligencia artificial funcione. Tanto tiempo perdido por fallos ridículos (usar una variable que no es, un símbolo que no pega, algo invertido, etc…) para lograr el pequeño (pero invencible) oponente automatizado. El procedimiento que hace el proceso para saber dónde mover el pad es el siguiente:

  1. Primero, coge la posición actual de la pelota, junto con una posición futura (2 puntos) (con las componentes de la velocidad y el punto actual se consigue) y hallamos la función de la recta.
  2. Una vez tengamos la ecuación de la recta, hallamos en que punto del eje vertical impactará la pelota una vez que haya llegado al rango del pad.
  3. En el caso de los rebotes, basta con ir reflejando el punto de impacto (por ejemplo, si el mínimo es 0 y el máximo es 400, si el hipotético punto de impacto fuese -500 en el eje y, al rebotar se reflejaría en un valor menor que 400 (tal vez menor que 0), y se repetiría este proceso hasta que quede en el rango [0,400] ).
  4. Para variar la dificultad, se puede (y lo haremos) implementar un pequeño sistema de tiempo de respuesta para que la máquina no calcule de forma instantánea el lugar dónde impactará.

Un ejemplo de traza es la siguiente:

Image

Además, me he tomado la molesta de grabar un pequeño vídeo. La máquina juega con el pad de la derecha (el lado “Pro”), mientras que yo juego con el lado izquierdo (heh):

Tal como está diseñada, es imposible vencerla. Habrá que añadir los sistemas de dificultad antes mencionados, además de intentar mover el pad justo antes de darle a la pelota para darle “efecto”.

Saludos.

Publicado en Uncategorized | Deja un comentario

Sistema básico de juego.

Tras una semana de trabajo, hemos conseguido desarrollar un pequeño sistema para probar el funcionamiento del modo del juego “1 contra 1”. Básicamente, es un bucle que, en función de eventos de entrada de teclado y tiempo, calcula las posiciones de los pads laterales, la pelota y el marcador. El diagrama de flujo del programa viene a ser lo siguiente:

  • Inicio
  • Cargar archivos  e inicialización de módulos
  • Iniciar bucle de ejecución: Mientras no se cierre la ventana…
    • Procesar eventos de teclado.
    • Calcular posiciones de ambos Pads.
    • Calcular posición de la pelota.
    • Comprobar resultados de juego (aún en juego, gana J1, gana J2).
    • Mostrar por pantalla los elementos necesarios (fondo, pads, pelota, marcador…).
    • Esperar ajuste de frames por segundo.
  • Fin

El modelo básico del sistema de juego se ajusta a eso, independientemente de las llamadas a las funciones del sistema o de la librería SDL. Además, tras una buena tarde divagando, logramos un sistema de colisiones y cálculo de “rebotes” bastante logrado.

Voy a tratar de explicarlo:

  1. Colisiones:
    El sistema de colisiones es muy sencillo. Basta con comparar los lados de 2 rectángulos para ver si se “atraviesan”. Como es un proceso algo largo (puesto que hay que comprobar cada rectángulo con sus correspondientes lados con otros rectángulos), nos hemos basado en un sistema de posicionamiento de la siguiente estructura por franjas (verticales):
    [ZONA MUERTA] [PAD] [CAMPO DE JUEGO] [PAD] [ZONA MUERTA]
    En cuanto se llega a una zona de “Pad”, se comprueba si la pelota está en el rango que debe estar. Si falla algo, la pelota pasa a la zona muerta, en la que avanza hasta los márgenes de la pantalla hasta pararse. Mientras la pelota esté en la zona “Campo de juego”, sólo se verificará las colisiones contra los márgenes superior e inferior, ya que no es necesario hacerlo para los pads.
  2. Velocidades:
    Para lograr cambios de velocidad y ángulos realistas, hemos tratado simplemente con vectores de velocidad (sólo para la pelota). Es decir, la pelota tiene 2 componentes (Vx, Vy) que varían en función de una serie de parámetros, y 1 módulo de velocidad para mantener las proporciones entra ambas componentes. Lo hemos realizado así dado que es más fácil trabajar con componentes que con ángulos.
  3. Rebotes:
    Los rebotes contra los márgenes superiores consisten en invertir la velocidad del eje Y, formando un ángulo de 90 grados.
    Este es el sistema más “complejo” que hemos encontrado. Se trata de desviar la pelota un ángulo proporcional a la separación con respecto al centro del pad contra el que choca. Dicho de otra forma, cuánto más a los bordes del pad toque la pelota, más se desvía ésta. Además, para un mayor realismo, si el pad se está moviendo éste añade “momento” a la pelota, con lo cual la desviación es aún mayor. El esquema es el siguiente:Así, se consigue un movimiento de la pelota más realista y se consigue que no describa un “patrón” a la hora de moverse.

A lo largo del fin de semana trataré de subir una pequeña “demo” para que se aprecie en tiempo real.
Aquí pongo un pequeño vídeo mostrando el funcionamiento. Espero que se aprecie:

Saludos.

Publicado en Uncategorized | 2 comentarios