目标

本小节我们制作一个屏幕环绕的效果,也就是当玩家走到屏幕的边界时,再继续走就从它的对面边界出来。这样,玩家始终走不出第一屏,这种效果在某些场景中或许会用到。

参考

本例参考自kidscancode的godot recipes中的screen wrap一节。地址我会放到置顶评论中。
https://kidscancode.org/godot_recipes/2d/screen_wrap/

场景结构

image.pngimage.png 场景结构与之前的小节基本一致,还是我们的icon.png。

原理

我们通过键盘的上下左右键来控制玩家的移动,并且检测玩家的position属性,当它超出窗口可见部分的矩形范围时,我们就强制设置其position属性到对面边界的位置。

实现基础的移动

  1. extends Sprite
  2. var speed = 200
  3. func _process(delta):
  4. var dir = Input.get_vector(
  5. "ui_left",
  6. "ui_right",
  7. "ui_up",
  8. "ui_down"
  9. )
  10. position += dir * speed * delta

基础移动的代码基本上与之前写的没有差别。

实现基础的环绕

  1. extends Sprite
  2. var speed = 200
  3. onready var screen_size = get_viewport_rect().size 获取视口矩形的大小
  4. func _process(delta):
  5. var dir = Input.get_vector(
  6. "ui_left",
  7. "ui_right",
  8. "ui_up",
  9. "ui_down"
  10. )
  11. position += dir * speed * delta
  12. if position.x > screen_size.x:
  13. position.x = 0
  14. if position.x < 0:
  15. position.x = screen_size.x
  16. if position.y > screen_size.y:
  17. position.y = 0
  18. if position.y < 0:
  19. position.y = screen_size.y

代码分析

image.png 为了实现环绕,我们首先使用CanvasItem.get_viewport_rect()来获取窗口可视区域的矩形,将其保存到screen_size变量中。
然后使用四个if语句来进行Sprite位置的判断,当玩家的位置超越边界时就瞬间位移到对面边界。
上面的代码运行后我们已经可以获得正确的屏幕环绕效果。

wrapf()函数

image.png 但是类似于之后我们将在《血量和经验、等级的设计策略》一节中讲到的钳制函数clamp(),这里我们可以使用wrapf()函数来进行值的循环,它可以让所赋值在给定的最小值和最大值之间循环,而不是钳制。
钳制函数clamp()和循环函数wrapf()都是 @GDScript
的成员方法,也就是GDScript中的全局函数,任何地方,任何时候都可以使用。

改进的代码

| ```swift position.x = wrapf(position.x, 0, screen_size.x) position.y = wrapf(position.y, 0, screen_size.y)

  1. | 通过使用循环函数wrapf(),我们可以将之前的四个if语句简化为两句。 |
  2. | --- | --- |
  3. <a name="e8XDT"></a>
  4. ## 最终代码
  5. 所以最终代码可以修改如下:
  6. ```swift
  7. extends Sprite
  8. var speed = 200
  9. onready var screen_size = get_viewport_rect().size
  10. func _process(delta):
  11. var dir = Input.get_vector(
  12. "ui_left",
  13. "ui_right",
  14. "ui_up",
  15. "ui_down"
  16. )
  17. position += dir * speed * delta
  18. position.x = wrapf(position.x, 0, screen_size.x)
  19. position.y = wrapf(position.y, 0, screen_size.y)

运行效果

基础动画示例2.gif