Godot

全文基于 Godot 4.3 编写

GDScript 是一門 物件導向指令式 程式設計語言

  • 極快的編譯和載入速度
  • 內建 Vector型矢量计算
  • 與靜態型別相比效能較差
  • 沒有 垃圾回收
  • 引擎會預設進行引用計數,在大多數情況下為你管理記憶體
  • 緩型別 。變數預設是動態型別

编辑器

界面

  • 菜单中文:编辑器>设置>界面>编辑器>编辑器语言:zh_CN;设置本地化启用
  • 属性中文:编辑器>设置>界面>检查器>默认属性名称样式:Localized
  • 编辑器tab页:按照scene顺序习惯,切换到不同scene工作,及新建

快捷键

类型功能WIN快捷键
目录树操作创建新文件编辑器: Ctrl+N
  
节点操作创建子节点选中节点:Ctrl+A
复制子节点选中节点:Ctrl+C Ctrl+V
创建主场景Ctrl+N
  
编辑窗口专注模式Ctrl+Shift+F11
关闭scene tabCtrl+Shift+W
关闭脚本文件Ctrl+W
双视图预览Ctrl+2
打开2D编辑器Ctrl+F1
打开3D编辑器Ctrl+F2
打开Script编辑器Ctrl+F3
打开AssetLib编辑器Ctrl+F4
脚本编程大写Shift+F4
小写Shift+F5
删除行Ctrl+Shift+K
复制行Ctrl+ALT+Down
  
运行操作控制台开关Ctrl+J
runF5
run sceneF6
pauseF7
stopF8
set breakpointF9
step_overF10
step_intoF11
continueF12
  

设置

  • 缩进自动处理:编辑器>文本>行为>缩进,每次ctrl+s会自动转换

插件

编程知识

场景(根节点)

  • 创建场景:编辑窗口tab页的加号,点击创建,选择根节点的场景类型
  • 创建关联脚本:选中场景tab时,点击场景栏过滤器右侧的脚本加号,作用域为所管辖的节点树
  • 项目启动场景:项目设置>运行>选择一个场景文件
  • 场景运行时:运行时,场景树会多出一行,可以查看remote的场景树,会实时更新包括怪物刷新时的场景树变化

节点(子节点)

  • 新建子节点
    • 场景栏:选中父节点,Ctrl+A
    • 脚本:new节点实例,通过$定位一个已有节点,对它.add_child(new_instance)
  • 定位节点
    • get_tree()
    • get_parent().get_node("Camera3D")
    • get_viewport().get_camera_3d()
    • $main_div/talent_box
    • node_instance..get_children()
  • 属性设置
    • 检查器:属性设置
      • button样式
        • 创建样式:主题覆盖>样式:新建StyleBoxFlat>设置颜色阴影等
        • 克隆样式:选中上述的样式,右键复制,再到别的按钮的主题覆盖的样式,右键粘贴
        • 统一样式:样式右键存为文件,别的地方再加载文件
      • textureRect样式
        • png图片的强制大小:扩展模式改为Ignore size,自定义大小64*64即可
    • 脚本:$main_div/talent_box/talent_info/Label.text = talent["desc"]
  • 移除子节点
    • 场景栏:选中子节点,delete
    • 脚本:已有节点.remove_child(exist_instance)

信号

  • 连接信号
    • 检查器节点-选择信号-连接-关联方法
    • 脚本
      • button.connect("mouse_entered", _on_talent_button_entered)
      • button.mouse_entered.connect(_on_talent_button_entered)

语法

  • 基本信息
    • 游戏窗口物理大小:get_viewport().get_visible_rect().size
    • 获取相机镜头:get_viewport().get_camera_3d()
  • 默认方法
    • _ready方法:scene加载时,会触发gd的默认方法
    • _process方法:场景逐帧自动触发的方法,此时空间为运动
      • 鼠标屏幕坐标:get_viewport().get_mouse_position() mouse pos ray camera
      • 窗口缩放比例:global_transform.basis.get_scale()
      • 窗口实际分辨率:get_viewport().get_visible_rect().size
    • _input  _输入,期间空间锁定静态,如果此时检查碰撞,会插空
    • _unhandled_input  _未处理的_输入
  • 字符串
    • 字符串格式化:"You collected %s coins" % [str(score)]
  • 运算
    • 随机值:randi() % n (0 ~ n-1之间取一个随机值,符合下标逻辑)
    • 浮点相等:touch_target_position.is_equal_approx(position),相当于==
  • 函数
    • 默认参数值:foo(param: String = “default”) 并且有默认值的放后面
    • 可变参数:foo(array or dict) 不支持*args 这样的形参 
  • 数据结构
    • list
      • 深拷贝:talent_exist_options.duplicate()
      • 合并:talent_all_options.append_array(talent_add_options)
      • 乱序:talent_add_options.shuffle()
      • 裁剪:talent_add_options.resize(5),不足5个用null填充

打包

windows

android

  • 安装开发工具
    • JDK环境:下载解压JDK
    • SDK环境:安装安卓studio
      • SDK管理器获取SDK路径
      • 勾选platform-tools、build-tools;34.0.0、platforms;android-34、cmdline-tools、cmake;3.10.2.4988404、ndk;23.2.8568313
    • 签名文件:JDK的keytool生成
    • # 示例
      keytool -keyalg(指定算法) RSA -genkeypair(生成密钥对) -alias(别名) androiddebugkey -keypass(别名密码) android -keystore(密钥文件名) debug.keystore -storepass(密钥密码) android -dname(证书拥有者) "CN=Android Debug,O=Android,C=US" -validity(有效期天) 9999 -deststoretype(目标密钥库类型) pkcs12
      # demo - debug key
      keytool -genkey -v -keystore docs3d.debug.keystore -storepass a123456 -alias docs3ddebug -keypass a123456 -keyalg RSA -keysize 2048 -validity 10000 -dname "C=CN, O=atibm, CN=Docs3d Debug"
      # demo - release key
      keytool -genkey -v -keystore docs3d.release.keystore -alias docs3drelease -keypass a123456 -storepass a123456 -keyalg RSA -keysize 2048 -validity 10000 -dname "C=CN, O=atibm, CN=Docs3d Release"
      # 执行结果
      正在为以下对象生成 2,048 位RSA密钥对和自签名证书 (SHA256withRSA) (有效期为 9,999 天):
               CN=AT, O=BJ, C=CN
  • 编辑器设置
    • 编辑器>导出>android
      • JDK路径:从环境变量JAVA_HOME自动加载
      • SDK设置:手动填入SDK路径
      • 调试签名:*.keystore文件路径
  • 导出设置
    • 项目>导出:添加android
    • 项目>导出>Android(可执行的)
      • 调试和发布的签名设置,用户名和密码,使用签名文件生成时的参数值
  • 导出时报错
    •  keytool invalid keystore format
      • 使用studio的keytool生成:"Android Studio 2024.2.1.12"\jbr\bin\keytool.exe,#无效
      • 更换系统的JDK版本:检查D:\codeAndroid\studio\Android Studio 2024.2.1.12\jbr\bin\java.exe的版本号,安装对应jdk #无效
      • 更换studio的jdk版本:studio>设置>build>gradle: jdk选择跟生成key的jdk环境一致 #成功!!!

实战

脚本

Demo

01_docs_2d

  • 设置大小
    • 项目>显示>窗口:宽长=480*720,拉伸为canvas_items,比例keep
  • Player 玩家
    • 本节点 Area2D 玩家范围侦测
    • 子节点 AnimatedSprite2D 动画效果,属性桢添加桢,往桢添加png并设置缩放
    • 子节点 CapsuleShape2D 用于判断碰撞,属性形状添加自身,2D调整蒙版覆盖png
    • 关联脚本 player.gd
      • 暴露速度属性:@export var speed = 400 # 声明后,在检查器面板会出现speed 参数
      • 暴露攻击信号:signal hit # 声明后,在节点面板会出现hit信号
      • 玩家操作定义:项目设置>输入映射,定义动作绑定按键
      • 脚本监听操作:在gd里用Input.is_action_pressed("move_right")
      • 移动处理
        • Vector2来产生方向和速度
        • $AnimatedSprite2D.flip_来控制移动方向的动画翻转
        • $AnimatedSprite2D.play()播放
        • velocity.normalized()来防止斜向速度不一致
        • position.clamp()来防止跑出画面
      • 碰撞处理:双节player节点的信号body_entered(body: Node2D)
  • Mob 怪物
    • 本节点 RigidBody2D
      • 重力设为0,不会自动坠落
      • 碰撞的遮罩1取消,确保怪物不会相互碰撞
    • 子节点 AnimatedSprite 增加fly swim walk 三个动画
    • 子节点 CapsuleShape2D 属性添加自身,2D调整蒙版覆盖png
    • 子节点 VisibleOnScreenNotifier2D 信号screen_exited超出屏幕时实现怪物消失
  • Main 主场景
    • 本节点 Node 用于处理游戏逻辑,不需要2D功能,所以不用Node2D
    • 子节点 ColorRect 背景色,属性>布局>锚点: 整个矩形覆盖全图(用textureRect则背景图)
    • 子节点 Player 拖拽进来关联到main下面
    • 子节点 MobTimer wait time属性=0.5,关联_on_mob_timer_timeout
    • 子节点 ScoreTimer wait time属性=1,关联_on_score_timer_timeout
    • 子节点 StartTimer wait time属性=2,one shot启用,关联_on_start_timer_timeout
    • 子节点 StartPosition(Marker2D) position属性=240, 450
    • 子节点 MobPath(Path2D) 怪物刷行的区域,2D视图,添加4个顶点,点闭合
      • 孙节点 MobSpawnLocation(PathFollow2D) 循着path自动旋转,用来产生随机位置
    • 关联脚本 main.gd
      • 暴露怪物场景属性:@export var mob_scene: PackedScene
      • 关联三个计时器信号、玩家击倒信号
    • 子节点 HUB 拖拽进来关联
    • 子节点  Music(AudioStreamPlayer) 设置Stream属性选择音频(mp3,),点三角下拉选唯一化,点音乐文件勾选循环,可以无限播放(有ffmpeg工具转换)
    • 子节点  DeathSound(AudioStreamPlayer) 死亡音效
  • HUD 玩家信息
    • 本节点 CanvasLayer 玩家信息,覆盖到游戏画面上层
    • 子节点 ScoreLabel 得分
      • 节点属性>主题覆盖>字体 选择资源里的Xolonium-Regular.ttf
    • 子节点 MessageLabel
    • 子节点 StartButton,关联main.gd的new_game
    • 子节点 MessageTimer 消息计数器

02_docs_3d

  • assert:3d模型glb文件
  • 操作设置:四个方向和跳
  • 设置分辨率720*540
  • layer层定义三层为player enemies world(碰撞:层=物理所在层,遮罩=监听层)
  • main.tscn
    • 本节点 Node 定义root节点为活动场景
    • 子节点 StaticBody3D 地板
      • 属性:物理层定义为world,遮罩空
      • 孙节点 StaticBody3D 定义地板的形状,节点属性>形状:BoxShape3D 生成立方形状,点这个shape后可设置大小60m*2m*60m
      • 孙节点 MeshInstance3D 定义地板的视觉效果,节点属性>网格:BoxMesh 立方体,大小也是60*2*60,开启U磁铁吸附功能,鼠标左键按住Y轴方向的绿色箭头,下移露出示意网格(节点属性>变换>位置:Y=-1m)
    • 子节点 DirectionalLight3D 光照
      • 属性:Light3D>阴影>法线偏置=1
    • 子节点 Marker3D
      • 属性:X轴旋转-45度
      • 孙节点 Camera3D 摄像头视野,设置Z轴偏离距离19m,正交阴影大小19m
    • 子节点 Path3D 怪物刷新路径
      • 孙节点 PathFollow3D 路径连接(path点的zyx位置都非常重要,其中y高度会影响怪物刷新高度,从而影响怪物的倾斜度,以及和玩家碰撞形状的高低关系,影响击杀怪物和玩家被击杀的判断)
    • 子节点 player
      • 在main上右键选择实例化,关联进来
    • 子节点 Control
      • 属性:主题>新建theme>点开可以选择可视化主题类型
      • 孙节点 Label 用于显示文字
    • 关联脚本 main.gd
      • 暴露属性 mob_scene 并将mob.tscn拖入该属性
  • player.tscn
    • 本节点 CharacterBody3D 身体
      • 由玩家控制而非物理引擎,具有环境碰撞,物理层player,遮罩enemies world与怪物和世界碰撞
    • 子节点 Node3D 承载3D模型
      • 本节点的变换属性Y轴可以控制玩家展示的高度
      • 将player.glb模型拖入,会自动产生一个孙项实例
    • 子节点 CollisionShape3D 碰撞形状
    • 子节点 Node3D 刷怪的外围路径
      • 孙节点 MeshInstance3D 设计具体的网格
    • 子节点 Area3D 定义被碰撞到会受伤的区域
      • 节点属性 monitoring 可检测来自别人的碰撞-开启,monitorable 可被别人检测-关闭,碰撞层-关闭,碰撞监听遮罩-改为2即怪物层(当怪物碰到它时,会有信号)
      • 孙节点  CollisionShape3D 
    • 子节点 AnimaltionPlayer 动画特效
      • 新建动画,点亮自动播放,点亮循环,左侧输入框的时长设为1.2秒
      • 到CharacterBody3D 身体节点的属性,每个属性右侧有钥匙图标,点击为这些属性建立动画效果
        • 变换Transform > 位置 Position
          • 初始状态,点击一次钥匙,创建position动画轴,添加桢1,移动到0.3秒
          • y=0.65,点击一次钥匙,创建桢2,移动到0.7秒
          • y=0.35,点击一次钥匙,创建桢3,移动到1.2秒
        • 变换Transform > 旋转 Rotation
          • 初始状态,点击一次钥匙,创建rotation动画周轴,添加桢1,移动到0.1秒
          • x=8,点击一次钥匙,添加桢2,移动到0.5秒
          • x=-9,点击一次钥匙,添加桢3,移动到1.2秒
        • 缓动效果设置
          • 选中p轴桢1和r轴桢1:属性>平滑曲线:0.42,即快进缓出
          • 选中r轴桢2:属性>平滑曲线:0.44
    • 关联脚本 player.gd
      • 移动控制
  • mob.tscn
    • 本节点 CharacterBody3D 身体
      • 物理层enemies,遮罩层空,表示怪物相互间穿越
    • 子节点 Node3D 拖入mob.glb
    • 子节点 VisibleOnScreenNotifier3D 怪物离屏信息
    • 子节点 AnimaltionPlayer 动画特效
      • 管理动画,新建库,全局库
    • 关联脚本 mob.gd
      • 玩家操作转为direction
      • direction转为velocity向量
      • 赋值给角色并执行运动
  • MusicPlayer.tscn
    • 本节点 AudioStreamPlayer 背景音乐
      • ogg音轨拖到流属性里,autoplay勾选
      • 项目>全局>自动加载:选择该场景,添加

03_bilibili_tilemap

  • 解析地砖:新建图块集后,将图片拖入图块集,弹窗点是则自动切割地砖
  • 2D→2.5D:TileMapLayer子节点>节点属性:新建图块集>图块形状选Isometric>图块大小:比如64*32这样,放入2.5D地砖就有2.5D效果。要求给的地砖纹理就有2.5D效果才行
  • 多层地图:旧版本在节点属性>排序>新增图层,每个图层分别设置Z索引高度;新版4.3每建立一个TileMapLayer节点就是一个图层
  • 地形集:属性>地形集>添加元素新增一个集合;再到tileset>绘制>地形>选择地形集>多选图块,并点亮地砖部分(内部)

04_bilibili_reburn

  • 像素风格
    • 纹理设置:需要设置配合一下,在项目设置>渲染>纹理:默认纹理过滤改为Nearest
  • 开始菜单
    • 子节点快速创建:可以复制粘贴,设置布局时,可以对x或y输入数字加减,控制完美的间距
    • 按钮样式:可以对button子节点的canvasItem的可见性,调制,透明为0后,再用设计图片放这就行了
    • 跳转:按钮信号关联方法内,get_tree().change_scene_to_file("res://scenes/startchoice.tscn")
  • 选择页
    • 玩家属性
      • 属性存储:新建孤立gd脚本,用于管理玩家属性,并设置项目全部变量
      • 属性写入:新建关联脚本,用输入信号触发写入属性,PlayerDB.set_attr(name, value)
      • 属性刷新:$main_div/attr_div/attr_value/CHA.text = str(value)
      • 属性按钮:关联方式
        • func _ready() -> void:
          
          	register_all_button()
          	
          func register_all_button():
          	# 遍历 attr_reduce 下的所有按钮,动态连接信号
          	for button in $main_div/attr_div/attr_reduce.get_children():
          		if button is Button:
          			button.pressed.connect(_on_reduce_pressed.bind(button))
          	for button in $main_div/attr_div/attr_increase.get_children():
          		if button is Button:
          			button.pressed.connect(_on_increase_pressed.bind(button))
  • 商店页
    • UI层:遍历inventory的item放入menu的grid
    • 数据层:inventory放入道具item.tres
    • 模型层:item_base定义模型属性,实例化出道具item.tres

todo:

  • 商店交互,购买和属性生效,道具的格子效果
  • 玩家拆为2层,model,真实玩家,固化道具,固化天赋;模拟玩家,继承道具,继承天赋,模拟道具,模拟天赋,交互应用天赋,装备道具
  • 拆出天赋,形成天赋model基本属性
  • 天赋单独拆出来model