Godot 4 教程《勇者传说》依赖注入 学习笔记(0):环境配置
文章目录
- 前言
- 相关地址
- 环境配置
- 初始化环境配置
- 文件夹结构
- 代码结构
- 代码运行
- 资源文件导入
- 像素风格窗口环境设置
- 背景设置,Tileap使用
- 自动TileMap
- 人物场景
- 动画节点添加
- 站立节点添加
- 移动动画添加
- 通过依赖注入获取Godot的全局属性
- 项目声明
- 当前项目逻辑讲解
- 角色下降
- 添加代码
- 位置问题的思考
- 在Node2D上面挂载Lable节点
- 在CharacterBody2D下面挂载
- 解决方案
- 修改代码
- 动画节点的问题,需要重新绑定
- 为什么我要这么写
- 动画效果
- 初始化AnimationPlayer
- 输入映射
- 获取输入
- 简单移动
- 完善输入和添加动画
- 完善跳跃手感
前言
我之前解决了C# 的IOC的配置,现在来认真学习一个完整的Godot 项目。我看B站上面这个教程非常的好,所以打算用C# 去复刻一下,使用IOC依赖注入的想法。
相关地址
十分钟制作横版动作游戏|Godot 4 教程《勇者传说》#0
人物素材
环境素材
Gclove2000/GodotNet_LegendOfPaladin
环境配置
- Windows 10
- .net core 8.0
- Visual Studio 2022
- godot.net 4.2.1
初始化环境配置
Godot.NET C# 工程化开发(1):通用Nuget 导入+ 模板文件导出,包含随机数生成,日志管理,数据库连接等功能
文件夹结构
- Godot:Godot项目+主要游戏逻辑代码
- GodotProgram:帮助类
代码结构
- GodotNet_LegndOfPaladin:Godot主要逻辑
- SceneModels:场景IOC对象
- SceneScirpts:场景对应脚本
- Util: Godot API帮助类
- PackedSceneHelper:打包场景加载
- Program:IOC容器
- GodotProgram:C# 主要逻辑
- Assets:资产文件
- DB:数据库对象
- Interfaces:接口
- Service:服务
- Utils:帮助类
代码运行
资源文件导入
人物素材
环境素材
像素风格窗口环境设置
背景设置,Tileap使用
自动TileMap
Godot 官方2D C#重构(3):TileMap使用
大致实现效果
绘制TimeMap地形需要比较强的熟练度。多多联系即可
人物场景
长按左键选择站立动画
动画节点添加
站立节点添加
点击6次,添加6个关键帧
移动动画添加
和上面的一样
通过依赖注入获取Godot的全局属性
Godot的全局属性是通过字符串的方式获取的,这非常容易出问题。而且我们也希望这种配置信息能在项目启动的时候就获取
Godot ProjectSettings 字符串对应数据
项目声明
public class GodotProjectSettingHelper{private NlogHelper nlogHelper;public readonly float Gravity = 0;public GodotProjectSettingHelper(NlogHelper nlogHelper){this.nlogHelper = nlogHelper;Gravity = (float)ProjectSettings.GetSetting("physics/2d/default_gravity");}}
当前项目逻辑讲解
所以我们新建一个场景的逻辑是
- 新增XXX.tscn
- 挂载XXXScene.sc脚本
- IOC注入XXXSceneModel.cs 类
- PackedSceneHelper添加对应的PackedScene
详情请看我的Github源码
Gclove2000/GodotNet_LegendOfPaladin
角色下降
添加代码
public class PlayerSceneModel : ISceneModel
{private NlogHelper nlogHelper;private GodotProjectSettingHelper godotProjectSettingHelper;public PlayerSceneModel(NlogHelper nlogHelper,GodotProjectSettingHelper godotProjectSettingHelper) {this.nlogHelper = nlogHelper;this.godotProjectSettingHelper = godotProjectSettingHelper;}private CharacterBody2D characterBody2D;public override void Process(double delta){//给角色一个速度,因为重力是加速度,所以角色的速度会不断的增加。characterBody2D.Velocity += new Vector2(0, godotProjectSettingHelper.Gravity * (float)delta);//让物体以这个速度进行移动characterBody2D.MoveAndSlide();nlogHelper.Debug($"x:{characterBody2D.Velocity.X},y:{characterBody2D.Velocity.Y}");}public override void Ready(){nlogHelper.Debug($"当前重力值为:{godotProjectSettingHelper.Gravity}");characterBody2D = this.Sence.GetNode<CharacterBody2D>("CharacterBody2D");}
}
位置问题的思考
我们知道CharacterBody2D就是为了获取CollisionShape2D的位置。因为他的位置取决于重力,物理碰撞,加速度等多方面因素。相当于他的位置是自动变化的
在Node2D上面挂载Lable节点
在CharacterBody2D下面挂载
解决方案
我们只需要CharacterBody2D给我们的位置更改即可,而在Godot中,Position都是相对父节点的位置。所以每次Character移动的时候,我们将CharacterBody2D的位置获取,然后我们将Character的相对位置 设置为0即可
修改代码
public override void Process(double delta)
{//给角色一个速度,因为重力是加速度,所以角色的速度会不断的增加。characterBody2D.Velocity += new Vector2(0, godotProjectSettingHelper.Gravity * (float)delta);//让物体以这个速度进行移动characterBody2D.MoveAndSlide();var postion = characterBody2D.Position;characterBody2D.Position = new Vector2(0, 0);this.Sence.Position += postion;}
动画节点的问题,需要重新绑定
主要,如果修改动画节点的位置,会导致绑定出现问题
为什么我要这么写
因为我们不一定会写横版战斗游戏,横版战斗是有重力的,但是俯视角战斗又没有重力了,或者说不是垂直向下的重力,而是俯视角的效果。比如【以撒的结合】
动画效果
在Godot中,AnimationPlayer通过【Play】这个函数来播放动画。但是Godot中,Play是通过字符串的形式调用的。为了保证字符串的正确性,我们添加一个Enum枚举类型来对其进行限制
初始化AnimationPlayer
//枚举类型,防止拼写错误
public enum AnimationFlame { REST, idel,running }......public override void Ready()
{nlogHelper.Debug($"当前重力值为:{godotProjectSettingHelper.Gravity}");//初始化子节点characterBody2D = this.Sence.GetNode<CharacterBody2D>("CharacterBody2D");animationPlayer = this.Sence.GetNode<AnimationPlayer>("AnimationPlayer");//播放动画animationPlayer.Play(AnimationFlame.idel.ToString());
}
输入映射
我们输入上下左右,一般都是wasd,但是因为我们可能要做手柄,可能也要做移动端。所以最好设置一个输入映射好一些。
我的输入是,wsad是上下左右,【j】/【空格】是跳跃
获取输入
Godot 输入处理
我们在任意一个节点下面去获取按钮事件
public override void Process(double delta)
{//获取move_left对应按下事件if (Input.IsActionPressed("move_left")){nlogHelper.Debug("move_left 按下");}}
简单移动
public const float RUN_SPEED = 200;
.......public override void Process(double delta)
{var velocity = new Vector2();var direction = Input.GetAxis(InputMapEnum.move_left.ToString(), InputMapEnum.move_right.ToString());var y = godotProjectSettingHelper.Gravity * (float)delta;var x = direction * RUN_SPEED;//在C# 中,velocity = characterBody2D.Velocity;//X是最终速度,所以不需要相加velocity.X = x;//给角色一个速度,因为重力是加速度,所以角色的速度会不断的增加。velocity.Y += y;characterBody2D.Velocity = velocity;//让物体以这个速度进行移动characterBody2D.MoveAndSlide();//同步场景根节点位置var postion = characterBody2D.Position;characterBody2D.Position = new Vector2(0, 0);this.Sence.Position += postion;
}
完善输入和添加动画
using Godot;
using GodotNet_LegendOfPaladin.Utils;
using GodotProgram.Interfaces;
using GodotProgram.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static GodotNet_LegendOfPaladin.Utils.GodotProjectSettingHelper;namespace GodotNet_LegendOfPaladin.SceneModels
{public class PlayerSceneModel : ISceneModel{public const float RUN_SPEED = 200;public const float JUMP_VELOCITY = -300;//枚举类型,防止拼写错误public enum AnimationFlame { idel, running,jump }#region IOC注入private NlogHelper nlogHelper;private GodotProjectSettingHelper godotProjectSettingHelper;public PlayerSceneModel(NlogHelper nlogHelper, GodotProjectSettingHelper godotProjectSettingHelper){this.nlogHelper = nlogHelper;this.godotProjectSettingHelper = godotProjectSettingHelper;}#endregion#region 子节点获取private CharacterBody2D characterBody2D;private AnimationPlayer animationPlayer;private Sprite2D sprite2D;public override void Ready(){nlogHelper.Debug($"当前重力值为:{godotProjectSettingHelper.Gravity}");//初始化子节点characterBody2D = this.Sence.GetNode<CharacterBody2D>("CharacterBody2D");animationPlayer = this.Sence.GetNode<AnimationPlayer>("AnimationPlayer");sprite2D = this.Sence.GetNode<Sprite2D>("Sprite2D");//播放动画animationPlayer.Play(AnimationFlame.idel.ToString());}#endregionpublic override void Process(double delta){//初始化速度var velocity = new Vector2();//初始化动画节点var animation = AnimationFlame.idel;var direction = Input.GetAxis(InputMapEnum.move_left.ToString(), InputMapEnum.move_right.ToString());var y = godotProjectSettingHelper.Gravity * (float)delta;var x = direction * RUN_SPEED;var isOnFloor = characterBody2D.IsOnFloor();//在C# 中,velocity = characterBody2D.Velocity;//X是最终速度,所以不需要相加velocity.X = x;//给角色一个速度,因为重力是加速度,所以角色的速度会不断的增加。velocity.Y += y;//如果在地上并且按下跳跃,则直接给一个y轴的速度if(isOnFloor && Input.IsActionJustPressed(InputMapEnum.jump.ToString())){velocity.Y = JUMP_VELOCITY;}if (isOnFloor){if (Mathf.IsZeroApprox(direction)){animation = AnimationFlame.idel;}else{animation = AnimationFlame.running;}}else{animation = AnimationFlame.jump;}//方向翻转if (!Mathf.IsZeroApprox(direction)){sprite2D.FlipH = direction < 0;}characterBody2D.Velocity = velocity;//让物体以这个速度进行移动characterBody2D.MoveAndSlide();//同步场景根节点位置var postion = characterBody2D.Position;characterBody2D.Position = new Vector2(0, 0);this.Sence.Position += postion;animationPlayer.Play(animation.ToString());}}
}
完善跳跃手感
如果玩过超级马里奥或者别的平台跳跃游戏,都知道有一个手感的东西。就是有个跳跃的提前量。我们现在是正好落地的时候按下跳跃才能跳起来,现在我们将跳跃的按钮进行存储,给与一定的缓冲间隔。
/// <summary>
/// 最长跳跃等待时间
/// </summary>
public const int JUMP_WAIT_TIME = 3000;
/// <summary>
/// 初始化的时候让时间往后退一点,防止时间过快
/// </summary>
private DateTime jumpLastTime = DateTime.Now.AddDays(-1);......
public override void Process(double delta)
{......if (Input.IsActionJustPressed(InputMapEnum.jump.ToString())){jumpLastTime = DateTime.Now;}if (isOnFloor){//如果在地上并且按下跳跃,则直接给一个y轴的速度//超时判断if (jumpLastTime.AddMilliseconds(JUMP_WAIT_TIME) > DateTime.Now){//如果刚好触发了跳跃,给个速度,将jumpLastTime推前velocity.Y = JUMP_VELOCITY;jumpLastTime = DateTime.Now.AddDays(-1);}......}......
}
相关文章:

Godot 4 教程《勇者传说》依赖注入 学习笔记(0):环境配置
文章目录 前言相关地址环境配置初始化环境配置文件夹结构代码结构代码运行 资源文件导入像素风格窗口环境设置背景设置,Tileap使用自动TileMap 人物场景动画节点添加站立节点添加移动动画添加 通过依赖注入获取Godot的全局属性项目声明 当前项目逻辑讲解角色下降添加代码位置问…...
强行让Java和Go对比一波[持续更新]
概述 很多Java开发如果想转Golang的话,比较让Java开发蛋疼的第一是语法,第二是一些思想和设计哲学的Gap,所以我这儿强行整理一波Java和Golang的对比,但是由于GO和Java在很多方面都有不同的设计,所以这些对比的项可以更…...
理解七层网络协议
osi体系结构 上三路(管数据) 应用层 通过http等,把传输的格式,数据打包 处理网络应用。直接为端用户服务,提供各类应用过程的接口和用户接口。例如:HTTP、Tenlent、FTP、SMTP、NFS等。基于TCP的FTP、HTTP…...

网络协议——HTTP协议
目录 编辑 一,HTTP协议基本认识 二,认识URL 三,http协议的格式 1,发送格式 2,回应格式 四,服务端代码 五,http报文细节 1,Post与Get方法 2,Content_lenth 3&…...

八股面试——数据库——索引
索引的概念 B树的概念: 索引的作用 聚簇索引与非聚簇索引 聚簇索引就是主键值,在B树上,通过主键大小(数据在B树叶子节点按主键顺序排序)寻找对应的叶子节点,叶子节点保存的一整条记录。 非聚簇索引&#x…...

【二分查找】Leetcode 二分查找
题目解析 二分查找在数组有序可以使用,也可以在数组无序的时候使用(只要数组中的一些规律适用于二分即可) 704. 二分查找 算法讲解 当left > right的时候,我们循环结束,但是当left和right缩成一个点的时候&#x…...

Python+Vuecil笔记
Nginx 进入目录: C:\nginx-1.20.2\nginx-1.20.2 start nginx 开始 nginx -s stop 停止 nginx -s quit 退出CSS 通过标签去写css 循环展示数据 JS 点击时执行事件 Django 配置media 在seetings里面修改 STATIC_URL /static/ MEDIA_URL /upload/ MEDIA_ROOT os.pat…...
C语言关于随机数知识点的总结
在C语言中,随机数的生成通常依赖于特定的库函数,最常用的是 <stdlib.h> 头文件中的 rand() 函数。以下是对随机数知识点的总结、举例和分析: 随机数知识点总结 1.随机数种子:rand() 函数生成的随机数是伪随机数࿰…...

网络应用层和传输层
网络中有很多协议这些协议的不同导致了分层这一现象,不同层的主要功能不一样。 应用层:应用程序。数据具体如何使用 传输层:关注起点和终点 网络层:关注路径规划 数据链路层:关注相邻节点的转发 物理层࿱…...
Vue3:优化-从响应式数据中获取纯数据
一、情景说明 我们知道,Vue3中,创建变量时,常用ref、reactive来包裹,这样,这个变量就是响应式数据 然而,有时候,我们只需要纯数据 例如,我们在调用后端接口的时候,我们只…...

C#.手术麻醉系统源码 手麻系统如何与医院信息系统进行集成?
C#.手术麻醉系统源码 手麻系统如何与医院信息系统进行集成? 手术麻醉系统与医院信息系统的集成是一个关键步骤,它有助于实现信息的共享和流程的协同,从而提高医疗服务的效率和质量。手麻系统与lis、his、pacs等系统的对接是医院信息化建设的重…...

学习CSS Flexbox 玩flexboxfroggy flexboxfroggy1-24关详解
欢迎来到Flexbox Froggy,这是一个通过编写CSS代码来帮助Froggy和朋友的游戏! justify-content 和 align-items 是两个用于控制 CSS Flexbox 布局的属性。 justify-content:该属性用于控制 Flexbox 容器中子项目在主轴(水平方向)…...
springboot项目如何配置跨域?
在Spring Boot项目中配置跨域(CORS,Cross-Origin Resource Sharing)主要是为了允许来自不同源(不同的协议、域名或端口)的前端应用能够访问后端API。Spring Boot提供了多种方式来配置跨域支持。 1. 使用CrossOrigin注…...

实现第一个动态链接库 游戏插件 成功在主程序中运行 dll 中定义的类
devc 5.11编译环境 dll编译环境设置参考 Dev c C语言实现第一个 dll 动态链接库 创建与调用-CSDN博客 插件 DLL代码和主程序代码如下 注意 dll 代码中的class 类名需要 和主程序 相同 其中使用了函数指针和强制类型转换 函数指针教程参考 以动态库链接库 .dll 探索结构体…...

算法第三十九天-验证二叉树的前序序列化
验证二叉树的前序序列化 题目要求 解题思路 方法一:栈 栈的思路是「自底向上」的想法。下面要结合本题是「前序遍历」这个重要特点。 我们知道「前序遍历」是按照「根节点-左子树-右子树」的顺序遍历的,只有当根节点的所有左子树遍历完成之后…...
Rust---复合数据类型之字符串与切片(2)
目录 字符串操作删除 (Delete)连接 (Concatenate)字符串转义前情回顾: Rust—复合数据类型之字符串(1) 字符串操作 删除 (Delete) 删除方法仅适用于 String 类型,分别是: pop(),remove(),truncate(),clear(),此外还有drain() 方法。 pop 方法:pop() 方法返回一个 O…...

iOS 应用内网络请求设置代理
主要通过URLSessionConfiguration 的connectionProxyDictionary 属性 为了方便其他同学使用,我们可以通过界面来进行设定(是否开启代理、服务端、端口),从而达到类似系统上的设定 具体链接参考:为 iOS 网络请求设置代理…...
什么是MariaDB
2024年4月6日,周六晚上 今晚在Debian12上安装mysql时,运行后却发现是MariaDB MariaDB是一个开源的关系型数据库管理系统(RDBMS),它是MySQL的一个分支和替代品。MariaDB由MySQL的原始开发者之一Michael "Monty&qu…...

【面试八股总结】传输控制协议TCP(三)
参考资料 :小林Coding、阿秀、代码随想录 一、TCP拥塞控制⭐ 1. 慢启动 – Slow Start 慢启动是指TCP连接刚建立,一点一点地提速,试探一下网络的承受能力,以免直接扰乱了网络通道的秩序。 慢启动算法: 初始拥塞窗口…...

今年过去了多少天?(switch)
//今年已经过去了几天? #include <stdio.h> int monthday(int year,int month){switch(month){case 1:return 31;case 2:if ((year % 4 0 && year % 100 ! 0)||year % 400 0){return 29;}else{return 28;}break;case 3:return 31;case 4:return 30;…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...