Behind the scenes with: Salmonomicon
The tips, tricks and secrets of Salmonicon's creators revealed
Welcome to the second post in our series on the work, techniques and secrets of creators, actively making games and experiences that bring Decentraland to life.
In this post we’re taking a look at the game Salmonomicon.
Although this game mostly got attention during the Decentraland launch event, it was actually created in September of the previous year (which in Decentraland time feels like a whole year ago). It was built as part of an internal hackathon by a team of Decentraland developers – Pravus, Mauricio and Nico – and makes use of several neat tricks we wanted to share.
You can find the full code for this scene in our public GitHub repo. Feel free to take ideas and use them with your own projects: https://github.com/pravusjif/salmonomicon
If you’re not familiar with the scene, you can also jump into the world and play it: play.decentraland.org/?position=-56,1
Or check out this demo video: https://www.youtube.com/watch?v=H78Mv_u-wJk
But onto the details of how we built Salmonomicon!
Raycasting is a common tool in game development. It basically consists of tracing a line in space (a ‘ray’) and checking if that line intersects with any other objects. It’s often used to simulate the field of view of an AI or to calculate the trajectory of a bullet.
At the time of developing Salmonomicon, raycasting had only just been added to the Decentraland SDK, so we started our brainstorming around the idea of making a game that took advantage of this.
In the game the monster goes through two different stages. In each of these stages it uses raycasting in a different way.
In the first of these stages, the monster is out to get you and is always moving slowly towards the player. If the player looks at the monster then it moves even faster. The way to defeat the monster is to look away from it at all times – something that goes against our instincts and leaves us with an uneasy feeling of not knowing how much danger we are in. The perfect ingredients for making a terrifying game experience!
To work this mechanic into our game, we did the following:
- In every frame we traced a ray between two points: the player’s position and the monster’s position, then we checked to see if this line hit any other objects
- If there was something in between the player and the monster, like a tree or a wall, we assumed the player was not in the monster’s field of view and was safe
- We also calculated the angle between the ray that we traced and the direction in which the player was looking. As the player faced in a direction closer to that of the monster, the angle got smaller. So as this happened, the monster started moving faster.
In the second stage of the game, once all the pages have been collected, the monster spins in place shooting lasers out of its eyes (of course!). Here we used raycasting in a different way. We wanted to detect if the player was hit by a laser, but unfortunately we don’t have a ‘player’ object that can be hit by the ray (not yet… interesting project to work on later). So the way we worked around this was by tracing two different rays:
- One ray went between the position of the player and that of the monster. On every frame we checked if there were any objects in between them, if there were any, then the player was shielded from the laser.
- The second ray went in the direction the monster was looking. If the ray hit any obstacles while the monster spun around, then we shortened the glowing red beam to match, so that the laser didn’t appear to pierce through trees.
We finally compared the direction of these two rays. It’s hard for them to be exactly equal, since a frame would need to land exactly right for that to happen, so we measured the angle between both rays and considered a margin of error. If the angle between them was small enough, then we could determine that the monster was facing the player. Once we confirmed that the monster was facing the player, and that there were no obstacles in between, then it was safe to say that the player had been hit by the laser.
Want to use raycasting in your own projects? Read more about how to use it in our docs: https://docs.decentraland.org/development-guide/raycasting/
As you play the game, you carry the severed head of Mika around with you; Mika being the chef at Decentraland headquarters in Buenos Aires. He was kind enough to lend his head for a photoshoot without knowing what bizarre things we’d be using the pictures for.
We chose to display his head as a 2D image on the UI, rather than a 3D object. Having a 3D object move together with the player doesn’t look as smooth since the position of the object isn’t adjusted in perfect sync with each frame leading to a distracting stutter. 2D also allowed us to honor the legacy of classic games like Doom.
As you hunt for the lost pages of a book, Mika’s eyes guide you in the direction of the closest page. For this we used several different pictures of Mika looking in different directions. Rather than using a separate image for each of these pictures, we put them all in a single sprite sheet. We only displayed a section of the image at a time and simply switched from one image mapping to another. This turned out to be much more efficient than having separate images, as we didn’t have to load and unload images onto the memory during play.
One strange and unexpected occurrence: at the time of building the game there was no third-person camera in Decentraland. When we tested the game later with the third person camera it looked like you were chasing yourself.
Read more about how to use UIs in a scene in our docs: https://docs.decentraland.org/development-guide/onscreen-ui/
The artist in our team, Mauricio, tried a really nice trick that added a whole other dimension of spooky to our game.
A skybox surrounds the scene, adding a night sky and a spooky forest backdrop. What’s innovative about this is that the normals of the model are intentionally only facing inwards, this means that if you look at the scene from the outside, you only see the backdrop and nothing blocks your view of what’s inside the scene. Once inside, though, you’re entirely immersed in the forest.
This skybox mesh also includes colliders that only have normals facing inwards, thanks to this you can easily walk in, but then you can’t leave… not until you defeat the curse of Salmonomicon. Once you win the game, the skybox is removed and you’re free to walk away. Removing the skybox also makes it daytime again, this has a dramatic effect on how the scene looks and accompanies the victorious music perfectly.
Read more about 3D modeling for Decentraland in the docs: https://docs.decentraland.org/3d-modeling/3d-models/
Stay tuned for future posts with more of Decentraland’s scene stars, including behind the scenes looks at projects like Block Runner, Dragon Race and more. You can also check out our previous post on The Infinity Engine.