¿Cómo detectar logros en los juegos?

10

Lo publiqué por error en stackoverflow y ahora publico aquí en base a una sugerencia en ese sitio ...

Esta es una pregunta conceptual de muy alto nivel. Digamos que en una aplicación de software tengo 4 acciones diferentes, por ejemplo: cargar, compartir, comentar y dar me gusta

Y quiero dar insignias de logros a usuarios como:

  • Novato - Sube tus primeros 5 archivos
  • Upload Junkie - Sube 20 archivos en 1 día
  • Night Crawler: sube un archivo después de la medianoche
  • Share-a-holic - Comparte 10 archivos diferentes
  • Me gusta-todo: como 20 archivos diferentes

entiendes la idea. ¿Cuál es la mejor manera de verificar y ver si un usuario ha logrado un logro particular sin tener que compilar la lógica del logro en mi código? Y ... - Conserve la capacidad de agregar nuevos logros después de la compilación (xml o db) - Los logros deben rastrear acciones específicas, número de veces y criterios adicionales (como la hora del día) - La detección debe estar cerca del tiempo real para que el usuario notifique casi instantáneamente cuando se completa un logro

Mi mayor pregunta es, ¿cómo puedo detectar estos logros? ¿Yo:

1) Verifique después de cada acción para ver si ... (La mayoría de las veces en tiempo real) 2) ¿Tiene otro programa que verifique la base de datos en todo momento con un conjunto de reglas? (Más fácil)

¿Hay otro paradigma que me falta? Siento que definitivamente lo es porque en muchos juegos (como el jetpack para iOS, por ejemplo), me notifican el logro que he desbloqueado en el instante en que lo desbloqueo, lo que me pareció bastante impresionante.

Gracias

Tan Rezaei
fuente
¿Ya has diseñado o realizado el sistema de logros y solo quieres saber cómo usarlo en el juego?
Harrison Brock

Respuestas:

6

Lo que generalmente hace es tener un sistema de "logro". Cualquier acción que ocurra llama al sistema de logros y dice "oye, esto acaba de suceder".

El sistema de logros suele ser un conjunto de reglas, generalmente compuesto de lógica combinatoria simple y contadores para varios "eventos". Es entonces la responsabilidad del sistema de logros trabajar, con la ayuda de las reglas y los contadores, qué sucedió y qué logros dar.

La razón por la que haces esto es doble.

  • No desea difundir su lógica de estado en toda su base de código.

  • a veces los logros requerirán combinaciones de "cosas" que pueden suceder en sistemas / tiempos / etc. completamente diferentes y difundir la lógica para esto alrededor de su base de código daría como resultado grandes cantidades de complejidad innecesaria.

La forma en que lo he hecho en el pasado es usar un sistema de reglas programables (donde el script es un término muy flexible, generalmente solo un tipo de comparador basado en datos). Entonces puedes decir algo parecido a:

  • Cuando "el usuario presionó algo" sucede "incremente" la variable "presionada".

Entonces podrías tener otra regla que es

  • Cuando la variable "presionada" es "mayor" que "algún valor", entrega el logro "bla"

O quizás

  • Cuando "el usuario mata al jefe" sucede "reparte" logro "bla".

El sistema de logros también tendrá la tarea de mantener el estado de los logros que ya se han entregado, para que no obtenga duplicados.

Matt D
fuente
0

Una buena manera de manejar esto podría ser un patrón de especificación. Tendría un administrador de logros, que periódicamente consultaría a sus usuarios por aquellos que coincidan con cualquiera de un conjunto de especificaciones. Por lo tanto, su clase de logro incluiría un nombre, logotipo, puntaje, etc., como de costumbre, y también una especificación que describe a un usuario que ha obtenido ese logro. Por ejemplo, en C #, el logro "Compartir un holic" podría verse así:

AchievementType ShareAHolic = new AchievementType
{
    Name = "Share-a-holic",
    Description = "Shared 10 files",
    Score = 25,
    Specification = (user => user.SharedFiles.Distinct().Count() > 10)
};

AchievementManager.AddAchievementType(ShareAHolic);

y luego, en el punto apropiado, su administrador de logros puede hacer algo como esto:

foreach (AchievementType achievement in AchievementTypes)
{
    var users = DB.Users.Where(achievement.Specification && !(user.Achievements.Contains(achievement)));
    foreach (User u in shareaholics)
    {
        AchievementManager.Award(u, achievement);
    }
}

El .Award()método de su administrador de logros también se puede llamar directamente en el punto apropiado si se puede detectar un logro de inmediato. También es posible que desee agregar un método para ejecutar estas comprobaciones en un usuario específico, de modo que pueda activar una comprobación después de eventos importantes para permitir a los usuarios obtener logros de inmediato.

anaximandro
fuente
Particionar los logros se vuelve rápidamente importante, AchType necesita una propiedad 'sope' que pueda ayudar a DB.Users.Where () para evitar logros no relacionados, cuando sea posible. Entonces, si el logro de compartir archivos solo se puede otorgar en PvP, solo busque PvP. Si bien algo genérico como el saqueo podría ser factible a nivel mundial y no tendría ese alcance.
hpavc