Animated tiles… more or less

Tonight I wanted to make something simple and fun: animate the water tiles for DeadBox. I created a 16×16 image for each frame of the animation, eight in total. Each image is simply a translation of the previous one by two pixels to the left, in order to give the illusion of waves when the animation is looping. Fortunately for me, Tiled has support for infinite looping animations, so I simply selected the first image from my tileset, opened the animation editor in the tileset menu, double-clicked on each frame, and set the duration of each frame to 150 milliseconds. The result was simple but pleasing:

I know, I know… This should have been a screen recording

But, when I tried to load a tilemap with animated tiles in Godot, I discovered that animation is not supported in Godot tilemaps. There are feature request for supporting animated tiles both in godot-tiled-importer and in Godot itself (here and here). The second link suggests some kind of workaround that maybe I will try in the future, but as for tonight, no animated tiles… 😦

Advertisements

Adding water and buoyancy to a platform game with Godot and Tiled

We definitely think that failed results are worth to be shared as the successful ones. That’s what this post is about.

DeadBox is a platform game that @notapixelstudio is working on. As stated in the article, we want to practice our knowledge and our ideas in game design/development with this funny game. So we are adding new features and new elements to the gameplay step by step.

We started with the collision box for the platform, the harmful tiles (spikes) and the one-way collision box (link).

We are working with Tiled, since it is easier for our purpose making maps with Tiled that with the Tilemap tool from Godot. Thanks to the Tiled automapping and the Godot plugin  we can import the tilemap and all the element with collision in Godot Engine, after applying the automapping (more in the Tiled docs). But importing the tilemap in the standard way in Godot, will create StaticBody2D with a ShapeCollision2D for the collision tiles, and for the background, no collisions.

With the water tile we needed something else, it is a tile different from the other ones. The best idea would be having an Area2D because we want to apply the buoyancy when entering in the water. So this is what we did:

Screenshot from 2018-03-10 00-05-06

Example of a tilemap with water

  1. Created the tiles on Tiled
  2. Updated the automapping with an Object Layer and not as a Tile Layer (important – see picture below)
  3. adding type “area” to water layer (in order to let the plugin godot-tiled-importer know that has to create an Area2D instead of a StaticBody2D)
  4. Create the level with a tilemap
  5. Import the tilemap in godot thanks to the above mentioned plugin
  6. Create a signal connection between the Area2D and the Hero.
Screen Shot 2018-03-10 at 11.25.10

Godot and Tiled recognise map TileMap type with collision or background

We need to get the water-tile type as a node from Godot and connect to the signal.

# World.tscn

func load_level(level):
[...]

# enable signals from water layer 
  var wl = map.get_node('water') 
  if wl: for water_area in wl.get_children():
     water_area.connect('body_entered', self, '_on_water_entered') 
     water_area.connect('body_exited', self, '_on_water_exited') 

  [...]

  func _on_water_entered(body): 
    if body.name == 'Hero':
      $Hero.enter_water() 

  func _on_water_exited(body): 
    if body.name == 'Hero': 
      $Hero.exit_water()

Now that we have the signal we need to write the buoyancy in the Hero.gd

var floating = 0

func _physics_process(delta):
   if floating:
      motion.y -= WATER_K * (position.y - sea_level)
 
func enter_water():
 if not floating:
   sea_level = position.y
   floating += 1
 
func exit_water():
 floating -= 1

The buoyancy is a mess right now, with a trial and error policy, here is a few examples:

The problem here is the oscillation, the idea was to treat the movement as a elasting/spring impulse so we have to figure it out how to do the trick.

and

Right now we are, kind of satisfied with the movement, but we will tweak when we will have more time.

Do you guys know a good way to implement buoyancy and dampening? Let us know.

One way collision tile with Tiled and Godot

This is deadbox icon. With it we want to explore the design and the development of a platform game in GodotEngine.

Today we are going to talk about One-way Collision box. Here is an example of our little hero with a one way collision box.

one_way_collision

Example of Deadbox jumping on and off one-way collision tiles

I see lot of tutorial that explains how to add manually a box and CollisionShape2D directly from Godot. But I haven’t seen anything on Tiled.

The maps in our games are made in Tiled. This allows us to build them in a easy way, and use all the fantastic features that Tiled has to offer. In another article we’d post something about our tileset setup, check it out here.

Below there is an image that shows our rules.tmx file. You can see the top left image showing the mapping layers:

  • harmful: layer for the elements of the map that hurt the player (or anything actually)
  • solid: layer for the collision elements, like wall, floor, ceiling, platform
  • bouncy: layer that allows the player to bounce when step on it (To be implemented yet)
  • water: layer object for the water tile (more in a future post)
  • jumpthrough: layer that will identify the one-way platform
  • regions: layer that allows the automapping for Tiled
  • art: layer that identifies our own tileset

In order to understand better the automapping, I suggest to read the docs.

In the top right picure we have the properties set of the above mentioned tile. We need to know its ID, in order to let Godot know what is the tile to which apply the function tile_set.tile_set_shape_one_way. Function that is not documented, that allows us to set, via code,  CollisionShape2D to One way collision (the same as checking the box “One Way Collision” in Godot).

After having the tilemap imported we need to find the proper layer and put the right CollisionShape to it. Unfortunately for us, the script doesn’t allow,  yet, handle types of tiles in a better way than we did it. A big shout out to the developer of this incredible plugin and hopefully the 3.1 version will be released soon enough, as stated here in this issue.

We adopted this workaround: on the gdscript of the root node World we add the following script

# World.gd
 # enable one-ways collision in jumpthrough layer
 var jtl = map.get_node('jumpthrough')
 if jtl:
 # workaround - waiting for a better implementation in godot-tiled-importer
 # reference: https://github.com/vnen/godot-tiled-importer/issues/37
   jtl.tile_set.tile_set_shape_one_way(123, 0, true)

#123 here is the index of the current tile into the tileset. For some reason the imported tileset starts the index from 1 instead of 0.

#0 is the collisionShape associated to that tile in the tileset.

This workaround is not stable because there is no way to find out the index of the CollisionShape that the plugin gives to the tile when importing the tilemap. That might change if you reimport it with a new map.

We might be wrong about the automapping and setting the right properties, let us know with a comment down below. We would like to know if there is anoter or a better way.

Fail and learn. 🙂

See you next time!

DeadBox tileset III

Screenshot from 2018-03-09 22-24-11

These are tests for the third version of a tileset for DeadBox. I believe this has a better polish than the previous ones. The fake “perspective” is a bit weird though, and the player seems to be floating above the floor rather than standing on it.

Screenshot from 2018-03-09 23-43-52

Because of the weird projection, spike tiles had to be drawn in lots of variants. The use of an additional layer helped in lowering the variations needed to interface spikes with left-facing walls.

Screenshot from 2018-03-10 00-05-06

Water also needed some special tiles for connecting to left-facing walls, and another layer to place it on top of spikes.

I hope to be able to tell Tiled to help me place the correct combinations of tiles, but I suspect that would only be possible with a nightmare of an automapping rule file.

I wonder if there are better, more easy to maintain techniques…

Celeste: open-source Player class

celeste

Being a huge fan of TowerFall, I was bound to love Celeste. They share a lot of similarities in platforming mechanisms, especially the use of dash. It’s by mastering dash techniques while playing TowerFall with your friends that you become so skilled to perform seemingly superhuman feats. To see an entire single-player game develop around twisting and turning that very mechanic is awesome.

Even more awesome is the fact that Matt Thorson and Noel Berry, the two developers of Celeste, recently decided to share the code of the Player Class:

Then, some days later:

A link to a very interesting post about the physics of TowerFall is also included in the FAQ document above.

DeadBox tileset II

blocks

This is the current “art” for both the tiles and the nameless character of DeadBox, in all its amateur glory. I tried to make it more streamlined than the previous one. It is also 16×16 pixels instead of 32×32, because I wanted to give a more pixelated feel when upscaled.

I am not sure about the blocks, but I find the black outline of the character quite useful.

In the lower-left corner you can see the metatiles we use to define solid and harmful tiles. They are automatically added by Tiled into separate layers whenever a regular tile is added. So, for example, whenever we draw spikes onto the art layer, the corresponding metatile is automatically added to the harmful layer (this is called automapping). We then export the tileset and tilemaps to the Godot engine, using a dedicated plugin. At runtime, Godot is able to distinguish how to handle a collision by telling apart the different layers.

I don’t know if this is a best practice or not, but I find it suitable for our current setup.

DeadBox

Several years ago, I was watching a trailer of the then-upcoming game Limbo. I honestly don’t know why, but I heavily misunderstood what the game was about. I remember running to one of my friends, and describing him what I believed was the central mechanism of the game:

  1. You try to beat the level;
  2. Whenever you die, you leave a corpse there;
  3. While replaying the level, you can use the corpse by jumping over it, thus avoiding whatever hazard killed you the first time.

I was very disappointed when I found out that the game was not about that (the game turned out very good, by the way). But that random event was the moment the idea behind DeadBox was born.

Screen Shot 2018-03-09 at 15.52.47

A screenshot from the current prototype

It is not an original idea of course, there is now at least one game out that is based on that very premise. But some days ago, when we were looking for an idea for our first attempt at developing a full game, I remembered about that concept and pitched it to the group.

It turned out they liked it a lot, way more than I do! Let’s see how it develops… 🙂