`
This commit is contained in:
parent
2f5c67e8ae
commit
735ae054ee
@ -1,4 +1,5 @@
|
||||
using MessagePack;
|
||||
using XNet.Business.Net;
|
||||
|
||||
namespace XNet.Business
|
||||
{
|
||||
|
||||
17
XNet.Business/Dto/Vec3.cs
Normal file
17
XNet.Business/Dto/Vec3.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using MessagePack;
|
||||
|
||||
namespace XNet.Business.Dto
|
||||
{
|
||||
[MessagePackObject]
|
||||
public class Vec3
|
||||
{
|
||||
[Key("x")]
|
||||
public float X { get; set; }
|
||||
|
||||
[Key("y")]
|
||||
public float Y { get; set; }
|
||||
|
||||
[Key("z")]
|
||||
public float Z { get; set; }
|
||||
}
|
||||
}
|
||||
59
XNet.Business/Entity/ControlPlayer.cs
Normal file
59
XNet.Business/Entity/ControlPlayer.cs
Normal file
@ -0,0 +1,59 @@
|
||||
using XNet.Business.Dto;
|
||||
|
||||
namespace XNet.Business.Entity
|
||||
{
|
||||
public class ControlPlayer
|
||||
{
|
||||
/// <summary>
|
||||
/// 用户ID
|
||||
/// </summary>
|
||||
public string Id { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 是否碰到非地面障碍物或者碰到其他对象,需要转向
|
||||
/// </summary>
|
||||
public bool IsNeedToOtherDir { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 是否可以控制动作
|
||||
/// </summary>
|
||||
public bool IsCanControl { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 上一次位置计时的时候的时间,用来判断AI是否走死
|
||||
/// </summary>
|
||||
public DateTime PrevToDirTime { get; set; } = DateTime.MinValue;
|
||||
|
||||
/// <summary>
|
||||
/// 临时存储的位置
|
||||
/// </summary>
|
||||
public Vec3 TmpPos { get; set; } = new Vec3();
|
||||
/// <summary>
|
||||
/// 将要去的位置
|
||||
/// </summary>
|
||||
public Vec3 ToPos { get; set; } = new Vec3();
|
||||
/// <summary>
|
||||
/// 存储当前的位置
|
||||
/// </summary>
|
||||
public Vec3 CurrentPos { get; set; } = new Vec3();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 临时存储的欧拉角
|
||||
/// </summary>
|
||||
public Vec3 TmpEuler { get; set; } = new Vec3();
|
||||
/// <summary>
|
||||
/// 目标欧拉角,角色朝向
|
||||
/// </summary>
|
||||
public Vec3 ToEuler { get; set; } = new Vec3();
|
||||
/// <summary>
|
||||
/// 当前线性插值欧拉角,角色朝向
|
||||
/// </summary>
|
||||
public Vec3 CurrentEuler { get; set; } = new Vec3();
|
||||
|
||||
/// <summary>
|
||||
/// 路径导航索引下标
|
||||
/// </summary>
|
||||
public int AgentIndex { get; set; } = 0;
|
||||
}
|
||||
}
|
||||
43
XNet.Business/Entity/PlayerRoom.cs
Normal file
43
XNet.Business/Entity/PlayerRoom.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using DotRecast.Detour.Crowd;
|
||||
using System.Collections.Concurrent;
|
||||
using XNet.Business.Dto;
|
||||
|
||||
namespace XNet.Business.Entity
|
||||
{
|
||||
/// <summary>
|
||||
/// 玩家房间实体
|
||||
/// </summary>
|
||||
/// <typeparam name="T">玩家实体(包括AI)</typeparam>
|
||||
public class PlayerRoom<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// 寻路导航对象
|
||||
/// </summary>
|
||||
public DtCrowd Crowd { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// 导航实体集合
|
||||
/// </summary>
|
||||
public ConcurrentDictionary<string, T> Players { get; set; } = new ConcurrentDictionary<string, T>();
|
||||
|
||||
/// <summary>
|
||||
/// 世界坐标最小值
|
||||
/// </summary>
|
||||
public Vec3 WorldMin { get; set; } = new Vec3();
|
||||
|
||||
/// <summary>
|
||||
/// 世界坐标最大值
|
||||
/// </summary>
|
||||
public Vec3 WorldMax { get; set; } = new Vec3();
|
||||
|
||||
|
||||
public PlayerRoom() { }
|
||||
|
||||
public PlayerRoom(DtCrowd crowd, Vec3 worldMin, Vec3 worldMax)
|
||||
{
|
||||
Crowd = crowd;
|
||||
WorldMin = worldMin;
|
||||
WorldMax = worldMax;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics;
|
||||
using System.Numerics;
|
||||
using XNet.Business.Net;
|
||||
using XNet.Business.PathNavigation;
|
||||
|
||||
namespace XNet.Business
|
||||
{
|
||||
|
||||
6
XNet.Business/Manager/SceneManager.cs
Normal file
6
XNet.Business/Manager/SceneManager.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace XNet.Business.Manager
|
||||
{
|
||||
public abstract class SceneManager
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace XNet.Business
|
||||
namespace XNet.Business.Net
|
||||
{
|
||||
|
||||
|
||||
@ -2,11 +2,10 @@
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using NanoidDotNet;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Net.Sockets;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace XNet.Business
|
||||
namespace XNet.Business.Net
|
||||
{
|
||||
public class WsConnectionManager
|
||||
{
|
||||
@ -3,7 +3,7 @@ using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace XNet.Business
|
||||
namespace XNet.Business.Net
|
||||
{
|
||||
public static class WsServer
|
||||
{
|
||||
@ -5,7 +5,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace XNet.Business
|
||||
namespace XNet.Business.Parser
|
||||
{
|
||||
// 1. 定义一个简单的几何输入类,适配 DotRecast 接口
|
||||
public class SimpleInputGeomProvider : IInputGeomProvider
|
||||
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace XNet.Business
|
||||
namespace XNet.Business.Parser
|
||||
{
|
||||
public class SimpleObjParser
|
||||
{
|
||||
@ -1,13 +1,12 @@
|
||||
using DotRecast.Core;
|
||||
using DotRecast.Core.Numerics;
|
||||
using DotRecast.Core.Numerics;
|
||||
using DotRecast.Detour;
|
||||
using DotRecast.Recast;
|
||||
using System.Numerics;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Buffers; // 引入 ArrayPool
|
||||
using System.Threading;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Numerics;
|
||||
using XNet.Business.Parser;
|
||||
|
||||
namespace XNet.Business
|
||||
namespace XNet.Business.PathNavigation
|
||||
{
|
||||
public class NavMeshManager
|
||||
{
|
||||
@ -5,7 +5,7 @@ using DotRecast.Detour.Crowd;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Numerics;
|
||||
|
||||
namespace XNet.Business
|
||||
namespace XNet.Business.PathNavigation
|
||||
{
|
||||
public class SceneAgent
|
||||
{
|
||||
32
XNet.Business/Tank/Entities/TankPlayer.cs
Normal file
32
XNet.Business/Tank/Entities/TankPlayer.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using XNet.Business.Entity;
|
||||
|
||||
namespace XNet.Business.Tank.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// 坦克对象
|
||||
/// </summary>
|
||||
public class TankPlayer : ControlPlayer
|
||||
{
|
||||
/// <summary>
|
||||
/// 上一次计算普通攻击的时候的时间,用来判断AI是否开始攻击
|
||||
/// </summary>
|
||||
public DateTime[] PrevToAttackTimes = Array.Empty<DateTime>();
|
||||
|
||||
/// <summary>
|
||||
/// 第一技能的等级
|
||||
/// </summary>
|
||||
public int Skill1Level { get; set; } = 1;
|
||||
/// <summary>
|
||||
/// 第二技能的等级
|
||||
/// </summary>
|
||||
public int Skill2Level { get; set; } = 1;
|
||||
/// <summary>
|
||||
/// 第三技能的等级
|
||||
/// </summary>
|
||||
public int Skill3Level { get; set; } = 1;
|
||||
/// <summary>
|
||||
/// 第四技能的等级
|
||||
/// </summary>
|
||||
public int Skill4Level { get; set; } = 1;
|
||||
}
|
||||
}
|
||||
100
XNet.Business/Tank/Manager/DeviceManager.cs
Normal file
100
XNet.Business/Tank/Manager/DeviceManager.cs
Normal file
@ -0,0 +1,100 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace XNet.Business.Tank.Manager
|
||||
{
|
||||
|
||||
public class BodyDevice
|
||||
{
|
||||
[JsonPropertyName("body")]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class WeaponDevice
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("attackPower")]
|
||||
public float AttackPower { get; set; } = 0.0f;
|
||||
|
||||
[JsonPropertyName("findFaceDistance")]
|
||||
public float FindFaceDistance { get; set; } = 0.0f;
|
||||
}
|
||||
|
||||
public class ArmorDevice
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("armor")]
|
||||
public float Armor { get; set; } = 0.0f;
|
||||
|
||||
[JsonPropertyName("blood")]
|
||||
public float Blood { get; set; } = 0.0f;
|
||||
}
|
||||
public class ChassisDevice
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("speed")]
|
||||
public float Speed { get; set; } = 0.0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设备信息
|
||||
/// </summary>
|
||||
public class DeviceInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 车身核心信息
|
||||
/// </summary>
|
||||
[JsonPropertyName("body")]
|
||||
public BodyDevice[] Body { get; set; } = Array.Empty<BodyDevice>();
|
||||
|
||||
/// <summary>
|
||||
/// 武器信息
|
||||
/// </summary>
|
||||
[JsonPropertyName("weapon")]
|
||||
public WeaponDevice[] Weapon { get; set; } = Array.Empty<WeaponDevice>();
|
||||
|
||||
/// <summary>
|
||||
/// 装甲信息
|
||||
/// </summary>
|
||||
[JsonPropertyName("armor")]
|
||||
public ArmorDevice[] Armor { get; set; } = Array.Empty<ArmorDevice>();
|
||||
|
||||
/// <summary>
|
||||
/// 底盘信息
|
||||
/// </summary>
|
||||
[JsonPropertyName("chassis")]
|
||||
public ChassisDevice[] Chassis { get; set; } = Array.Empty<ChassisDevice>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设备管理类
|
||||
/// </summary>
|
||||
public class DeviceManager
|
||||
{
|
||||
public static readonly DeviceManager Instance = new DeviceManager();
|
||||
|
||||
public DeviceInfo DeviceInfo { get; set; } = default!;
|
||||
private DeviceManager() { }
|
||||
|
||||
|
||||
public void Init()
|
||||
{
|
||||
string path = Path.Combine(AppContext.BaseDirectory, "role", "device.json");
|
||||
if (File.Exists(path))
|
||||
{
|
||||
string json = File.ReadAllText(path);
|
||||
DeviceInfo = System.Text.Json.JsonSerializer.Deserialize<DeviceInfo>(json)!;
|
||||
Console.WriteLine($"角色设备信息配置文件: {path} 加载成功 ");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Write($"角色设备信息配置文件: {path} 不存在 ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
9
XNet.Business/Tank/Manager/TankSceneManager.cs
Normal file
9
XNet.Business/Tank/Manager/TankSceneManager.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using XNet.Business.Manager;
|
||||
|
||||
namespace XNet.Business.Tank.Manager
|
||||
{
|
||||
public class TankSceneManager : SceneManager
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Numerics;
|
||||
using XNet.Business;
|
||||
using XNet.Business.Manager;
|
||||
|
||||
namespace XNet.Api.Controllers
|
||||
{
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
using Scalar.AspNetCore;
|
||||
using XNet.Business;
|
||||
using XNet.Business.Manager;
|
||||
using XNet.Business.Net;
|
||||
using XNet.Business.PathNavigation;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@ -19,6 +22,9 @@ builder.Services.AddSingleton<WsConnectionManager>();
|
||||
builder.Services.AddHostedService<GameLoopService>();
|
||||
var app = builder.Build();
|
||||
|
||||
// 提供 wwwroot 目录中的文件
|
||||
app.UseStaticFiles();
|
||||
|
||||
// 启动WebSocket服务
|
||||
app.MapWebSocketServer(app.Services.GetRequiredService<WsConnectionManager>());
|
||||
|
||||
|
||||
@ -31,4 +31,8 @@
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="wwwroot\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
61
XNet/wwwroot/role/device.json
Normal file
61
XNet/wwwroot/role/device.json
Normal file
@ -0,0 +1,61 @@
|
||||
{
|
||||
"body": [
|
||||
{
|
||||
"name": "body0"
|
||||
},
|
||||
{
|
||||
"name": "body1"
|
||||
},
|
||||
{
|
||||
"name": "body2"
|
||||
}
|
||||
],
|
||||
"weapon": [
|
||||
{
|
||||
"name": "weapon0",
|
||||
"attackPower": 20,
|
||||
"findFaceDistance": 6
|
||||
},
|
||||
{
|
||||
"name": "weapon1",
|
||||
"attackPower": 18,
|
||||
"findFaceDistance": 6
|
||||
},
|
||||
{
|
||||
"name": "weapon2",
|
||||
"attackPower": 25,
|
||||
"findFaceDistance": 6
|
||||
}
|
||||
],
|
||||
"armor": [
|
||||
{
|
||||
"name": "armor0",
|
||||
"armor": 6,
|
||||
"blood": 350
|
||||
},
|
||||
{
|
||||
"name": "armor1",
|
||||
"armor": 5,
|
||||
"blood": 350
|
||||
},
|
||||
{
|
||||
"name": "armor2",
|
||||
"armor": 8,
|
||||
"blood": 350
|
||||
}
|
||||
],
|
||||
"chassis": [
|
||||
{
|
||||
"name": "chassis0",
|
||||
"speed": 2.8
|
||||
},
|
||||
{
|
||||
"name": "chassis1",
|
||||
"speed": 3.2
|
||||
},
|
||||
{
|
||||
"name": "chassis2",
|
||||
"speed": 2.4
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user