Creación de Un Juego de Plataformas 2D en UNITY
Creación de Un Juego de Plataformas 2D en UNITY
Creación de Un Juego de Plataformas 2D en UNITY
2
DEDICATORIA / CITA
3
ABSTRACT
Por un lado un videojuego es que un tipo de producto que aúna múltiples disciplinas
tanto técnicas (programación, BD, mecánicas, física…) como artísticas (diseño, anima-
ción, ilustración…) sin olvidar el apartado de conceptualización, guion, documentación…
apartado audiovisual, etc. Con todos estos procesos necesarios para producir un video-
juego abarco de forma completa la formación recibida en el Grado Multimedia.
Por otro lado la elección de Unity 5.x como herramienta de desarrollo y C# como len-
guaje de programación, es algo que he echado en falta en el temario optativo del Grado
y por tanto no podía desaprovechar la oportunidad para aprenderlos. Pienso que cono-
cer Unity me puede ser muy útil a nivel profesional por su potencia y versatilidad para
crear proyectos multiplataforma.
Para finalizar debo aclarar los objetivos finales propuestos; dado que el tiempo de desa-
rrollo del proyecto no es todo extenso que requeriría la producción de un producto final
acabado de cierta calidad, he decidido limitar la ejecución a una demo funcional jugable
con sólo algunos personajes, monstruos, mecánicas y escenarios, sin que esto delimite
la parte inicial creativa de guion y trasfondo, que me permita continuar el desarrollo
una vez concluida la entrega del TFG.
El juego correrá como aplicación sobre Windows y sobre navegador web con plug-in de
Unity y requerirá de teclado para controlarlo. Una versión para dispositivos móviles se
contemplaría como una segunda etapa tras la finalización del proyecto.
4
NOTACIONES
Texto interior destacado: Tipografía Calibri 14pt Bold RGB (27, 102, 143)
Citas: Tipografía Calibri 18pt Italic y entre comillas “” RGB (27, 102, 143)
ejemplo:
using UnityEngine;
using System.Collections;
using System;
using UnityEngine.SceneManagement;
5
AGRADECIMIENTOS
Gracias.
6
INDICE
1. Introducción .......................................................................................................... 8
2. Descripción ............................................................................................................ 9
3. Objectivos............................................................................................................... 10
3.1. Principales ................................................................................................ 10
3.2. Secundarios .............................................................................................. 10
4. Marco teórico/Escenario ....................................................................................... 11
5. Contenidos ............................................................................................................ 12
6. Metodología .......................................................................................................... 13
7. Arquitectura de la aplicación ................................................................................. 14
8. Plataforma de desarrollo ....................................................................................... 16
9. Planificación ........................................................................................................... 17
10. Proceso de trabajo ............................................................................................... 18
11. APIs utilizadas ...................................................................................................... 19
12. Diagramas UML .................................................................................................... 21
13. Prototipos ............................................................................................................ 23
13.1. Lo-Fi ........................................................................................................ 23
13.2. Hi-Fi ........................................................................................................ 28
14. Guiones ................................................................................................................ 36
15. Perfiles de usuario ............................................................................................... 38
16. Usabilidad/UX ...................................................................................................... 40
18. Tests ..................................................................................................................... 41
19. Versiones de la aplicación .................................................................................... 45
23. Bugs ..................................................................................................................... 46
25. Presupuesto ......................................................................................................... 47
26. Análisis de mercado ............................................................................................. 48
27. Márquetin y ventas .............................................................................................. 49
7
INTRODUCCIÓN
Figura 2 - UNRAVEL
8
DESCRIPCIÓN
El proyecto consiste en la creación de un videojuego indie para Windows y que alterna-
tivamente podrá ejecutarse a través del navegador web gracias al plug-in de Unity.
El juego narrará la historia de un pequeño dragón que tendrá que encontrar a sus
otros hermanos ocultos por un escenario donde tendrá que superar trampas y vencer
a enemigos. A medida que rescate a otros dragones estos podrán ser utilizados por el
usuario, reemplazando al personaje principal, para poder superar ciertos puntos, ya que
cada dragon contará con habilidades diferentes.
Figura 3 - Megaman 3
UFOURIA · Nintendo NES (1991)
Figura 4 - UFOURIA
Sagas como Megaman o juegos como Ufouria serán una referencia en cuanto a mecá-
nicas; estos juegos huyen en cierta forma de la linealidad común en los juegos de pla-
taformas y dan al usuario cierta libertad en la toma de decisiones. El primero dispone
de un orden de pantallas no lineal y en el segundo hay libertad de movimiento por el
mundo donde discurre la aventura. Estos mecanismos siempre me han parecido intere-
santes ya que provoca que el usuario deba pensar para tomar las decisiones más ade-
cuadas.
9
OBJETIVOS
Es necesario establecer unos objetivos que sirvan como hoja de ruta de trabajo para la
consecución con éxito del proyecto. Dado que ésta es una aventura nueva, con nuevas
herramientas de desarrollo y procesos que por ahora me son desconocidos, hay que
establecer unos objetivos principales básicos y otros adicionales.
De esta forma se pueden concentrar los esfuerzos en completar las tareas fundamen-
tales y, en caso de disponer de más tiempo, algunas adicionales. Todo en función de las
dificultades que surjan y el tiempo disponible.
PRINCIPALES
· Realización de una demo jugable de un juego de plataformas 2D con Unreal Engine 5.x
· Crear un guion, diseño y programación escalables que permitan la ampliación, mejora
y continuación del proyecto una vez entregado el TFG.
· El producto tendrá una estética y acabado visual agradable.
· Creación, animación e implementación de mecánicas para al menos 1 personaje prin-
cipal y 2 secundarios.
· Creación de un escenario con recursos visuales variado y que permita una duración de
juego de entre 5 y 10 minutos.
· Poner en práctica los conocimientos adquiridos en el Grado Multimedia en las áreas
de producción, diseño y programación.
· Adquirir experiencia y nuevos conocimientos incorporando herramientas como Unity,
lenguajes como C# y procesos mediante el uso de otras herramientas de animación.
SECUNDARIOS
10
MARCO TEÓRICO / ESCENARIO
La industria de los videojuegos ha despertado un creciente interés por los juegos inde-
pendientes sobre todo desde la llegada de internet a la mayoría de hogares, convirtien-
do a las conexiones de banda ancha en el canal ideal para la distribución. La comunidad
indie se concentra entorno a varios portales de distribución como Steam o Xbox live
arcade que actúan como intermediarios entre desarrolladores y usuarios finales. Estas
plataformas concentran un gran catalogo donde se organizan los juegos en función de
su temática posibilitando las búsquedas de juegos similares, filtrados por precio, etc.
Este servicio no está exento de coste para el desarrollador, que ve como de cada venta
una parte se la queda el intermediario. Pese a esto sigue siendo un canal de distribu-
ción más adecuado para el desarrollador indie que el soporte físico. Actualmente estas
plataformas cuentan con miles de títulos disponibles y en aumento.
Este auge de videojuegos indie también ha venido propiciado por un aumento y simpli-
ficación de las herramientas para desarrolladores que simplifica enormemente la tarea
en comparación con épocas pasadas. Por otro lado el aumento de dispositivos móviles
inteligentes, como smartphones y tabletas, capaces de correr juegos ha ampliado el
número de lugares y situaciones donde un usuario puede disfrutar de un videojuego.
11
CONTENIDOS
· Un evento de jefe final donde el jugador se enfrentará contra un enemigo que dispon-
drá de sus propias mecánicas.
12
METODOLOGÍA
Para poder desarrollar este videojuego hay que avanzar en diferentes áreas disciplina-
res.
La primera de ella es la elaboración de la idea principal, lo que podríamos llamar el
GUIÓN de la obra. Aquí se define el título, historia, contexto, hilo argumental, caracte-
rísticas de los escenarios, personajes, monstruos, mecánicas, menús… Es importante
definir todo lo máximo posible para poder planificar las tareas de producción de forma
eficaz.
El software que se utilizará en esta etapa será Mockups para la creación de esquemas
de pantallas y MS Word para el guion.
Una vez definido el proyecto pasamos al desarrollo del mismo que correrá a cargo del
motor de videojuegos multiplataforma Unity versión 5.x. Esta herramienta permite la
creación de juegos en 2D y 3D. En este caso se ha optado por un tipo de proyecto 2D.
El lenguaje de programación elegido será C# por su potencia y uso en el mercado. Con
él, crearemos los scripts que se encargarán de controlar la física, movimiento de objetos
en pantalla, eventos… en definitiva, la programación del videojuego. En la primera fase
se utilizarán gráficos temporales que posteriormente serán substituidos por los defi-
nitivos, aunque esta etapa se superpone con la de diseño a medida que sea necesario
ajustar los diseños a las mecánicas.
El diseño tendrá también diferentes etapas, empezando por bocetos creados “a mano
alzada” hasta su digitalización mediante herramientas como Photoshop e Ilustrator. En
este punto se crearán los gráficos de menús, pantallas y elementos como personajes,
enemigos, etc.
Una vez creados los diseños entramos en fase de animación. Las animaciones en pan-
talla serán producto de la programación y de las animaciones creadas mediante Unity o
aplicaciones como Spine o Spriter. Estas animaciones tendrán que ajustarse a las mecá-
nicas implementadas, como saltos del personaje, estado idle, etc.
Por último la edición de las músicas y efectos de sonido deberán ser tratados y edita-
dos de ser necesario en Adobe Audition o similar.
El desarrollo se irá documentando en esta memoria en el transcurso del avance del pro-
yecto teniendo en cuenta las entregas.
13
ARQUITECTURA DE LA APLICACIÓN
Los siguientes diagramas de flujo muestran:
· El primer diagrama refleja la arquitectura de la aplicación en cuanto a las opciones de navegación que encontrará el usuario.
· Este diagrama muestra la arquitectura narrativa de la demo que se pretende realizar para la entrega final.
14
· Por último, el 3er diagrama muestra la arquitectura narrativa del juego completo, tarea a continuar después de la entrega final.
15
PLATAFORMA DE DESARROLLO
- Capacidad para compilar para diferentes tipos de plataforma. Motor gráfico Direct3D
(Windows), OpenGL (Mac y Linux), OpenGL ES (Android e iOS), WebGL (web).
- Incorpora prácticamente todos los elementos necesarios para el desarrollo: Motor de
físicas para detectar colisiones, animación de sprites, audio, generación de partículas,
construcción de escenarios, programación, etc.
- Lenguaje de programación C#.
- Soporte de Photoshop para la edición de sprites.
16
PLANIFICACIÓN
La planificación se divide en varias etapas: conceptualización, diseño, producción y testeo. Además durante todo el proyecto se
complementa esta memoria.
Aunque las áreas quedan definidas cronológicamente, dado que tanto Unity como C# y las herramientas de animación son desco-
nocidas para mi hay una fase de aprendizaje de estas herramientas que abarca todo el proceso de principio a fin.
En paralelo a la producción iré cumplimentando la memoria periódicamente y no dejando esta tarea para los días finales a cada
entrega.
17
PROCESOS DE TRABAJO
· Conceptualización/Aprendizaje
Es la etapa inicial donde se desarrolla el argumento, personajes, ambientación… del
juego. A través de un proceso de brainstorming se toman y desechan ideas hasta confi-
gurar un puzle atractivo.
En esta etapa se realizan esbozos de escenarios, personajes así como se definen las me-
cánicas a desarrollar posteriormente.
En paralelo se realiza una tarea de recopilación de documentación, avanzamos en el
aprendizaje del lenguaje C# y hacemos una primera toma de contacto con la herramien-
ta Unity.
· Diseño
Una vez tenemos definido como va a ser nuestro juego es el momento de traducir los
esbozos creados de personajes y elementos del escenario a gráficos que serán utiliza-
dos en nuestro juego. Creamos los sprites necesarios a través de Ilustrator y Photoshop.
· Producción
Es la fase principal donde se realiza el ensamblado de los gráficos creados previamente,
se crean las animaciones, efectos de sonido y programación.
· Testeo
Es la etapa final donde hacemos las últimas modificaciones en base a la experiencia que
el juego transmite y gracias al feedback que puedan dar otros usuarios.
18
APIS UTILIZADAS
Estos son algunos de los componentes que UNITY permite que asociemos a los Ga-
meObjects y que he utilizado en el juego:
Los tipos de objetos canvas se utilizan para confección la UI del juego, portrait, vida del
personaje, contador de estrellas y piezas, menús del juego… permiten que a diferentes
resoluciones estos se escalen de forma no proporcional con el juego para permitir que
siempre sean visibles.
19
El componente Rigidbody2D permite dotar de físicas a un GameObject, en el podemos
configurar la masa, gravedad, fijar algún eje de coordenadas, etc. Los objetos con grave-
dad 1 automáticamente caerán al reproducir el juego y por tanto requieren del uso de
Colliders para que colisionen.
Los tipos de objetos canvas se utilizan para confección la UI del juego, portrait, vida del
personaje, contador de estrellas y piezas, menús del juego… permiten que a diferentes
resoluciones estos se escalen de forma no proporcional con el juego para permitir que
siempre sean visibles.
20
DIAGRAMAS UML
21
Diagramas animación personaje ELGAR
22
PROTOTIPOS
LO-FI
Los prototipos de baja fidelidad nos sirven para definir la estructura de navegación y
la ubicación de los distintos elementos en la interfaz. Posteriormente se utilizará para
crear los diseños finales.
23
Algunos prototipos gráficos dibujados a mano alzada del personaje principal; ITH
24
Bocetos de enemigos
25
Resto de personajes (personalidad, expresiones)
26
Bocetos escenario y jefe de nivel 1 (ELGAR)
27
HI-FI VERSIÓN ALPHA
Menú principal
28
29
Personaje principal (ITH)
A partir del boceto realizado a mano alzada trazamos el personaje en Adobe Illustrator.
En Photoshop hacemos los últimos retoques y separamos cada elemento en archivos
PNG con alpha channel. Importamos los elementos en Spriter para realizar la animación
de cada pieza por separado.
30
Animación personaje en Spriter
A partir del boceto realizado a mano alzada trazamos el personaje en Adobe Illustrator.
En Photoshop hacemos los últimos retoques y separamos cada elemento en archivos
PNG con alpha channel. Importamos los elementos en Spriter para realizar la animación
de cada pieza por separado.
Animación IDLE
31
Animación RUN
Animación JUMP
32
Escenario
Composición en Illustrator a partir de elementos vectoriales. Edición en Photoshop y
cortado en 3 bloques que se irán repitiendo a medida que el personaje avance por el
escenario. De esta forma evitamos la carga de una imagen muy grande que cubra todo el
ancho por donde se mueve el personaje.
33
HI-FI VERSIÓN BETA
Menú principal
34
35
GUIONES
MOVIE INTRO
NOTAS
· Los huevos de dragón toman las características del medio donde se hayan incubado lo
que provoca la variación de color, personalidad y habilidades de cada dragón.
· Cuando ITH se encuentra a cada hermano debe derrotarlo para liberarlo del poder que
lo controla, una vez derrotado el personaje pasa a ser elegible por el jugador y podrá
hacer uso de sus habilidades, necesarias para superar ciertas zonas.
· Cada huevo está escondido en diferentes tipos de terreno, con enemigos y escenarios
diferentes.
36
Baby dragons y características:
REGIUS es la palabra que conforman las iniciales de los 6 dragones. Significa “lio” en la-
tín y también es una especie de serpiente Python, que será el monstruo final del juego.
37
PERFILES DE USUARIO
Podemos clasificar a los usuarios que juegan a videojuegos según su género, edad, for-
mación, procedencia y frecuencia de uso o tipo de jugador.
GÉNERO
Tradicionalmente los videojuegos era un medio de ocio más extendido entre el género
masculino que el femenino. En la última década esta tendencia se está igualando.
EDAD
El consumidor medio de videojuegos ronda los 30, los menores de 20 son los mayores
consumidores mientras que a partir de los 50 el porcentaje de usuarios es bajo.
Hay que tener en cuenta el corte generacional, ya que el consumo de videojuegos no
se popularizó de forma domestica hasta los 90 y por tanto es probable que las próximas
generaciones de jugadores incluyan personas de mayor edad si lo comparamos con la
situación actual.
38
TIPO DE JUGADOR
Define el tiempo que dedica al uso de videojuegos y con qué nivel de interés o esfuerzo.
· Novel: jugador con poca o nula experiencia. Requiere procesos de adaptación más
largos.
· Casual: jugador que juega esporádicamente y de forma irregular. Busca mecánicas sen
cillas e historias no demasiado complejas.
· Habitual: Dedica parte de su tiempo de ocio a los videojuegos sin buscar un grado de
perfección elevado.
· Hardcore: Dedica gran parte de su tiempo a los videojuegos. Busca nuevos retos cons
tantemente, mejorar y competir.
· Profesional: Los videojuegos se han convertido en su medio de vida. Buscan la
excelencia y optimización máxima para mantener ese estado.
39
USABILIDAD/UX
Por un lado necesitamos unos controles fáciles de entender, y por eso debemos mini-
mizar el número de botones a utilizar para que así sea más sencillo recordar las diferen-
tes acciones. Una opción es utilizar los controles habituales en este tipo de juegos para
asegurar una toma de control rápida con usuarios habituados a este tipo de juegos.
Por otro lado, los menús deben disponer de elementos visualmente claros y atractivos,
la interfaz debe permitir identificar cada elemento de forma rápida para así acelerar
esta fase de aprendizaje y poder dedicar el mayor tiempo al disfrute del usuario.
Por último, una vez dominada la interfaz y los controles, hay que asegurar que la curva
de dificultad de las mecánicas dentro del juego, sea la adecuada. Es por esto que debe-
mos evitar la sensación de frustración en el usuario en el caso de plantear situaciones
excesivamente complejas sobretodo en la fase inicial de juego. Por el contrario también
debemos evitar que el reto no se vuelva excesivamente sencillo ya que puede llevar a la
monotonía, al aburrimiento y al abandono del juego.
40
TESTS
FASE 1
Esta fase se realizará de forma inicial a medida que vayamos creando los sprites gráficos
que compondrán el juego. Buscar opiniones de terceros nos puede servir para acabar
de ajustar o modificar aquellos elementos que no concuerden o sean mejorables desde
el punto de vista de otros usuarios.
Una vez definido el apartado gráfico haremos lo mismo con las mecánicas de movi-
miento y salto del personaje así como de algún enemigo. Toda esta información nos
servirá para comprobar si vamos en la buena línea y para obtener puntos de vista que
hayamos podido obviar.
Este testeo inicial se realizará de forma iterativa y contará con un muestreo de perso-
nas muy selecto, intentando buscar perfiles profesionales que puedan aportar ideas y
opiniones de mayor valor.
FASE 2
Una vez el juego ya esté implementado se realizará una fase de testeo más profunda,
buscando un muestreo mucho mayor, diverso y un tanto aleatorio. Para ello buscare-
mos en nuestro entorno más cercano personas de diferentes rangos de edades, sexo,
interés, frecuencia de juego, etc.
Para ampliar el muestreo utilizaremos las redes sociales para dar a conocer el juego y
obtener información de otras personas. Podemos utilizar un generador de encuestas
online donde los usuarios entren y de forma rápida puedan contestar a una serie de
preguntas que les hagamos, esto facilitaría la tarea de recopilación de información.
41
TESTEO VERSIÓN ALPHA
DALILA
Programadora
Valoración Demo Alpha - Positiva
Observaciones a mejorar
· Visualmente hay objetos que no se ven muy bien como las estrellas.
· No se aprecia dónde te puedes caer.
· Incorporar algún boucing cuando se recogen objetos.
· Cerrar el juego, aunque sea una versión demo. (Solucionado v.A1.1)
ESTHER CORRALES
Diseñadora
Valoración Demo Alpha - Muy Positiva
Observaciones a mejorar
· Desenfoque suave del fondo para dar efecto profundidad.
· Contrastar objetos que puedan ser recogidos.
· Modificar piernas personaje e incorporar algún efecto sutil al saltar.
42
TESTEO VERSIÓN BETA
Para el testeo de la versión Beta primero la enseñe en el entorno más cercano del que
obtuve un report de errores mostrados en este enlace:
https://docs.google.com/document/d/1sauiQ-i34KUqwaqX6VhjR5YkoQIZOOeguYbGC-
2T7i_E/edit
Una vez corregidos la abrí a más usuarios creando una encuesta donde recoger infor-
mación del tipo de usuario que ha testeado el juego y preguntando qué cosas mejora-
rían:
https://docs.google.com/forms/d/e/1FAIpQLScQVp3YSny6Z2Fe_WHUktaox41O1doJG-
M2QRik3tda_e2If1A/viewform
43
44
VERSIONES DE LA APLICACIÓN
ALPHA α
Versión del juego con los primeros sprites agregados y alguna mecánica implementada
del personaje principal.
(Entrega prevista 4 Diciembre 2016)
BETA β
Versión del juego completa con todas los sprites y mecánicas implementadas. Versión
lista para la fase de testeo de usuarios.
(Entrega prevista 4 Enero 2017)
v. 1.0
Versión completa del juego con cambios implementados gracias al feedback de los
usuarios que hayan testeado la aplicación.
(Entrega prevista 16-25 Enero 2017)
45
BUGS
Plataforma móvil
Descripción: al subirse el personaje no se mueve con ella.
Solución: sumar la velocidad de la plataforma a la del personaje.
46
PRESUPUESTO
Software
Dado que disponemos de licencias para la suite de Adobe y para la versión gratuita
de Unity tampoco ha supuesto un coste el software. En el caso de que el juego se co-
mercializase necesitaríamos adquirir una licencia comercial de Unity y otra licencia de
Photoshop e Illustrator.
Recursos humanos
Este proyecto ha sido desarrollado en su totalidad por mi y por tanto no ha supuesto
tampoco un coste económico. En un escenario de desarrollo del juego por un equipo
multidisciplinar podríamos desglosar los siguientes costes por perfil profesional y nú-
mero de horas:
Diseñador \ Artista 30€ / hora 100 horas 3000 €
Programador 40€ / hora 150 horas 6000 €
Animador 35€ / hora 100 horas 3500 €
Diseñador de niveles 20€ / hora 50 horas 1000 €
Técnico de sonido 20€ / hora 15 horas 300 €
Especialista en marketing 15€ / hora 25 horas 375 €
Total: 14750 €
47
ANÁLISIS DE MERCADO
A pesar de que competir en el sector del juego indie está complicado por el alto volu-
men de oferta y no tan elevada demanda, el sector tiene su público, así que de con-
seguir un producto original y de suficiente calidad se puede sobresalir y ser económi-
camente viable. Casos como Limbo, Super Meat boy, Braid o Minecraft son grandes
ejemplos de que con escasos recursos se pueden crear grandes obras.
http://www.gamingobserver.com/20152016-us-video-and-computer-game-industry-overview-report/
48
MÁRQUETIN Y VENTAS
Para que el proyecto sea viable económicamente necesitamos darlo a conocer. Hoy en
día existen miles de juegos en el mercado con características similares por lo que es
muy complicado dar a conocer el juego sin una campaña de marketing adecuada.
Existen plataformas como STEAM que son utilizadas por millones de usuarios y donde
podemos dar a conocer nuestro juego. Para conseguirlo se creó Steam Greenlight que
busca apoyar a los desarrolladores de juegos independientes. Gracias a esta iniciativa se
dan a conocer una oferta de juegos y es la comunidad la que decide, a través de vota-
ciones, que juegos pasan el filtro y cuáles no.
Para que nuestro juego figure dentro de Steam Greenlight necesitaremos preparar una
portada, 4 o más capturas, un video del juego en funcionamiento y al menos 2 parrafos
que describan el juego y los requisitos de sistema. Los usuarios de Steam podrán enton-
ces acceder a la página propia del juego y votar Si o No según lo interesados que estén
en el juego. Una vez alcanzados un número suficiente de votos positivos Valve se pone
en contacto con los desarrolladores para definir un calendario de entrega (si el juego no
está acabado) y un precio para el producto. Este proceso tiene un coste de $100.
Aunque la iniciativa es buena a la práctica las votaciones de Greenlight reflejan más las
habilidades publicistas que no la calidad del juego en sí. Es por tanto necesario dar a co-
nocer el juego en todos los medios de los que dispongamos, como foros y redes socia-
les (Facebook, Twiter, Google+...) que apunten a nuestra página de Steam Greenlight.
Encontramos otras vías de comercialización en las plataformas que Xbox Arcade, Sony o
Nintendo ofrecen para desarrolladores independientes. Previamente debemos evaluar
los costes que suponen los ports a estas plataformas, condiciones y licencias necesarias.
49
ENTREGABLES DEL PROYECTO
Resto de documentos
50
CÓDIGO FUENTE (EXTRACTOS)
AnimateObject.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
AnimatePuzzle.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
}
IEnumerator destroyStar(float howmanyseconds){
yield return new WaitForSeconds (howmanyseconds);
//GameObject.FindWithTag(“ManaItems”).GetComponent<AudioSource>().Play();
Destroy (gameObject);
}
}
51
BarScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
void Start ()
{
content.fillAmount = fillAmount;
}
}
bossWalls.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
CameraEffects.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
}
// Update is called once per frame
void Update () {
if(isShaking)
{
ShakeCamera();
}
}
52
private IEnumerator RemoveShake(float t)
{
//Wait for camera shake
yield return new WaitForSeconds(t);
//Remove it slowly
float time = 0.0f;
float maxTime = t / 2;
float initialLinearForce = linearForce;
float initialRotationForce = rotationForce;
while (time < 1)
{
time += Time.deltaTime / maxTime;
linearForce = Mathf.Lerp(initialLinearForce, 0, time);
rotationForce = Mathf.Lerp(initialLinearForce, 0, time);
//Debug.Log(“LinearForce: “ + linearForce);
yield return null;
}
this.isShaking = false;
}
CameraFollow.cs
using UnityEngine;
using System.Collections;
[SerializeField]
public GameObject targetToFollow;
53
CameraSub.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
CharacterElgar.cs
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
using System;
[Header(“Physic materials”)]
public PhysicsMaterial2D bouncingMaterial;
public PhysicsMaterial2D stopBouncingMaterial;
#region FSM_VARIABLES
private int chargesCount, stalactitesCount;
private bool hasBounced, hasStalactited, hasChangedDirection;
private float bouncingTime;
#endregion
void Start ()
{
// STOP PLAYER CONTROL ON START
player = GameObject.FindGameObjectWithTag(“Player”);
54
soundShout = GameObject.FindGameObjectWithTag(“SoundElgarShout”);
objEscalactita1 = GameObject.FindGameObjectWithTag (“Escalactita1”);
objEscalactita2 = GameObject.FindGameObjectWithTag (“Escalactita2”);
objEscalactita3 = GameObject.FindGameObjectWithTag (“Escalactita3”);
objEscalactita4 = GameObject.FindGameObjectWithTag (“Escalactita4”);
objEscalactita5 = GameObject.FindGameObjectWithTag (“Escalactita5”);
stopZone1 = GameObject.FindGameObjectWithTag(“StopZone1”).GetComponent<Transform>();
stopZone2 = GameObject.FindGameObjectWithTag(“StopZone2”).GetComponent<Transform>();
vulnerableTrigger = transform.FindChild(“VulnerableTrigger”).gameObject;
frontColliderTrigger = transform.FindChild(“FrontCollider”).gameObject;
sphereColliderTrigger = transform.FindChild(“BounceCollider”).gameObject;
startPoint = GameObject.Find(“ElgarColliders/InitialPoint”).GetComponent<Transform>();
isTransitioningState = false;
myRigidbody = GetComponent<Rigidbody2D> ();
myAnimator = GetComponent<Animator> ();
myAnimator.SetBool(“Stoped”, true);
InitialiseElgarToState(ElgarState.CHARGE);
void Update()
{
if (bossBegin) {
UpdateElgarStateMachine();
}
}
55
case ElgarState.STALACTITE:
if (stalactitesCount >= maxStalactites)
{
isTransitioningState = true;
Debug.Log(“[Elgar] Changing state to Charge”);
StartCoroutine(SetNextState(ElgarState.CHARGE));
}
break;
}
}
}
void FixedUpdate () {
if (bossBegin)
{
if (!isTransitioningState)
{
switch (elgarState)
{
case ElgarState.CHARGE:
UpdateDirection();
myAnimator.SetBool(“Stoped”, false);
Charge();
break;
case ElgarState.STALACTITE:
Stalactite();
break;
case ElgarState.BOUNCE:
Bounce();
break;
}
}
}
}
56
[SerializeField]
private Transform transformB;
// Use this for initialization
void Start () {
posA = childTransform.localPosition;
posB = transformB.localPosition;
nexPos = posB;
}
// Update is called once per frame
void Update () {
Move ();
}
private void Move()
{
childTransform.localPosition = Vector3.MoveTowards(childTransform.localPosition, nexPos, speed * Time.
deltaTime);
if (Vector3.Distance (childTransform.localPosition, nexPos) <= 0.1)
{
ChangeDestination ();
}
}
private void ChangeDestination()
{
nexPos = nexPos != posA ? posA : posB;
}
}
GetComponent<CircleCollider2D>().sharedMaterial = bouncingMaterial;
GetComponent<CircleCollider2D>().enabled = true;
Invoke(“AddBounceForce”, 0.5f);
hasBounced = true;
}
}
57
gameObject.GetComponent<AudioSource> ().Stop ();
Camera.main.GetComponent<CameraEffects>().Shake(0.2f, 0.3f, 0.6f);
col.GetComponent<AudioSource> ().Play ();
ChangeDirection(0.1f);
chargesCount++;
}
else if (col.CompareTag(“StopZone2”))
{
gameObject.GetComponent<AudioSource> ().Stop ();
Camera.main.GetComponent<CameraEffects>().Shake(0.2f, 0.3f, 0.6f);
col.GetComponent<AudioSource> ().Play ();
ChangeDirection(-0.1f);
chargesCount++;
}
}
58
private void StalactitePiecesFallPhysics()
{
objEscalactita1.GetComponent<AudioSource> ().Play ();
objEscalactita1.transform.position = new Vector2(UnityEngine.Random.Range(-10f, -5f), 12.5f);//9.15f,39f),12.5f);
objEscalactita1.GetComponent<Rigidbody2D>().gravityScale = UnityEngine.Random.Range(0.5f, 3f);
objEscalactita2.transform.position = new Vector2(UnityEngine.Random.Range(-4f, 1f), 12.5f);//9.15f,39f),12.5f);
objEscalactita2.GetComponent<Rigidbody2D>().gravityScale = UnityEngine.Random.Range(0.5f, 3f);
objEscalactita3.transform.position = new Vector2(UnityEngine.Random.Range(2f, 7f), 12.5f);//9.15f,39f),12.5f);
objEscalactita3.GetComponent<Rigidbody2D>().gravityScale = UnityEngine.Random.Range(0.5f, 3f);
objEscalactita4.transform.position = new Vector2(UnityEngine.Random.Range(8f, 14f), 12.5f);//9.15f,-
39f),12.5f);
objEscalactita4.GetComponent<Rigidbody2D>().gravityScale = UnityEngine.Random.Range(0.5f, 3f);
objEscalactita5.transform.position = new Vector2(UnityEngine.Random.Range(15f, 20f), 12.5f);//9.15f,-
39f),12.5f);
objEscalactita5.GetComponent<Rigidbody2D>().gravityScale = UnityEngine.Random.Range(0.5f, 3f);
Invoke(“IncrementStalactitesCount”, 1.0f);
}
CollisionTrigger.cs
using UnityEngine;
using System.Collections;
[SerializeField]
private BoxCollider2D platformCollider;
[SerializeField]
private BoxCollider2D platformTrigger;
59
controls.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class controls : MonoBehaviour {
public GameObject musicPlayerSFX;
public Button boton_back_controls;
// Use this for initialization
void Start () {
musicPlayerSFX = GameObject.FindGameObjectWithTag (“SfxPushBack”);
}
credits.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
ElgarVulnerableTrigger.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(RenderEffects))]
public class ElgarVulnerableTrigger : MonoBehaviour {
// definir tiempo cd entre golpes
public float maxHitTime = 1.5f;
private float hitTime;
60
void OnTriggerEnter2D(Collider2D col)
{
if(col.CompareTag(“Player”) && (Time.time - hitTime) > maxHitTime)
{
if (player.GetComponent<Animator> ().GetBool (“land”)) {
player.GetComponent<Player> ().invulnerable = true;
StartCoroutine (Invulnerability (0.3f));
hitTime = Time.time;
Debug.Log (“[Elgar] GOT HIT BY PLAYER! 1 LIFE LESS ON BOSS !! lets lower his HP points
by 10”);
content.fillAmount = content.fillAmount - 0.1f;
if (content.fillAmount > 0f) {
////myRigidbody.AddForce (new Vector2 (0, jumpForce));player.GetCompo-
nent<Rigidbody2D>()
player.GetComponent<Rigidbody2D> ().velocity = new Vector2 (0, 0);
player.GetComponent<Rigidbody2D> ().AddForce (new Vector2 (0, 450));
sfxHit.Play ();
effects.Blink (
transform.parent.GetComponent<SpriteRenderer> (),
Color.red,
1.0f);
} else {//GAME OVER WIN
//player.transform.position = new Vector2 (-8.5f, -4);
StartCoroutine(EndingBattle(player.transform, new Vector2(-8.5f, -4f)));
player.GetComponent<Player> ().inBossStage = true;
player.GetComponent<Animator> ().SetFloat (“speed”, 0);
//player.GetComponent<Animator> ().speed = 0;
player.GetComponent<Animator> ().SetBool (“land”, true);
player.GetComponent<Rigidbody2D> ().velocity = new Vector2 (0, 0);
//
StartCoroutine(EndingBattle(elgar.transform, new Vector2(12f, -4f)));
//elgar.transform.position = new Vector2 (12, -4);//Vector2.Lerp(elgar.Get-
Component<Rigidbody2D> ().position,new Vector2(0f,0f),3);//
elgar.GetComponent<CharacterElgar> ().bossBegin = false;
elgar.GetComponent<Animator> ().SetBool (“Stoped”, true);
elgar.GetComponent<Rigidbody2D> ().velocity = new Vector2 (0, 0);
//
musicBoss.Stop ();
musicBossKill.Play ();
//
//postBossDialog.SetActive(true);
postBossDialog.GetComponent<Animator> ().enabled = true;
elgar.GetComponent<AudioSource>().Stop();
//postBossDialog.GetComponent<Animator> ().Play ();
}
}
}
}
61
enemy.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[SerializeField]
private float monsterSpeed;
[SerializeField]
private bool startToLeft;
// Use this for initialization
private int monsterDirection;
void Start () {
if (startToLeft == true) {
monsterDirection = -1;
} else {
monsterDirection = 1;
}
myAnimator = this.GetComponent<Animator> ();
myRigidbody = this.GetComponent<Rigidbody2D> ();
//myRigidbody = gameObject.GetComponent<Rigidbody2D>;
//myRigidbody.velocity = new Vector2(5, myRigidbody.velocity.y);
}
// Update is called once per frame
void Update () {
//myRigidbody = new Vector2 (50, 0);
if (!myAnimator.GetBool (“death”)) {
myRigidbody.velocity = new Vector2 (monsterSpeed * monsterDirection, 0);
} else {
myRigidbody.velocity = new Vector2 (0, 0);
}
//myRigidbody.AddForce(new Vector2(25, 0), ForceMode2D.Impulse);
}
62
fading.cs
using UnityEngine;
using System.Collections;
GameController.cs
using UnityEngine;
using System.Collections;
void Start ()
{
score = 0;
UpdateScore ();
}
public void AddScore (int newScoreValue)
{
score += newScoreValue;
UpdateScore ();
}
void UpdateScore()
{
scoreText.text = “score: “ + score;
}
}
63
GameOverWin.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
introIth.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
dialog.SetActive(false);
myCamera = Camera.main;
}
// Update is called once per frame
void Update () {
if (!playerState.hasSeenScene1 && this.gameObject.transform.position.y <= 0) {
myAnimator.SetBool (“eggland”, true);
StartCoroutine (KillEgg(1.8f));
}
64
else if(playerState.hasSeenScene1)
{
RelocatePlayerAndRemoveEgg(startPoint.position);
}
}
IEnumerator KillEgg(float howmanyseconds){
//player.GetComponent<Player>().controlEnabled = false;
//player.GetComponent<Player>().inBossStage = true;
yield return new WaitForSeconds (howmanyseconds);
RelocatePlayerAndRemoveEgg(new Vector2(gameObject.transform.position.x, gameObject.transform.position.y));
dialog.SetActive(true);
//player.GetComponent<Player>().controlEnabled = true;
//player.GetComponent<Player>().inBossStage = false;
playerState.hasSeenScene1 = true;
}
introMovie.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
[RequireComponent (typeof(AudioSource))]
public class introMovie : MonoBehaviour {
public MovieTexture movie;
public AudioSource audio;
private bool manualpause;
private Texture myRaw;
private GameObject skiptext;
private bool waitload;
/*
void Awake(){
myRaw=GetComponent<RawImage> ().texture = movie as MovieTexture;
}
*/
void Start () {
waitload = false;
manualpause = false;
skiptext = GameObject.FindGameObjectWithTag (“SkipText”);
GetComponent<RawImage> ().texture = movie as MovieTexture;
//GetComponent<RawImage>().material.mainTexture=movie;
audio = GetComponent<AudioSource> ();
audio.clip = movie.audioClip;
movie.Play ();
audio.Play ();
//loadLevel1();
}
void Update () {
if (!waitload) {
if (Input.GetKeyDown (KeyCode.Space) && movie.isPlaying) {
manualpause = true;
movie.Pause ();
} else if (Input.GetKeyDown (KeyCode.Space) && !movie.isPlaying) {
manualpause = false;
movie.Play ();
}
65
if (!movie.isPlaying && !manualpause) {
Debug.Log (“loadScene1”);
loadLevel1 ();
}
if (Input.GetKeyDown (KeyCode.Escape)) {
loadLevel1 ();
}
}
}
private void loadLevel1(){
manualpause = true;
movie.Pause ();
audio.Pause ();
waitload = true;
skiptext.SetActive (false);
SceneManager.LoadScene(“level_01”);
}
}
Jumper.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
LevelHandler.cs
using UnityEngine;
using System.Collections;
using System;
using UnityEngine.SceneManagement;
66
void Awake()
{
overlay.pixelInset = new Rect (0, 0, Screen.width, Screen.height);
StartCoroutine (FadeToClear ());
}
public void ReloadLevel()
{
//StartCoroutine(FadeToBlack(() => SceneManager.LoadScene(SceneManager.GetActiveScene())));
SceneManager.LoadScene (SceneManager.GetActiveScene ().buildIndex);
}
private IEnumerator FadeToClear()
{
overlay.gameObject.SetActive (true);
overlay.color = Color.black;
float rate = 1.0f / fadeTime;
float progress = 0.0f;
while (progress < 1.0f)
{
overlay.color = Color.Lerp (Color.black, Color.clear, progress);
progress += rate * Time.deltaTime;
yield return null;
}
overlay.color = Color.clear;
overlay.gameObject.SetActive (false);
}
main_menu.cs
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
void Start () {
musicPlayer=GameObject.Find (“MUSIC”);
}
public void PlayGame(){
GameObject.FindWithTag (“SfxPush”).GetComponent<AudioSource> ().Play ();
Destroy(musicPlayer);
SceneManager.LoadScene(“intro_movie”);//level_01
}
67
public void OpControls(){
GameObject.FindWithTag (“SfxPush”).GetComponent<AudioSource> ().Play ();
SceneManager.LoadScene(“controls”);
}
public void OpCredits(){
GameObject.FindWithTag (“SfxPush”).GetComponent<AudioSource> ().Play ();
SceneManager.LoadScene(“credits”);
}
public void OpQuit(){
Application.Quit ();
}
}
menu_music.cs
using UnityEngine;
using UnityEngine.SceneManagement;
if (musicPlayer == null) {
musicPlayer = this.gameObject;
musicPlayer.name = “MUSIC”;
DontDestroyOnLoad (musicPlayer);
} else {
if (this.gameObject.name != “MUSIC”) {
Destroy (this.gameObject);
}
}
/*
if (sfxPushButton == null) {
sfxPushButton = this.gameObject;
sfxPushButton.name = “SFXpush”;
DontDestroyOnLoad (sfxPushButton);
}
*/
//DontDestroyOnLoad(this.gameObject);
//DontDestroyOnLoad(transform.gameObject);
}
PauseMenu.cs
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
PauseUI.SetActive (false);
}
68
void Update(){
//if(Input.GetButtonDown(*Pause*)){
if (Input.GetKeyDown (KeyCode.Escape)) {
if (!paused) {
GameObject.FindWithTag (“PauseSound”).GetComponent<AudioSource> ().Play ();
}
GameObject.FindWithTag (“GameMusic”).GetComponent<AudioSource> ().UnPause ();
paused = !paused;
}
if(paused){
PauseUI.SetActive(true);
AudioListener.pause = true;
GameObject.FindWithTag (“GameMusic”).GetComponent<AudioSource> ().Pause ();
Time.timeScale=0;
}
if(!paused){
AudioListener.pause = false;
PauseUI.SetActive(false);
Time.timeScale=1;
}
platformLeave.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
69
PlatformMovement.cs
using UnityEngine;
using System.Collections;
[SerializeField]
private float speed;
[SerializeField]
private Transform childTransform;
[SerializeField]
private Transform transformB;
// Use this for initialization
private bool incolision;
void Start () {
player=GameObject.FindGameObjectWithTag(“Player”);
incolision = false;
posA = childTransform.localPosition;
posB = transformB.localPosition;
nexPos = posB;
}
Player.cs
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.SceneManagement;
using System;
[RequireComponent(typeof(RenderEffects))]
public class Player : MonoBehaviour {
private enum ElgarState { CHARGE, STALACTITE, BOUNCE };
private Rigidbody2D myRigidbody;
70
private float posicionPersonajeX;
private float posicionY;
[SerializeField]
private float timeInvulnerableAfterHit;
[SerializeField]
public bool inBossStage;
[SerializeField]
private float movementSpeed;
[SerializeField]
private Transform[] groundPoints;
[SerializeField]
private LayerMask whatIsGround;
[SerializeField]
private bool airControl;
[SerializeField]
private float jumpForce;
[SerializeField]
private float groundRadius;
//
//private int countMana;
private int countEgg;
public Text countManaText;
public Text countEggText;
private GameObject txtRef, personaje;
//
//
private AudioSource coinSoundEffect,sfxGameOver;//public
private AudioSource sfxHit;
71
void Start () {
damageAmount = 0.15f;
gameover = false;
GameObject personaje = GameObject.FindGameObjectWithTag(“Player”);
//timeInvulnerableAfterHit = 0f;
effects = GetComponent<RenderEffects>();
puzzlecount = 0;
animaSpeed=2f;
baseRunForce = movementSpeed;
ps = GameObject.FindGameObjectWithTag (“PauseSound”).GetComponentInChildren <ParticleSystem>
();
sfxHit=GameObject.FindGameObjectWithTag(“SFXPlayerDamaged”).GetComponent<AudioSource>();
sfxGameOver=GameObject.FindGameObjectWithTag(“SFXGameOver”).GetComponent<AudioSource>();
if (inBossStage) {
elgarBoss = GameObject.FindGameObjectWithTag (“Elgar”).GetComponent<Animator>();
}
}
void Update()
{
if (!inBossStage && !gameover)
{
HandleInput();
}
CheckGameOver();
}
// Update is called once per frame
void FixedUpdate () {
if (!inBossStage && !gameover)
{
//MOVEMENT SPEED AND JUMP INCREASED WITH MANA STARS
movementSpeed = baseRunForce + (playerState.mana / 40);
isGrounded = IsGrounded();
//Debug.Log (horizontal);
HandleMovement(horizontal);
Flip(horizontal);
HandleLayers();
ResetValues();
}
72
if(gameover){
Time.timeScale=0;
}
}
73
}
}
}
return false;
}
posicionPersonajeX = gameObject.transform.position.x;
posicionY = -7f;
GameObject.FindWithTag(“WaterEffect”).transform.position = new Vector3(posicionPersonajeX, posicionY);
GameObject.FindWithTag(“WaterEffect”).GetComponent<ParticleSystem>().Play();
GameObject.FindWithTag(“Water”).GetComponent<AudioSource>().Play();
GameObject.FindWithTag(“Water”).GetComponent<BoxCollider2D>().enabled = false;
controlEnabled = false;
//RELOAD SCENE
//StartCoroutine(reloadScene(2));
playerState.Damage(1.0f);
}
else if (col.CompareTag(“MovingPlatform”))
{
gameObject.transform.SetParent (col.transform);
//transform.parent = col.transform;
}
74
else if (col.CompareTag(“Puzzle1”))
{
col.gameObject.GetComponentInChildren<BoxCollider2D> ().enabled=false;
StartCoroutine (SetPuzzle (0.5f,1));
GameObject.FindWithTag(“EggItems”).GetComponent<AudioSource>().Play();
puzzlecount = puzzlecount + 1;
}
else if (col.CompareTag(“Puzzle2”))
{
col.gameObject.GetComponentInChildren<BoxCollider2D> ().enabled=false;
StartCoroutine (SetPuzzle (0.5f,2));
GameObject.FindWithTag(“EggItems”).GetComponent<AudioSource>().Play();
puzzlecount = puzzlecount + 1;
}
else if (col.CompareTag(“Puzzle3”))
{
col.gameObject.GetComponentInChildren<BoxCollider2D> ().enabled=false;
StartCoroutine (SetPuzzle (0.5f,3));
GameObject.FindWithTag(“EggItems”).GetComponent<AudioSource>().Play();
puzzlecount = puzzlecount + 1;
}
else if (col.CompareTag(“Enterboss”))
{
col.GetComponent<AudioSource> ().Play ();
StartCoroutine(loadBossScene(1));
}
//ESCALACTITAS
else if (col.CompareTag(“Escalactita1”) || col.CompareTag(“Escalactita2”) || col.CompareTag(“Escalacti-
ta3”)|| col.CompareTag(“Escalactita4”)|| col.CompareTag(“Escalactita5”) )
{
if (!invulnerable) {
invulnerable = true;
StartCoroutine(Invulnerability (timeInvulnerableAfterHit));
Debug.Log (“HIT!!!!!!!!!!!!”);
sfxHit.Play ();
playerState.Damage(0.20f);
if (content.fillAmount > 0) {
content.fillAmount = playerState.life;
}
effects.Blink (
GetComponent<SpriteRenderer> (),
Color.red,
1.0f);
}
75
StartCoroutine (Invulnerability (timeInvulnerableAfterHit));
StartCoroutine (KillBabosa(col.transform.root.gameObject));
}
//BOSS
} else if (col.CompareTag (“Enemy”)) {
if (!invulnerable && !gameObject.GetComponent<Animator> ().GetBool (“land”)) {
invulnerable = true;
StartCoroutine(Invulnerability (timeInvulnerableAfterHit));
sfxHit.Play ();
//CHARGE, STALACTITE, BOUNCE
if (elgarBoss.GetBool (“Bouncing”)) {
//Debug.Log (“bouncing..........”);
//damageAmount = 0.10f;
playerState.Damage(0.10f);
}
else if (elgarBoss.GetBool (“Stalactite”)) {
//Debug.Log (“stala..........”);
//damageAmount = 0.15f;
playerState.Damage(0.15f);
}
else if (!elgarBoss.GetBool (“Stoped”)) {
//Debug.Log (“run..........”);
//damageAmount = 0.25f;
playerState.Damage(0.25f);
Debug.Log (“HIT!!!!!!!!!!!!”);
if (content.fillAmount > 0) {
content.fillAmount = playerState.life;
}
effects.Blink (
GetComponent<SpriteRenderer> (),
Color.red,
1.0f);
}
}
/*//DIE
CheckGameOver();*/
}
76
IEnumerator reloadScene(int howmanyseconds){
Debug.Log(“Reloading scene and resting playerState”);
playerState.Reset();
yield return new WaitForSeconds (howmanyseconds);
SceneManager.LoadScene (SceneManager.GetActiveScene ().buildIndex);
}
IEnumerator SetCountText(float howmanyseconds){
yield return new WaitForSeconds (howmanyseconds);
//countManaText.text = countMana.ToString ();//+” x”;
countManaText.text = playerState.mana.ToString();
var emission = ps.emission;
emission.rateOverTime = playerState.mana;
}
IEnumerator SetPuzzle(float howmanyseconds, int quepuzzle){
yield return new WaitForSeconds (howmanyseconds);
GameObject.FindWithTag (“UIpuzzle” + quepuzzle).SetActive (false);
GameObject.FindWithTag (“Puzzle” + quepuzzle + “b”).SetActive (false);
if (puzzlecount == 3) {
GameObject.FindWithTag(“Barrier”).SetActive(false);
}
}
IEnumerator loadBossScene(int howmanyseconds){
yield return new WaitForSeconds (howmanyseconds);
SceneManager.LoadScene(“level_boss”);
}
IEnumerator Invulnerability(float howmanyseconds){
yield return new WaitForSeconds (howmanyseconds);
invulnerable = false;
}
IEnumerator KillBabosa(GameObject quebabosa){
yield return new WaitForSeconds (1.8f);
Destroy (quebabosa);
}
}
PlayerState.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
void Awake()
{
if (_instance != null && _instance != this)
{
Destroy(this.gameObject);
}
else
{
_instance = this;
Reset();
_instance.hasSeenScene1 = _instance.hasSeenBossScene = false;
DontDestroyOnLoad(transform.gameObject);
}
}
77
public void Damage(float amount)
{
_instance.life -= amount;
}
popITH.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
RenderEffects.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
sprite.color = Color.white;
}
}
78
ResetScalactitas.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
void Update(){
if (gameObject.transform.position.y < -50) {
gameObject.GetComponent<Rigidbody2D> ().gravityScale = 0;
gameObject.GetComponent<Rigidbody2D> ().velocity = new Vector2(0,0);
gameObject.transform.position = new Vector2 (gameObject.transform.position.x, 12.5f);
}
}
}
ScrollingBackground.cs
using UnityEngine;
using System.Collections;
leftIndex = 0;
rightIndex = layers.Length - 1;
}
lastCameraX = cameraTransform.position.x;
if (scrolling) {
if (cameraTransform.position.x < (layers [leftIndex].transform.position.x + viewZone))
ScrollLeft ();
if (cameraTransform.position.x > (layers [rightIndex].transform.position.x - viewZone))
ScrollRight ();
}
}
79
private void ScrollLeft(){
int lastRight = rightIndex;
layers [rightIndex].position = Vector3.right * (layers [leftIndex].position.x - backgroundSize);
leftIndex = rightIndex;
rightIndex--;
if (rightIndex < 0)
rightIndex = layers.Length - 1;
}
private void ScrollRight(){
int lastLeft = leftIndex;
layers [leftIndex].position = Vector3.right * (layers [rightIndex].position.x + backgroundSize);
rightIndex = leftIndex;
leftIndex++;
if (leftIndex == layers.Length)
leftIndex = 0;
}
}
sfx_click.cs
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;
if (musicPlayer == null) {
musicPlayer = this.gameObject;
musicPlayer.name = “sfx_play”;
DontDestroyOnLoad (musicPlayer);
} else {
if (this.gameObject.name != “sfx_play”) {
Destroy (this.gameObject);
}
}
}
80
SFX_playthis.cs
using UnityEngine;
using System.Collections;
sfx_script.cs
using UnityEngine;
using System.Collections;
if (musicPlayer == null) {
musicPlayer = this.gameObject;
musicPlayer.name = “sfx_playback”;
DontDestroyOnLoad (musicPlayer);
} else {
if (this.gameObject.name != “sfx_playback”) {
Destroy (this.gameObject);
}
}
}
}
StartBoss.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
void Start()
{
player = GameObject.FindWithTag(“Player”);
elgar = GameObject.FindWithTag(“Elgar”);
bossMusic = GameObject.FindWithTag(“MusicBoss”);
elgarHpBar = GameObject.FindWithTag(“ElgarCanvas”);
elgarHpBar.GetComponent<CanvasGroup>().alpha = 0;
prebossMusic = GameObject.FindWithTag(“MusicPreBoss”);
81
prebossIntro = GameObject.FindWithTag(“PreBossIntro”);
playerState = GameObject.FindWithTag(“PlayerState”).GetComponent<PlayerState>();
if (skipIntro || playerState.hasSeenBossScene) {
Debug.Log(“LOLOLOL : “ + skipIntro + “ | “ + playerState.hasSeenBossScene);
StartFight();
}
}
//player.GetComponent<Rigidbody2D>().constraints = RigidbodyConstraints2D.None;
//player.GetComponent<Animator>().enabled = true;
prebossIntro.SetActive(false);
player.GetComponent<Player>().inBossStage = false;
bossMusic.GetComponent<AudioSource>().Play();
prebossMusic.GetComponent<AudioSource>().Stop();
elgar.GetComponent<CharacterElgar>().bossBegin = true;
elgarHpBar.GetComponent<CanvasGroup>().alpha = 1;
}
82
CAPTURAS DE PANTALLA
VERSIÓN ALPHA
83
VERSIÓN BETA
84
85
86
87
88
Escenario versión alpha en UNITY (5.3)
89
Entorno programación MonoDevelop-Unity
90
INSTALACIÓN
INSTALACIÓN
91
CONTROLES
Utiliza el cursor del ratón para moverte Pulsa la tecla ESC durante el juego para
por el menú principal del juego. que aparezca un menú de opciones,
Selecciona PLAY para iniciar el juego, selecciona una opción en el menú para:
controles para ver las teclas de control volver al juego, reiniciar partida, volver
del personaje, ver créditos o salir. al menú o salir del juego.
92
OBJETIVOS
ARGUMENTO
ITH es un bebe dragón que debe buscar a sus hermanos que han sido secuestrados
por un ser desconocido. En la búsqueda deberá enfrentarse a ellos para que recu-
peren la memoria. Cada dragón tiene una personalidad y habilidades diferentes que
combinadas permitirán avanzar en esta aventura para rescatar al resto del nido y
averiguar la identidad de su captor.
LOS PROTAGONISTAS
93
OBJETOS
PIEZAS DE PUZZLE
Consigue todas las piezas de puzzle para progresar y acceder a nuevas zonas, se
encuentran escondidas por el mapa.
ESTRELLAS DE MANA
Consigue tantas como puedas para volverte mas ágil, puedes conseguir acumular
hasta 100 para mejorar hasta un 40% tu velocidad de movimiento. Te serán de ayu-
da para derrotar al jefe final.
Las estrellas pequeñas aportan 1 unidad a tu contador de estrellas.
Las estrellas grandes aportan 5 unidades a tu contador de estrellas.
BURBUJAS
94
ENEMIGOS
BABOSAS
Si te tocan perderás 10 puntos de vida. Evítalas o salta sobre ellas para eliminarlas.
AGUA
Ten cuidado y no caigas al agua, ITH no sabe nadar! Si caes perderás toda la vida y
tendrás que volver a comenzar.
ESTALACTITAS
Caen de las cuevas y si te impactan te harán perder una buena cantidad de vida.
95
LIBRO DE ESTILO
Imagen de la marca
lorem ipsum dolor sit amet, consectetur adipiscing elit. dunc eget
pretium tellus, a ullamcorper est. fusce vitae est ut nunc pellentes-
que varius. maecenas ex orci, porta nec ultrices id, rhoncus lacinia
turpis.
96
PLAN DE NEGOCIO/RESUMEN EJECUTIVO
Los modelos de negocio más utilizados en la industria del videojuego son los siguientes:
Pay to play
El usuario tiene que pagar para poder instalar y jugar con la aplicación. Una vez realiza-
do este pago el usuario es libre de jugar el tiempo que desee.
Freemium
Permite jugar de forma gratuita pero con limitaciones, ya sea por tiempo, funcionali-
dad, capacidad, uso, etc. Si el usuario desea saltarse estas restricciones debe pagar por
la aplicación.
Micropagos
Permite la descarga gratuita pero algunos elementos del contenido son de pago. El ob-
jetivo de este modelo es atraer al jugador inicialmente y que una vez este dentro pueda
comprar elementos no indispensables en el juego. Es un modelo que funciona muy bien
para usuario/desarrollador ya que permite ajustarse a la capacidad económica de cada
usuario.
Subscripción
El usuario debe realizar un pago periódico (mensual, anual...) para poder jugar. Suele
ser un modelo utilizado en aplicaciones que requieren un mantenimiento y actualiza-
ción de contenidos y que generan un gasto de servidores importante.
97
GLOSARIO
API
Interface de programación de aplicaciones (Application Programming Interface) es un
conjunto de funciones y procedimientos recogidos en una biblioteca informática con la
finalidad de ser utilizada por otro programa.
Bug
Nombre que se atribuye a un fallo, error en la aplicación o funcionamiento inesperado
C#
Lenguaje de programación desarrollado por Microsoft que forma parte del .Net Fra-
mework. Es un lenguaje multi-paradigma, orientado a objetos, funcional, genérico,
imperativo y declarativo.
Detección de colisiones
Hace referencia a la resolución del problema computacional de detectar la intersección
entre 2 objetos en un programa o juego.
Framework
Conjunto de estándares que forman una infraestructura para el desarrollo de software.
GUI
La interfaz gráfica de usuario (Graphic User Interface) es una interfaz que utiliza ele-
mentos gráficos que permite un control intuitivo del usuario a través de la interacción
con esta.
Script
Archivo de texto escrito en un lenguaje de programación que contiene los comandos
para realizar unos procedimientos como dotar de interactividad al juego.
Sprite
Imagen de dos dimensiones que se integra en una escena más grande dentro de un
juego o aplicación.
Sprite sheet
Fichero compuesto por varios sprites que se organizan en un único fichero para aligerar
la carga del procesador gráfico que trabaja mejor cargando una única imagen separán-
dola en memoria que cargando cada una por separado.
98
BIBLIOGRAFÍA
Greg Lukosek (2016) Learning C# by Developing Games with Unity 5.x Second Edition
https://www.amazon.es/Learning-Developing-Games-Unity-Second/dp/1785287591/
ref=sr_1_1?s=foreign-books&ie=UTF8&qid=1476874452&sr=1-1&keywords=learning+-
c%23+by
99
CONCLUSIÓN FINAL
Y es que la tarea de crear un videojuego es muy costosa ya que requiere del uso de
muchas disciplinas. En el mundo laboral normalmente hay especialistas que ejecutan
cada una de ellas, por lo que para una sola persona la realización de todas ellas requie-
re mucha polivalencia y esfuerzo.
Pese a todo, creo que fue una buena decisión “lanzarme a la aventura” de aprender a
utilizar UNITY ya que a nivel profesional ahora me siento preparado para afrontar posi-
bles proyectos realizados con ella. Lo cierto es que llevaba bastante tiempo queriendo
aprender a utilizarla pero nunca encontraba el momento. A veces es necesario hacer
uno de estos gestos, salir de la zona de confort, saltar a terreno desconocido y afrontar
la decisión tomada.
He pasado por muchos momentos en este proyecto, muchos altibajos, ha sido una
carrera de obstáculos que he ido superando paso a paso... me he caído algunas veces
pero he continuado y por fin veo la meta final.
Y con este proyecto también acaba una larga travesía, una etapa. Ya voy pensando en la
siguiente.
¡Gracias!
DOWNLOAD LINK
http://goo.gl/SdsgY2
100