Game
Hedgehogs Can Fly
7 years ago

Image-Based Level System


As demonstrated in this video (at 2:30), the level system in the game works using image files.

5d0aaaf4dee70.png

This has several benefits:

  • I don’t have to write a level editor, and can use a fully featured image editor to make levels instead.

  • Low iteration time. There is no pre-processing step to get from image file to game data, the game uses the image files directly so “edit to play” time is low.

  • Lots of variety. Levels are not constrained to a simple tile grid allowing for terrain of any shape to create interesting levels.

I implemented this system in C++ using SFML for graphics, this devlog will outline the system and how it works. Be prepared for low level details!

Basics

In the game there are various terrain types. These are things like solid walls, bounce pads and lava. Every terrain type has a corresponding colour used to colour-code the image files. So the images files use colours corresponding to terrain types to build up a level. The game opens the image file and copies the pixels straight into it’s own buffer. We now have all the terrain data we need inside the game. Now we have to figure out how to draw it..

Rendering

We have the terrain DATA, but we don’t want to just render this because it would look pretty boring..

5d0aaaf550537.png

We can render the terrain with a fragment shader. For those that don’t know, a fragment shader is a little program that runs on the graphics card for every pixel of an object that you want to be drawn. It’s job is to decide what colour pixel should be rendered in any given position. Usually you just have a texture that you want to draw so the fragment shader just looks up a pixel from there, but we can do more complicated things. We can create a fragment shader that takes in our terrain data and uses it to draw the level with nicer textures.

In the game I decided that each terrain type will be rendered using a different texture.

  • Bouncy | Slow | Sticky | Lava


  • 5d0aaaf5abb89.png
    5d0aaaf61bf3c.png
    5d0aaaf685e49.png
    5d0aaaf6f1dc3.png

The fragment shader takes in the terrain data we loaded earlier and all of the textures for the different terrain types. Given a position, the fragment shader looks it up in the terrain data to determine the terrain type at this position. It uses this information to select the texture corresponding to the terrain type (one of the textures shown above). It then outputs a pixel from the selected texture. To handle empty space, the terrain fragment shader just outputs a transparent pixel.

In Hedgehogs Can Fly, the terrain ended up looking very abstract with mostly solid colours, but any textures can be used. You could use the same code to render grassy terrain for example.

Now we have a system that allows you create levels using colour coded images and render them with arbitrary textures. One question still remains, how do the physics work?

Physics

We want to simulate basic physics. We want the hedgehog to be flung around the level and bounce against solid terrain. For this to be possible, we need to figure out two main things: collisions and normals.

Collisions

We can look up specific coordinates in our terrain data to find out if they are solid or not. We know the position of the player, so the basic idea is to test points on the edge of the player to see if they are inside a solid part of the terrain. This is made simpler by the player object being a circle. You can do some basic trig to generate a list of points at the edge of the circle to test. Using this method we can determine the point of collision which we’ll need to calculate the normal..

Normals

To do any sort of physics when the player collides with the terrain, we need to know the normal vector of the terrains surface at the collision point. A normal vector of a surface is the vector pointing “away” from it.

5d0aaaf784193.png

This is a little tricky, since we only have an array of terrain data to work with, there is no inherent represenation of shapes.

To calculate the normal vector, you could introduce some sort of pre-processing step and bake the data into the image somehow, but this would increase the iteration time. In Hedgehogs Can Fly, I came up with a way to estimate the normal at any point near/on the terrain surface.

When a collision is dectected, we have the contact point. We know this point is somewhere near or on the terrain “surface”:

5d0aaaf87551d.png

We can call this point c. We then sample points around c in a square.

5d0aaaf8cc8f1.png

We can look up these points in the terrain data to determine if they are “solid” or “empty”. (Image zoomed up. Red dots denote solid pixels)

5d0aaaf9333eb.png

We take all of the sampled solid points and compute their average position, this produces a new point that we’ll call s. (Shown in blue)

5d0aaaf99a4ba.png

We can see that s is “deeper” in the terrain than c is. The normal vector is then just the vector from s to c.

5d0aaafa0fc64.png

I’ve found this method to work surprisingly well, It means that normals can be computed on the fly eliminating the need for a pre-processing step. Here’s a gif of the normal computation in action:

5d0aaafa6de6f.gif

As I run the cursor over the edge of the terrain, the normal vector is calculated pretty accurately!

Done!

If you found that interesting, let me know so I can do more stuff like this!
Twitter
YouTube

Terrrain Data

5d0aaafb796fd.png

In-Game

5d0aaafbd9de2.png


0 comments

Loading...

Next up

Release Date Hello everyone! I finally have a release date locked in for the game :) It will come out on March 8th! Here’s a gif to celebrate..

"Fireworks"

Different Terrains

Short intro of us 💕✌️

We're an eletro duo based in Seoul 🇰🇷 Heavily influenced by the 90s.

Our new album #Xennials is all about the nostalgia of that era 💽 CD listenin 📟 beeper beepin 💾 floppy disks floppin days 😎

Stream now! 🎧

https://open.spotify.com/album/3YwWhnHWVy5cA8XOpbaGRA?si=8E9awqU…

This Satuday we invite to watch another #speedpainting of our artist Daniel Faiad.

How great is this scene of #Pecaminosa?

#ScreenShotSaturday | #IndieDev | #DigitalArt

Shoobies leave a sticky trail of mucus in their wake, which can impede movement for any creature that steps in it.

Successful landing

#screenshotsaturday

Path of Kami: The Evolution of the Lore

Enemies can also suddenly spawn through Realm Rifts. These Rift Spawns are going to be stronger than the ones wandering around. TBD on the enemies... #screenshotsaturday #godstear #madewithunity

Terraria