I’ve built a small tool to create tileable, seamless textures.
I’ve used this method to create the night sky of my Ludum Dare 38 Game. It’s an easy way to create the stars of the night sky in few minutes.
Start with two layers, one for the dark sky and one for the stars. The dark sky is just uses a dark, blue color. The star layer contains a mixture of light colors. It is up to you how you create this layer. I painted the layer randomly with 3 colors and used the Smudge Tool to mix them. Make sure the star layer has an alpha layer.
To convert the randomly colored layer into stars the RGB Noise Filter is used, which can be found under Filters → Noise → RGB Noise …. Set up the filter as shown below. The Red, Green and Blue Noise is completely disabled and only the Alpha Noise is applied. If you do not see the Alpha slider of the filter make sure that the layer has an Alpha Channel.
After applying the filter for the first time the result does not look very promising. If you keep applying the filter repeatedly (using the Ctrl+F shortcut) the remaining color will get sparser and sparser. Keep doing this until you are satisfied with the density of the stars. The results should look like the example below.
You want to go the final step with your loved one but damn it is expensive. Living on a small floating island there isn’t much to earn money with, but you have to find a way before it is too late. Farm the little land you have to rack up the money you need.
The worth of objects changes with time. Most objects get more valuable over time, but only to a certain point. Once they exceeded this point the value deteriorates until they are completely worthless.
It is your job to find out how long processes have to run for an optimal outcome.
This requires keen observation and managing your time between different tasks.
- WASD and Arrow-Keys: Walk and Jump
- Spacebar: Use selected tool
- Mouse: Control build menu
- 1-8: Change Tool
- Hammer: Interact with most objects
- Wood: Plant trees
- Wheat: Plant Wheat
- Other: there might be hidden functionalities
Third Party Tools/Assets
The texture are tileable in X and Y direction and have a resolution of 2048×2048.
All textures are licensed under CC-BY 4.0
In a game with a static camera (looking down at the level) it is important to align the character movement with the camera. Failing to do so creates a distorted input feeling as the input and the actions of the player character don’t correspond to each other. To achieve a correct movement, the directions have to projected from the screen onto the scene.
Naive implementations of player movement use the axis of the coordinate system as directions. Left and Right correspond to the [1,0,0] direction and Up and Down to the[0,0,1] direction. This implementation is correct and usable as long as the camera is correctly aligned to this axis. If the camera is not aligned the movement directions no longer correspond to the perceived directions of the player (see image above). To correct this we have to extract the directions from the camera.
To compute our new directions we unproject three points from camera space to world space. Most framework/engine have built in functions to do this ( godot, opengl, unity ). We have to preform 3 unprojections for the points: (0,0), (1,0) and (0,1). By substracting the result of latter two from the former we obtain two 3D-Vectors that represent our new directions. To receive planar movement direction set the height value (mostly y) to zero and normalize the vectors.
var p0 = cam.project_position(Vector2(0,0)) var pH = cam.project_position(Vector2(10,0)) var pV = cam.project_position(Vector2(0,10)) camH = pH - p0 camV = pV - p0 camH.y = 0 camV.y = 0 camH = camH.normalized() camV = camV.normalized()
camH is the horizontal movement direction and camV the vertical. Instead of using the axis of the coordinate system ([1,0,0] and [0,0,1]) as movement directions, use camH for left/right movement and camV for up/down movement.
The input material
I took photos of the grass in my backyard to create a grass texture. The camera was held at shoulder height pointing down. I cropped the image into a 1:1 image. Try to keep the image as big as possible. Do not scale it into your desired dimension yet!
Make it tileable!
There are two methods to make the image tileable/seamless.
The easiest way to create a tileable texture is to use the “Make Seamless” tool (Filters->Map->Make Seamless).
If you aren’t satisfied by the results of the Make Seamless filter you can also do it by hand.
Start by applying an x/2, y/2 offset by using the Layer->Transform->Offset tool.
This will offset the image in such a way that the opposite border match each other perfectly, but it only shifts the problem. You should notice that there are two lines, one horizontal, one vertical, were the image doesn’t fit together. You can remove the visible borders in various ways, e.g. using the clone and blur tool.
Removing the midrange frequencies
At this point we cloud use the texture, but we will go one step further. The image still contains midrange frequencies, that we want to remove. The midrange frequencies will produce ugly tiling effects if the texture is repeated often.
Start by duplicating the seamless texture and apply a tileable blur (Filters->Blur->Tileable Blur) onto the duplicated version. Choose a high radius, roughly 10% of the images size. This will create a layer containing the mid and low frequencies.
To preserve the low frequencies create a new texture below the two existing. Use the Color Picker with a big radius to select an average color of the texture and fill the new texture with this color.
We now have one layer containing the mid and low frequencies, one containing the low frequencies and one containing all frequencies.
To create a layer containing the high frequencies set the mode of the blurred layer to “Grain extract” and move it above the original layer. By Merging these two layers you gain a new layer containing only the high frequencies. After merging set the mode of the resulting layer to “Grain merge” and merge the two remaining layers. This creates our final image containing the high and low frequencies but no mid frequencies.
Note: I scaled the images to save bandwidth