feat: add pathfinding
This commit is contained in:
@ -39,12 +39,12 @@ namespace Client.Application.ViewModels
|
||||
worldHandler.RequestAttackOrFollow(Id);
|
||||
}
|
||||
|
||||
private void OnMouseRightClick(object? obj)
|
||||
private async Task OnMouseRightClick(object? obj)
|
||||
{
|
||||
worldHandler.RequestMoveToEntity(Id);
|
||||
await pathMover.MoveUntilReachedAsync(creature.Transform.Position);
|
||||
}
|
||||
|
||||
public CreatureListViewModel(WorldHandler worldHandler, CreatureInterface creature, Hero hero)
|
||||
public CreatureListViewModel(WorldHandler worldHandler, AsyncPathMoverInterface pathMover, CreatureInterface creature, Hero hero)
|
||||
{
|
||||
creature.PropertyChanged += Creature_PropertyChanged;
|
||||
creature.Transform.Position.PropertyChanged += Position_PropertyChanged;
|
||||
@ -52,11 +52,12 @@ namespace Client.Application.ViewModels
|
||||
hero.PropertyChanged += Hero_PropertyChanged;
|
||||
MouseLeftClickCommand = new RelayCommand(OnMouseLeftClick);
|
||||
MouseLeftDoubleClickCommand = new RelayCommand(OnMouseLeftDoubleClick);
|
||||
MouseRightClickCommand = new RelayCommand(OnMouseRightClick);
|
||||
MouseRightClickCommand = new RelayCommand(async (o) => await OnMouseRightClick(o));
|
||||
|
||||
this.creature = creature;
|
||||
this.hero = hero;
|
||||
this.worldHandler = worldHandler;
|
||||
this.pathMover = pathMover;
|
||||
}
|
||||
|
||||
private void HeroPosition_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
@ -94,5 +95,6 @@ namespace Client.Application.ViewModels
|
||||
private readonly CreatureInterface creature;
|
||||
private readonly Hero hero;
|
||||
private readonly WorldHandler worldHandler;
|
||||
private readonly AsyncPathMoverInterface pathMover;
|
||||
}
|
||||
}
|
||||
|
@ -77,16 +77,17 @@ namespace Client.Application.ViewModels
|
||||
worldHandler.RequestAttackOrFollow(Id);
|
||||
}
|
||||
|
||||
private void OnMouseRightClick(object? obj)
|
||||
private async Task OnMouseRightClick(object? obj)
|
||||
{
|
||||
worldHandler.RequestMoveToEntity(Id);
|
||||
await pathMover.MoveUntilReachedAsync(creature.Transform.Position);
|
||||
}
|
||||
|
||||
public CreatureMapViewModel(WorldHandler worldHandler, CreatureInterface creature, Hero hero)
|
||||
public CreatureMapViewModel(WorldHandler worldHandler, AsyncPathMoverInterface pathMover, CreatureInterface creature, Hero hero)
|
||||
{
|
||||
this.creature = creature;
|
||||
this.hero = hero;
|
||||
this.worldHandler = worldHandler;
|
||||
this.pathMover = pathMover;
|
||||
creature.PropertyChanged += Creature_PropertyChanged;
|
||||
creature.Transform.PropertyChanged += Transform_PropertyChanged;
|
||||
creature.Transform.Position.PropertyChanged += Position_PropertyChanged;
|
||||
@ -95,7 +96,7 @@ namespace Client.Application.ViewModels
|
||||
hero.PropertyChanged += Hero_PropertyChanged;
|
||||
MouseLeftClickCommand = new RelayCommand(OnMouseLeftClick);
|
||||
MouseLeftDoubleClickCommand = new RelayCommand(OnMouseLeftDoubleClick);
|
||||
MouseRightClickCommand = new RelayCommand(OnMouseRightClick);
|
||||
MouseRightClickCommand = new RelayCommand(async (o) => await OnMouseRightClick(o));
|
||||
}
|
||||
|
||||
private void VitalStats_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
@ -149,6 +150,7 @@ namespace Client.Application.ViewModels
|
||||
private readonly CreatureInterface creature;
|
||||
private readonly Hero hero;
|
||||
private readonly WorldHandler worldHandler;
|
||||
private readonly AsyncPathMoverInterface pathMover;
|
||||
private float scale = 1;
|
||||
private static readonly float MAX_RADIUS = 10;
|
||||
private static readonly float MIN_RADIUS = 2;
|
||||
|
@ -74,21 +74,22 @@ namespace Client.Application.ViewModels
|
||||
{
|
||||
worldHandler.RequestPickUp(Id);
|
||||
}
|
||||
private void OnMouseRightClick(object? obj)
|
||||
private async Task OnMouseRightClick(object? obj)
|
||||
{
|
||||
worldHandler.RequestMoveToEntity(Id);
|
||||
await pathMover.MoveUntilReachedAsync(drop.Transform.Position);
|
||||
}
|
||||
|
||||
public DropListViewModel(WorldHandler worldHandler, Drop drop, Hero hero)
|
||||
public DropListViewModel(WorldHandler worldHandler, AsyncPathMoverInterface pathMover, Drop drop, Hero hero)
|
||||
{
|
||||
this.drop = drop;
|
||||
this.hero = hero;
|
||||
this.worldHandler = worldHandler;
|
||||
this.pathMover = pathMover;
|
||||
drop.PropertyChanged += Drop_PropertyChanged;
|
||||
drop.Transform.Position.PropertyChanged += DropPosition_PropertyChanged;
|
||||
hero.Transform.Position.PropertyChanged += HeroPosition_PropertyChanged;
|
||||
MouseLeftClickCommand = new RelayCommand(OnMouseLeftClick);
|
||||
MouseRightClickCommand = new RelayCommand(OnMouseRightClick);
|
||||
MouseRightClickCommand = new RelayCommand(async (o) => await OnMouseRightClick(o));
|
||||
}
|
||||
|
||||
private void HeroPosition_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
@ -126,5 +127,6 @@ namespace Client.Application.ViewModels
|
||||
private readonly Drop drop;
|
||||
private readonly Hero hero;
|
||||
private readonly WorldHandler worldHandler;
|
||||
private readonly AsyncPathMoverInterface pathMover;
|
||||
}
|
||||
}
|
||||
|
@ -56,21 +56,22 @@ namespace Client.Application.ViewModels
|
||||
{
|
||||
worldHandler.RequestPickUp(Id);
|
||||
}
|
||||
private void OnMouseRightClick(object? obj)
|
||||
private async Task OnMouseRightClick(object? obj)
|
||||
{
|
||||
worldHandler.RequestMoveToEntity(Id);
|
||||
await pathMover.MoveUntilReachedAsync(drop.Transform.Position);
|
||||
}
|
||||
|
||||
public DropMapViewModel(WorldHandler worldHandler, Drop drop, Hero hero)
|
||||
public DropMapViewModel(WorldHandler worldHandler, AsyncPathMoverInterface pathMover, Drop drop, Hero hero)
|
||||
{
|
||||
this.drop = drop;
|
||||
this.hero = hero;
|
||||
this.worldHandler = worldHandler;
|
||||
this.pathMover = pathMover;
|
||||
drop.PropertyChanged += Creature_PropertyChanged;
|
||||
drop.Transform.Position.PropertyChanged += Position_PropertyChanged;
|
||||
hero.Transform.Position.PropertyChanged += HeroPosition_PropertyChanged;
|
||||
MouseLeftClickCommand = new RelayCommand(OnMouseLeftClick);
|
||||
MouseRightClickCommand = new RelayCommand(OnMouseRightClick);
|
||||
MouseRightClickCommand = new RelayCommand(async (o) => await OnMouseRightClick(o));
|
||||
}
|
||||
|
||||
private void HeroPosition_PropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||
@ -94,6 +95,7 @@ namespace Client.Application.ViewModels
|
||||
private readonly Drop drop;
|
||||
private readonly Hero hero;
|
||||
private readonly WorldHandler worldHandler;
|
||||
private readonly AsyncPathMoverInterface pathMover;
|
||||
private float scale = 1;
|
||||
private static readonly float MAX_RADIUS = 8;
|
||||
private static readonly float MIN_RADIUS = 2;
|
||||
|
@ -59,7 +59,7 @@ namespace Client.Application.ViewModels
|
||||
{
|
||||
if (hero != null)
|
||||
{
|
||||
Creatures.Add(new CreatureListViewModel(worldHandler, @event.Creature, hero));
|
||||
Creatures.Add(new CreatureListViewModel(worldHandler, pathMover, @event.Creature, hero));
|
||||
AddCreature(@event.Creature);
|
||||
}
|
||||
}
|
||||
@ -74,8 +74,8 @@ namespace Client.Application.ViewModels
|
||||
{
|
||||
if (hero != null)
|
||||
{
|
||||
Drops.Add(new DropListViewModel(worldHandler, @event.Drop, hero));
|
||||
Map.Drops.Add(new DropMapViewModel(worldHandler, @event.Drop, hero));
|
||||
Drops.Add(new DropListViewModel(worldHandler, pathMover, @event.Drop, hero));
|
||||
Map.Drops.Add(new DropMapViewModel(worldHandler, pathMover, @event.Drop, hero));
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ namespace Client.Application.ViewModels
|
||||
{
|
||||
if (hero != null)
|
||||
{
|
||||
Map.Creatures.Add(new CreatureMapViewModel(worldHandler, creature, hero));
|
||||
Map.Creatures.Add(new CreatureMapViewModel(worldHandler, pathMover, creature, hero));
|
||||
}
|
||||
}
|
||||
|
||||
@ -145,10 +145,11 @@ namespace Client.Application.ViewModels
|
||||
Map.Creatures.RemoveAll(x => x.Id == id);
|
||||
}
|
||||
|
||||
public MainViewModel(WorldHandler worldHandler)
|
||||
public MainViewModel(WorldHandler worldHandler, AsyncPathMoverInterface pathMover)
|
||||
{
|
||||
this.worldHandler = worldHandler;
|
||||
Map = new MapViewModel(worldHandler);
|
||||
this.pathMover = pathMover;
|
||||
Map = new MapViewModel(pathMover);
|
||||
}
|
||||
|
||||
public ObservableCollection<ChatMessageViewModel> ChatMessages { get; } = new ObservableCollection<ChatMessageViewModel>();
|
||||
@ -162,5 +163,6 @@ namespace Client.Application.ViewModels
|
||||
public MapViewModel Map { get; private set; }
|
||||
public Hero? hero;
|
||||
private readonly WorldHandler worldHandler;
|
||||
private readonly AsyncPathMoverInterface pathMover;
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,10 @@ using System.Collections.Specialized;
|
||||
using Client.Application.Commands;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Windows;
|
||||
using Client.Infrastructure.Service;
|
||||
using System.Windows.Data;
|
||||
using Client.Domain.DTO;
|
||||
using System.Windows.Documents;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
@ -138,11 +142,17 @@ namespace Client.Application.ViewModels
|
||||
drop.Scale = scale;
|
||||
drop.VieportSize = new Vector3((float)ViewportWidth, (float)ViewportHeight, 0);
|
||||
}
|
||||
|
||||
foreach (var node in Path)
|
||||
{
|
||||
node.Scale = scale;
|
||||
node.VieportSize = new Vector3((float)ViewportWidth, (float)ViewportHeight, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ICommand MouseLeftClickCommand { get; }
|
||||
private void OnLeftMouseClick(object? obj)
|
||||
private async Task OnLeftMouseClick(object? obj)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
@ -159,7 +169,8 @@ namespace Client.Application.ViewModels
|
||||
(float)(mousePos.Y - ViewportHeight / 2) * scale + hero.Transform.Position.Y,
|
||||
hero.Transform.Position.Z
|
||||
);
|
||||
worldHandler.RequestMoveToLocation(location);
|
||||
|
||||
await pathMover.MoveUntilReachedAsync(location);
|
||||
}
|
||||
|
||||
public void OnMouseWheel(object sender, MouseWheelEventArgs e)
|
||||
@ -189,13 +200,58 @@ namespace Client.Application.ViewModels
|
||||
mousePosition.Y = (float)(mousePos.Y - ViewportHeight / 2) * scale + hero.Transform.Position.Y;
|
||||
}
|
||||
|
||||
public MapViewModel(WorldHandler worldHandler)
|
||||
public MapViewModel(AsyncPathMoverInterface pathMover)
|
||||
{
|
||||
Creatures.CollectionChanged += Creatures_CollectionChanged;
|
||||
Drops.CollectionChanged += Drops_CollectionChanged;
|
||||
this.worldHandler = worldHandler;
|
||||
MouseLeftClickCommand = new RelayCommand(OnLeftMouseClick);
|
||||
Path.CollectionChanged += Path_CollectionChanged;
|
||||
MouseLeftClickCommand = new RelayCommand(async (o) => await OnLeftMouseClick(o));
|
||||
mousePosition.PropertyChanged += MousePosition_PropertyChanged;
|
||||
BindingOperations.EnableCollectionSynchronization(Path, pathCollectionLock);
|
||||
this.pathMover = pathMover;
|
||||
this.pathMover.Path.CollectionChanged += PathMover_Path_CollectionChanged;
|
||||
}
|
||||
|
||||
private void PathMover_Path_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
lock(pathCollectionLock)
|
||||
{
|
||||
if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null)
|
||||
{
|
||||
if (hero != null)
|
||||
{
|
||||
foreach (var item in e.NewItems)
|
||||
{
|
||||
var node = (PathSegment)item;
|
||||
Path.Add(new PathNodeViewModel(node.From, node.To, hero));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Remove && e.OldItems != null)
|
||||
{
|
||||
foreach (var item in e.OldItems)
|
||||
{
|
||||
Path.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Reset)
|
||||
{
|
||||
Path.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Path_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null)
|
||||
{
|
||||
foreach (var item in e.NewItems)
|
||||
{
|
||||
var node = (PathNodeViewModel)item;
|
||||
node.Scale = scale;
|
||||
node.VieportSize = new Vector3((float)ViewportWidth, (float)ViewportHeight, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MousePosition_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
@ -232,9 +288,11 @@ namespace Client.Application.ViewModels
|
||||
public ObservableCollection<MapBlockViewModel> Blocks { get; } = new ObservableCollection<MapBlockViewModel>();
|
||||
public ObservableCollection<CreatureMapViewModel> Creatures { get; } = new ObservableCollection<CreatureMapViewModel>();
|
||||
public ObservableCollection<DropMapViewModel> Drops { get; } = new ObservableCollection<DropMapViewModel>();
|
||||
public ObservableCollection<PathNodeViewModel> Path { get; } = new ObservableCollection<PathNodeViewModel>();
|
||||
|
||||
public readonly static float MIN_SCALE = 1;
|
||||
public readonly static float MAX_SCALE = 64;
|
||||
private readonly AsyncPathMoverInterface pathMover;
|
||||
private MapImageSelector selector = new MapImageSelector();
|
||||
private Dictionary<uint, MapBlockViewModel> blocks = new Dictionary<uint, MapBlockViewModel>();
|
||||
private Hero? hero;
|
||||
@ -242,6 +300,6 @@ namespace Client.Application.ViewModels
|
||||
private double viewportWidth = 0;
|
||||
private double viewportHeight = 0;
|
||||
private Vector3 mousePosition = new Vector3(0, 0, 0);
|
||||
private readonly WorldHandler worldHandler;
|
||||
private object pathCollectionLock = new object();
|
||||
}
|
||||
}
|
||||
|
80
Client/Application/ViewModels/PathNodeViewModel.cs
Normal file
80
Client/Application/ViewModels/PathNodeViewModel.cs
Normal file
@ -0,0 +1,80 @@
|
||||
using Client.Application.Commands;
|
||||
using Client.Domain.Common;
|
||||
using Client.Domain.Entities;
|
||||
using Client.Domain.Service;
|
||||
using Client.Domain.ValueObjects;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Client.Application.ViewModels
|
||||
{
|
||||
public class PathNodeViewModel : ObservableObject
|
||||
{
|
||||
public Vector3 From => new Vector3(
|
||||
(from.X - hero.Transform.Position.X) / scale + (VieportSize.X / 2),
|
||||
(from.Y - hero.Transform.Position.Y) / scale + (VieportSize.Y / 2),
|
||||
0
|
||||
);
|
||||
|
||||
public Vector3 To => new Vector3(
|
||||
(to.X - hero.Transform.Position.X) / scale + (VieportSize.X / 2),
|
||||
(to.Y - hero.Transform.Position.Y) / scale + (VieportSize.Y / 2),
|
||||
0
|
||||
);
|
||||
|
||||
public float Radius => MAX_RADIUS - (1 / MapViewModel.MIN_SCALE - 1 / scale) / (1 / MapViewModel.MIN_SCALE - 1 / MapViewModel.MAX_SCALE) * (MAX_RADIUS - MIN_RADIUS);
|
||||
|
||||
public float Scale
|
||||
{
|
||||
get => scale;
|
||||
set
|
||||
{
|
||||
if (scale != value)
|
||||
{
|
||||
scale = value;
|
||||
OnPropertyChanged("From");
|
||||
OnPropertyChanged("To");
|
||||
OnPropertyChanged("Radius");
|
||||
}
|
||||
}
|
||||
}
|
||||
public Vector3 VieportSize
|
||||
{
|
||||
get => vieportSize;
|
||||
set
|
||||
{
|
||||
if (vieportSize != value)
|
||||
{
|
||||
vieportSize = value;
|
||||
OnPropertyChanged("From");
|
||||
OnPropertyChanged("To");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PathNodeViewModel(Vector3 from, Vector3 to, Hero hero)
|
||||
{
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.hero = hero;
|
||||
hero.Transform.Position.PropertyChanged += HeroPosition_PropertyChanged;
|
||||
}
|
||||
|
||||
private void HeroPosition_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged("From");
|
||||
OnPropertyChanged("To");
|
||||
}
|
||||
|
||||
private readonly Vector3 from;
|
||||
private readonly Vector3 to;
|
||||
private readonly Hero hero;
|
||||
private float scale = 1;
|
||||
private static readonly float MAX_RADIUS = 10;
|
||||
private static readonly float MIN_RADIUS = 2;
|
||||
private Vector3 vieportSize = new Vector3(0, 0, 0);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user