THUAI8/interface/AvaloniaUI_debug_interface/debug_interface/ViewModels/MapViewModel.cs

464 lines
19 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//MapViewModel.cs
using System;
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Avalonia.Media;
using Avalonia.Threading;
using Grpc.Core;
using installer.Data;
using installer.Model;
using debug_interface.Models;
using System.Collections.Generic;
using Avalonia.Controls.Shapes;
using Avalonia.Controls;
using Google.Protobuf;
using System.Linq; // 解决Concat错误
using Protobuf;
namespace debug_interface.ViewModels
{
public partial class MapViewModel : ViewModelBase
{
private const int GridSize = 50;
[ObservableProperty]
private ObservableCollection<MapCell> mapCells = new();
// 添加缺失的字段
private Canvas? characterCanvas;
private Dictionary<string, Grid> characterElements = new Dictionary<string, Grid>();
private MainWindowViewModel? viewModel;
public MapViewModel()
{
// 初始化地图单元格
InitializeMapCells();
}
// 设置Canvas和ViewModel引用的方法
public void SetCanvasAndViewModel(Canvas canvas, MainWindowViewModel vm)
{
characterCanvas = canvas;
viewModel = vm;
RefreshCharacters();
}
// 更新角色位置的方法
private void UpdateCharacterPosition(Grid element, int x, int y)
{
if (characterCanvas == null) return;
// 更新位置
Canvas.SetLeft(element, x);
Canvas.SetTop(element, y);
}
private void InitializeCharacters(IEnumerable<CharacterViewModel> characters, Color color)
{
if (characterCanvas == null || viewModel == null) return;
foreach (var character in characters)
{
var id = $"{color.ToString()}_{character.Name}";
if (!characterElements.ContainsKey(id))
{
var grid = new Grid { Width = 15, Height = 15 };
var ellipse = new Ellipse
{
Width = 15,
Height = 15,
Fill = new SolidColorBrush(Colors.White),
Stroke = new SolidColorBrush(color),
StrokeThickness = 2,
Tag = character.Name
};
grid.Children.Add(ellipse);
ToolTip.SetTip(grid, character.Name);
characterCanvas.Children.Add(grid);
characterElements[id] = grid;
}
var element = characterElements[id];
UpdateCharacterPosition(element, character.PosX, character.PosY);
character.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(CharacterViewModel.PosX) || e.PropertyName == nameof(CharacterViewModel.PosY))
{
UpdateCharacterPosition(element, character.PosX, character.PosY);
}
};
}
}
//初始化地图单元格
public void InitializeMapCells()
{
MapCells.Clear();
for (int i = 0; i < GridSize; i++)
{
for (int j = 0; j < GridSize; j++)
{
MapCells.Add(new MapCell
{
CellX = i,
CellY = j,
CellType = MapCellType.OpenLand,
DisplayColor = new SolidColorBrush(Colors.White),
DisplayText = ""
});
}
}
}
// 更新整个地图
public void UpdateMap(MessageOfMap mapMessage)
{
for (int i = 0; i < mapMessage.Rows.Count && i < GridSize; i++)
{
for (int j = 0; j < mapMessage.Rows[i].Cols.Count && j < GridSize; j++)
{
int index = i * GridSize + j;
if (index < MapCells.Count)
{
UpdateCellType(i, j, mapMessage.Rows[i].Cols[j]);
}
}
}
}
private void UpdateCellType(int x, int y, PlaceType placeType)
{
int index = x * GridSize + y;
if (index >= 0 && index < MapCells.Count)
{
var cell = MapCells[index];
cell.DisplayText = ""; // 重置文本
cell.ToolTipText = ""; // 重置提示
// 根据地形类型设置单元格属性
switch (placeType)
{
case PlaceType.Home: // 出生点通常也是建筑或特殊区域
cell.CellType = MapCellType.Building; // 假设是建筑
cell.DisplayColor = new SolidColorBrush(Colors.Cyan); // 特殊颜色标记出生点
cell.ToolTipText = "家园";
break;
case PlaceType.Space:
cell.CellType = MapCellType.OpenLand;
cell.DisplayColor = new SolidColorBrush(Colors.White);
cell.ToolTipText = "空地";
break;
case PlaceType.Barrier:
cell.CellType = MapCellType.Obstacle;
cell.DisplayColor = new SolidColorBrush(Colors.DarkGray);
cell.ToolTipText = "障碍物";
break;
case PlaceType.Bush:
cell.CellType = MapCellType.Grass;
cell.DisplayColor = new SolidColorBrush(Colors.LightGreen);
cell.ToolTipText = "草丛";
break;
// 资源和建筑类型由特定的 UpdateXXX 方法处理,这里不再覆盖颜色和类型
// case PlaceType.EconomyResource:
// case PlaceType.AdditionResource:
// case PlaceType.Construction:
// case PlaceType.Trap:
// break; // 由其他方法设置详细信息
default:
cell.CellType = MapCellType.OpenLand; // 未知视为OpenLand
cell.DisplayColor = new SolidColorBrush(Colors.LightGray); // 用浅灰标记未知
cell.ToolTipText = "空地";
break;
}
// 如果placeType是资源/建筑/陷阱,后续的 UpdateXXX 会覆盖这里的设置
}
}
//private void UpdateCellType(int x, int y, PlaceType placeType)
//{
// int index = x * GridSize + y;
// if (index >= MapCells.Count) return;
// // 根据地形类型设置单元格属性
// switch (placeType)
// {
// case PlaceType.Home:
// MapCells[index].CellType = MapCellType.Building;
// MapCells[index].DisplayColor = new SolidColorBrush(Colors.Gold);
// break;
// case PlaceType.Space:
// MapCells[index].CellType = MapCellType.OpenLand;
// MapCells[index].DisplayColor = new SolidColorBrush(Colors.White);
// break;
// case PlaceType.Barrier:
// MapCells[index].CellType = MapCellType.Obstacle;
// MapCells[index].DisplayColor = new SolidColorBrush(Colors.DarkGray);
// break;
// case PlaceType.Bush:
// MapCells[index].CellType = MapCellType.Grass;
// MapCells[index].DisplayColor = new SolidColorBrush(Colors.LightGreen);
// break;
// case PlaceType.EconomyResource:
// MapCells[index].CellType = MapCellType.Resource;
// MapCells[index].DisplayColor = new SolidColorBrush(Colors.Gold);
// break;
// case PlaceType.AdditionResource:
// MapCells[index].CellType = MapCellType.Resource;
// MapCells[index].DisplayColor = new SolidColorBrush(Colors.Purple);
// break;
// case PlaceType.Construction:
// MapCells[index].CellType = MapCellType.Building;
// MapCells[index].DisplayColor = new SolidColorBrush(Colors.Brown);
// break;
// case PlaceType.Trap:
// MapCells[index].CellType = MapCellType.Obstacle;
// MapCells[index].DisplayColor = new SolidColorBrush(Colors.Red);
// break;
// default:
// MapCells[index].CellType = MapCellType.OpenLand;
// MapCells[index].DisplayColor = new SolidColorBrush(Colors.LightGray);
// break;
// }
//}
public void UpdateCharacterPositions(IEnumerable<CharacterViewModel> buddhistsTeam, IEnumerable<CharacterViewModel> monstersTeam)
{
// 使用System.Linq的Concat扩展方法
var allCharacters = buddhistsTeam.Concat(monstersTeam);
foreach (var character in allCharacters)
{
int index = (int)(character.PosX * GridSize + character.PosY);
if (index >= 0 && index < MapCells.Count)
{
MapCells[index].DisplayText = character.Name;
}
}
}
// 更新建筑
public void UpdateBuildingCell(int x, int y, string team, string buildingType, int hp)
{
int index = x * GridSize + y;
if (index >= 0 && index < MapCells.Count)
{
var cell = MapCells[index];
cell.CellType = MapCellType.Building;
//cell.DisplayText = buildingType.Substring(0, 1); // 先用文字代替后面修改为显示HP
cell.DisplayColor = team == "取经队"
? new SolidColorBrush(Colors.DarkRed)
: new SolidColorBrush(Colors.DarkBlue);
// 更新HP和Tooltip
// 注意游戏规则中未明确建筑的最大血量这里用传入的hp作为当前值假设需要一个最大值才能显示 current/max
// 暂时只显示类型和当前HP
// TODO: 获取建筑的最大HP (可能需要从游戏规则或新消息字段获取)
int maxHp = GetBuildingMaxHp(buildingType); // 需要实现这个辅助方法
cell.DisplayText = $"{hp}/{maxHp}";
cell.ToolTipText = $"类型: {buildingType}\n队伍: {team}\n血量: {hp}/{maxHp}";
// 触发UI更新 (如果MapCell的属性变更没有自动通知)
// OnPropertyChanged(nameof(MapCells)); // ObservableCollection通常会自动处理子项变更通知但如果直接修改子项属性有时需要手动触发
}
}
//public void UpdateBuildingCell(int x, int y, string team, string buildingType, int hp)
//{
// int index = x * GridSize + y;
// if (index >= 0 && index < MapCells.Count)
// {
// MapCells[index].CellType = MapCellType.Building;
// MapCells[index].DisplayText = buildingType.Substring(0, 1);
// MapCells[index].DisplayColor = team == "取经队"
// ? new SolidColorBrush(Colors.DarkRed)
// : new SolidColorBrush(Colors.DarkBlue);
// OnPropertyChanged(nameof(MapCells));
// }
//}
// 更新陷阱
public void UpdateTrapCell(int x, int y, string team, string trapType)
{
int index = x * GridSize + y;
if (index >= 0 && index < MapCells.Count)
{
var cell = MapCells[index];
cell.CellType = MapCellType.Trap; // 使用新的类型
//cell.DisplayText = trapType.Substring(0, 1);
cell.DisplayColor = team == "取经队"
? new SolidColorBrush(Colors.IndianRed) // 可以为不同陷阱设置不同颜色
: new SolidColorBrush(Colors.CornflowerBlue);
// 更新Tooltip (陷阱没有血量)
cell.DisplayText = ""; // 陷阱通常不显示血量文本
cell.ToolTipText = $"类型: {trapType}\n队伍: {team}";
// OnPropertyChanged(nameof(MapCells));
}
}
//public void UpdateTrapCell(int x, int y, string team, string trapType)
//{
// int index = x * GridSize + y;
// if (index >= 0 && index < MapCells.Count)
// {
// MapCells[index].CellType = MapCellType.Obstacle;
// MapCells[index].DisplayText = trapType.Substring(0, 1);
// MapCells[index].DisplayColor = team == "取经队"
// ? new SolidColorBrush(Colors.IndianRed)
// : new SolidColorBrush(Colors.CornflowerBlue);
// OnPropertyChanged(nameof(MapCells));
// }
//}
// 更新资源
public void UpdateResourceCell(int x, int y, string resourceType, int process) // process 是采集进度/剩余量
{
int index = x * GridSize + y;
if (index >= 0 && index < MapCells.Count)
{
var cell = MapCells[index];
cell.CellType = MapCellType.Resource;
// cell.DisplayText = process.ToString(); // 显示剩余量
cell.DisplayColor = new SolidColorBrush(Colors.Gold); // 经济资源用金色
// 更新HP和Tooltip
int maxResource = 10000; // 根据规则经济资源上限1w
cell.DisplayText = $"{process}/{maxResource}";
cell.ToolTipText = $"类型: {resourceType}\n剩余量: {process}/{maxResource}";
// OnPropertyChanged(nameof(MapCells));
}
}
//public void UpdateResourceCell(int x, int y, string resourceType, int process)
//{
// int index = x * GridSize + y;
// if (index >= 0 && index < MapCells.Count)
// {
// MapCells[index].CellType = MapCellType.Resource;
// MapCells[index].DisplayText = process.ToString();
// MapCells[index].DisplayColor = new SolidColorBrush(Colors.DarkGreen);
// OnPropertyChanged(nameof(MapCells));
// }
//}
// 更新额外资源
public void UpdateAdditionResourceCell(int x, int y, string resourceName, int hp) // hp 是 Boss 血量
{
int index = x * GridSize + y;
if (index >= 0 && index < MapCells.Count)
{
var cell = MapCells[index];
cell.CellType = MapCellType.Resource; // 仍然是资源类型
// cell.DisplayText = hp.ToString(); // 显示Boss血量
// 根据资源类型选择颜色
if (resourceName.Contains("生命")) // 规则是生命之泉
{
cell.DisplayColor = new SolidColorBrush(Colors.LightPink); // 淡粉色
}
else if (resourceName.Contains("狂战") || resourceName.Contains("疯人")) // 规则是狂战士之力
{
cell.DisplayColor = new SolidColorBrush(Colors.OrangeRed); // 橙红色
}
else if (resourceName.Contains("疾步") || resourceName.Contains("快步")) // 规则是疾步之灵
{
cell.DisplayColor = new SolidColorBrush(Colors.LightSkyBlue); // 天蓝色
}
else if (resourceName.Contains("视野") || resourceName.Contains("广视")) // 规则是视野之灵
{
cell.DisplayColor = new SolidColorBrush(Colors.MediumPurple); // 紫色
}
else
{
cell.DisplayColor = new SolidColorBrush(Colors.Purple); // 未知用紫色
}
// 更新HP和Tooltip
// TODO: 获取加成资源Boss的最大HP (可能需要从游戏规则或新消息字段获取)
int maxHp = GetAdditionResourceMaxHp(resourceName); // 需要实现此辅助方法
cell.DisplayText = $"{hp}/{maxHp}";
cell.ToolTipText = $"类型: {resourceName} (Boss)\n血量: {hp}/{maxHp}";
// OnPropertyChanged(nameof(MapCells));
}
}
//public void UpdateAdditionResourceCell(int x, int y, string resourceName, int value)
//{
// int index = x * GridSize + y;
// if (index >= 0 && index < MapCells.Count)
// {
// MapCells[index].CellType = MapCellType.Resource;
// MapCells[index].DisplayText = value.ToString();
// // 根据资源类型选择颜色
// if (resourceName.Contains("生命池"))
// {
// MapCells[index].DisplayColor = new SolidColorBrush(Colors.LightGreen);
// }
// else if (resourceName.Contains("疯人"))
// {
// MapCells[index].DisplayColor = new SolidColorBrush(Colors.OrangeRed);
// }
// else
// {
// MapCells[index].DisplayColor = new SolidColorBrush(Colors.Purple);
// }
// OnPropertyChanged(nameof(MapCells));
// }
//}
private void RefreshCharacters()
{
if (characterCanvas == null || viewModel == null) return;
characterCanvas.Children.Clear();
characterElements.Clear();
InitializeCharacters(viewModel.BuddhistsTeamCharacters, Colors.Red);
InitializeCharacters(viewModel.MonstersTeamCharacters, Colors.Blue);
}
// 辅助方法根据建筑类型获取最大HP(根据游戏规则文档)
public int GetBuildingMaxHp(string buildingType)
{
return buildingType switch
{
"兵营" => 600,
"泉水" => 300,
"农场" => 400,
_ => 0 // 其他或未知类型
};
}
// 辅助方法根据资源名称获取Boss最大HP (根据游戏规则文档)
// 注意Boss血量会变化这里可能需要根据当前游戏阶段判断暂时用一个代表值
public int GetAdditionResourceMaxHp(string resourceName)
{
// 简化处理,取最大阶段的值或一个固定值
if (resourceName.Contains("生命")) return 400;
if (resourceName.Contains("狂战")) return 600;
if (resourceName.Contains("疾步")) return 300;
if (resourceName.Contains("视野")) return 300;
return 0; // 未知
}
}
}