Kotoran’s Shadow / Kronoscide

Logo Kronoscide Pantalla Menú Pantalla Partida en juego Pantalla Ganar
Kotoran’s Shadow

Descargar Juego Descargar Código Fuente

El juego

El objetivo del juego es conseguir entrar al castillo para encontrar la corona de Kotoran. Para ello deberás activar varios interruptores/palancas para ir abriendo las puertas que te impiden el acceso a las diferentes zonas. A lo largo de tu recorrido, te encontrarás con espectros que te perseguirán y trampas colocadas en los caminos, las cuales te lanzarán proyectiles. Por cada impacto de un enemigo, o proyectil, se te restará una gota de sangre, evita que te alcancen para no perderlas todas y morir. Por otro lado, tú también podrás atacar con un disparo a los espectros y recuperar sangre comiéndote los solomillos que encuentres. Una vez alcances la corona, habrás finalizado el juego y logrado tu objetivo.

Historia

Nuestro protagonista, Kedi, se encuentra en un convoy de carromatos que viaja por todo el país ofreciendo espectáculos, un pequeño mercado y demás actividades lúdicas por todos los pueblos por los que pasa.

Un día, llegan a la región de Fur, una región un tanto pequeña en la que podemos encontrar una aldea donde viven un reducido número de habitantes, un bosque infestado de bestias con las que hay que lidiar si se quiere atravesar, y un gran castillo perteneciente a un rey muy antiguo que pereció hace ya dos siglos en condiciones muy extrañas: el rey Kotoran.

Una vez llegan a dicha región, Kedi, un joven aventurero adicto a la acción y a meterse en líos, se entera por medio de los aldeanos del lugar que el rey Kotoran no sólo dejó trampas y acertijos dentro del castillo, sino que dejó un valioso tesoro dentro de él, el cual nadie ha podido obtener aún pues no mucha gente ha logrado salir vivo del castillo una vez dentro.

Kedi, haciendo caso omiso de las advertencias de los aldeanos, se encapricha con el tesoro que hay dentro del castillo y decide ir a por él, enfrentándose a todo lo que se le ponga por en medio. ¿Lo conseguirá?

Características principales

  • Explora 3 zonas diferentes en busca de misterios.
  • Combate contra los espectros.
  • Activa los interruptores necesarios para seguir avanzando.
  • Consigue jamones para recuperar tu vida.
  • Esquiva las trampas que te puedan perjudicar.
  • Consigue la corona que salve al reino de Fur…

Memoria de desarrollo

Idea

Trabajando en el juego

Trabajando en el juego

Al principio tuvimos diferentes opiniones respecto al tipo de juego que queríamos hacer, dado que era nuestra primera toma de contacto con un Amstrad CPC. Teníamos claro que queríamos un juego con perspectiva cenital, y discutimos la posibilidad de hacer un juego totalmente combativo y de supervivencia, donde el protagonista permanecería en un solo escenario a la espera de enemigos que aparecerían por rondas.

Fran, nuestro profesor, nos recomendó realizarlo lo más parecido posible a la idea que teníamos para el juego de nuestro proyecto ABP. Al final decidimos hacer un juego más dado a la exploración y con diversas pantallas para recorrer, enemigos a los que enfrentarte o evitar y desbloqueando puertas para llegar a tu objetivo.

Investigación

Para hacernos una idea del aspecto que tiene el código de los juegos en Amstrad, descargamos el código fuente de algunos juegos que se presentaron en el concurso del año pasado. Rápidamente nos dimos cuenta de que programando en C dispondríamos de unos gráficos mejores, por lo tanto elegimos ese lenguaje.

Implementación de librerías y herramientas

Para empezar a programar en C, tratamos de configurar el cpc-dev-tool-chain, sin embargo no pudimos hacerlo hasta que el profesor subió un video tutorial explicativo a Youtube. Tras ello, ya estábamos en condiciones de empezar.

Arquitectura del juego

Para empezar hemos creado una variable Ticks que nos permite controlar el tiempo que va pasando en el juego, un simple número entero que se incrementa en cada iteración. Lo siguiente ha sido crear diferentes archivos para cada estado (Menú, Juego, Intro, etc.) para separar el código y organizarlo mejor. Hecho esto, mediante un Switch en el bucle del juego ejecutamos un estado u otro. Cada estado tiene una función para inicializarlo (Init), otro para actualizar el juego (Update) y otro para dibujar todo lo que no sea estático (Render).

Implementación del movimiento del jugador

La parte de comprobar las teclas que se van pulsando fue fácil gracias a Cpcrslib, sin embargo nos enfrentábamos al problema de que el movimiento en vertical no se incrementa igual que el horizontal. Para subsanarlo decidimos hacer el incremento en el eje X con menos frecuencia que el eje Y. Utilizando la operación módulo con la variable de Ticks (ciclos del bucle que lleva el juego) podíamos controlar eso, cada 8 ciclos en el eje X (Ticks & 7) y cada 2 ciclos en el eje Y (Ticks & 1). Para controlar la animación del personaje al moverse, usamos una estrategia similar, cada X ciclos cambiábamos entre un frame u otro.

Escenarios y colisiones

El dibujado del escenario se realiza a partir de una matriz de caracteres, donde cada número corresponde a un tile. Mediante un doble bucle dibujamos 1 a 1 cada tile.

Las colisiones con el escenario se gestionan comprobando que tipo de tile hay en la posición hacia la que te diriges. Hacemos 2 comprobaciones una desde cada esquina del bounding box del personaje del lado hacia donde te vas a mover.

Colisiones entre sprites

Esta colisión es similar a la anterior con respecto a que comprueba la siguiente posición hacia la que te vas a mover. Pero en este caso hay que comprobarlo con todos los sprites que se mueven, ya sea enemigos o disparos. La función que comprueba la colisión comprueba si 2 rectángulos intersectan.

Sonido

Para el sonido hemos usado la librería “cpcwyzlib” y el programa WYZTracker (creado por Augusto Ruiz). Ambos recursos los hemos encontrado en la referencia oficial de la librería cpcrslib en el apartado de sonidos. Cabe destacar que la versión en español de esta referencia está obsoleta, por lo que se recomienda consultarla en inglés. El programa es un tracker que nos permite crear nuestras propias composiciones e instrumentos, además de crear efectos. No permite exportar el código para añadirlo a nuestro juego. Luego usamos las funciones de la librería para reproducir la música y los efectos en el juego.

Además, se ha utilizado el programa AY Sound FX Editor para crear los efectos desde 0 y utilizar sus parámetros a la hora de meterlos en el videojuego.

Gráficos y animación del personaje

Al principio no sabíamos como implementar los gráficos, y preguntamos a nuestro profesor sobre la existencia de algún programa para exportar el código de los mismos, RGAS(Retro Game Asset Studio), aunque también experimentamos con ConvImgCPC. Todos los gráficos del juego se han creado usando RGAS, el cual te permite elegir el tipo de paleta, el modo de color y a que lenguaje quieres exportar tu trabajo. Al principio resultó complicado de manejarlo, dado que no tienen ningún manual y hay herramientas ocultas, como el bote de pintura (rueda del ratón) y la creación de líneas y círculos (ctrl y shift). Todos los elementos interactivos del juego tienen una dimensión de 16×16, incluso las casas que están formadas por 4 o 6 diles de 16×16.

Disparo

Trabajando en el juego

Trabajando en el juego

A la hora de implementar el disparo para el personaje, se ha añadido el botón espacio para activar la actividad de disparar el cual, una vez se pulsa, se crea un sprite delante de la posición donde esté mirando el personaje y, con una velocidad constante, se lanza este sprite en la dirección definida. Solo puede realizar un disparo a la vez, por lo que si el personaje ha disparado y la bala no se ha borrado, no podrá disparar. Por otro lado, también hay un lapso de tiempo entre un disparo y otro, por lo que si se ha disparado y la bala choca antes de que este lapso pase, no se podrá disparar hasta que pase.

Si este sprite choca contra algo solido, este desaparece desencadenando dos acciones diferentes según contra qué choque. Si choca contra la pared, una puerta, un botón o el cañón, simplemente borramos el sprite de la bala y recargamos la variable de ataque del personaje.

Por otro lado, si el sprite choca contra un enemigo, además de eliminarse el sprite de la bala y recargar la variable de ataque del personaje, esta colisión restará una vida al enemigo. En caso de que el enemigo se quede sin vidas, también se eliminará su visualización.

Enemigos e IA

La inteligencia artificial se basa en una maquina de estados finita, por la cual el enemigo siempre está en un único estado, que tendrá un comportamiento predeterminado.

Además, el enemigo tiene una serie de atributos con un valor variable que se genera aleatoriamente cada vez que se crea el enemigo (cuando se entra en una pantalla).

Estos atributos son:

  • Valor: Afecta a si el enemigo huirá o atacara cuando vea al protagonista, su rango es entre 0 y 7. También afecta a otras cosas, como decidir si ir a un sonido que haya oído.
  • Ido: Afecta a la capacidad de oír sonidos, su valor es entre 0 y 7.
  • Vida: son los golpes que necesita el enemigo para morir, su rango es entre los valores 1 y 4.

En cuanto a los diferentes estados que puede tener el enemigo, son:

  • Patrullar: Se mueve aleatoriamente entre un rango determinado, sin poder salir de él. Este es el estado en el que empiezan los enemigos por defecto.
  • Atacar: Se mueve hacia el protagonista. Cuando lo toca le hace daño y desaparece el enemigo.
  • Huir: Se mueve en dirección opuesta a la del protagonista, si choca contra un obstáculo cambia de dirección.
  • Ir al disparo: se mueve hacia la posición donde oyó disparar al protagonista. Cuando llega a la posición cambia al estado buscar o al estado regresar en función de su valor.
  • Regresar: Regresa a su posición inicial, cuando llega pasa al estado patrullar.
  • Buscar: se mueve aleatoriamente por el mapa.

Además de los estados, también tiene una serie de acciones que pueden cambiar el estado en el que se encuentra el enemigo:

  • Ver: Si el protagonista está en la misma fila o columna que el enemigo, y no hay obstáculos en medio, el enemigo le verá, y cambiara su estado a atacar o a huir en función de su valor. Esta acción se realiza en todos los estados menos en atacar y en huir.
  • Oír: Si el protagonista dispara, se comprobara si está en el rango de escucha del enemigo, si lo está, se comprobara si este le consigue oír en función de su atributo oír, y por último, si lo oye, decidirá si va a buscarlo o no en función de su atributo valor. Si lo hace, pasara al estado Ir al disparo.

También cuenta con un algoritmo de pathfinding para moverse por el mapa, al ser este un poco laberíntico. El algoritmo de pathfinding consiste en que si colisiona contra una pared, comprobara hacia qué lado tiene que moverse por la pared en función de si tiene salida o no, para ello usa el mapa del nivel, para comprobar, por ejemplo, si al moverse hacia la derecha choca contra una pared, y el protagonista está encima de él, comprobara si en la pared, por encima de él tiene una salida, en caso de ser así, se moverá hacia arriba, si no, comprobara si por la parte de abajo de la pared tiene salida, y si la tiene, se moverá hacia abajo.

Por último, si el enemigo se queda atascado en una zona (no se mueve), pasara automáticamente al estado buscar.

Cambio de escenarios

Para hacer el cambio de escenarios se utilizó un Struct y así guardar para cada mapa las transiciones entre los mismos. Ese struct tiene 4 componentes equivalentes a las 4 direcciones que se pueden escoger en el mapa, cada una de ellas guarda el mapa al que se debe de ir cuando el jugador va a sobrepasar el mapa. Si no hay ningún mapa al que ir la componente tendrá valor -1 y el personaje no se movería en esa dirección.

Cargar las imágenes de fondo

Aprovechamos la función UnExo de cpcrslib para poder cargar las imágenes de transición entre los estados. En este punto tuvimos problemas para que el color que se mostrase fuese el mismo que el que se había diseñado. Para ajustar el problema se tuvo que crear varias paletas distintas, una por cada uno de las imágenes y tuvimos que ir cambiando entre ellas cada vez que queríamos dibujar esa imagen.

Ficha Técnica

Lenguaje utilizado: C
Tamaño en Kbytes: .dsk: 200KB, .dct: 44KB
Modo gráfico: Modo 0
Librerías: cpcrslib, cpcwyzlib
Compilación: Seguimos el método de este tutorial: https://www.youtube.com/watch?v=FvAg-xmWZHM&list=UUSdIAKvPxlB3VlFDCBvI46A

Software utilizado

  • Notepad++
  • Cygwin (32 bits)
  • cpc-dev-tool-chain
  • cpcrslib
  • cpcwyzlib
  • Retro Game Asset Studio
  • ConvImgCPC
  • ManageDSK
  • WyzTracker
  • Cdt2Wav (64 bits)
  • Exomizer
  • AY Sound FX Editor
  • WYZTracker -> Augusto Ruiz de Retroworks

Uso

Para iniciar el juego se debe usar la instrucción run”kotoran.

1 comment on “Kotoran’s Shadow / Kronoscide”

  1. Pingback: ¿Cómo se hace un videojuego? 32- Desarrollo de juegos para Amstrad CPC y PC en la Universidad de Alicante | ¿Cómo se hace un videojuego?

Leave A Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.