Godot Version
4.3
Question
Hi
I’m am trying to do something I expected to be simple, but apparently I cannot find the error, so here I am asking for help.
I made a simple tilemap with water tiles and dirt tiles. When I move into the water the player is no longer on land and will begin to collide with the dirt tiles.
That part was really simple.
The next part is the capability to once more enter the land. To do so I expanded the 16x16 rectangle to 24x24 and translated it by 4. This should add a 4 pixel padding to the landmass that is not a part of the tilemap collider. Thus I should be able to press “space” when up against the landmass and stay on land.
For some reason part 2 does not work. I have found that not only does the shape not expand, but there seems to be a spot in the corner that it considers land as well…
Now even more confused I have the landarea working as intended, with the global location and yet another hidden “landmass” in the corner. The hidden “landmass” in the corner does seem to grow worse as I scale the rectangle shape, but nothing happens to the landmass.
I cannot seem to find any documentation on collision calculation. Does anyone have experience on this topic?
using Godot;
using System.Linq;
public partial class Phase : Node
{
[Export] TileMapLayer tilemap;
[Export] Node2D player;
bool _isOnLand = true;
Vector2 lastPlayerPosition;
int counter = 0; // Limit frames processed if no movement or action, so logs are more informative
readonly Vector2I[] SURROUNDING_NEIGHBOURS = new Vector2I[] { new(-1, -1), new(0, -1), new(1, -1), new(-1, 0), new(1, 0), new(-1, 1), new(0, 1), new(1, 1) };
public override void _Process(double delta)
{
if (lastPlayerPosition == player.Position && counter > 10 && !Input.IsActionJustPressed("space")) return;
if (lastPlayerPosition != player.Position || Input.IsActionJustPressed("space")) counter = 0;
var isOnLand = UpdateOnLand(_isOnLand);
tilemap.CollisionEnabled = !isOnLand;
if (_isOnLand != isOnLand) GD.Print(isOnLand ? "On land" : "In water");
_isOnLand = isOnLand;
lastPlayerPosition = player.Position;
counter++;
}
public bool UpdateOnLand(bool isOnLand)
{
var localPosition = tilemap.ToLocal(player.Position);
var mapCoords = tilemap.LocalToMap(localPosition);
if (Input.IsActionJustPressed("space"))
{
return true;
}
// Water tile is fourth
else if (tilemap.GetCellAtlasCoords(mapCoords).X == 3)
{
var surroundingTiles = SURROUNDING_NEIGHBOURS.Where((x, i) =>
{
var tileCoord = x + mapCoords;
var isInWater = tilemap.GetCellAtlasCoords(tileCoord).X == 3;
if (isInWater)
{
var tileShape = new RectangleShape2D();
tileShape.Size = new Vector2I(16, 16);
var tileCoordGlobal = tilemap.ToGlobal(tilemap.MapToLocal(tileCoord));
var collisionShape2D = player.GetChild<CollisionShape2D>(0);
var tileTransform = new Transform2D(new Vector2I(1, 0), new Vector2I(0, 1), tileCoordGlobal);
var isStillSomewhatOnLand = collisionShape2D.Shape.Collide(collisionShape2D.Transform, tileShape, tileTransform);
return isStillSomewhatOnLand;
}
return false;
}).ToList();
if (!surroundingTiles.Any())
{
return false;
}
}
return isOnLand;
}
}