Closed3
WinUI3 の Canvas を使ってマイクラのプレイヤーの移動軌跡をリアルタイム描画する
こういうの作ったのでメモ。
実行環境
- Minecraft Java Edition 1.21.8
- MinecraftConnection 3.0.0(β版)
- WinUI3
- .NET 9 / C#
MinecraftConnection はさておき、GUIで描画するためのコード。
まずはXAMLから。
MainWindow.xaml
<Window
x:Class="GuiApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:GuiApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="GuiApp">
<Window.SystemBackdrop>
<MicaBackdrop />
</Window.SystemBackdrop>
<Grid>
<Canvas x:Name="MotionCanvas" Background="White"/>
</Grid>
</Window>
コードビハインド
MainWindow.cs
public sealed partial class MainWindow : Window
{
private List<Position> playerMotions = new List<Position>();
public MainWindow()
{
InitializeComponent();
CompositionTarget.Rendering += OnRender;
StartMotionUpdate();
}
private async void StartMotionUpdate()
{
var command = new MinecraftCommand("127.0.0.1", 25575, "your-pass");
while (true)
{
var data = await command.DataGetEntityAsync("player-name");
var info = data.Position;
DispatcherQueue.TryEnqueue(() =>
{
if (playerMotions.Count > 200)
{
playerMotions.RemoveAt(0);
}
playerMotions.Add(info);
});
System.Diagnostics.Debug.WriteLine($"X:{info.X} Y:{info.Y} Z:{info.Z}");
await Task.Delay(5);
}
}
private void OnRender(object? sender, object e)
{
MotionCanvas.Children.Clear();
double canvasWidth = MotionCanvas.ActualWidth;
double canvasHeight = MotionCanvas.ActualHeight;
double scale = 20;
foreach (var motion in playerMotions)
{
var ellipse = new Ellipse
{
Width = 5,
Height = 5,
Fill = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 255, 0, 0))
};
// Canvas 中心を (0,0) として座標をマッピング
double x = canvasWidth / 2 + motion.X * scale;
double y = canvasHeight / 2 - motion.Z * scale; // Z を Y に投影
Canvas.SetLeft(ellipse, x);
Canvas.SetTop(ellipse, y);
MotionCanvas.Children.Add(ellipse);
}
}
}
- CompositionTarget.Rendering は毎フレーム呼び出されるイベントハンドラ
- StartMotionUpdate() は非同期にして常時実行(座標取ってくるより早そう、Waitしてもよかったかな?)
- マイクラのY座標は高さになるので、Canvas用に、マイクラのZ座標をCanvasのY座標へ反映
double y = canvasHeight / 2 - motion.Z * scale;
- マイクラでの座標をそのままCanvasに描画するとめっちゃ小さかったので、20倍にスケーリング(ここは経験則から)
Windows.UI.Color ってカラープリセットないので、RGBAで指定するのがちょい面倒だったり。
このスクラップは4日前にクローズされました