Godot3游戏引擎入门之五:上下左右移动动画(上)

Godot3游戏引擎入门之五:上下左右移动动画(上)

一、前言

前面的几篇文章陆陆续续开始介绍 2D 游戏中对玩家的一些基本操作流程了,不过功能实现非常有限,接下来我想完完整整的打造一个小 Demo :在封闭的游戏场景里控制玩家自由移动,从而达到一些简单的目标。那么, first thing first ,从解决*上下左右*移动功能实现开始!

上下左右移动也叫 Top-down 移动动画,这篇文章我会通过 Godot 中的节点以及相关的代码来实现玩家主角的基本移动控制。之后,再改造一下游戏场景,让我们的主角自由行走在有限的世界里。一如往常,老司机带路,如果你是编程新手,那么,前方高能请系好安全带啦!当然,前面的文章也讨论过了, GDScript 脚步非常简单,不熟悉的话可以浏览一下本系列之前的文章。

主要内容: Godot 2D 中玩家的上下左右移动及碰撞实现

阅读时间: 5 分钟

永久链接:http://liuqingwen.me/blog/2018/10/10/introduction-of-godot-3-part-5-the-basic-top-down-movement-part-1/

系列主页:http://liuqingwen.me/blog/tags/Godot/

二、正文

本篇目标

  1. 使用 AnimationPlayer 节点工具创建状态动画
  2. 使用代码控制玩家的上下左右移动功能
  3. 简单的摄像机使用和地图碰撞检测实现
  4. 通过代码实现 RigidBody2D 刚体节点的运动

创建动画

相信看了上篇文章的朋友应该对 AnimationPlayer 这个功能强大的动画工具有了一定的了解。之前只是利用它最基础的功能实现了一个简单的天鹅飞舞动画,接来下我们要使用AnimationPlayer 节点实现稍微复杂的动画制作——玩家的各种状态动画实现。

我们先创建一个场景,根节点改名为 Game ,添加两个子节点: Sprite (命名为Player )和 AnimationPlayer 节点。 Player 节点的图片材质是一张 4x5 的 SpriteSheet 精灵图集,四行分别代表下、左、右、上移动动画:

player_sprite_sheet.png

和上篇文章制作天鹅动画操作一样,分别制作四个移动动画,这四个动画都设置为循环播放,动画时长和步进大家可以自己尝试进行设置不同的时间,直到自己满意为止吧,我的就随便设置了: 时长 0.8 ,步进 0.2 ,具体设置参考上一篇文章:Godot3游戏引擎入门之四:给主角添加动画(下)。接下来才是重点:我们制作一个游戏启动时刻玩家入场动画。其实这个游戏大可不必这样做,完全是为了演示 AnimationPlayer 的强大功能,并增加一些喜感吧,当然也有一定借鉴意义,哈哈。

玩家 Player 入场动画的基本思路是这样的:主角从场景中央稍微偏上的位置快速移动到屏幕中央( position ),同时尺寸由小逐渐放大到正常缩放( scale ),并伴随透明度从*完全透明*到*完全不透明*( modulate/a ),动画最后再加上一段玩家闪现的动画进行强调( visible )。哈哈,颇有主角粉墨登场的戏份啊!欢呼吧,骚年~ :sunglasses:

思路有了,关键在于使用 AnimationPlayer 来进行创建了。之前的动画制作都是一个轨道解决一个动画,但是这个动画不同了,需要一个动画实现多个属性的控制,这里就需要多个轨道了,每个属性分别创建一个轨道,然后对属性设置关键帧进行动画控制,这里需要注意的第一点是: Godot 3.1 alpha 版本中对位置和缩放属性不能直接使用钥匙?️按钮创建相应的轨道和关键帧,会重复创建轨道,这应该是一个 Bug ,不过不要紧,我们使用普通的做法,手动创建 Property Track 属性轨道,选择 Player 节点的相应属性,之后可以正常使用钥匙?️按钮创建关键帧,部分操作如下图:

godot_5_property_track.jpg

上图中的*勾选贝塞尔曲线过渡方式*大家可以尝试一下,看看和平滑过渡有什么不同的效果吧。接下来,动画中透明度的设置是通过 Sprite 节点的 Modulate 颜色属性的Alpha(A) 通道设置实现的,至于闪现是通过控制节点的可见性 Visible 属性实现的,只要是属性, AnimationPlayer 就能创建动画,就是这么强!

godot_5_visible_and_color.jpg

最后记得把入场动画(名为 start )设置为自动播放,不要设置循环播放,毕竟主角登场了就不要重复了。

代码控制

动画制作完后的任务就交给代码来实现了!代码和上一篇文章里的左右移动代码没啥本质区别,只是多了两个方向而已,不过有两点新鲜玩意。第一个是我设置了速度变量,它是一个 Vector2 矢量,这样做的目的是:即使我们同时按住两个按键,玩家依然可以跑动或者原地踏步!大家可以体会下和上一节的不同之处。

第二个可谓是一个可以“节约生命”的功能,还记得上一节里怎么监控按键的吗?需要一个一个的常亮比如: KEY_A/KEY_LEFT 表示 A 键和左方向键。如果你是 Unity 的开发者,那么你对按键设置肯定非常熟悉,这里我不得不说 Unity 在这方面做得还是非常棒的,对键盘、操纵杆的控制设置很到位。 Godot 中同样也可以进行简化设置,比如把A 键和左方向键统一到自定义按键 left 中,具体设置在 Project Settings 中的Input Map 下添加自定义输入控制:

godot_5_keyboard_settings.jpg

设置完就可以开森地写代码了:

extends Node2D

onready var player = $Player
onready var animationPlayer = $Player

var currentAnimation = 'start'
var speed = 200

func _ready():
    camera.position = player.position

func _process(delta):
    var velocity = Vector2(0, 0) # 速度变量
    var isMoving = false # 是否按键移动
    var newAnimation = currentAnimation # 动画变量

    if Input.is_action_pressed('left'):
        velocity.x += -1
        newAnimation = 'left'
        isMoving = true
    if Input.is_action_pressed('right'):
        velocity.x += 1
        newAnimation = 'right'
        isMoving = true
    if Input.is_action_pressed('up'):
        velocity.y += -1
        newAnimation = 'up'
        isMoving = true
    if Input.is_action_pressed('down'):
        velocity.y += 1
        newAnimation = 'down'
        isMoving = true

    # 速度不为0,移动玩家位置
    if velocity.length() > 0:
        # 注意这里 normalize 速度矢量,否则会出现斜着走速度比单方向速度快
        player.position += velocity.normalized() * speed * delta

    # 根据是否有按键按下和新动作更新动画
    updateAnimation(isMoving, newAnimation)

func updateAnimation(isMoving, newAnimation):
    # 如果有移动按键按下,并且改变方向,则切换动画
    if isMoving and currentAnimation != newAnimation:
        animationPlayer.current_animation = newAnimation
        animationPlayer.play(newAnimation)
        currentAnimation = newAnimation
    # 未移动,但又非开始的情况,那么止移动动画
    elif ! isMoving and currentAnimation != 'start':
            animationPlayer.stop()
            currentAnimation = 'start'
    # 其他情况比如同方向继续移动,或者在开始的时候都不用处理

完成后效果:

godot_5_result1.gif

摄像机节点

对于上面实现的效果感想如何?嗯,移动是没问题了,入场动画有,只是没有录制进来,有兴趣的朋友可以到 Github 上下载源码自己运行看看效果。不过,问题是,玩家完全可以脱离视野离家出走啊——所谓破墙而走!三种解决方式:

  1. 第一种是限制移动,让玩家在固定视窗内行动,即通过判断玩家位置坐标计算有没有超出限制范围,上一篇介绍过了
  2. 第二种是使用物理碰撞,把假的墙壁设置为真实的墙壁,这种方式下面会将
  3. 第三种是非正面解决方式,即给我们的游戏添加一个摄像机,而这个摄像机时刻跟随主角运动,那么主角就不会脱离视野了

好吧,后面两种是这篇文章的目标,对于设置摄像机,和其他游戏引擎没有区别:添加一个摄像机节点,设置一下就好了,非常简单。在 Godot 中摄像机节点是 Camera2D ,添加一个节点到游戏场景后,我们通过代码控制摄像机保持和玩家位置一致,这里唯一一个要设置的地方就是:勾选 Camera2D 的 Current 属性,激活摄像机。同时,我还稍微拉伸了镜头,使得游戏场景被放大——通过设置摄像机的 Zoom 参数实现。

godot_5_camera_viewport.jpg

上图中,最下方的文字说明了视窗属性的设置:视口模式 Mode 为 2d ,缩放模式Aspect 设置为 keep ,即保持比例,这些设置都在 Project Settings 里能找到。作用很简单,如果不设置,那么默认情况下,我们的游戏进入全屏状态后是不会进行缩放的,就像下面这样:

godot_5_no_camera.jpg

最后在 player.position += velocity.normalized() * speed * delta 这一句后面添加一点代码:

# 省略代码......

# 速度不为0,移动玩家位置
if velocity.length() > 0:
    # 注意这里 normalize 速度矢量,否则会出现斜着走速度比单方向速度快
    player.position += velocity.normalized() * speed * delta
    # 更新摄像机,玩家始终在视窗内活动
    updateCameraPosition()
    # 省略代码......

func updateCameraPosition():
    camera.position = player.position

运行游戏,查看效果:

godot_5_result2.gif

接下来解决玩家移动无范围限制的问题。 :smiley:

添加碰撞

文章有点长,偷下懒,暂时到这里,接下来的内容放到下一节。 Stay tuned!

三、小结(上)

除了代码,这是一篇非常简单的文章,使用 AnimationPlayer 制作多个动画,以及单个动画多个轨道;使用 Camera2D 跟随玩家移动视野;设置按键规则和视窗缩放属性等。接下来的重点就交给本章的下节吧。

假期没有更新,带孩子在外面和家里玩了 8 天,哈哈!话说回来,嗯,还是那句:原创不易啊,希望大家喜欢! :smile:

我的博客地址: http://liuqingwen.me ,欢迎关注我的微信公众号:IT自学不成才

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值