参考

单词

传送门的单词是portal。

传送门场景

我们用Area2D来实现传送门。
image.pngimage.png

  1. extends Area2D
  2. export(NodePath) var next_portal # 出口 -- 指向另一个传送门
  3. func _on_portal_body_entered(body):
  4. if body.is_in_group("player"):
  5. if next_portal:
  6. body.global_position = get_node(next_portal).get_exit_pos()
  7. func get_exit_pos():
  8. return find_node("Position2D").global_position

玩家场景

玩家还是KinematicBody2D,只是这里将其添加到“player”分组中。
image.pngimage.png
代码如下:

  1. extends KinematicBody2D
  2. var speed = 200.0 # 速度 像素/秒
  3. var dir = Vector2.ZERO # 方向
  4. # 每帧执行
  5. func _process(delta):
  6. dir = Input.get_vector("ui_left","ui_right","ui_up","ui_down")
  7. position += dir * speed * delta

主场景

在主场景中我们实例化Player、以及两个Protal。并为每个Protal添加一个Positon2D节点,分别设置其传送出来之后的位置。
image.png
image.png

运行效果

2222992222.gif

总结

1.实例化场景的子节点问题。

这里做了一个小测试,就是为代码子节点的实例化场景再添加一个子节点,那么在远程视图中,可看到它是被放置在了实例化场景的所有子节点的后面。
image.pngimage.png

2.如何实现节点配置警告?

物理体如果没有碰撞形状的子节点,就会弹出提示。
而一旦物理体拥有碰撞形状子节点,它就会被自动利用,而无需任何代码。

  1. tool
  2. extends Area2D
  3. func _get_configuration_warning():
  4. if has_node("Position2D"):
  5. return ""
  6. else:
  7. return "您需要添加一个Position2D子节点"

这里的has_node是按名称来判断的,而不是类型,因此我们使用封装好的find_child_as_class()函数。

  1. tool
  2. extends Area2D
  3. func _get_configuration_warning():
  4. if find_child_as_class(self,"Position2D"):
  5. return ""
  6. else:
  7. return "您需要添加一个Position2D子节点"
  8. # 返回对应类名的子节点(返回找到的第1个)
  9. func find_child_as_class(node:Node,className:String):
  10. var children = node.get_children()
  11. for child in children:
  12. if child.is_class(className):
  13. return child