找回密码
 立即注册
首页 业界区 安全 Godot 2D游戏开发笔记

Godot 2D游戏开发笔记

姚望舒 6 小时前
本篇笔记是对[想在2025年做游戏?用Godot做出你的第一个2D游戏吧:安装Godot_哔哩哔哩_bilibili]的总结
Part0 系统

游戏引擎及导出模板下载官网
设置语言:gamemanager界面右上角Settings
创建新项目:左上角“+创建”
(进入项目之后)
​        左下角:文件系统 可将外部文件直接拖入以导入 导入的文件可双击预览
​        左上角:节点管理(场景树)
​        右侧:检查器
​        右上角:运行项目
​        顶部:切换2D 3D 脚本(Script)
​        顶部下方:切换对节点的选择、移动、旋转、锁定等操作
​        鼠标中键:拖动视角
​        鼠标滚轮:缩放视角
​        中间蓝色框:默认渲染区域
文件管理
​        游戏场景(.tscn)放在Scenes文件夹
​        代码文件(.gd)放在Scripts文件夹
设置窗口缩放
项目->项目设置->显示->窗口->拉伸->模式,可选择让场景随窗口放大缩小
viewport 像素吸附
canvas_items 不限像素
管理导出模板
编辑器->管理导出模板->下载或导入
导出项目
项目->导出->添加,选择操作系统->启用内嵌PCK
Part1 搭建场景

添加一个”Node2D“作为根节点
在该Node2D根节点下
​        添加”Sprite2D“节点作为场景
​                在右侧的检查器中,将所需的场景拖入”Texture“中
像素风格设置:左上角项目->项目设置->渲染->纹理->将默认纹理过滤设置为Nearest
设置主场景:第一次运行项目时会弹出窗口,将背景场景设置为主场景即可
添加摄像机:Camera2D(粉色方框)
​        在右侧检查器中,改变”Zoom“的数值以改变方框大小
Part2 创建玩家并添加动画

点击顶部下方场景栏的加号”+“,新建一个场景
添加节点“CharacterBody2D”作为玩家的根节点
在该节点下添加”AnimatedSprite2D“节点
左侧会出现一个黄三角警告,需要在右侧检查器中,设置"SpriteFrames"图片帧
点击Animation->SpriteFrames右边的,新建SpriteFrames,再点击创建好的SpriteFrames即可打开之
在下方的SpriteFrames栏中,上侧的网格图标可分割并添加数个图片,组成一个动画(如”idle“待机动画)
​        动画帧率可调
​        可设置游戏开始时就自动播放某一动画
将玩家场景添加到主场景:回到主场景(背景场景)左侧节点栏上方,用链接图标即可将某一场景添加到主场景
Part3 添加代码

为玩家添加代码:选中玩家场景的根节点,点击右上侧一个有绿色加号的图标
​        使用Nodeefault模板
​        可通过”创建“新代码或”加载“已有代码的方式将代码挂载到某一节点
Part4 操控玩家

为玩家设置速度(附2之5,6)
以键盘操控玩家移动
​        接收输入信号:项目->项目设置->输入映射->添加新动作并分配键位
实时检测键盘的输入(附2之8)
将玩家的速度赋值为输入与速度的乘积,形如:
  1. velocity=Input.get_vector(”left“,"right","up","down")*move_speed
复制代码
Part5 播放动画

在角色的脚本中,声明一个类型为AnimatedSprite2D的变量animator,并使其暴露在检测器中(附2之10)
在检测器中,给animator的“Animator”赋值(可拖动或选择)为Part2中创建的AnimatedSprite2D节点(在场景树中)
在特定情况下播放动画,如在角色速度为0时播放待机(idle)动画,否则播放跑步动画,形如:
  1. if velocity == Vector2.ZERO:
  2.         animator.play("idle")
  3. else:
  4.         animator.play("run")
复制代码
Part6 添加碰撞体-场景边界空气墙

在主场景中,添加一个"StaticBody2D"节点
​        在其之下添加"CollisionShape2D"节点
​                在右侧的检查器中为其添加“Shape”,其中的“WorldBoundaryShape2D”适合用来做空气墙,检查器中的“Transform”->"osition"可用于精确调整位置
可将所有空气墙整合到一个Node2D节点下,并锁定,以使场景整洁
Part7 添加碰撞体-角色

在角色场景的根节点下,添加一个“CollisionShape2D”节点
​        在右侧的检查器中添加“Shape”,用合适的图形概括角色外形。
Part8 创建敌人

新建场景,以“Area2D”作为敌人的根节点
​        Area2D是一个物理节点,可检测是否有别的物理节点碰到了它
用“AnimatedSprite2D”为敌人添加动画,方法同前
用“CollisionShape2D”为敌人添加碰撞体,方法同前
回到主场景,注意不要选中任何节点,将敌人的场景链接到主场景中
Area2D下没有velocity参数,但可以通过改变position来控制敌人的移动,形如:
  1. position += Vector2(-100,0) * delta
复制代码
(若不加“* delta”则会导致按帧改变位置,使移速过快)
解决玩家与怪的叠放次序问题:
​        按照物体在y轴上的坐标来渲染:选中根节点->在右侧检查器中选择"Ordering"->勾选 Y Sort Enabled
Part9 碰撞检测

来到敌人场景->右侧节点面板下找到信号栏->选择body_entered(body: Node2D)->选择敌人节点并连接
自动创建了如下函数
  1. func _on_body_entered(body: Node2D) -> void:
复制代码
每次body entered信号被触发,该函数下语句便会被执行
需判断敌人碰到的是玩家而非他物:
  1. if body is CharacterBody2D: #body指碰到的物体
复制代码
Part10 游戏结束并刷新场景

实现”碰到敌人就输掉游戏“
来到玩家代码,添加函数:
  1. func game_over():
  2.         get_tree().reload_current_scene() #重新加载当前场景
复制代码
回到敌人代码
  1. if body is CharacterBody2D: #body指碰到的物体
  2.         body.game_over() #body即代指玩家,可直接调用写好的game_over函数
复制代码
设置游戏结束时玩家的动画,在game_over函数中:
  1. await get_tree().create_timer(3).timeout #等待3秒倒计时
复制代码
可使用bool型变量记录游戏是否结束
添加失败动画,方法同前
在game_over函数中,播放该动画:
  1. animator.play("game_over")
复制代码
总结如下:
  1. func game_over():
  2.         animator.play("game_over")
  3.         await get_tree().create_timer(3).timeout
  4.         get_tree().reload_current_scene()
复制代码
Part11 不断发射子弹

新建场景,Area2D作根节点,Sprite2D作子弹图片,CollisionShape2D作碰撞体
添加脚本:子弹移动同前
每隔一段时间就发射子弹
回到玩家节点,添加“Timer”节点,在右侧的检查器中,不勾选“One Shot”以使循环执行,勾选“Autostart”以使在游戏开始时自动执行
在Timer的节点->信号栏中,双击“timeout()“,将其连接到玩家的代码上,可将其命名成”_on_fire“
可在Timer节点的检查器中对这个倒计时循环进行精细的控制
声明一个类型为”PackedScene“的变量来储存子弹的场景,命名为”bullet_scene“
在_on_fire函数下,新声明一个局部变量bullet_node来存子弹场景,并让其生成在玩家边合适的位置:
  1. func _on_fire() -> void
  2.         var bullet_node = bullet_scene.instantiate()
  3.         bullet_node.position = position #前一个position是子弹的,后一个是玩家的
  4.         get_tree().current_scene.add_child(bullet_node)
复制代码
回到玩家场景的根节点,将右侧检查器中的“Bullet Scene”快速加载为子弹的场景
可在_on_fire函数中自由设计开火条件(如只能站定才能开火,游戏结束后无法开火等)
Part12 性能优化

在子弹的_ready()函数加添加一个倒计时(附2之16)
倒计时结束后摧毁生成的子弹(附2之20)
Part13 消灭敌人-分组功能

给敌人添加被消灭的动画,方法同前,注意死亡动画不需要重复播放
检测敌人被子弹打到
回到敌人场景根节点,添加area_entered(area: Area2D)信号,并连接到敌人的代码
区分敌人和子弹,避免敌人碰到自己人而触发被消灭
回到子弹场景,右侧节点->分组->添加分组并命名为“bullet”
回到敌人代码,判断撞到的是否为子弹:
  1. func _on_area_entered(area: Area2D) ->void
  2.         if area.is_in_group("bullet"):#被子弹撞到了
  3.         #让敌人停止运动
  4.         $CollisionShape2D.queue_free() #删除敌人碰撞体积,防止尸体吞箭
  5.         #摧毁打死敌人的子弹
  6.         #播放死亡动画
  7.         #摧毁死亡的敌人
复制代码
Part14 不断生成敌人

在主场景的根节点上(重点)新建代码“GameManager”
回到主场景,添加一个Timer节点,勾选Autostart
在该Timer节点的信号面板中,双击timeout(),选中根节点的GameManager以连接,可命名为_spawn_slime()
希望敌人随机生成在一定范围中
​        范围赋值为随机值(附2之23)
生成敌人和生成子弹代码类似:
  1. @export var slime_scene : PackedScene
  2. func _spawn_slime() -> void:
  3.         var slime_node = slime_scene.instantiate()
  4.         slime_node.position = Vector2(x,randf_range(a,b))
  5.         get_tree().current_scene.add_child(slime_node)
复制代码
选中场景根节点,在右侧的检查器中看到Slime Scene变量,将其设置成敌人的场景
使敌人生成得越来越快
声明一个类型为Timer的变量spawn_timer,通过控制它来控制生成间隔,记得在检查器中将其设置到连接了生成敌人代码的Timer上。
  1. func _process(delta: float) -> void:
  2.         spawn_timer.wait_time -= 0.2 * delta
  3.         spawn_timer.wait_time = clamp(spawn_timer.wait_time,1,3)
复制代码
敌人到达左侧边界,则摧毁
  1. if position.x < value:
  2.         quene_free()
复制代码
Part15 记分

在GameManager代码中,声明一个记分的变量score:
  1. @export var score : int = 0
复制代码
在敌人被消灭的代码中,获取主场景的根节点(因为GameManager连接在那)
  1. get_tree().current_scene.score += 1
复制代码
Part16 UI

回到主场景,添加"CanvasLayer"节点,出现的蓝色大框为其渲染区
在CanvasLayer之下,添加“Label”节点,在右侧检查器的Text中编辑文字,可自由设置文字参数
如:Theme Overrides中可设置字体、颜色、大小等
在其下Fonts可快速加载某一字体文件(.ttf)
显示分数
来到GameManager代码,声明一个类型为Label的变量
  1. @export var score_label : Label
复制代码
将score节点拖动到GameManager检查器中的score_label中
在process函数中实时显示分数:
  1. score_lable.text = "Score: " + str(score)
复制代码
显示Game Over
创建好节点后,先点右侧眼睛按钮让它隐藏
在玩家死亡代码中,告诉GameManager播放gameover
  1. get_tree().current_scene.show_game_over()
复制代码
在GameManager中设置show_game_over函数,显示gameover
  1. @export var game_over_label: Label
  2. func show_game_over()
  3.         game_over_label.visible = true
复制代码
在检查器中将game over label设置成gameover节点
Part17 音乐音效

需要循环播放的,要在预览界面勾选“循环”并重新导入
音效
来到玩家场景,添加节点“AudioStreamPlayer”
将音效文件拖入节点右侧检查器中,可调节其参数
可使用拖动的方式,将音效节点拖到对应的代码函数中,使其按需播放
可用.play()或.stop()来控制其播放与停止
.playing 表示它正在播放,是一种状态
背景音乐
在主场景添加节点“AudioStreamPlayer”,将BGM文件拖入检查器,勾选Autoplay
令失败重启不影响BGM播放
让BGM节点存在于主场景节点之外,使用godot自动加载功能,与主场景同时存在
将BGM保存为一个场景,而非节点
左上角项目->项目设置->全局->自动加载->BGM场景->+添加
附1 快捷键

2D界面中按F 使选中的节点居中
ctrl+A 新建节点
ctrl+Z 撤回
ctrl+D 复制并粘贴
ctrl+S 保存
ctrl+X 剪切整行代码
旋转中按住ctrl 磁吸
F5 运行项目
F8 退出运行
附2 系统函数与参数



  1. func _ready() -> void:
复制代码
该函数下的语句会在游戏开始运行时或被加入场景时被执行


  1. print()
复制代码
输出括号中的内容


  1. func _process(delta: float) -> void:
复制代码
该函数下的语句会在游戏的每一帧被执行(基于电脑可能有所不同)
若改成 _physics_process则会以固定60帧/秒运行


  1. extends CharaceterBody2D
复制代码
出现在代码顶端,表示该代码是由CharaceterBody2D类型延申而来,可用其下的参数


  1. velocity = v
复制代码
CharacterBody2D特有的参数,给节点速度赋值v


  1. Vector2(x,y)
复制代码
二维向量,能表示在x轴,y轴上的数值


  1. move_and_slide()
复制代码
CharacterBody2D特有的功能,可让该节点以设置好的velocity来移动


  1. Input.get_vector(negative_x,positive_x,negative_y,positive_y)
复制代码
获取左,右,上,下四个方向上的输入


  1. var a : int = 1
复制代码
声明a是一个值为1的整型变量


  1. @export
复制代码
将某个变量暴露在左侧检查器中


  1. Vector2.ZERO
复制代码
向量值为0,可用于判断速度是否为零,形如velocity == Vector2.ZERO


  1. animator.play()
复制代码
animator为自定义的AnimatedSprite2D类型变量,该函数功能为播放括号中指定的动画


  1. position
复制代码
节点的世界坐标


  1. func _on_body_entered(body: Node2D) -> void:
复制代码
Area2D的函数,每次body entered信号被触发(碰到物体),该函数下语句便会被执行


  1. get_tree().reload_current_scene()
复制代码
重新加载当前场景


  1. get_tree().create_timer(t).timeout
复制代码
创建倒计时,括号中的t为具体的时间


  1. bullet_scene.instantiate()
复制代码
bullet_scene为自定义的PackedScene类型变量,该函数可生成一个bullet_scene节点


  1. get_tree().current_scene.add_childe(node)
复制代码
将第二个括号中的node节点变成当前场景的子节点


  1. return
复制代码
提前结束函数


  1. queue_free()
复制代码
摧毁当前节点


  1. area.is_in_group("group1")
复制代码
这个area场景属于分组“group1”


  1. area.queue_free()
复制代码
摧毁area节点


  1. randf_range(a,b)
复制代码
a~b之间随机生成一个数(含a不含b)


  1. clamp(value,min,max)
复制代码
将value的值限制在min和max之间
附3 报错

1.indented
与缩进有关的报错

来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除

相关推荐

您需要登录后才可以回帖 登录 | 立即注册