Be Stiff! is a small game developed ni XNA, soon to be released in different flavors. The nicest flavor is the free one. Come here soon for videos, screenshots and more info.
This is taking a lot of time, but I think we are getting there. Be Stiff! is being modified… a lot. You see, some time ago I mentioned I needed a graphics designer or someone who knows about making stuff looking nice. Well since a couple (or three) months ago, I’ve been working with a great guy who indeed knows some stuff about graphics and design. So I expect to have soon some new screens and videos to show.
In the meantime, I’ve been playing around with Java. More specific with the LibGdx library which happens to be quite awesome. I’ve been porting part of the Be Stiff! code there as an excersise (I’m not planning to port the full game -for now- as some parts are Directx specific and I really don’t know how to convert that to OpenGL) like the 2D skeleton animation engine. Mayebe something for Android with emerge from this. Or maybe not.
I’ve been working on fixing a couple of bugs. The good news is that the Xbox version is working nice and the garbage has been significantly reduced, which means that I have a constant 60 frames per second on the console.
I’ve been working on a new tileset, so here’s a video showing it. But I want to talk a little on the game’s AI too. Look at the video, at the 7th second you’ll see that the enemy is calling for help (“F1″ he screams), then the guy with a pistol takes the elevator for checking out what’s going on.
I wanted to make the enemies smart enough to make the game challenging and force the player to at least think twice before entering shooting like crazy. That’s why the field of view is restricted, you cant run all the time, and the enemies try to attack in a coordinated way.
If an enemy spots you, he will call the closest partners. Then they try to coordinate by surrounding the player, by blocking the exits from the zone the player is in. Let me explain this with a couple of images:
Be Stiff Game AI Example
This image shows part of the map in the map editor (I’m using OGMO editor, if someone is interested), the yellow squares represent zones in the map, and the blue squares represent portals (not this kind of portals!). The portals represent a connection between two zones, indicating the enemy which action they should take to move from one zone to another (walk, jump, take an elevator…), so moving from one point to another is just an implementation of the A* algorithm for finding the best path, and tell the enemy to move to all the portals and perform the needed actions until he reaches the destination. The idea was inspired from this great article in Gamasutra.
So, what happens if an enemy spots the player? He calls for help (the “F1″ from the video), and when the help comes, they try to cover all the portals of the zone the player is in. In our example, if the player is spotted in the roof, the enemy will call for help, and they will cover the two portals the player should use in case he wants to flee:
Game AI Anemy Positioning
If the player kills one of the enemies, the “enemy team” reorganizes itself trying to cover as good as they can the player’s position. If the enemy team realizes that it can’t accomplish its goal (kill the player), it dissolves and then each enemy individually attacks the player (without any kind of coordination).
Pfew! That was a lot of text, anyway this was a quick view on how the AI works, I hope someone finds this interesting.
God, this is killing me. I’ve been through the whole development deciding which graphics style I want for the game. Now I have some kind of pixel art, but I’m still not convinced. Playing with Inkscape I finally got something, but still… not convinced at all, here is an before/after comparison:
OK, here’s the todo list (of the most urgent stuff to add):
- Add the storyline.
- Add more levels.
- Improve the code for hanging from the ledges (automatically hang?)
- Code for limited ammo and the chance to pick up a pistol when unarmed.
- Add the arena levels: Arena levels are infinite time levels where enemies are constantly spawning, so your score depends on how long you survived (and how many bad guys you killed). In some levels you are unarmed, in others you have the pistol.
Then I’ll work on graphics and music to improve them (or look for someone to improve them).
Aprovecho una pausa para hacer una pequeña actualización con el sistema de puntos en el juego, que ha sido uno de los temas espinosos durante el diseño. Resulta que por un lado quería que hubieran puntos en el juego, me encanta el concepto del High Score, es parte el espíritu que quería darle. El problema era cómo enfocar los puntos. Lo más lógico hubiera sido, un enemigo muerto, una cantidad de puntos, un objetivo alcanzado, otros puntos más. El problema de este enfoque es que el máximo puntaje por cada nivel es bastante estático: Hay cinco enemigos, tres objetivos, 100 puntos por enemigo, 50 puntos por objetivo, pues el puntaje máximo de ese nivel serían 650, y superarlos sería imposible.
Lo que pretendo es que el máximo puntaje sea algo más difícil de conseguir, de hecho que ni siquiera se pueda calcular cual es el máximo puntaje por cada nivel. Una solución a ese problema era la de, en lugar de puntuar objetivos y enemigos, que el puntaje estuviera determinado por el tiempo en acabar el nivel. A menor tiempo, mejor resultado. El problema es que ese enfoque rompe con toda la idea que tenía del juego, de que no fuera un juego de ir a toda velocidad, que estamos aquí para infiltrarnos en edificios y cosas así, no para cruzar corriendo por las pantallas. Está bien ir rápido, pero que no sea la única motivación.
La solución a la que llegué finalmente fue una mezcla entre las dos cosas, puntos por objetivos y tiempo. Resulta que los puntos tienen un valor fijo que está ponderado según el tiempo que se tardó en conseguirlo (S es el puntaje final, P el puntaje base por el objetivo y T el tiempo transcurrido en milisegundos):
Con esto, por ejemplo si a un objetivo le damos un puntaje base de 800, el puntaje que se consigue según la cantidad de segundos transcurrida es:
Parece complicado, pero no lo es una vez se ven los resultados, el puntaje se estabiliza cerca del minuto donde ya no es tan necesario ir con prisas. Igualmente se registra el tiempo con el que se consigue acabar un nivel, con lo que el jugador tiene la posibilidad de elegir cómo orientar cada nivel, e incluso el recorrido dentro de éste.
A ver como traduzco todo esto al inglés, por cierto…
English
So much time without an update. At least in the devblog, because the game development has continued without pause… well with some pauses. First the graphics: I changed the animations from a sprotesheet approach to a 2d skeleton system (inspired from here), the results are smoother animations, yay! The the lights and shadows system, which at the first I used Catalin Zima’s fantastic approach, as seen on the next video.
Castellano
Buf, bastante tiempo sin actualizar. Bueno, sin actualizar el devblog, pero el desarrollo sí que ha avanzado bastante. Primero, los gráficos, de los que me extenderé un poco más adelante. Cambié de un sistema basado en sprites animados a un sistema de esqueletos en 2D, el resultado, animaciones mucho más fluidas. Luego, el sistema de luces y sombras, en un principio usé la fantástica implementación de Catalin Zima basada en sombras a partir de píxeles en lugar de polígonos, aquí un video explicándolo:
English
The results were quite good, but I wasn’t totally happy with the shadows, that looked a little crispy, so I moved onto Krypton XNA great library. And now I’m happier:
Castellano
Los resultados estaban bastante bien, pero las sobras no me convencían del todo, así que me cambié Krypton XNA. Ahora sí:
It’s been a long time since the last update; lot of work (my full time job, I mean), summer holidays and… more work.
The physics engine integration is almost done, some details are pending though, I’ve made a lot of changes in the graphics in order to test colors, animations and such (also I created a Tile engine for the world drawing). And now I added a small detail: You can’t see through walls, but you can “see” the world noises. I mean, only the character’s line of sight is drawn (and the map shadowed when it is not possible to see), but the noises can be seen as text (an explosion makes “boom” if you know what I mean). Anyway, here’s a video showing how it works. The graphics are not definitive. I’m working on drawing by hand the graphics in order to give them a “sketch” feeling this is how they should look:
Castellano
Ha pasado un tiempo desde que no hacía ninguna actualización. Mucho trabajo, vacaciones de verano y bueno… algo más de trabajo.
La integración con el motor de físicas está bastante avanzada, quedan algunos detalles, he hecho varios cambios en los gráficos para ir probando colores y tal… Y ahora tiene por fin implementado un detalle: El no poder ver a través de las paredes, pero sí “ver” los sonidos. Quiero decir, si hay algo que no puede ver el personaje desde su punto de vista, no lo ve (el mapa se sigue mostrando eso sí, pero sombreado), pero los ruidos que hacen los enemigos sí que se pueden ver, como texto. Un video vale más que mil palabras en todo caso. Los gráficos no son los finales, estoy probando de dibujar los gráficos “a mano”, dándoles un aire de boceto (arriba se puede ver un ejemplo).
English
Looking for a better way to implement explosions (allow your character to cover to avoid damage and rotate the elements accordingly to the explosion’s angle), I found this interesting thread in the Box2D forums. I ported the code to C# and the results (in slow motion) can be seen in the video below (after the spanish text). Hooray for explosions!
Castellano
Buscando una mejor forma de implementar explosiones (esto es, poder cubrirte para evitar daños y rotar los objetos de acuerdo al ángulo respecto a la explosión), me encontré con este interesante hilo en los foros de Box2D. Convertí el código a C# y el resultado (en cámara lenta) es el que viene a continuación. ¡Vivan las explosiones!
Until now, I’ve been using Gleed2D for the level editing, but the problem was that the editor was too generic, so for each object in the level I had to define all its variables by hand. Plus, it seems that the development has stopped.
Now I’ve moved on to Ogmo Editor, which works great, as it uses a project definition with all the objects and their variables for creating the levels (variables like the elevator’s paths, or the zones and portals for the enemies pathfinding).
Is perfect, and works great thanks to OgmoXNA which makes the level importing to an XNA project a really easy process.
Castellano
Hasta el momento estaba usando Gleed2D para el diseño de los niveles de Be Stiff! El problema es que el editor era demasiado genérico, teniendo que definir demasiadas variables para cada objeto en el nivel. Además parece ser que el desarrollo del editor ha sido abandonado.
Ahora me he mudado a Ogmo Editor, que va perfecto, principalmente porque se puede hacer una definición de cada objeto y sus variables en un proyecto, con lo que luego al crear un nivel, cada objeto ya vendrá con sus variables respectivas (el ascensor con su camino determinado, cada zona y sus puntos de transición para el pathfinding de los enemigos, etc).
En fin, una maravilla, que funciona a la perfección con OgmoXNA para importar los niveles a un proyecto XNA (que es mi caso).