有些日子没有更新了,实在是琐事缠身啊,今天继续开始自学Godot4,继续完善地宫相关功能,在地宫中安装第二道门,只有主人公拿到钥匙才能开启这扇门,所以我们在合适位置放置一个宝箱,主人公开启宝箱后,获得开门钥匙。先看一下展示效果。
一、开启宝箱获得钥匙
新建场景,根节点设为StaticBody2D,命名为Chest,保存到场景目录下。
1.部署节点。
依次添加AnimatedSprite2D用于播放宝箱开和关动画;CollisionShape2D表示宝箱的碰撞体,主人公不能穿越宝箱。Area2D用于监测主人公的攻击,当主人公攻击宝箱后,宝箱打开并展现钥匙;Sprite2D节点,命名keys,用于表示宝箱中的钥匙 ,节点目录如下:
2.节点属性设置
下面依次设置各节点。
在AnimatedSprite2D的属性检查器中,设置新建动画,然后在动画面板中建立open和Close动画,每个动画就1帧,表示宝箱的开启和关闭两种状态,宝箱的素材,可以在本节的源代码中找到。
在CollisionShape2D检查器中shape属性设置新建RectangleShape2D,然后调整大小和位置到合适。
给Area2D节点添加CollisionShape2D子节点,并给子节点添加矩形碰撞区域,大小覆盖宝箱。
给Keys节点添加Area2D子节点,再给Area2D子节点添加CollisionShape2D子节点,命名为CheckPeople,调整合适大小,这个碰撞是为了使主人公拾取钥匙,所以大小要比宝箱大一些,同时把Disabled启用,隐藏该节点,当主人公打开宝箱的时候,钥匙才显示出来,主人公才能拾取。
3.添加代码
给根节点添加代码,具体如下:
extends StaticBody2D
@onready var animated_sprite_2d = $AnimatedSprite2D #获取宝箱动画节点
@onready var collision_shape_2d = $Area2D/CollisionShape2D #获取碰撞节点
@onready var check_people = $Keys/KeyCheck/CheckPeople #获取钥匙拾取节点
@onready var keys = $Keys #获取钥匙节点
#主人公攻击宝箱信号
func _on_area_2d_area_entered(area):
animated_sprite_2d.play("open")#播放宝箱打开动画
collision_shape_2d.set_deferred("disabled",true) #将攻击宝箱的碰撞设为不可用
await get_tree().create_timer(.3).timeout #等待0.3秒,
keys.show() #钥匙显示出来
await get_tree().create_timer(.3).timeout #等待0.3秒,表示钥匙拾取的个等待
check_people.set_deferred("disabled",false) #将钥匙拾取检测设为可用
#钥匙拾取检测信号
func _on_key_check_body_entered(body):
if body.name =="Player":#当是主人公的时候
keys.queue_free() #钥匙销毁
body.stats.keycount +=1 #主人公钥匙计数加一
最后在underground场景实例化该节点,并把宝箱放到合适位置。
二、在上方显示获取钥匙信息
这部分完成的效果如下:
新建场景,更目录设置为BoxContainer,命名为InfoContainer,并保存到场景目录下。
1.新建节点
依次为根节点添加Label节点,命名为CoinCount表示金币的数量;添加TextureRect节点,命名为CoinIco表示金币图标;添加Label节点,命名为KeyCount表示钥匙的数量;添加TextureRect节点,命名为KeyIco表示钥匙图标;在CoinIco节点和KeyCount节点之间添加Control节点,用于隔开金币和钥匙一定距离。
2.节点设置
CoinCount和KeyCount节点的Text属性均设置为0,Theme Overrrides->Font Sizes属性下Font Size启用,并设置为10px。
CoinIco和KeyIco节点的Texute属性对应拖入金币和钥匙的图标。
最后将根节点调整为右上对其,并适当调整边距。
3.添加代码
为根节点添加代码,具体如下:
extends HBoxContainer
@export var stats:Stats #定义状态为输入变量
@onready var coin_count = $CoinCount #获取金币数量节点
@onready var key_count = $KeyCount #获取钥匙数量节点
func _ready():
stats.coin_changed.connect(update_coin) #链接金币数量改变信号到本节点update_coin函数
stats.key_changed.connect(update_key) #链接钥匙数量改变信号到本节点的update_key函数
func update_coin():#金币数量改变信号
coin_count.text = str(stats.coincount) #将金币数量显示出来
func update_key():
key_count.text = str(stats.keycount) #将钥匙数量显示出来
修改Status.gd代码如下:
class_name Stats #定义当前节点为Stats类
extends Node #继承Node节点
signal health_changed #定义血量变化信号
signal coin_changed #定义金币变化信号
signal key_changed #定义钥匙数量变化信号
@export var max_health: int = 100 #定义最大血量
@onready var health: int = max_health: #当前血量,默认等于最大血量
set(v): #输入血量
v = clampi(v, 0, max_health) #控制输入的血量0到最大血量之间
if health == v: #如果当前血量和输入血量相同,就会退出
return
health = v #将当前血量设置为输入值
health_changed.emit() #发出信号
@onready var coincount:int=0: #定义金币数量默认为0
set(v): #输入金币数量
coincount=v #当前金币数量设置为输入值
coin_changed.emit() #发出金币改变信号
@onready var keycount:int=0: #定义钥匙数量,默认为0
set(v): #输入钥匙数量
keycount=v #将当前钥匙数量设置为输入值
key_changed.emit() #发出钥匙改变信号
最后进入Player场景,在CanvasLayer节点下实例化InfoContainer节点,并将Stats设置Stats节点。
三、用钥匙打开宝箱
切换到underground场景,先将TileMap修改一下留出一个可以通过的缺口,并铺设地面,如下:
1.节点部署
新建场景,更目录设置为StaticBody2D,命名为KeyDoor,并保存到场景目录下。
依次为根节点添加AnimatedSprite2D节点,命名为DoorAnima表示门有关的动画;添加CollisionShapte2D节点,命名为IntoCollision,用于碰撞检测,当门关闭时,人是不能进入的,当打开时人才能通过;添加Area2D节点,用来检测主人公是否进入;实例化Tips节点(这是我们第节第三十一节添加的类),用于信息提示。
2.节点设置
在DoorAnima节点的检查器中Animation->Sprite Frames设置为新建SpriteFrames,在其动画帧面板上新建3个动画,一个是Close动画表示门的关闭状态,一个是Open动画表示门的打开状态,最后一个是Charge动画表示开门的动画。
IntoCollision节点检查器中CollisionShape2d->Shape设置为新建RectangeShape2D,并调整到合适大小和位置。
给CheckInArea添加CollisionShape2D子节点,然后在该节点检查器中CollisionShape2d->Shape设置为新建RectangeShape2D,并调整到合适大小和位置。
3.添加代码
为根节点添加如下代码:
extends StaticBody2D
@onready var door_anima = $DoorAnima #获取门的动画节点
@onready var into_collision = $IntoCollision #获取门碰撞节点
@onready var tips = $Tips #获取提示信息节点
@onready var incollision = $CheckInArea/Incollision #获取主人公进入检测节点
#主人公进入检测信息
func _on_check_in_area_body_entered(body):
if body.name=="Player" : #当主人公进行检测碰撞区
if body.stats.keycount<1: #果主人公钥匙数量为0
tips.infoText="这道门,似乎只有用钥匙才能打开" #提示信息
return #退出该函数
else: #如果主人公有钥匙
incollision.set_deferred("disabled",true) #主人公检查碰撞失效
body.stats.keycount -=1 #主任公的钥匙数量减一
door_anima.play("Charge") #播放门的打开动画
await door_anima.animation_finished #等待动画播放完毕
door_anima.play("Open") #播放门的打开状态动画
into_collision.set_deferred("disabled",true) #设置门的碰撞检测失效,主人公可以进入
最后在underground节点下实例化该场景,并将门移动预留的位置。
ok,这样本节的内容就可以收工了。效果如下: