A new level is available! This one is pretty tough, you can test it right away here:
Enjoy! :)
A new level is available! This one is pretty tough, you can test it right away here:
Enjoy! :)
Hi! I am so sorry this did not work, what version did you try? In browser or by download? I am updating them today so I could possibly solve that one :)
Thanks a lot for the feedback!
[NEWS] The mode hard is now available in our free online demo on itch.io! Solve the puzzles in mirror mode by staying out of sight from your past selves... Enjoy!
Thanks for your likes it means a lot to us :)
TEIY is a turn-based puzzle game where meeting with yourself means Game Over.
To win the game, you will need to use your past selves at your advantage. They reproduce your actions exactly as you made them, but you should avoid them at all cost.
This is our first game as Gamocrates Studio and we chose Godot as our game engine, which has been very cool and user-friendly so far for our 2D-isometric game. You can already play the free demo on itch.io (No download required)
We truly appreciate any kind of feedbacks and support about our work. It is like our little baby and we hope that you will enjoy the experience :)
#Some screens of the game!
The problem is at lines 7 and 9 in the outputs: I should only have sprite of the new instance of map, 1148, but it seems the one of old instance, 1142, is still here as well. Then the freeing deletes it but it is still here as a deleted node.
Hello everybody!
I am programming a game with my friends and we have run into an issue when it comes to restarting our game. I wanted to understand what was happening exactly, so I created a project with minimal code to reproduce the error I could not understand.
In a nutshell: I am creating a brand new instance of my map scene when restarting, but it seems to keep datas from the old instance of that scene.
Can someone put an eye on my code please? I find it very disturbing. Problem in bold in the outputs.
The code for the main scene, that has no child:
#main.gd
extends Node2D
var current_map
var current_map_scene = preload("res://map.tscn")
# Called when the node enters the scene tree for the first time.
func _ready():
load_map(current_map_scene)
func load_map(map_scene):
var map_instance = map_scene.instance()
if current_map != null:
remove_child(current_map)
current_map.queue_free()
current_map = map_instance
add_child(current_map)
current_map.connect("restart",self,"_on_restart")
func _on_restart():
load_map(current_map_scene)
The code in my map scene. It only has a single sprite (godot texture) as a child.
#map.gd
extends Node2D
signal restart
var error_dict : Dictionary
# Called when the node enters the scene tree for the first time.
func _ready():
if !error_dict.has(0):
error_dict[0] = []
for element in get_children():
error_dict[0].push_back(element)
print("new error dict:")
print(error_dict)
func _process(delta):
if Input.is_action_just_pressed("ui_accept"):
emit_signal("restart")
if Input.is_action_just_pressed("ui_down"):
print("Consult error dict")
print(error_dict)
Steps to reproduce:
- Put the main scene as the main of the project
- Run
- Press "down", then "space", then "down".
The output:
OpenGL ES 3.0 Renderer: GeForce GTX 1050 Ti/PCIe/SSE2
new error dict:
{0:[[Sprite:1142]]}
Consult error dict
{0:[[Sprite:1142]]}
new error dict:
{0:[[**Sprite:1142**], [Sprite:1148]]}
Consult error dict
{0:[[**Deleted Object**], [Sprite:1148]]}
Hello!
Don't know if this can help, but move_and_slide gives a pre-defined collision response and if you want another one, you should use the more generic move_and_collide method to define yourself the collision response. If you don't specify any collision response, move_and collide will simply stop your character, which is (if I understand well) what you are trying to do.
More on this in the doc:
https://docs.godotengine.org/en/3.1/tutorials/physics/physics_introduction.html#kinematicbody2d
I have found the origin of my problem, so I answer to my own post so that if someone runs into the same problem he can get an idea of where it comes from.
It was related with this issue: https://github.com/godotengine/godot/issues/2231
What improved my detection of an intermediary collision shape between my two points was playing with my tile offset.
Here is my bloc sprite:
When I added my collision polygon :
The solution that improved (but not working 100% yet) my case:
Why is that so? In order to display my sprite with good alignment with the tilemap (with "top left" alignment), I needed to put an offset of -62 pixels on the tile in y direction. Then, I aligned my collision polygon so that it matches the borders of the wall (at ground level) on the tileset.
And here was my mistake! Even if the collision polygon is a child of the tile sprite, the offset you put on the sprite is actually not used for the collision polygon. The offset used for the collision polygon is automatic, equal to half the size of the sprite. This means that:
I think this lack of correlation between collision shape offset and sprite offset is counterintuitive and that it would be interesting to fix it :) . Apart from that I have a very nice time using Godot.
Nice evening!
Hello! I would also be interested if someone knew of a built-in solution to deal with this :)
However intuitively, I think it is simpler to split the tile in two. This is the solution recommended in this blog (about Unity but more generally adressing sorting issues in isometric space): https://connect.unity.com/p/articles-what-i-learned-from-trying-to-make-an-isometric-game-in-unity
Because at the moment you use that type of multi-cell objet, you cannot use y sorting at all anymore. I am new so I am not sure, but I guess there could be optimization in the built-in y sorting that would be difficult to get with custom sorting. Actually I am not even sure there IS an existing sorting order that does what we want without splitting.
Tell me if you find something! :)
Hum, the most important par did not display well:
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
PS: I had a limit of characters, so the code you see here is not exact, I replaced some parts of it by comments.
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