Godot 游戏引擎学习 第三课

Godot 游戏引擎学习 第三课

December 21, 2020

今天要做的是像玛丽奥游戏里的那样,添加一些金币旋转漂浮在空中,玩家控制的角色一碰到它便会发出 “叮” 的一声,便往上漂浮且慢慢消失!让我们来实现这个功能把。

(怎么感觉自己像是在写教程一样  O - O)

首先我们要思考这个金币有什么样的特性呢?

  1. 它是个金币
  2. 它会被游戏角色碰到
  3. 它是漂浮着的,还会动
  4. 游戏角色碰到它之后它会慢慢往上升,同时慢慢消失
  5. 还会播放声音

它是个金币

知道他的特性之后就好解决了,首先它能被碰到,说明它有碰撞体。这里我们利用 Area2D 来实现,Area2D 是用来包含碰撞检测节点 CollisionShape2D 的容器,而 CollisionShape2D 可以用来检测碰撞。

然后,我们要做个金币。而且还会动,所以我们利用 Godot 的 AnimatedSprite 来实现图像和动画的效果,新建一个名为金币的场景,并在场景内添加 AnimatedSpriteSprite 在 2d 游戏中是一个或一组连续可动的图片,他们的连续播放形成了动画。

添加好 AnimatedSprite 后,我们在 IDE 右侧的属性编辑窗口中新增一个 SpriteFrames,点击后把准备好的精灵素材拖入下方出现的容器里,并添加 CollisionShape2D 且拉伸到完全覆盖金币图片,然后点击属性里的 Playing 复选框即可实现动画效果。

image-20201221215308644

它会被碰到

这里我们要利用 Godot 一个很重要的特性:Signal,官方介绍如下:

信号是 Godot 的 观察者 模式的版本。它们允许一个节点发出其他节点可以监听和响应的消息。例如,与其持续检查按钮是否被按下,不如在按下按钮时发出信号。

在我的理解里大概意思:是一个在街上你碰到我了,我可以主动开口想你说话。以前写软件编程的时候像是:我在路上碰到你,我跟你说希望你说话,然后你才开口说话。当然这只是我自己粗浅的个人理解,也许以后学更深入的地方会更明朗一些吧。

怎么创建信号?我们可以通过代码的方式也可以通过图形界面的方式。

image-20201221221055496

选中 Area2D 父节点,在右侧的面板上点击节点按钮,然后点击下方信号。之后会出现一列当前场景里所有可以使用的信号方法。其中 body_entered(body: Node) 的作用是:当设定的碰撞区域检测到和其他有碰撞属性的空间时发送信号。下面设置接受方法的名称,然后便会自动切换到 Script 模式,并生成相应的代码。

extends Area2D

func _on_Coin_body_entered(body):
    queue_free()

当然,这一过程你可以直接通过代码实现,但是我前几天看别人视频写过,但是现在忘记 0 0,之后想起来再加进来把。

然后我们在函数主体中调用 queue_free() 函数,这个函数是在系统空闲的时候销毁当前对象。也可以用 free() 函数,但是我看官方文档说这个函数是立即销毁对象,如果在销毁期间调用了该函数可能会引起游戏错误或者崩溃。

运行后可以发现角色一碰到金币金币就自动消失了。

它会上下漂浮,玩家碰到会有声音并慢慢上浮消失

这里我们要利用 Godot 的 AnimationPlayer 来创建动画控制器,它可以控制场景内的多个物件的动画效果。添加后点击下方的动画标签,选择新建,并键入动画名字后就能下新建动画了

image-20201221222203464

创建好后我们点击下方的动画标签进入动画编辑窗口,然后点击右侧的钥匙图案即可插入相应属性的关键帧,几乎所有的属性都可以用于插入关键帧,甚至是通过关键帧调用方法、音频、动画等各种属性。

我们在第零秒插入一个 offset 属性的关键帧,然后在第 0.4 秒再插入一个 offset 的关键帧,并把第一个关键帧的 offset-y 值设为 0,第二个设为 - 8,也就是说在第 0 秒开始金币会慢慢向上移动,到第四秒达到设定值停止,然后点击右侧的循环按钮即可。

image-20201221223652724

运行游戏可以看到,我们到目前为止我们就完成了金币的上下飘动效果(这里要注意,我在设置的时候碰到一个问题,金币实例化到主场景后不会有上下飘动的效果,后来找了好久发现没开启加载后自动播放,也就是上图右上方的红框区域)

利用这个我们可以玩出很多花样,我们可以创建第二个动画,用于游戏角色碰撞到金币时播放的动画:一直向上飘去,并慢慢消失。我们可以同样通过添加 offset-y 控制金币向上移动,并且为 modulate 添加一个关键,让他慢慢透明化。(modulate 可以用于控制贴图的颜色、透明度。)

这里视频作者说了一个小 BUG,就是如果在动画持续时间之内手速够快的话,在金币消失之前可以再吃一次金币,所以要在正常状态下将 Area2Dmonitoring 属性开启,在角色碰到金币的动画里将 monitoring 设为关闭

我们先在 Area2D 下添加一个 AudioSteamPlayer 组件用于播放声音。(这里说下我踩的坑:我在导入的时候没注意到音频素材默认情况下是勾选了 Loop 的按钮,第一次测试的声音一直播放,导致后面一个判断没办法进行,找了好久发现导入的时候要把 Loop 关掉,并重新导入才可以,看下图。)

image-20201221224532769

准备好后我们就可以过 AnimationPlayer 的方法调用轨道在特定的时间调用 AudioSteamPlayerplay(0) 方法播放声音,并在播放完之后调用 Area2Dqueue_free() 销毁自己。

然后再脚本里写下如下代码:

extends Area2D

func _on_Coin_body_entered(body):

    # 直接播放角色碰到金币后的动画
	$AnimationPlayer.play("picked")

上面说的通过 AnimationPlayer 调用声音播放和动画结束后销毁自己只是一种方式,你也可以通过纯代码的方法实现这个功能,具体代码如下:

extends Area2D

func _on_Coin_body_entered(body):
    # 播放声音
    $AudioStreamPlayer.play(0)
    # 等待声音播放完毕
    yield($AudioStreamPlayer,"finished")
    # 声音播放完毕后销毁自己
    queue_free()

这一课学习的效果

第三课

加入评论