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 we are working on. As already stated, we want to practice our knowledge and our ideas in game design/development with this fun 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 boxes.

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 by importing the tilemap in the standard way in Godot, a StaticBody2D with a ShapeCollision2D will be created 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:

  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 the type “area” to the 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 abovementioned 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... we are going on using a trial and error approach. Here are a few of our attempts at it:


Test buoyancy: Now we definitely know how NOT to do it. Struggling with it for a few hour. The idea is that when Deadbox enters in the water starts to float in it#godot3 #gamedevlife #GodotEngine #indiedevhour #gamedev #indiedev #godotengine #deadbox pic.twitter.com/elkN6BFlIB
— notapixel (@notapixelstudio) 9 marzo 2018

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


Tweak on the buoyancy, oscillation is still too fast, but looks better.#godotengine #gamedev #deadbox #indiegame pic.twitter.com/npJC4fLYYg
— notapixel (@notapixelstudio) 10 marzo 2018

and


buoyancy and water: First Success! Still is a bit jumpy, but now looks more or less like is floating. 😀 pic.twitter.com/ulotnd3q9s
— notapixel (@notapixelstudio) 9 marzo 2018

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.

Leave a comment

Log in with itch.io to leave a comment.