将Excel导出工具内嵌到项目工程中

This commit is contained in:
小李xl 2023-12-17 17:50:42 +08:00
parent af912b46e3
commit 1d90d42ecf
79 changed files with 93 additions and 1254 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,347 +0,0 @@
前言: 该文档仅针对`DungeonShooting_Godot`目录下的Godot工程
**注意:** 新版文档编写中...
目录:
---
## 1.启动项目
**Godot版本:** Godot4x
**.net版本:** .net6.0
使用Godot打开`project.godot`, 如果是第一次打开项目会弹出一个找不到资源的提示, 这是因为项目没有编译过, 点击Godot右上角`build`, 然后打`开项目设置`, 在`插件`这一个页签下启用`DungeonShooting_plugin`这个插件, 然后项目就可以正常运行了
---
## 2.项目资源
### 2.1.目录结构
所有资源严格划分类别, 并放入指定的文件夹
**项目目录结构如下:**
* ./addons: 项目插件目录
* ./prefab: 预制体资源目录
* ./resource 美术,音乐,配置文件等资源放置路径
* ./scene 场景资源
* ./src 代码资源
### 2.2.脚本获取资源
为了方便代码获取资源以及排除代码中引用丢失资源的情况, 项目中使用`ResourcePath`类来放置所有资源路径, 该类常量值即代表资源路径, 使用`ResourceManager.Load()`来加载资源
举个例子, 某资源在编辑器中的路径为:
```text
res://resource/theme/mainTheme.tres
```
那么在`ResourcePath`中的代码就为:
```csharp
public const string resource_theme_mainTheme_tres = "res://resource/theme/mainTheme.tres";
```
加载该资源的代码为:
```csharp
var resource = ResourceManager.Load<Theme>(ResourcePath.resource_theme_mainTheme_tres);
```
### 2.3.重新生成ResourcePath
如果项目中有资源变动, 则可以使用`Tools`页签下的`重新生成ResourcePath.cs文件`
![](文档资源/image_6.png)
---
## 3.游戏框架
### 3.1.简述
游戏框架分为三部分:
1. 游戏核心系统
2. UI模块系统
3. 代码生成系统
**游戏核心系统**: 以游戏玩法为中心的逻辑代码, 包括玩家, 敌人, 武器, 被动, 道具, 地牢生成, 房间规则, 存档逻辑等
**UI模块系统**: 用户操作界面的逻辑代码
**代码生成系统**: 自动生成便于开发的资源的逻辑代码
**编辑器系统**: 用于用于自定义游戏内容
### 3.2.游戏核心系统
在`Main/ViewCanvas/SubViewportContainer/SubViewport`的子节点将开启4倍缩放, 并且启用完美像素
该节点放置除UI以外的任何节点
#### 3.2.1.什么是ActivityObject
定义: 游戏内所有可活动物体的基类叫做`ActivityObject`
源代码: [ActivityObject.cs](../DungeonShooting_Godot/src/framework/activity/ActivityObject.cs)
`ActivityObject`的意由来: 为了方便统一管理物体, 并且减少子类代码沉积, 因此将所有活动物体都需要用到的逻辑抽到一个统一的类中, 并命名为`ActivityObject`, 所有的活动物体都需要继承该类
`ActivityObject`提供的基础功能:
* `Component`组件管理
* 协程功能
* 外力控制运动
* 纵轴运动模拟 (自由落体, 投抛物体等)
* 数据标记
* 对象归属区域
* 互动逻辑接口
通过下面这张图可以了解游戏中的物体与`ActivityObject`的关系 (注意: 该图为早期开发版本的继承关系图, 后面开发可能会有修改)
![](文档资源/2023-03-26_030144.png)
#### 3.2.2.ActivityObject常用功能
##### 自定义组件
这个功能类似于`Unity`的`MonoBehaviour`, 组件必须继承`Component`类, 组件的作用是拆分功能代码, 开发者可以将相同功能的代码放入同一个组件中, 与`Godot`的`Node`不同的是, 挂载到`ActivityObject`上的组件并不会生成一个`Node`节点, 它相比于`Node`更加轻量
自定义组件代码:
```csharp
public class MyComponent : Component
{
}
```
调用`ActivityObject.AddComponent()`添加组件:
```csharp
var component = activityInstance.AddComponent<MyComponent>();
```
注意: 一个`ActivityObject`上不允许挂载多个相同的组件
##### 运动控制
`ActivityObject`的移动由自身的`MoveController`组件控制, 非特殊情况下不要直接修改`ActivityObject`的位置, 而是使用`MoveController.AddConstantForce()`函数来添加外力
```csharp
//添加一个向右的外力, 速度为100
var force = activityInstance.MoveController.AddConstantForce("ForceName"); //外力必须起名称, 而且在运动控制器中必须唯一
force.Velocity = new Vector2(0, 100);
//以下为精简写法
var force = activityInstance.MoveController.AddConstantForce(new Vector2(0, 100), 0); //创建匿名外力, 但是与上面不同的是当速率变为 0 时自动销毁
```
物体的运动方向就是所有外力总和的方向, 通过`MoveController.Velocity`可以获取当前运动速度
##### 垂直方向运动
当游戏中需要制作飞行物体或者模拟投抛运动时, 就需要控制物体纵轴所处高度, `ActivityObject`中提供了一系列控制纵轴方向运动的属性和函数, 以下列举几个关键属性和函数:
```csharp
/// <summary>
/// 当前物体的海拔高度, 如果大于0, 则会做自由落体运动, 也就是执行投抛代码
/// </summary>
public float Altitude { get; set; } = 0;
/// <summary>
/// 物体纵轴移动速度, 如果设置大于0, 就可以营造向上投抛物体的效果, 该值会随着重力加速度衰减
/// </summary>
public float VerticalSpeed { get; set; } = 0;
/// <summary>
/// 物体下坠回弹的强度
/// </summary>
public float BounceStrength { get; set; } = 0.5f;
/// <summary>
/// 物体下坠回弹后的运动速度衰减量
/// </summary>
public float BounceSpeed { get; set; } = 0.75f;
/// <summary>
/// 是否启用垂直方向上的运动模拟, 默认开启, 如果禁用, 那么下落和投抛效果, 同样 Throw() 函数也将失效
/// </summary>
public bool EnableVerticalMotion { get; set; } = true;
```
垂直运动也提供了一些可供重写的虚函数:
```csharp
/// <summary>
/// 开始投抛该物体时调用
/// </summary>
protected virtual void OnThrowStart()
{
}
/// <summary>
/// 投抛该物体达到最高点时调用
/// </summary>
protected virtual void OnThrowMaxHeight(float height)
{
}
/// <summary>
/// 投抛状态下第一次接触地面时调用, 之后的回弹落地将不会调用该函数
/// </summary>
protected virtual void OnFirstFallToGround()
{
}
/// <summary>
/// 投抛状态下每次接触地面时调用
/// </summary>
protected virtual void OnFallToGround()
{
}
/// <summary>
/// 投抛结束时调用
/// </summary>
protected virtual void OnThrowOver()
{
}
```
如果需要模拟飞行效果则需要设置`Altitude`值大于0, 并且将`EnableVerticalMotion`设置为`false`
如果需要自由落体, 则直接设置`Altitude`值大于0
如果需要上抛运动, 则直接设置`VerticalSpeed`值大于0
如果值`BounceStrength`和`BounceSpeed`设置成1, 则投抛的物体在地上会一直朝一个方向弹跳
如果需要投抛物体不需要每个关键值都设置一遍信息, 只需要调用`ActivityObject.Throw()`函数即可:
```csharp
/// <summary>
/// 将该节点投抛出去
/// </summary>
/// <param name="altitude">初始高度</param>
/// <param name="rotate">旋转速度</param>
/// <param name="velocity">移动速率</param>
/// <param name="verticalSpeed">纵轴速度</param>
public void Throw(float altitude, float verticalSpeed, Vector2 velocity, float rotate);
```
调用示例, 模拟弹壳投抛落在地上弹跳的过程
```csharp
var startPos = GlobalPosition;
var startHeight = 6;
var direction = GlobalRotationDegrees + Utils.RandomRangeInt(-30, 30) + 180;
var verticalSpeed = Utils.RandomRangeInt(60, 120);
var velocity = new Vector2(Utils.RandomRangeInt(20, 60), 0).Rotated(direction * Mathf.Pi / 180);
var rotate = Utils.RandomRangeInt(-720, 720);
var shell = ActivityObject.Create<ShellCase>(ActivityIdPrefix.Shell + "0001");
shell.Throw(startPos, startHeight, verticalSpeed, velocity, rotate);
```
##### 协程
该功能与`Unity`的协程功能类似, 在协程函数中通过`yield`关键字暂停执行后面的代码, 并将控制权返还给`ActivityObject`, 协程常被用在动画处理和资源异步加载
`ActivityObject`中协程相关函数:
```csharp
/// <summary>
/// 开启一个协程, 返回协程 id, 协程是在普通帧执行的, 支持: 协程嵌套, WaitForSeconds, WaitForFixedProcess
/// </summary>
public long StartCoroutine(IEnumerator able);
/// <summary>
/// 根据协程 id 停止协程
/// </summary>
public void StopCoroutine(long coroutineId);
/// <summary>
/// 停止所有协程
/// </summary>
public void StopAllCoroutine();
```
协程`yield return`返回特殊值类型如下:
* **WaitForSeconds**: 当前协程等待秒数
* **WaitForFixedProcess**: 当前协程等待帧数
* **IEnumerator**: 嵌套执行子协程, 等子协程执行完毕后才会继续执行后面的代码
协程`yield return`如果返回除以上数据类型以外的数据, 将忽略返回值
调用实例, 以下代码在`ActivityInstance`初始化时执行协程`StartRotation`, 协程在60帧内让物体每帧角度加1
```csharp
public override void OnInit()
{
StartCoroutine(StartRotation());
}
private IEnumerator StartRotation()
{
for (int i = 0; i < 60; i++)
{
RotationDegrees += 1;
//结束这一帧, 返回0会被忽略返回值
yield return 0;
}
}
```
### 3.3.地牢
#### 3.3.1.地牢概述
游戏中的地牢由若干层组成, 每一层地牢又由数个小房间随机拼接而成, 由起始房间开始, 成树状连接; 每一层地牢有一个起始房间, 和至少一个通向另一层的结束房间, 房间与房间之间由过道连接, 过道不会交叉和重叠
房间有以下类别 (目前代码还未完成区分类型的功能):
* **起始房间**: 由上一层地牢的结束房间进入该房间, 每层包含一个起始房间
* **结束房间**: 进入另一层地牢, 每层只是包含一个结束房间
* **普通战斗房间**: 进入该房间时会关上门, 并刷出若干波敌人, 消灭所有敌人后开门
* **boss战房间**: 进入房间时会关上没, 刷出boss, 消灭boss后开门
* **奖励房间**: 给予玩家武器或者道具奖励的房间
* **商店**: 玩家买卖道具装备的房间
* **事件房间**: 触发剧情或者解锁NPC的房间
### 3.4.UI系统
#### 3.4.1.UI系统概述
游戏内的物体, 例如`ActivityObject`等都是在`Main/ViewCanvas/SubViewportContainer/SubViewport`节点下, 并且启用了完美像素, 但是UI恰恰相反,它们直接位于`Main`节点下, 既没有4倍缩放也没有完美像素
游戏中的UI分为4个层级, 分别为
* Bottom: 最底层, 层级为5
* Middle: 中间层, 层级为15
* Height: 较高层, 层级为25
* Pop: 最顶层, 层级为35
UI场景根节点必须继承`UiBase`类, 并且生命周期由`UiManager`控制
UI代码放置位置: `src/game/ui/**/**.cs`
UI场景资源放置位置: `prefab/ui/**.tscn`
源代码: [UiBase.cs](../DungeonShooting_Godot/src/framework/ui/UiBase.cs), [UiManager.cs](../DungeonShooting_Godot/src/framework/ui/UiManager.cs)
打开指定UI:
```csharp
var ui = UiManager.OpenUi("UI名称");
```
关闭Ui
```csharp
UiManager.DisposeUi(ui);
```
#### 3.4.2.UI代码生器
为了减低开发者制作UI的复杂程度, 避免手写获取UI节点的代码, 我们设计了一套自动生成UI层级代码的功能, 该功能在编辑器中会监听开发者对于UI场景的修改, 并及时生成相应的UI代码, 并且开发者的UI逻辑类继承生成的UI类, 即可方便的获取UI节点, 可以节省大量时间, 因为代码是实时生成的, 因此一旦有节点改名或者移动位置, 重新生成UI代码后, 引用该节点的代码就会出现编译错误, 方便开发者修改
##### 创建UI
在`Tools`页签下找到`创建游戏UI`, 输入UI名称即可点击创建UI
![](文档资源/image_14.png)
创建完毕后编辑器会离开打开该UI场景
观察文件系统可以注意到, 编辑器为我创建并保存了场景和代码, 并且还生成了一个`MyUiPanel.cs`的文件, 该文件就是我们写UI逻辑代码的地方, 并且命名方式为`UI名称`+`Panel`, 这个Panel类继承了自动生成出来的UI类
![](文档资源/image_15.png)
![](文档资源/image_16.png)
动态生成的UI代码的节点对象由`IUiNode`包裹, 为了子节点与内助属性区分方便, 生成出来的代码会为每一层的名称加上前缀`L_`, 同理如果需要获取子节点则直接寻找以`L_`开始的属性
例如节点在编辑器的路径为`Group/Button`, 那么在代码里就是`L_Group.L_Button`
源代码: [IUiNode.cs](../DungeonShooting_Godot/src/framework/ui/IUiNode.cs)
通过以下这个gif就可以直观感受到该功能的便捷之处
![](文档资源/gif_4.gif)
##### 打开UI
创建完成UI后, 编辑器也会在`UiManager`中生成打开该UI和获取UI实例的Api
![](文档资源/image_17.png)
那么可以直接调用`UiManager`中的函数打开该UI
```csharp
UiManager.Open_MyUi();
```
#### 3.4.3.常用功能
##### 生命周期
`UiBase`包含4个生命周期函数:
```csharp
/// <summary>
/// 创建当前ui时调用
/// </summary>
public virtual void OnCreateUi()
{
}
/// <summary>
/// 当前ui显示时调用
/// </summary>
public virtual void OnShowUi()
{
}
/// <summary>
/// 当前ui隐藏时调用
/// </summary>
public virtual void OnHideUi()
{
}
/// <summary>
/// 销毁当前ui时调用
/// </summary>
public virtual void OnDestroy()
{
}
```
#### 包裹UI节点的IUiNode
获取`Node`实例: 使用例如`L_Group.L_Button`的代码获取的节点并不是`Godot`节点对象, 而是包裹对象, 需要从`Instance`属性中获取原生`Node`对象
克隆节点: 使用`IUiNode.Clone()`可以完整的克隆当前节点以及子节点
嵌套UI: 使用`IUiNode.OpenNestedUi()`即可以当前节点为根节点打开子级UI

View File

@ -1,23 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="NPOI" Version="2.6.0" />
</ItemGroup>
<ItemGroup>
<None Include="excelFile/**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="excelFile\Test.xlsx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -1,16 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DungeonShooting_ExcelTool", "DungeonShooting_ExcelTool.csproj", "{F6A26370-A918-40F0-8D78-414213011172}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F6A26370-A918-40F0-8D78-414213011172}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F6A26370-A918-40F0-8D78-414213011172}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F6A26370-A918-40F0-8D78-414213011172}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F6A26370-A918-40F0-8D78-414213011172}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@ -1,2 +0,0 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/PencilsConfiguration/ActualSeverity/@EntryValue">WARNING</s:String></wpf:ResourceDictionary>

View File

@ -1,26 +0,0 @@

public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("准备导出excel表...");
bool success;
if (args.Length >= 3)
{
success = ExcelGenerator.ExportExcel(args[0], args[1], args[2]);
}
else
{
success = ExcelGenerator.ExportExcel();
}
if (success)
{
Console.WriteLine("excel表导出成功!");
}
else
{
Console.WriteLine("excel表导出失败!");
}
}
}

View File

@ -1,31 +0,0 @@
using System.Text.Json.Serialization;
/// <summary>
/// 可序列化的 Color 对象
/// </summary>
public class SerializeColor
{
public SerializeColor(float r, float g, float b, float a)
{
R = r;
G = g;
B = b;
A = a;
}
public SerializeColor()
{
}
[JsonInclude]
public float R { get; private set; }
[JsonInclude]
public float G { get; private set; }
[JsonInclude]
public float B { get; private set; }
[JsonInclude]
public float A { get; private set; }
}

View File

@ -1,30 +0,0 @@

using System.Text.Json.Serialization;
/// <summary>
/// 可序列化的 Vector2 对象
/// </summary>
public class SerializeVector2
{
public SerializeVector2(float x, float y)
{
X = x;
Y = y;
}
public SerializeVector2(SerializeVector2 v)
{
X = v.X;
Y = v.Y;
}
public SerializeVector2()
{
}
[JsonInclude]
public float X { get; private set; }
[JsonInclude]
public float Y { get; private set; }
}

View File

@ -1,32 +0,0 @@
using System.Text.Json.Serialization;
/// <summary>
/// 可序列化的 Vector3 对象
/// </summary>
public class SerializeVector3
{
public SerializeVector3(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
public SerializeVector3(SerializeVector3 v)
{
X = v.X;
Y = v.Y;
}
public SerializeVector3()
{
}
[JsonInclude]
public float X { get; private set; }
[JsonInclude]
public float Y { get; private set; }
[JsonInclude]
public float Z { get; private set; }
}

View File

@ -1,16 +1,22 @@
using System.Text.Json;
#if TOOLS
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Text.RegularExpressions;
using Config;
using Godot;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Array = Godot.Collections.Array;
using Environment = System.Environment;
namespace Generator;
public static class ExcelGenerator
{
private const string CodeOutPath = "src/config/";
private const string JsonOutPath = "resource/config/";
private const string ExcelFilePath = "excelFile";
private static HashSet<string> _excelNames = new HashSet<string>();
private enum CollectionsType
{
@ -21,7 +27,6 @@ public static class ExcelGenerator
private class MappingData
{
public string TypeStr;
public string TypeName;
public CollectionsType CollectionsType;
@ -58,18 +63,31 @@ public static class ExcelGenerator
public Dictionary<string, Type> ColumnType = new Dictionary<string, Type>();
public List<Dictionary<string, object>> DataList = new List<Dictionary<string, object>>();
}
public static bool ExportExcel()
/// <summary>
/// 导出 Excel 表
/// </summary>
public static void ExportExcel()
{
return ExportExcel(ExcelFilePath, JsonOutPath, CodeOutPath);
var excelPath = "excel/";
var jsonPath = "resource/config/";
var codePath = "src/config/";
ExportExcel(excelPath, jsonPath, codePath);
}
/// <summary>
/// 导出 Excel 表
/// </summary>
/// <param name="excelFilePath">excel文件路径</param>
/// <param name="jsonOutPath">json配置输出路径</param>
/// <param name="codeOutPath">代码输出路径</param>
public static bool ExportExcel(string excelFilePath, string jsonOutPath, string codeOutPath)
{
Console.WriteLine("当前路径: " + Environment.CurrentDirectory);
Console.WriteLine("excel路径: " + excelFilePath);
Console.WriteLine("json输出路径: " + jsonOutPath);
Console.WriteLine("cs代码输出路径: " + codeOutPath);
_excelNames.Clear();
Debug.Log("当前路径: " + Environment.CurrentDirectory);
Debug.Log("excel路径: " + excelFilePath);
Debug.Log("json输出路径: " + jsonOutPath);
Debug.Log("cs代码输出路径: " + codeOutPath);
try
{
var excelDataList = new List<ExcelData>();
@ -93,13 +111,13 @@ public static class ExcelGenerator
{
throw new Exception("excel表文件名称不允许叫'ExcelConfig.xlsx'!");
}
Console.WriteLine("excel表: " + fileInfo.FullName);
Debug.Log("excel表: " + fileInfo.FullName);
excelDataList.Add(ReadExcel(fileInfo.FullName));
}
}
}
Console.WriteLine($"一共检测到excel表共{excelDataList.Count}张.");
Debug.Log($"一共检测到excel表共{excelDataList.Count}张.");
if (excelDataList.Count == 0)
{
return true;
@ -119,6 +137,11 @@ public static class ExcelGenerator
//保存配置和代码
foreach (var excelData in excelDataList)
{
if (excelData.TableName == "ActivityBase")
{
//生成初始化 ActivityObject 代码
GeneratorActivityObjectInit(excelData);
}
File.WriteAllText(codeOutPath + "ExcelConfig_" + excelData.TableName + ".cs", excelData.OutCode);
var config = new JsonSerializerOptions();
config.WriteIndented = true;
@ -725,24 +748,42 @@ public static class ExcelGenerator
private static void PrintError(string message)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(message);
Console.ResetColor();
Debug.LogError(message);
}
/// <summary>
/// 字符串首字母小写
/// </summary>
public static string FirstToLower(this string str)
//生成 ActivityObject.Ids 代码
private static void GeneratorActivityObjectInit(ExcelData activityExcelData)
{
return str.Substring(0, 1).ToLower() + str.Substring(1);
var code1 = "";
foreach (var item in activityExcelData.DataList)
{
var id = item["Id"];
var name = item["Name"] + "";
var intro = item["Intro"] + "";
code1 += $" /// <summary>\n";
code1 += $" /// 名称: {name} <br/>\n";
code1 += $" /// 简介: {intro.Replace("\n", " <br/>\n /// ")}\n";
code1 += $" /// </summary>\n";
code1 += $" public const string Id_{id} = \"{id}\";\n";
}
var str = $"using Config;\n\n";
str += $"// 根据配置表注册物体, 该类是自动生成的, 请不要手动编辑!\n";
str += $"public partial class ActivityObject\n";
str += $"{{\n";
str += $" /// <summary>\n";
str += $" /// 存放所有在表中注册的物体的id\n";
str += $" /// </summary>\n";
str += $" public static class Ids\n";
str += $" {{\n";
str += code1;
str += $" }}\n";
str += $"}}\n";
File.WriteAllText("src/framework/activity/ActivityObject_Init.cs", str);
}
/// <summary>
/// 字符串首字母大写
/// </summary>
public static string FirstToUpper(this string str)
{
return str.Substring(0, 1).ToUpper() + str.Substring(1);
}
}
}
#endif

View File

@ -4,7 +4,6 @@ using System;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Godot;
namespace Generator;

View File

@ -2,8 +2,6 @@
using System;
using System.IO;
using System.Text.RegularExpressions;
using Godot;
namespace Generator;

View File

@ -1,352 +0,0 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v7.0/win-x64",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v7.0": {},
".NETCoreApp,Version=v7.0/win-x64": {
"DungeonShooting_ExcelTool/1.0.0": {
"dependencies": {
"NPOI": "2.6.0"
},
"runtime": {
"DungeonShooting_ExcelTool.dll": {}
}
},
"Enums.NET/4.0.0": {
"runtime": {
"lib/netcoreapp3.0/Enums.NET.dll": {
"assemblyVersion": "4.0.0.0",
"fileVersion": "4.0.0.0"
}
}
},
"MathNet.Numerics.Signed/4.15.0": {
"runtime": {
"lib/netstandard2.0/MathNet.Numerics.dll": {
"assemblyVersion": "4.15.0.0",
"fileVersion": "4.15.0.0"
}
}
},
"Microsoft.IO.RecyclableMemoryStream/2.2.0": {
"runtime": {
"lib/net5.0/Microsoft.IO.RecyclableMemoryStream.dll": {
"assemblyVersion": "2.2.0.0",
"fileVersion": "2.2.0.0"
}
}
},
"Microsoft.Win32.SystemEvents/6.0.0": {
"runtime": {
"runtimes/win/lib/net6.0/Microsoft.Win32.SystemEvents.dll": {
"assemblyVersion": "6.0.0.0",
"fileVersion": "6.0.21.52210"
}
}
},
"NPOI/2.6.0": {
"dependencies": {
"Enums.NET": "4.0.0",
"MathNet.Numerics.Signed": "4.15.0",
"Microsoft.IO.RecyclableMemoryStream": "2.2.0",
"Portable.BouncyCastle": "1.9.0",
"SharpZipLib": "1.3.3",
"SixLabors.Fonts": "1.0.0-beta18",
"SixLabors.ImageSharp": "2.1.3",
"System.Configuration.ConfigurationManager": "6.0.0",
"System.Security.Cryptography.Xml": "6.0.1",
"System.Text.Encoding.CodePages": "6.0.0"
},
"runtime": {
"lib/net6.0/NPOI.OOXML.dll": {
"assemblyVersion": "2.6.0.0",
"fileVersion": "2.6.0.0"
},
"lib/net6.0/NPOI.OpenXml4Net.dll": {
"assemblyVersion": "2.6.0.0",
"fileVersion": "2.6.0.0"
},
"lib/net6.0/NPOI.OpenXmlFormats.dll": {
"assemblyVersion": "2.6.0.0",
"fileVersion": "2.6.0.0"
},
"lib/net6.0/NPOI.dll": {
"assemblyVersion": "2.6.0.0",
"fileVersion": "2.6.0.0"
}
}
},
"Portable.BouncyCastle/1.9.0": {
"runtime": {
"lib/netstandard2.0/BouncyCastle.Crypto.dll": {
"assemblyVersion": "1.9.0.0",
"fileVersion": "1.9.0.1"
}
}
},
"SharpZipLib/1.3.3": {
"runtime": {
"lib/netstandard2.1/ICSharpCode.SharpZipLib.dll": {
"assemblyVersion": "1.3.3.11",
"fileVersion": "1.3.3.11"
}
}
},
"SixLabors.Fonts/1.0.0-beta18": {
"runtime": {
"lib/netcoreapp3.1/SixLabors.Fonts.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
},
"SixLabors.ImageSharp/2.1.3": {
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "6.0.0",
"System.Text.Encoding.CodePages": "6.0.0"
},
"runtime": {
"lib/netcoreapp3.1/SixLabors.ImageSharp.dll": {
"assemblyVersion": "2.0.0.0",
"fileVersion": "2.1.3.0"
}
}
},
"System.Configuration.ConfigurationManager/6.0.0": {
"dependencies": {
"System.Security.Cryptography.ProtectedData": "6.0.0",
"System.Security.Permissions": "6.0.0"
},
"runtime": {
"lib/net6.0/System.Configuration.ConfigurationManager.dll": {
"assemblyVersion": "6.0.0.0",
"fileVersion": "6.0.21.52210"
}
}
},
"System.Drawing.Common/6.0.0": {
"dependencies": {
"Microsoft.Win32.SystemEvents": "6.0.0"
},
"runtime": {
"runtimes/win/lib/net6.0/System.Drawing.Common.dll": {
"assemblyVersion": "6.0.0.0",
"fileVersion": "6.0.21.52210"
}
}
},
"System.Formats.Asn1/6.0.0": {},
"System.Runtime.CompilerServices.Unsafe/6.0.0": {},
"System.Security.AccessControl/6.0.0": {},
"System.Security.Cryptography.Pkcs/6.0.1": {
"dependencies": {
"System.Formats.Asn1": "6.0.0"
},
"runtime": {
"runtimes/win/lib/net6.0/System.Security.Cryptography.Pkcs.dll": {
"assemblyVersion": "6.0.0.0",
"fileVersion": "6.0.522.21309"
}
}
},
"System.Security.Cryptography.ProtectedData/6.0.0": {
"runtime": {
"runtimes/win/lib/net6.0/System.Security.Cryptography.ProtectedData.dll": {
"assemblyVersion": "6.0.0.0",
"fileVersion": "6.0.21.52210"
}
}
},
"System.Security.Cryptography.Xml/6.0.1": {
"dependencies": {
"System.Security.AccessControl": "6.0.0",
"System.Security.Cryptography.Pkcs": "6.0.1"
},
"runtime": {
"lib/net6.0/System.Security.Cryptography.Xml.dll": {
"assemblyVersion": "6.0.0.0",
"fileVersion": "6.0.822.36306"
}
}
},
"System.Security.Permissions/6.0.0": {
"dependencies": {
"System.Security.AccessControl": "6.0.0",
"System.Windows.Extensions": "6.0.0"
},
"runtime": {
"lib/net6.0/System.Security.Permissions.dll": {
"assemblyVersion": "6.0.0.0",
"fileVersion": "6.0.21.52210"
}
}
},
"System.Text.Encoding.CodePages/6.0.0": {
"dependencies": {
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
}
},
"System.Windows.Extensions/6.0.0": {
"dependencies": {
"System.Drawing.Common": "6.0.0"
},
"runtime": {
"runtimes/win/lib/net6.0/System.Windows.Extensions.dll": {
"assemblyVersion": "6.0.0.0",
"fileVersion": "6.0.21.52210"
}
}
}
}
},
"libraries": {
"DungeonShooting_ExcelTool/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Enums.NET/4.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-d47SgeuGxKpalKhYoHqFkDPmO9SoE3amSwVNDoUdy4d675/tX7bLyZFHdjfo3Tobth9Y80VnjfasQ/PD4LqUuA==",
"path": "enums.net/4.0.0",
"hashPath": "enums.net.4.0.0.nupkg.sha512"
},
"MathNet.Numerics.Signed/4.15.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-LFjukMRatkg9dgRM7U/gM4uKgaWAX7E0lt3fsVDTPdtBIVuh7uPlksDie290br1/tv1a4Ar/Bz9ywCPSL8PhHg==",
"path": "mathnet.numerics.signed/4.15.0",
"hashPath": "mathnet.numerics.signed.4.15.0.nupkg.sha512"
},
"Microsoft.IO.RecyclableMemoryStream/2.2.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-uyjY/cqomw1irT4L7lDeg4sJ36MsjHg3wKqpGrBAdzvZaxo85yMF+sAA9RIzTV92fDxuUzjqksMqA0+SNMkMgA==",
"path": "microsoft.io.recyclablememorystream/2.2.0",
"hashPath": "microsoft.io.recyclablememorystream.2.2.0.nupkg.sha512"
},
"Microsoft.Win32.SystemEvents/6.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A==",
"path": "microsoft.win32.systemevents/6.0.0",
"hashPath": "microsoft.win32.systemevents.6.0.0.nupkg.sha512"
},
"NPOI/2.6.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Pwjo65CUH3MiRnBEbVo8ff31ZrDGdGyyFJyAEncmbTQ0/gYgDkBUnGKm20aLpdwCpPNLzvapZm8v5tx4S6qAWg==",
"path": "npoi/2.6.0",
"hashPath": "npoi.2.6.0.nupkg.sha512"
},
"Portable.BouncyCastle/1.9.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-eZZBCABzVOek+id9Xy04HhmgykF0wZg9wpByzrWN7q8qEI0Qen9b7tfd7w8VA3dOeesumMG7C5ZPy0jk7PSRHw==",
"path": "portable.bouncycastle/1.9.0",
"hashPath": "portable.bouncycastle.1.9.0.nupkg.sha512"
},
"SharpZipLib/1.3.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-N8+hwhsKZm25tDJfWpBSW7EGhH/R7EMuiX+KJ4C4u+fCWVc1lJ5zg1u3S1RPPVYgTqhx/C3hxrqUpi6RwK5+Tg==",
"path": "sharpziplib/1.3.3",
"hashPath": "sharpziplib.1.3.3.nupkg.sha512"
},
"SixLabors.Fonts/1.0.0-beta18": {
"type": "package",
"serviceable": true,
"sha512": "sha512-evykNmy/kEE9EAEKgZm3MNUYXuMHFfmcLUNPw7Ho5q7OI96GFkkIxBm+QaKOTPBKw+L0AjKOs+ArVg8P40Ac9g==",
"path": "sixlabors.fonts/1.0.0-beta18",
"hashPath": "sixlabors.fonts.1.0.0-beta18.nupkg.sha512"
},
"SixLabors.ImageSharp/2.1.3": {
"type": "package",
"serviceable": true,
"sha512": "sha512-8yonNRWX3vUE9k29ta0Hbfa0AEc0hbDjSH/nZ3vOTJEXmY6hLnGsjDKoz96Z+AgOsrdkAu6PdL/Ebaf70aitzw==",
"path": "sixlabors.imagesharp/2.1.3",
"hashPath": "sixlabors.imagesharp.2.1.3.nupkg.sha512"
},
"System.Configuration.ConfigurationManager/6.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-7T+m0kDSlIPTHIkPMIu6m6tV6qsMqJpvQWW2jIc2qi7sn40qxFo0q+7mEQAhMPXZHMKnWrnv47ntGlM/ejvw3g==",
"path": "system.configuration.configurationmanager/6.0.0",
"hashPath": "system.configuration.configurationmanager.6.0.0.nupkg.sha512"
},
"System.Drawing.Common/6.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==",
"path": "system.drawing.common/6.0.0",
"hashPath": "system.drawing.common.6.0.0.nupkg.sha512"
},
"System.Formats.Asn1/6.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-T6fD00dQ3NTbPDy31m4eQUwKW84s03z0N2C8HpOklyeaDgaJPa/TexP4/SkORMSOwc7WhKifnA6Ya33AkzmafA==",
"path": "system.formats.asn1/6.0.0",
"hashPath": "system.formats.asn1.6.0.0.nupkg.sha512"
},
"System.Runtime.CompilerServices.Unsafe/6.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==",
"path": "system.runtime.compilerservices.unsafe/6.0.0",
"hashPath": "system.runtime.compilerservices.unsafe.6.0.0.nupkg.sha512"
},
"System.Security.AccessControl/6.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==",
"path": "system.security.accesscontrol/6.0.0",
"hashPath": "system.security.accesscontrol.6.0.0.nupkg.sha512"
},
"System.Security.Cryptography.Pkcs/6.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ynmbW2GjIGg9K1wXmVIRs4IlyDolf0JXNpzFQ8JCVgwM+myUC2JeUggl2PwQig2PNVMegKmN1aAx7WPQ8tI3vA==",
"path": "system.security.cryptography.pkcs/6.0.1",
"hashPath": "system.security.cryptography.pkcs.6.0.1.nupkg.sha512"
},
"System.Security.Cryptography.ProtectedData/6.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-rp1gMNEZpvx9vP0JW0oHLxlf8oSiQgtno77Y4PLUBjSiDYoD77Y8uXHr1Ea5XG4/pIKhqAdxZ8v8OTUtqo9PeQ==",
"path": "system.security.cryptography.protecteddata/6.0.0",
"hashPath": "system.security.cryptography.protecteddata.6.0.0.nupkg.sha512"
},
"System.Security.Cryptography.Xml/6.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-5e5bI28T0x73AwTsbuFP4qSRzthmU2C0Gqgg3AZ3KTxmSyA+Uhk31puA3srdaeWaacVnHhLdJywCzqOiEpbO/w==",
"path": "system.security.cryptography.xml/6.0.1",
"hashPath": "system.security.cryptography.xml.6.0.1.nupkg.sha512"
},
"System.Security.Permissions/6.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-T/uuc7AklkDoxmcJ7LGkyX1CcSviZuLCa4jg3PekfJ7SU0niF0IVTXwUiNVP9DSpzou2PpxJ+eNY2IfDM90ZCg==",
"path": "system.security.permissions/6.0.0",
"hashPath": "system.security.permissions.6.0.0.nupkg.sha512"
},
"System.Text.Encoding.CodePages/6.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==",
"path": "system.text.encoding.codepages/6.0.0",
"hashPath": "system.text.encoding.codepages.6.0.0.nupkg.sha512"
},
"System.Windows.Extensions/6.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==",
"path": "system.windows.extensions/6.0.0",
"hashPath": "system.windows.extensions.6.0.0.nupkg.sha512"
}
}
}

View File

@ -1,12 +0,0 @@
{
"runtimeOptions": {
"tfm": "net7.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "7.0.0"
},
"configProperties": {
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false
}
}
}

Binary file not shown.

View File

@ -7,7 +7,7 @@ dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter="build/*"
exclude_filter="excel/*,build/*"
export_path="build/android/build.apk"
encryption_include_filters=""
encryption_exclude_filters=""
@ -22,7 +22,7 @@ gradle_build/use_gradle_build=true
gradle_build/export_format=0
gradle_build/min_sdk=""
gradle_build/target_sdk=""
architectures/armeabi-v7a=true
architectures/armeabi-v7a=false
architectures/arm64-v8a=true
architectures/x86=false
architectures/x86_64=false
@ -215,8 +215,8 @@ dedicated_server=false
custom_features=""
export_filter="all_resources"
include_filter=""
exclude_filter="resource/map/tileMaps/*"
export_path="../../DungeonShooting_Export/windows/game.exe"
exclude_filter="resource/map/tileMaps/*,excel/*,build/*"
export_path="build/windows/game.exe"
encryption_include_filters=""
encryption_exclude_filters=""
encrypt_pck=false

View File

@ -1 +1 @@
[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[{"Position":{"X":0,"Y":0},"Size":{"X":14,"Y":16},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]},{"Position":{"X":35,"Y":-27},"Size":{"X":30,"Y":12},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":8,"Y":32},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0002","Weight":100,"Attr":{"CurrAmmon":"7","ResidueAmmo":"70"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-50,"Y":7},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0004","Weight":100,"Attr":{"CurrAmmon":"180","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-63,"Y":-18},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0005","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"40"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-31,"Y":-16},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0003","Weight":100,"Attr":{"CurrAmmon":"12","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-54,"Y":33},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0006","Weight":100,"Attr":{"CurrAmmon":"20","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":2,"Y":-25},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0007","Weight":100,"Attr":{"CurrAmmon":"60","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-76,"Y":21},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0008","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"120"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-87,"Y":46},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0009","Weight":100,"Attr":{"CurrAmmon":"1","ResidueAmmo":"25"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":34,"Y":-1},"Size":{"X":24,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0011","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":45,"Y":55},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0012","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-90,"Y":-26},"Size":{"X":13,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0013","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-91,"Y":-6},"Size":{"X":14,"Y":13},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0014","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-73,"Y":66},"Size":{"X":14,"Y":14},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]}],[{"Position":{"X":72,"Y":62},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0003","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":67,"Y":28},"Size":{"X":16,"Y":17},"SpecialMarkType":0,"DelayTime":0.5,"MarkList":[{"Id":"prop5000","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":67,"Y":-12},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":36,"Y":25},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1.5,"MarkList":[{"Id":"prop0002","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-24,"Y":8},"Size":{"X":18,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0010","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-20,"Y":34},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0010","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0},{"Id":"prop0006","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]}]]},{"Name":"test2","Weight":100,"Remark":"","WaveList":[[{"Position":{"X":0,"Y":0},"Size":{"X":0,"Y":0},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]}]]}]
[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[{"Position":{"X":0,"Y":0},"Size":{"X":14,"Y":16},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]},{"Position":{"X":35,"Y":-27},"Size":{"X":30,"Y":12},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":8,"Y":32},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0002","Weight":100,"Attr":{"CurrAmmon":"7","ResidueAmmo":"70"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-50,"Y":7},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0004","Weight":100,"Attr":{"CurrAmmon":"180","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-63,"Y":-18},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0005","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"40"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-31,"Y":-16},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0003","Weight":100,"Attr":{"CurrAmmon":"12","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-54,"Y":33},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0006","Weight":100,"Attr":{"CurrAmmon":"20","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":2,"Y":-25},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0007","Weight":100,"Attr":{"CurrAmmon":"60","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-76,"Y":21},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0008","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"120"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-87,"Y":46},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0009","Weight":100,"Attr":{"CurrAmmon":"1","ResidueAmmo":"25"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":34,"Y":-1},"Size":{"X":24,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0011","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":45,"Y":55},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0012","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-90,"Y":-26},"Size":{"X":13,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0013","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-91,"Y":-6},"Size":{"X":14,"Y":13},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0014","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-73,"Y":66},"Size":{"X":14,"Y":14},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]}],[{"Position":{"X":72,"Y":62},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0003","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":67,"Y":28},"Size":{"X":16,"Y":17},"SpecialMarkType":0,"DelayTime":0.5,"MarkList":[{"Id":"prop5000","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":67,"Y":-12},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":36,"Y":25},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1.5,"MarkList":[{"Id":"prop0002","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-24,"Y":8},"Size":{"X":18,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0010","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-20,"Y":34},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0010","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0},{"Id":"prop0006","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]}]]}]

View File

@ -1,6 +1,6 @@
[gd_resource type="Theme" load_steps=61 format=3 uid="uid://ds668te2rph30"]
[ext_resource type="FontFile" uid="uid://cad0in7dtweo5" path="res://resource/font/VonwaonBitmap-16px.ttf" id="1_1e6k7"]
[ext_resource type="FontFile" uid="uid://l2h5n3elepgp" path="res://resource/font/VonwaonBitmap-16px.ttf" id="1_1e6k7"]
[sub_resource type="StyleBoxFlat" id="2"]
content_margin_left = 6.0

View File

@ -1,255 +0,0 @@
#if TOOLS
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using Godot;
namespace Generator;
/// <summary>
/// 地牢房间数据生成器
/// </summary>
public static class DungeonRoomGenerator
{
/// <summary>
/// 根据名称在编辑器中创建地牢的预制房间, open 表示创建完成后是否在编辑器中打开这个房间
/// </summary>
public static bool CreateDungeonRoom(string groupName, string roomType, string roomName, bool open = false)
{
try
{
var path = GameConfig.RoomTileDir + groupName + "/" + roomType;
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
//创建场景资源
var prefabFile = path + "/" + roomName + ".tscn";
var prefabResPath = "res://" + prefabFile;
if (!Directory.Exists(GameConfig.RoomTileDir))
{
Directory.CreateDirectory(GameConfig.RoomTileDir);
}
//加载脚本资源
// 这段代码在 Godot4.0.1rc1中会报错, 应该是个bug
// var scriptRes = GD.Load<CSharpScript>("res://src/framework/map/DungeonRoomTemplate.cs");
// var tileMap = new TileMap();
// tileMap.Name = roomName;
// tileMap.SetScript(scriptRes);
// var scene = new PackedScene();
// scene.Pack(tileMap); //报错在这一行, 报的是访问了被销毁的资源 scriptRes
// ResourceSaver.Save(scene, prefabResPath);
//临时处理
{
var tscnCode = $"[gd_scene load_steps=2 format=3]\n" +
$"\n" +
$"[ext_resource type=\"Script\" path=\"res://src/framework/map/DungeonRoomTemplate.cs\" id=\"dungeonRoomTemplate\"]\n" +
$"\n" +
$"[node name=\"{roomName}\" type=\"TileMap\"]\n" +
$"format = 2\n" +
$"script = ExtResource(\"dungeonRoomTemplate\")\n";
File.WriteAllText(prefabFile, tscnCode);
//重新保存一遍, 以让编辑器生成资源Id
var scene = GD.Load<PackedScene>(prefabResPath);
ResourceSaver.Save(scene, prefabResPath);
}
//打包房间配置
GenerateRoomConfig();
//生成 UiManager_Methods.cs 代码
UiManagerMethodsGenerator.Generate();
//打开房间
if (open)
{
Plugin.Plugin.Instance.GetEditorInterface().OpenSceneFromPath(prefabResPath);
}
}
catch (Exception e)
{
Debug.LogError(e.ToString());
return false;
}
return true;
}
/// <summary>
/// 执行生成 RoomConfig.json 操作, 返回是否执行成功
/// </summary>
public static bool GenerateRoomConfig()
{
Debug.Log("生成RoomConfig.json流程得改");
// try
// {
// //地图路径
// var tileDir = GameConfig.RoomTileDir;
// //地图描述数据路径
// var tileDataDir = GameConfig.RoomTileDataDir;
//
// var tileGroup = new DirectoryInfo(tileDir).GetDirectories();
// var tileDataGroup = new DirectoryInfo(tileDataDir).GetDirectories();
//
// //所有地图列表
// var map = new Dictionary<string, FileInfo>();
//
// //地图场景
// foreach (var groupDir in tileGroup)
// {
// var groupName = groupDir.Name;
// var typeDirArray = groupDir.GetDirectories();
// //遍历枚举, 获取指定路径文件
// foreach (DungeonRoomType roomType in Enum.GetValues(typeof(DungeonRoomType)))
// {
// var typeName = DungeonManager.DungeonRoomTypeToString(roomType);
//
// //收集所有文件名称
// var tempFileDataInfos = typeDirArray.FirstOrDefault(dirInfo => dirInfo.Name == typeName);
// if (tempFileDataInfos != null)
// {
// foreach (var fileInfo in tempFileDataInfos.GetFiles())
// {
// if (fileInfo.Extension == ".tscn")
// {
// var pathInfo = new FileInfo(groupName, roomType, typeName, ResourceManager.RemoveExtension(fileInfo.Name));
// map.TryAdd(pathInfo.GetPath(), pathInfo);
// }
// }
// }
// }
// }
//
// //地图配置数据
// foreach (var groupDir in tileDataGroup)
// {
// var groupName = groupDir.Name;
// var typeDirArray = groupDir.GetDirectories();
// //遍历枚举, 获取指定路径文件
// foreach (DungeonRoomType roomType in Enum.GetValues(typeof(DungeonRoomType)))
// {
// var typeName = DungeonManager.DungeonRoomTypeToString(roomType);
//
// //收集所有文件名称
// var tempFileDataInfos = typeDirArray.FirstOrDefault(dirInfo => dirInfo.Name == typeName);
// if (tempFileDataInfos != null)
// {
// foreach (var fileInfo in tempFileDataInfos.GetFiles())
// {
// if (fileInfo.Extension == ".json")
// {
// var pathInfo = new FileInfo(groupName, roomType, typeName, ResourceManager.RemoveExtension(fileInfo.Name));
// map.TryAdd(pathInfo.GetPath(), pathInfo);
// }
// }
// }
// }
// }
//
// //剔除多余的 tile.json
// foreach (var item in map)
// {
// var path = item.Key;
// if (!File.Exists(tileDir + path + ".tscn"))
// {
// map.Remove(path);
// var filePath = tileDataDir + path + ".json";
// if (File.Exists(filePath))
// {
// Debug.Log($"未找到'{tileDir + path}.tscn', 删除配置文件: {filePath}");
// File.Delete(filePath);
// }
// }
// }
//
// //手动生成缺失的 tile.json
// foreach (var item in map)
// {
// if (!File.Exists(tileDataDir + item.Key + ".json"))
// {
// var tscnName = tileDir + item.Key + ".tscn";
// var packedScene = ResourceManager.Load<PackedScene>(tscnName, false);
// if (packedScene != null)
// {
// var dungeonRoomTemplate = packedScene.Instantiate<DungeonRoomTemplate>();
// var usedRect = dungeonRoomTemplate.GetUsedRect();
// var dungeonTile = new DungeonTileMap(dungeonRoomTemplate);
// dungeonTile.SetFloorAtlasCoords(new List<Vector2I>() { new Vector2I(0, 8) });
// //计算导航网格
// dungeonTile.GenerateNavigationPolygon(0);
//
// DungeonRoomInfo.SaveConfig(new List<DoorAreaInfo>(), usedRect.Position, usedRect.Size,
// item.Value.GroupName, item.Value.RoomType, item.Value.FileName, dungeonRoomTemplate.Weight);
// dungeonRoomTemplate.QueueFree();
// }
// }
// }
//
// var roomGroupMap = new Dictionary<string, DungeonRoomGroup>();
// //var list = new List<DungeonRoomSplit>();
// //整合操作
// foreach (var item in map)
// {
// var path = item.Key;
// var configPath = tileDataDir + path + ".json";
// var split = new DungeonRoomSplit();
// split.ScenePath = ResourceManager.ToResPath(tileDir + path + ".tscn");
// split.RoomPath = ResourceManager.ToResPath(configPath);
//
// if (!roomGroupMap.TryGetValue(item.Value.GroupName, out var group))
// {
// group = new DungeonRoomGroup();
// group.GroupName = item.Value.GroupName;
// roomGroupMap.Add(group.GroupName, group);
// }
//
// group.GetRoomList(item.Value.RoomType).Add(split);
// }
//
// //写出配置
// var config = new JsonSerializerOptions();
// config.WriteIndented = true;
// var text = JsonSerializer.Serialize(roomGroupMap, config);
// File.WriteAllText(GameConfig.RoomTileConfigFile, text);
//
// Debug.Log("地牢房间配置, 重新打包完成!");
// }
// catch (Exception e)
// {
// Debug.LogError(e.ToString());
// return false;
// }
return true;
}
private class FileInfo
{
public FileInfo(string groupName, DungeonRoomType roomType, string typeName, string fileName)
{
GroupName = groupName;
RoomType = roomType;
TypeName = typeName;
FileName = fileName;
}
public string GroupName;
public DungeonRoomType RoomType;
public string TypeName;
public string FileName;
public string GetPath()
{
return GroupName + "/" + TypeName + "/" + FileName;
}
}
}
#endif

View File

@ -1,76 +0,0 @@
#if TOOLS
using System;
using System.IO;
using System.Text.Json;
using Config;
using Godot;
using Array = Godot.Collections.Array;
namespace Generator;
public static class ExcelGenerator
{
public static void ExportExcel()
{
var arr = new Array();
var excelPath = "excel/excelFile/";
var jsonPath = "resource/config/";
var codePath = "src/config/";
OS.Execute("excel/DungeonShooting_ExcelTool.exe", new string[] { excelPath, jsonPath, codePath }, arr);
foreach (var message in arr)
{
Debug.Log(message);
}
try
{
GeneratorActivityObjectInit();
Debug.Log("生成'src/framework/activity/ActivityObject_Init.cs'成功!");
}
catch (Exception e)
{
Debug.LogError(e.ToString());
}
}
//生成初始化 ActivityObject 代码
private static void GeneratorActivityObjectInit()
{
var text = File.ReadAllText($"resource/config/{nameof(ExcelConfig.ActivityBase)}.json");
var array = JsonSerializer.Deserialize<System.Collections.Generic.Dictionary<string, object>[]>(text);
var code1 = "";
foreach (var item in array)
{
var id = item["Id"];
var name = item["Name"] + "";
var intro = item["Intro"] + "";
code1 += $" /// <summary>\n";
code1 += $" /// 名称: {name} <br/>\n";
code1 += $" /// 简介: {intro.Replace("\n", " <br/>\n /// ")}\n";
code1 += $" /// </summary>\n";
code1 += $" public const string Id_{id} = \"{id}\";\n";
}
var str = $"using Config;\n\n";
str += $"// 根据配置表注册物体, 该类是自动生成的, 请不要手动编辑!\n";
str += $"public partial class ActivityObject\n";
str += $"{{\n";
str += $" /// <summary>\n";
str += $" /// 存放所有在表中注册的物体的id\n";
str += $" /// </summary>\n";
str += $" public static class Ids\n";
str += $" {{\n";
str += code1;
str += $" }}\n";
str += $"}}\n";
File.WriteAllText("src/framework/activity/ActivityObject_Init.cs", str);
}
}
#endif

View File

@ -239,7 +239,7 @@ public partial class Player : Role
protected override void OnAffiliationChange(AffiliationArea prevArea)
{
//BrushPrevPosition = null;
BrushPrevPosition = null;
base.OnAffiliationChange(prevArea);
}

View File

@ -84,7 +84,7 @@ public partial class Knife : Weapon
//播放挥刀特效
SpecialEffectManager.Play(
Master,
ResourcePath.resource_sprite_weapon_weapon0004_KnifeHit1_png, "default",
ResourcePath.resource_spriteFrames_weapon_Weapon0004_hit_tres, "default",
Master.MountPoint.Position,
Master.MountPoint.Rotation + Mathf.DegToRad(Attribute.UpliftAngle + 60),
AnimatedSprite.Scale,

View File

@ -201,7 +201,7 @@ public partial class DungeonManager : Node2D
World = GameApplication.Instance.CreateNewWorld();
yield return 0;
//生成地牢房间
var random = new SeedRandom();
var random = new SeedRandom(205371406);
_dungeonGenerator = new DungeonGenerator(CurrConfig, random);
_dungeonGenerator.Generate();
yield return 0;

View File

@ -303,7 +303,7 @@ public partial class EditorToolsPanel : EditorTools
/// </summary>
private void OpenExportExcelFolder()
{
var path = Environment.CurrentDirectory + "\\excel\\excelFile";
var path = Environment.CurrentDirectory + "\\excel";
System.Diagnostics.Process.Start("explorer.exe", path);
}

View File

@ -1,5 +1,8 @@
一款由Godot开发的地牢射击类型的游戏, 脚本语言使用的是C#, 当前项目使用的Godot版本: Godot_v4.2
## 一款由Godot开发的地牢射击类型的游戏
**Godot版本:** `4.2.1 mono`
**.Net版本:** `8.0`
---
### 游戏定义
@ -9,24 +12,24 @@
**游戏类型:** Roguelite, 俯视角, 地牢探索, 双摇杆射击
**参考游戏:** 挺进地牢, 元气骑士, 废土之王
**核心简介:** 游戏整体流程由数层地牢组成, 每层又由数个房间组成, 每个房间有一堵门隔开, 玩家每进入一个房间, 需要清理房间内所有的敌人, 方可离开和进入下一个房间,
玩家需要在这些房间中探索, 战斗, 收集掉落的道具和被动, 一步步成长, 击败boss, 进入下一层, 如此往复, 直到击败最后一层boss即可通关.
玩家需要在这些房间中探索, 战斗, 收集掉落的道具和被动, 一步步成长, 击败boss, 进入下一层, 如此往复, 直到击败最后一层boss即可通关.
但本作与市面上常规地牢射击游戏不同的是, 玩家与敌人共用武器资源, 玩家击败敌人便可拾起敌人的武器, 并且更加注重环境互动要素
**游戏背景:** 构思中
![gif](DungeonShooting_Document/文档资源/preview_gif.gif)
---
### 启动项目
git仓库的目录结构如下
> ├ DungeonShooting_Document (项目帮助文档, 更新日志相关的目录)
> ├ DungeonShooting_ExcelTool (项目excel配置表导出工具源代码)
> ├ DungeonShooting_Document (更新日志相关的目录)
> └ DungeonShooting_Godot (Godot工程目录)
下载好指定的Godot版本, 注意使用的是Godot_Mono版, 使用Godot打开`DungeonShooting_Godot/project.godot`, 如果是第一次打开项目会弹出一个找不到资源的提示, 这是因为项目没有编译过, 点击Godot右上角`build`, 然后打`开项目设置`, 在`插件`这一个页签下启用`DungeonShooting_plugin`这个插件, 然后项目就可以正常运行了
使用GodotMono版打开`DungeonShooting_Godot/project.godot`, 如果是第一次打开项目会弹出一个找不到资源的提示, 这是因为项目没有编译过, 点击Godot右上角`build`, 然后打`开项目设置`, 在`插件`这一个页签下启用`DungeonShooting_plugin`这个插件, 然后项目就可以正常运行了
---
### 其他
**开发日志:** [开发日志.md](DungeonShooting_Document/开发日志.md)
**哔哩哔哩:** https://space.bilibili.com/259437820
**项目Ui插件:** https://github.com/xlljc/Ds_Ui