¡Sticks & Stones en GreenLight! ¡Vótanos!

Estamos enormemente emocionados de compartir con vosotros que Sticks & Stones está ya en GreenLight.

greenlight

¿Qué es GreenLight?

Es el sistema que usa Steam para determinar qué juegos pueden venderse en su tienda online. Lo característico de este sistema es que es la propia comunidad la que elige esto. Publicas una campaña con imágenes, vídeo y una descripción de tu juego, y Steam propone una sencilla pregunta a los consumidores:

¿Comprarías este juego si estuviera disponible en Steam?

  • SI
  • No gracias / No me interesa
  • Preguntarme luego

Si disponéis de una cuenta de Steam, ayúdanos a conseguir el GreenLight y ¡VOTADNOS!

sticksstonesgreenlightpee

Highsight and Us. Us and Highsight.

Gamers del mundo!

El pasado miércoles a las 2:00 am (8:00 pm) tuvimos la oportunidad de ver cómo Sticks & Stones era jugado por alguien totalmente ajeno a nosotros. Le habíamos hecho llegar la última build a un chico en EE. UU. con su propio canal de Twitch llamado Highsight y pudimos ver cómo jugaba. En vivo. ¡A todo el mundo!

¿Qué tal fue? 

Pues….

En las palabras del chico: Not bad guys. Not bad at all. I  really hope to hear more from you. 

Pudimos ver cómo exploraba y comía champiñones, pudimos ver al público alabando a las Gunslingers (las “Cowboy Robot Thingies”), pudimos ver cómo crafteaba, pudimos ver cómo experimentaba mientras crafteaba. Habló de lo interesante del estilo gráfico y de lo prometedor de las holoballs  y de cómo era posible adivinar las intenciones de las holoballs a partir del personaje que eran.

Nos hizo recomendaciones sobre la UI, cosas que hacíamos bien (“it’s the easiest crafting system I’ve used“),  cosas para mejorar y cómo mejorarlas (“it all feels too disconnected, you should take Minecraft as  an  example of how to do it perfectly“) y cosas que hacíamos mal (“why shouldn’t this item replace the one’s that’s already in place?“). Al final, nos permitió ver cómo juega alguien sin tener a uno de nosotros inspeccionando cada cosa que hace por encima del hombro, para darnos la tenue satisfacción de confirmar (de nuevo 😉 ) que la idea en la que hemos invertido tanto funciona.

Ya estaremos anunciando por aquí cuando haya otra transmisión así: el equipo entero quedó con la misma sensación luego de que terminara, somnolientos y exhaustos, a las 4:00 am del miércoles: queremos más.

Nos vemos!

Traje, hologramas y realidad aumentada

En Sticks & Stones eres un concursante en un show televisivo que mezcla supervivencia y acción. El concursante debe enfrentarse a enemigos un tanto especiales: las Holo-Balls, unas esferas que se desplazan por el suelo y proyectan hologramas.

gunslinger
Arte de juego – Gunslinger

gunslinger
Ilustración – Gunslinger

El concursante va equipado con un traje especial que le permite interactuar con las Holo-Balls, y unas lentillas de realidad aumentada que proporcionan una experiencia de combate segura.

El traje está conectado a un sistema de monitorización que controla las constantes vitales y la interacción con las Holo-Balls. Si durante el reto sufre algún desmayo o pérdida de conocimiento, el traje lo notifica al sistema y una unidad de emergencia viene a socorrerlo, provocando automáticamente su derrota. El traje también reconoce un impacto causado por algún objeto de realidad aumentada (proyectil) o Holo-Ball. Los impactos reducen los puntos de golpe de los que dispone el traje y si llegan a 0 el concursante también es derrotado.

ferguson-suit
Arte de juego – Concursante

Los proyectiles que lanzan algunas Holo-Balls son creados mediante la realidad aumentada, incapaces de causar daño físico al concursante. Existen varios tipos de proyectiles o balas y su aspecto determina sus características.

Cuando un holograma o artefacto de realidad aumentada se ve de color rojizo indica que está potenciado, mejorando sus propiedades normales.

super-bullet-normal Super bala
super-bullet-chargedSuper bala potenciada

 mega-bullet-normal  Mega bala
mega-bullet-charged Mega bala potenciada

 

Sticks & Stones te pone a prueba en un reto único y difícil, mezclando naturalezatecnología. ¿Podrás abrirte paso hasta el final partiendo de los palos y piedras que encuentres en el camino?

 

Nueva Holoball: Torpigdo

Hace unas semanas mostramos algunas de las Holoballs. Hoy te enseñamos a Torpigdo, un cerdo montado en un cañón que dispara balas muy poderosas.

Se dice que Torpigdo fue un aviador reconocido que acabó pilotando un cañón de tierra… que no te engañe su aspecto, detrás de sus gafas de aviador se esconde un poderoso enemigo al que respetar.

Su ataque es a distancia (range). Durante un breve periodo de tiempo cargará un poderoso disparo que lanzará a alta velocidad a través de su cañón. Su poder ofensivo es compensado con su falta de movilidad.


Test chamber: Torpigdo – Indie DB

Si quieres probar enfrentarte a Torpigdo, ¡descarga nuestra build y ponlo a prueba! Te retamos a derrotarlo devolviéndole sus disparos con el escudo holográfico.

Si te gusta, ¡compartelo!

 

 

Nueva Build Disponible, JUGAD!

Ya era hora. Aunque el año empezó hace 25 días, hemos estado trabajando día y noche y fines de semana y festivos y no festivos y días de cumpleaños y festivos no nacionales y festivos galácticos para poder llegar a esto.

¡De acuerdo! ¿Dónde la descargo?

¡Qué entusiasmo!

Aquí desde Dropbox. Pero si lo prefieres por algún motivo, en indiedb también está disponible.

No, no, es verdad. Me apresuré. Pero de acuerdo, tienes mi atención ¿Qué hay de nuevo?

¿Qué hay de nuevo? !¿Qué hay de nuevo?! “¿Qué hay de nuevo?”, pregunta.

Por qué no mejor te lo descargas y dejas que la majestuosidad te eleve hasta Proxima Centauri.

Buen intento, ahora dime: ¿qué hay de nuevo con respecto a la última vez que jugué?

Perdón, perdón. Hay:

  • Nuevos enemigos: dile adiós a las arañas y dile hola a las Holo-balls. Llevamos tiempo hablando de ellas, pero ahora vas a poder sentir lo que es ser golpeadas por su furia.
  • Mejoras visuales: mira cómo salen chispas cuando golpees a una Holo-ball. Mira cómo una de ellas (no diremos cuál) acumula Energía Oscura para pegarte un pepazo fulminante. Mira cómo la nieve queda estampadas con tus pasos ligeros mientras te mueves en el escenario o cómo tus huellas se entrecruzan con el rastro sucedáneo de holo-balls con miras a destruirte (¡!). Mira el humo, ¡EL HUMO!
  • Escenarios nuevos: complace tu mirada con la pradera nevada, el bosque, el pantano. Tienes que saber que hay cierta aleatoriedad así que es posible que no lo veas a la primera, ni a la segunda. Tampoco es para que las cuentes. Juega, disfruta, eso es todo.

De acuerdo. Suena bien. ¿Tengo que pagar por esto?

¡JA! Esa es la mejor parte. No (aunque posiblemente querrás pagar luego). Es una build. No es un juego completo. Hay mucho por hacer y mucho por pulir, pero te da una idea de lo que viene.

Si quieres ayudarnos, y nos fascina que quieras ayudarnos, sería muy conveniente que regaras la voz. Twitter, Tumblr, Facebook, Tinder, Tuenti, Google+ (no, mentira, nadie usa eso), LinkedIn, MySpace (¿todavía existe MySpace?), Pinterest, StumbleUpon, Reddit, donde quieras. Un comentario, un enlace a la descarga, lo que quieras. Todo ayuda ;).

Más vale que no me decepcionen…

No lo haremos.

De acuerdo. ¿Dónde la descargo?

Directamente desde Dropbox.

O de nuevo, si prefieres, también puedes descargarla desde indiedb.

Muchas gracias chicos.

No, no, gracias a ti artificio narrativo.

More Foes

La comunidad indie es una comunidad sana y en constante crecimiento, por eso es habitual encontrar a un equipo indie hablando de otro.

Hace unas semanas hablábamos del videojuego Wizards of Legend, esta vez lo hacemos de More Foes, un pequeño estudio indie llevado por dos personas.

More Foes empezó desarrollando un videojuego llamado Chosen, muy prometedor y con un sello muy personal. Sobretodo para los fans de QuakeDoom, porque claramente hay muchas referencias y guiños que recuerdan a los títulos insignia de Id Software.

Por el momento, a fecha de 2017, han pausado el proyecto Chosen, aunque esperan continuarlo. En su lugar han empezado un nuevo desarrollo, Nazis Time. Un videojuego menos ambicioso, pero igualmente prometedor.

Nazis Time se presenta como un top-down shooter con generación procedural de mapas, donde manejamos a dos carismáticos personajes: Adam y Ricky.



Me encanta el diseño artístico y la puesta en escena que nos ofrece este estudio, por su sello explícito y visceral y por su propuesta Pixel Art bien cuidada.

Espero que sean capaces de terminarlos, porque estaré encantado de poderlos jugar.

Os dejo el enlace a su Blog y Twitter para que los podáis seguir.


More Foes: Twitter & Blog


¡Desde Sticks & Stones les deseamos mucha suerte!

 

El reto de combinar ciertas mecánicas – Solución

En la entrada de hoy, vamos a explicar cómo hemos afrontado el mayor (por lo menos, hasta la fecha) de los problemas de diseño de Sticks & Stones.

Allá por noviembre publicamos una entrada en la que hablábamos del reto de combinar ciertas mecánicas, y de cómo el hecho de aventurarnos a experimentar con ellas nos ocasionó ciertos problemas:

Rogue-like – Empezar desde cero – VS – Crafting – Construcción progresiva

El problema aquí es que puede llegar a cansar el tener que pasar siempre por las mismas fases del crafting, recolectar ingredientes, craftear, recolectar ingredientes, craftear, …

Rogue-like– Zonas pequeñas – VS – Supervivencia – Sensación de exploración

El problema aquí casi casi se lee solo. El juego tendrá zonas más bien pequeñas, pero la sensación de supervivencia se consigue con ambientes muy grandes para potenciar la necesidad de explorar.

En el artículo actual, desarrollaremos la solución que diseñamos para paliar estos problemas, que aunque, si bien no los elimina por completo, los minimiza bastante.

– ANTES –

Para poder explicar esto,  volvamos al  esquema de juego que teníamos hasta entonces:

gamerunold

 

El desarrollo del juego era muy sencillo, el jugador aparecía en la Zona A y tenía que pasar por todas las demás zonas hasta llegar a la última. Todas y cada una de las zonas tenía partes de exploración, recolección de recursos y combate.

– ACTUAL –

En la actualidad hemos apostado por el siguiente esquema :

gamerunnew

 

El desarrollo aquí se concentra en  empezar en la zona central y recorrer las zonas A, B, C y D en el orden que se quiera, para finalmente ir a la zona final. Con la peculiaridad que la zona central es exclusivamente de exploración y recolección, mientras que las zonas A, B, C y D se centran, casi en exclusiva, en combate. Así, para acceder a la zona final, antes habrá que finalizar las zonas de la A a la D.

ANALISIS

A priori parece una solución bastante sencilla – solo se mueven 4 cajitas y flechitas entre ambos esquemas. Pero este nuevo enfoque aporta un montón de ventajas, mejoras y mitiga bastante los problemas descritos anteriormente.

Vayamos a ver punto por punto lo que nos aporta este nuevo enfoque:

 

PLANIFICACIÓN

Empezamos el juego en la zona central, llena de recursos y sin ninguna amenaza. Somos nosotros los que decidimos el tiempo que invertimos para recolectar recursos y construir nuestras propias armas. Cuando nos sintamos preparados para entrar en combate, solo será necesario coger uno de los 4 ascensores disponibles (A, B, C o D).

¿Qué nos aporta este cambio de enfoque y el nuevo esquema? Pues que el juego ya NO marca el camino ni el ritmo de jugador, sino que cada uno escogerá el suyo propio, haciendo el juego más estratégico, más frenético o más conservador, dependiendo del momento y las necesidades.

Aparte de eso, la construcción está basada de tal modo que, esta primera zona sea la que concentre la mayoría de recursos en todo el juego, lo que hace que tengamos que medir muy bien su uso.

En el anterior esquema, el hecho de que era necesario avanzar de forma obligatoria por las zonas (sin poder volver atrás), hacía que la recolección y la exploración fuera más necesaria e incierta. Ya que no sabías nunca qué recursos ibas a encontrarte en las futuras zonas, y muchas veces acababas con el síndrome de Diógenes recogiendo todo lo que podías cargar en la mochila.

REPETICIÓN MÁS VARIADA

La posibilidad de afrontar cualquiera de las 4 zonas desde el minuto 1, permite que las partidas sean más variadas, ya que cada zona tiene sus propios enemigos, retos, peculiaridades y dificultades que hacen que se tengan que afrontar de forma muy distinta, y llegar a ellas con recursos diversos.

En el anterior esquema, el orden de las zonas era prefijado y las partidas, al conocerse el camino a seguir, podían convertirse en una repetición de acciones de forma sistemática. Adicionalmente nos enfrentábamos a una limitación a nivel de diseño, que consistía en desarrollar el entorno de tal modo que todas las zonas tuvieran recursos suficientes para poder ir avanzando en el juego.

RUN NO LINEAL

El talón de Aquiles de cualquier diseño Rogue-like es la linealidad y puede crear frustración. Los que estén familiarizados con el concepto de juego rogue-like saben que la base siempre es la misma: jugar-morir-aprender, jugar-morir-aprender, jugar-morir-aprender… Así hasta acabar el juego (o no).

Por lo que el empezar cada partida siempre desde el principio, puede convertirse en un camino de frustración, que, en consecuencia, lleva a la triste verdad: el juego cae en el olvido a la primera de cambio.

Creemos que este nuevo esquema de orden no-lineal que se traduce en poder finalizar las 4 zonas en el orden que se quiera, debería ayudar mucho a afrontar de forma más amena el desarrollo del juego. Además, claro está, de toda la variedad que se le pueda dar a nivel de contenido (selector de concursantes, sponsors, ventajas, etc…)

¿Qué os parece esta solución? ¿Creéis que es un esquema y una vuelta de tuerca que podría  funcionar?

Nos encantaría saber vuestras impresiones y leer cualquier comentario al respecto, tanto si creéis que es buen enfoque como no.

Muchas gracias por leernos.

 

¡Cómo molan las Holoballs!

El concepto de Holoball nos ha acompañado desde muy temprano, nació en los inicios del proyecto Sticks & Stones. Ha ido tomado varias formas, colores y comportamientos, pero su esencia se ha mantenido.

La idea es tan simple como atractiva:

Holoball – bola que proyecta un holograma sobre si misma.

Partiendo de esta base tan sencilla, las Holoballs se presentan como los enemigos de los concursantes, impidiéndoles que alcancen su objetivo – finalizar el show.

Centrémonos en qué son exactamente las Holoballs. Por una parte, su exterior está recubierto de un material parecido al caucho que le otorga omniresistencia (resistencia a prácticamente todo). Y por otra banda, las tripas de estas bolas albergan un sistema de engranajes que les permiten coger tracción sobre cualquier superficie conocida.

A nivel técnico, la superficie de las Holoballs está llena de micro-cámaras, que tienen la capacidad de proyectar hologramas representando cualquier forma y color. Y en el caso de necesidad, es posible proyectar hologramas a distancia, aunque siempre hasta cierto límite.

Cada una de las Holoballs puede ser programada para tener un aspecto y un comportamiento totalmente distinto. Y aunque técnicamente son casi indestructibles, están preparadas para recibir y procesar cualquier tipo de daño, tanto físico como holográfico.

Aquí tenéis un pequeño esquema de las tripas de las astutas Holoballs:

holoball

Una vez explicado esto, os dejamos un pequeño avance de algunas Holoballs que tenemos desarrolladas hasta ahora.

El pistolero (Gunslinger)

gunslinger

Esta Holoball centra su ataque a distancia (range). Siempre lleva consigo su revólver con 6 disparos en la recámara. Su mecánica es perseguir al concursante y rodearlo mientras le dispara sin parar.

El Carnero Salvaje (Wild Ram)

wildram

El carnero ataca cuerpo a cuerpo (melee) con su embestida. Tiene poca tracción y sus movimientos son un poco impredecibles a la vez que ágiles. Es crítico calcular sus movimientos y estudiarlos para saber cuando se le puede atacar.

 

En la medida que vayamos desarrollando más Holoballs, os las mostraremos aquí.

Y como siempre, si os ha gustado el artículo: ¡compartidlo!

Diseño y programación – Supervivencia y consumibles

En este post contaré cómo hemos diseñado y programado el sistema de supervivencia y consumibles, que afectan directamente a la mecánica de supervivencia.

El post se divide en 3 apartados:

  1. Supervivencia: la mecánica relacionada con los consumibles.
  2. Consumibles: los objetos que representan el concepto de consumibles.
  3. Colores: los colores que identifican los diferentes indicadores de supervivencia.

 

Supervivencia

Es una de las mecánicas del videojuego que sirve para hacer más difícil el reto al jugador. Durante la partida, sufrirá de hambre, deshidratación y sueño. Para lidiar con ello, tendrá que buscarse la vida, sobre todo utilizando el entorno natural en el que se encuentra. Podrá cazar animales, beber agua, dormir, recoger frutos silvestres, fruta, setas y otras tantas cosas.

Por tanto, la supervivencia mide tres factores:

  • Hambre hunger-icon
  • Deshidratación dehydration-icon
  • Sueño sleep-icon

Cada uno de estos factores tiene su indicador y se dividen en varias propiedades, que permite tener el control del estado de supervivencia de los personajes.

survival-status

Propiedades de supervivencia

La supervivencia está vinculada a los personajes orgánicos, como los concursantes, de manera que cada personaje define dos métricas importantes para cada uno de los factores de supervivencia (hambre, deshidratación y sueño):

  • El tiempo que tarda en desmayarse
  • La cantidad de puntos que necesita para quedar saciado

El código que verás a continuación, es parte del script de un personaje orgánico, donde definimos las propiedades de supervivencia.

  • Tiempo desmayo por hambre: indica el tiempo para desmayarse por hambre o desnutrición, expresado en segundos.
  • Tiempo desmayo por deshidratación: indica el tiempo para desmayarse por deshidratación, expresado en segundos.
  • Tiempo desmayo por sueño: indica el tiempo para desmayarse por sueño, expresado en segundos.
  • Puntos para saciar el hambre: puntos necesarios para saciar completamente el hambre.
  • Puntos para hidratarse: puntos necesarios para hidratarse completamente.
  • Puntos para aliviar sueño: puntos necesarios para aliviar el sueño completamente.
  • Tiempo durmiendo para recuperar sueño: tiempo necesario que se necesita dormir para recuperar completamente el sueño, expresado en segundos.
/// <summary>
/// Cualquier personaje del juego que sea orgánico, por ejemplo un concursante o un animal de la fauna.
/// </summary>
public abstract class OrganicCharacter : CharacterBase
{

...

  /// <summary>
  /// Tiempo para desmayarse por hambre o desnutrición (en segundos).
  /// </summary>
  public abstract float TimeToFaintFromHunger { get; protected set; }

  /// <summary>
  /// Tiempo para desmayarse por deshidratación (en segundos).
  /// </summary>
  public abstract float TimeToFaintFromDehydration { get; protected set; }

  /// <summary>
  /// Tiempo para desmayarse por sueño (en segundos).
  /// </summary>
  public abstract float TimeToFaintFromSleep { get; protected set; }

  /// <summary>
  /// Puntos necesarios para nutrirse al completo y saciar el hambre.
  /// </summary>
  public abstract ushort PointsToSatiateHunger { get; protected set; }

  /// <summary>
  /// Puntos necesarios para hidratarse al completo y saciar la sed.
  /// </summary>
  public abstract ushort PointsToHydrate { get; protected set; }

  /// <summary>
  /// Puntos necesarios para aliviar el sueño.
  /// </summary>
  public abstract ushort PointsToAlleviateSleep { get; protected set; }

  /// <summary>
  /// Tiempo necesario para recuperarse por completo del sueño,
  /// desde un estado completamente agotado o cansado por sueño (en segundos).
  /// </summary>
  public abstract float SleepTimeForFullRecovery { get; protected set; }

...

}

Métodos de consumo de los personajes

El código que añado a continuación, muestra algunos de los métodos de los personajes orgánicos, que permiten interactuar con los consumibles o consultar el estado de supervivencia.

  • Comprobar desmayo: indica si el personaje se ha desmayado por alguna de las propiedades de supervivencia.
  • Consumir: actualiza los indicadores de supervivencia del personaje para un consumible.
  • Beber una bebida: actualiza los indicadores de supervivencia de un personaje para una bebida.
  • Beber de un contenedor: da un sorbo a la bebida contenida en el contenedor de bebidas.
  • Dormir: actualiza el indicador de supervivencia que corresponde con el sueño aumentando los puntos correspondientes al tiempo dormido.
/// <summary>
/// Cualquier personaje del juego que sea orgánico, por ejemplo un concursante o un animal de la fauna.
/// </summary>
public abstract class OrganicCharacter : CharacterBase
{
 
...

 /// <summary>
 /// Indica si el personaje se ha desmayado por falta de comida, hidratación o cansancio.
 /// </summary>
 /// <returns>'Verdadero' si se ha desmayado, 'Falso' en caso contrario.</returns>
 public bool IsFaint()
 {
   return (CurrentFeedingPoints <= 0 || CurrentHydrationPoints <= 0 || CurrentStimulationPoints <= 0);
 }

 /// <summary>
 /// Consumir algún alimento, bebida o estimulante.
 /// Modificará el estado de supervivencia del individuo.
 /// </summary>
 /// <param name="consumable">Objeto a consumir.</param>
 public void Consume(Consumable consumable)
 {
   if (consumable != null)
   {
     // Alimentación
     float estimatedFeedingPoints = (consumable.FeedingPoints + CurrentFeedingPoints);

     if (estimatedFeedingPoints > PointsToSatiateHunger)
     {
       estimatedFeedingPoints = PointsToSatiateHunger;
     }

     CurrentFeedingPoints = estimatedFeedingPoints;

    // Hidratación
    float estimatedHydrationPoints = (consumable.HydrationPoints + CurrentHydrationPoints);

    if (estimatedHydrationPoints > PointsToHydrate)
    {
      estimatedHydrationPoints = PointsToHydrate;
    }

    CurrentHydrationPoints = estimatedHydrationPoints;

    // Estimulante
    float estimatedStimulationPoints = (consumable.StimulationPoints + CurrentStimulationPoints);

    if (estimatedStimulationPoints > PointsToAlleviateSleep)
    {
      estimatedStimulationPoints = PointsToAlleviateSleep;
    }

    CurrentStimulationPoints = estimatedStimulationPoints;
  }
 }

 /// <summary>
 /// Consumir una bebida.
 /// Modificará el estado de supervivencia del individuo, normalmente afectando a su hidratación.
 /// </summary>
 /// <param name="drinkSource">Fuente o surtidor de bebida.</param>
 public void Drink(IDrinkSource drinkSource)
 {
   if (drinkSource != null)
   {
     GameObject drinkCandidate = GameObjectFactory.GetSample(drinkSource.DrinkType);

     if (drinkCandidate is Drink)
     {
       Drink drink = (Drink)drinkCandidate;
       Consume(drink);
     }
   }
 }

 /// <summary>
 /// Beber o dar un sorbo de un contenedor de bedida, por ejemplo, una cantimplora.
 /// </summary>
 /// <param name="drinkContainer">Contenedor de bedida del que se va a dar un sorbo.</param>
 public void Drink(DrinkContainer drinkContainer)
 {
   if (drinkContainer != null)
   {
     if (!drinkContainer.IsEmpty())
     {
       drinkContainer.Use();
       Drink(drinkContainer as IDrinkSource);
     }
   }
 }

 /// <summary>
 /// Dormir un tiempo limitado.
 /// Modificará el indicador de sueño del individuo.
 /// </summary>
 /// <param name="sleepTime">Tiempo de descanso o sueño (en segundos).</param>
 public void Sleep(float sleepTime)
 {
   float calculatedPointsBySecond = sleepTime * SurvivalStatusEngine.GetRecoveryPointsWhenSleep(this);
   float estimatedStimulationPoints = (CurrentStimulationPoints + calculatedPointsBySecond);

   if (estimatedStimulationPoints > PointsToAlleviateSleep)
   {
     estimatedStimulationPoints = PointsToAlleviateSleep;
   }

   CurrentStimulationPoints = estimatedStimulationPoints;
 }

...

}

Los tres indicadores de supervivencia (hambre, deshidratación y sueño) tienen un valor que va disminuyendo con el tiempo, cuando cualquiera de estos llega a 0, el concursante se desmaya y pierde la partida. Para impedir que eso ocurra, el concursante debe consumir ciertas cosas para aumentar dicho valor. Estas cosas son las que antes he llamado consumibles.

 

Consumibles

En el videojuego, un elemento consumible es cualquier cosa que se puede consumir, como por ejemplo carne, agua, setas, fruta… Todos los consumibles tienen lo que llamamos puntos de supervivencia.

Puntos de supervivencia

Los consumibles otorgan puntos de supervivencia al consumirlos, aumentando el tiempo que el personaje puede aguantar sin desmayarse. Cuando hablamos de puntos usamos la siguiente nomenclatura:

  • Para saciar el hambre: puntos de alimento
  • Para hidratarse: puntos de hidratación
  • Para aliviar el sueño: puntos de estimulación

Por ejemplo, consumir moras añade 7 puntos de alimento a los indicadores de supervivencia del personaje. Esto aumentará el tiempo que tiene el concursante antes de desmayarse por hambre.

survival-stats-example

Es posible que un consumible pueda dar puntos a más de un indicador de supervivencia. Por ejemplo una naranja, otorga puntos de alimentación e hidratación.

Caducidad

Los consumibles pueden caducar, lo que significa que transcurrido su tiempo de caducidad se echan a perder y no se pueden consumir.

Actualmente tenemos deshabilitada esta opción por temas de jugabilidad. Creemos que es una mecánica más pesada que divertida y por el momento no la utilizamos.

Esto abre la puerta a otras mecánicas interesantes, como por ejemplo: si un consumible caducado se encuentra en un contenedor con otros consumibles, podría contagiar al resto y acelerar el tiempo que tardan en echarse a perder… Pero como he dicho, es una mecánica que de momento no vamos a utilizar 😛

El código de los consumibles

En nuestro código disponemos de una clase que representa este concepto de objeto consumible, a la que llamamos Consumable.

Las propiedades más relevantes son:

  • Puntos de alimentación: cantidad de puntos de alimentación que se obtiene al consumirlo.
  • Puntos de hidratación: cantidad de puntos de hidratación que se obtienen al consumirlo.
  • Puntos de estimulante: cantidad de puntos de estimulante que se obtienen al consumirlo.
  • Tiempo de caducidad: tiempo total que tarda en caducar.

Los métodos más relevantes son:

  • Comprobar estado de caducidad: indica si el consumible ha caducado.
  • Comprobar si caduca: indica si el consumible caduca. Hay consumibles a los que no aplica la caducidad en el videojuego, como por ejemplo el agua.
/// <summary>
/// Cualquier elemento que se puede consumir, como por ejemplo bebida, comida, estimulantes, etc.
/// </summary>
public abstract class Consumable : GameObject
{
 #region Constructor
 protected Consumable() : base()
 {
   if (BaseExpirationTime > 0)
   {
     float minExpirationTime = BaseExpirationTime * ((100f - ExpirationTimeMargin) / 100f);
     float maxExpirationTime = BaseExpirationTime * ((100f + ExpirationTimeMargin) / 100f);
     float expirationTime = CustomConstants.Random.Next((int)minExpirationTime, (int)maxExpirationTime);
     ExpirationTime = expirationTime;
     RemainingExpirationTime = expirationTime;
   }
 }
 #endregion

 #region Properties
 /// <summary>
 /// Margen en el que el tiempo de caducidad definido puede variar (en porcentaje).
 /// </summary>
 protected const float ExpirationTimeMargin = 10;

 /// <summary>
 /// Puntos de alimento que se obtienen al consumir esto.
 /// Sirven para saciar el hambre y mitigar la desnutrición.
 /// </summary>
 public abstract ushort FeedingPoints { get; }

 /// <summary>
 /// Puntos de hidratación que se obtienen al consumir esto.
 /// Sirven para saciar la sed y mitigar la deshidratación.
 /// </summary>
 public abstract ushort HydrationPoints { get; }

 /// <summary>
 /// Puntos de estimulación contra el sueño que se obtienen al consumir esto.
 /// Sirven para combatir el sueño, como la cafeína.
 /// </summary>
 public abstract ushort StimulationPoints { get; }

 /// <summary>
 /// <para>Tiempo base que tarda esto en echarse a perder, con el tiempo
 /// expirado no se puede consumir (en segundos).
 /// </para>
 /// <para>El tiempo real de caducidad queda definido por un margen pequeño
 /// que puede acortar o alargar la duración total.</para>
 /// <para>El valor 0 indica que no caduca.</para>
 /// </summary>
 public abstract float BaseExpirationTime { get; }

 /// <summary>
 /// Tiempo restante, que le queda al consumible para caducar o echarse a perder (en segundos).
 /// </summary>
 public float RemainingExpirationTime { get; set; } = 0;

 /// <summary>
 /// <para>Tiempo real que tarda esto en echarse a perder.</para>
 /// <para>Este tiempo no es constante, depende de un pequeño margen definido
 /// internamente que puede acortar o alargar la caducidad.</para>
 /// <para>Ver 'ExpirationTimeMargin'</para>
 /// </summary>
 public float ExpirationTime { get; protected set; } = 0;
 #endregion

 /// <summary>
 /// Obtiene el porcentaje actual de caducidad del consumible.
 /// Representa porcentualmente cuanto tiempo le queda para caducarse.
 /// </summary>
 /// <returns>Porcentaje restante antes de caducar.</returns>
 public float GeCurrentExpirationPercent()
 {
   return (RemainingExpirationTime / ExpirationTime) * 100f;
 }

 /// <summary>
 /// Indica si el consumible ha caducado.
 /// </summary>
 /// <returns>'Verdadero' si ha caducado, 'Falso' en caso contrario.</returns>
 public bool IsExpired()
 {
   return (IsExpirable() && RemainingExpirationTime <= 0);
 }

 /// <summary>
 /// <para>Indica si el consumible tiene tiempo de caducidad.</para>
 /// <para>Nota: Un consumible con una tiempo base de caducidad de 0 se considera no-caduco.</para>
 /// </summary>
 /// <returns>'Verdadero' si puede caducar, 'Falso' en caso contrario.</returns>
 public bool IsExpirable()
 {
   return (BaseExpirationTime > 0);
 }
}

La naranja sería un ejemplo de implementación de un consumible:

/// <summary>
/// <para>Naranja natural. Se obtiene del naranjo.</para>
/// <para>Datos orientativos del fruto: Calorías: 47; Agua: 87%</para>
/// </summary>
public class Orange : Consumable, IInventariable, IDamageDealer
{

...

 #region Inventariable
 public InventariableType InventariableType { get; } = InventariableType.Orange;

 public bool Stackable { get; } = true;

 public float Weight { get; } = 0.2f;
 #endregion

 #region Consumable
 public override float BaseExpirationTime { get; } = 0f;

 public override ushort FeedingPoints { get; } = 28;

 public override ushort HydrationPoints { get; } = 10;

 public override ushort StimulationPoints { get; } = 0;
 #endregion

 #region Damage Dealer
 public DamageSource DamageSource { get; } = new DamageSource(
 new Dictionary<DamageType, int>()
   {
     { DamageType.Crushing, 1 }
   },
   null);

 public bool CanBeHurled { get; } = true;
 #endregion
}

 

Colores

A cada factor de supervivencia le hemos asociado un color que permita identificarlo.

hunger-icon                        dehydration-icon                     sleep-icon
Hambre        
Deshidratación        Sueño

Utilizamos una clase que centraliza estos valores en forma de constantes, de manera que podamos cambiar estos valores de forma fácil si lo necesitamos.

Para elegir los colores hemos utilizado Adobe Kuler, una herramienta muy útil e interesante para buscar sintonía entre colores.

/// <summary>
/// Color base relacionado con el hambre.
/// </summary>
public static Color HungerColor new Color(139, 127, 89);
 
/// <summary>
/// Color base relacionado con la deshidratación.
/// </summary>
public static Color HydrationColor new Color(140, 190, 178);
 
/// <summary>
/// Color base relacionado con el sueño.
/// </summary>
public static Color SleepColor new Color(198, 168, 201);

Eso es todo (a alto nivel) en cuanto a diseño y programación sobre el sistema de supervivencia y los consumibles.

Si tienes dudas o curiosidad por saber el detalle de alguna cosa ¡espero tus comentarios!

 

 

El Motor del Videojuego – III

Contexto

Si acabas de aterrizar en el Blog, te recomiendo que antes de continuar que te dejes caer por aquí:

Así mismo recomiendo leer también las 2 entradas que hablan sobre YokaiEngine – el motor que estamos creando para desarrollar Sticks & Stones:

Auto-cast de objetos

El artículo de hoy se va a centrar en lo que llamo auto-cast de objetos de Flash a C#.

Para que me sea más sencillo de explicar en qué consiste el auto-cast, voy a recurrir de nuevo a nuestro personaje de ejemplo Sigfrid – El Paladín.

Imaginemos que hemos creado una animación en Flash y la llamamos paladin:

paladin_instance

Tal y como hemos hablado en anteriores artículos, el motor es capaz de replicar todos los objetos Flash y sus animaciones de forma recursiva, y reconstruirlos tal cual en C#.

Sólo basta con definir en la Screen de juego una variable del tipo CustomSprite (propia del motor) con el mismo nombre que hemos usado en el Flash:

public class Screen PlayableScreen
{
      public CustomSprite paladin; 
}

Y obtenemos lo siguiente:

paladin

Imaginemos por un momento que queremos acceder a cualquier parte de la animación, por ejemplo a la espada. Para ello deberemos realizar los siguientes pasos:

  1. Dar un nombre identificativo al objeto Flash
  2. Crear jerarquía de clases C# para definir padres-hijos

Vamos a asignar un nombre al objeto de la espada, en este caso le llamaremos weapon.

weapon_instance

Clases tipadas

Sigfrid, nuestro paladin, va a dejar de ser una clase del tipo CustomSprite (que es genérica) para pasar a tener su propia clase – PaladinCharacter. Lo que nos va a permitir poder definir dentro contenido propio:

public class Screen PlayableScreen
{
      public PaladinCharacter paladin; 
}
public class PaladinCharacter CustomSprite
{
      public CustomSprite weapon;
}

De esta manera ya podríamos tener acceso al arma a través del objeto paladin, y por ejemplo hacerla desaparecer:

public class Screen PlayableScreen
{
    public void RemoveWeapon()
    {
        paladin.weapon.Visible = false;
    }

no_weapon

Cuando el motor recrea los objetos del Flash, lo que hace es crear instancias automáticamente al tipo indicado en la definición de la variable. En nuestro caso:

  • paladin lo castea al tipo PaladinCharacter
  • sword lo castea al tipo CustomSprite

Recursividad

Esta técnica de auto-cast es recursiva y puede comprender todos los niveles que se necesiten. Profundizando más en el mismo ejemplo, podríamos tener la siguiente estructura:

public class PaladinCharacter CustomSprite
{
      public Weapon weapon;
      public Helmet helmet;
      public Shield shield;
}
public class Weapon CustomSprite
{
      public Blade blade;
      public Grid grip;    
      public CrossGuard crossGuard;
}
public class GripCustomSprite
{
      public Handle handle;
      public Jewel jewel;    
}

Listas

El auto-cast también funciona con listas. En el caso que tengamos más de un objeto del mismo tipo, por ejemplo los brazos (en este caso 2), en el Flash los identificamos con el mismo nombre acabado en número  (arm0 y arm1):

instance_arm

Ahora solo basta con tiparlo como una lista y ya:

public class PaladinCharacter CustomSprite
{
      public Weapon weapon;
      public Helmet helmet;
      public Shield shield;
      public List<Arm> arm;
}

Generar cualquier estructura jerarquizada de objetos es muy útil para poder realizar animaciones complejas y aún así tener el control total de acceso a cualquier objeto (para poder realizar la transformación).

 

¡Si te ha gustado compártelo! :]