Hello everybody! I am new in this forum and to Godot, and I am trying to use raycast2D functionnality to test if one point of my scene is in visual contact with another one in an isometric tilemap. However, the resulting behavior is inpredictible so I guess I did not plainly understand how it works. This is why I am asking you some help :)
Description of my case:
I am using for my isometric grid, a tileset of three tile types: walls, ground, and lighted ground. I have two characters, one animated and moves with the arrows and the other not animated and moves with a,w,s,d. Both movements are cell-by cell, and the program testes if the destination cell is a wall and in that case does not move. For a game I will create later, I need a function that testes, for two input cells, if there is a wall between their centers. An image is always better:
My idea was to put a collision polygon on the wall tile, so that when I create a Raycast2D between the center of my ogre case and the center of my godot icon case, I can know immediately if there is a wall between these.
Here is my architecture:
The function to test if there is visual contact between two cases is in the script of TileMap "Ground":
func areInVisualContact(mapPosition1,mapPosition2):
var worldPosition1 = map_to_world(mapPosition1)
var worldPosition2 = map_to_world(mapPosition2)
var space_state = get_world_2d().direct_space_state
var intersections = space_state.intersect_ray(worldPosition1, worldPosition2)
print(intersections)
if intersections:
print(intersections.collider.name)
return false
else:
return true
Both characters have pretty much the same script, and at each move of one of them the program is trying to (but not succeeding) test if both of them are in visual contact, and highlights their cases using third tile type when this is the case.
However, the results are quite random and I get intersections when there is no wall in between... More than that, the function "areInVisualContact" do not have the same behavior for its two variables. intersect_ray do not have a symetric behavior? Any ideas?
Here are the scripts and outputs:
For ogre:
extends KinematicBody2D
onready var player = get_node(".")
onready var playerSprite = get_node("PlayerSprite")
onready var tileMap = get_node("../..")
onready var grid = get_node("..")
onready var walls = get_node("../../Walls")
onready var ground = get_node("../../Ground")
onready var otherCharacter = get_node("../VirtualBody")
export var playerTime = 4.0/25.0
var velocity = 0
var currentTileIndex = -1
var destinationTileIndex = -1
# Called when the node enters the scene tree for the first time.
func _ready():
cellSize = grid.get_cell_size()
mapUpVector.x = 0
mapUpVector.y = -1
mapRightVector.x = 1
mapRightVector.y = 0
mapCurrentPosition = grid.world_to_map(playerSprite.position)
startPosition = grid.map_to_world(mapCurrentPosition)
currentPosition = get("global_position")
set("Node2D/transform/position",startPosition)
originString = "Right"
destinationString = "Right"
originDirection = rightVector
destinationDirection = rightVector
currentAnimation = "IdleRight"
playerSprite.play(currentAnimation)
func get_input():
currentAnimation = playerSprite.get_animation() #Toujours la apres l'animation?
if currentAnimation.find("Idle") == 0: #ne prend les inputs que lorsque le personnage est arrete
if Input.is_action_pressed("ui_down"):
mapDestinationPosition = mapCurrentPosition-mapUpVector
destinationTileIndex = walls.get_cellv(mapDestinationPosition)
destinationString = "Down"
if destinationTileIndex != 0:
destinationPosition = grid.map_to_world(mapDestinationPosition)
destinationDirection = destinationPosition - currentPosition
return true
elif Input.is_action_pressed("ui_left"):
# Idem but left
elif Input.is_action_pressed("ui_up"):
# Idem but up
elif Input.is_action_pressed("ui_right"):
# Idem but right
else:
return false
func _process(delta):
if get_input():
if destinationString != originString:
turningAnimationString = "Turning"+destinationString+"From"+originString
playerSprite.play(turningAnimationString)
else:
if destinationTileIndex != 0:
velocity = sqrt(destinationDirection.dot(destinationDirection))/playerTime
else:
velocity = 0
walkingAnimationString = "Walking"+destinationString
playerSprite.play(walkingAnimationString)
#Move the sprite using direction and velocity
var motion = destinationDirection.normalized() * (velocity * delta)
move_and_collide(motion)
currentPosition = get("global_position")
if ((currentPosition - destinationPosition).dot(destinationDirection) > 0) && (destinationTileIndex !=0 ):
set("global_position", destinationPosition)
ground.set_cellv(mapCurrentPosition,1)
mapCurrentPosition = mapDestinationPosition
velocity = 0
playerSprite.play("Idle"+destinationString)
otherCharacter.call("refreshLight")
refreshLight()
func refreshLight():
if ground.areInVisualContact(mapCurrentPosition,otherCharacter.mapCurrentPosition):
ground.set_cellv(mapCurrentPosition,2)
else:
ground.set_cellv(mapCurrentPosition,1)
func _on_PlayerSprite_animation_finished():
#... Not of interest here
`
For Godot icon:
onready var otherCharacter = get_node("../KinematicBody2D")
# Called when the node enters the scene tree for the first time.
func _ready():
#...
mapCurrentPosition = grid.world_to_map(Vector2(1,0))
set("global_position",currentPosition)
#...
func get_input():
if Input.is_action_just_pressed("ui_down2"):
#...
elif Input.is_action_just_pressed("ui_left2"):
#...
elif Input.is_action_just_pressed("ui_up2"):
#...
elif Input.is_action_just_pressed("ui_right2"):
#...
#...
func _process(delta):
i#...
if ((currentPosition - destinationPosition).dot(destinationDirection) > 0) && (destinationTileIndex !=0 ):
set("global_position", destinationPosition)
ground.set_cellv(mapCurrentPosition,1)
mapCurrentPosition = mapDestinationPosition
velocity = 0
otherCharacter.call("refreshLight")
refreshLight()
func refreshLight():
#...
Outputs:
{}
{}
{}
{}
{collider:[TileMap:1329], collider_id:1329, metadata:(-2, -4), normal:(-0.447214, 0.894427), position:(256, -256), rid:[RID], shape:0}
Walls
{collider:[TileMap:1329], collider_id:1329, metadata:(-2, -4), normal:(-0.447214, -0.894427), position:(256, -256), rid:[RID], shape:0}
Walls
I am sorry it was a bit complicated to explain I hope you have understood... Thank you very much for your help! Don't hesitate with further questions!
Guillaume