I have a game in which I have an eye in a head that should always move towards a piece of food (or another piece of food). The head is moved by the player. The food has a fixed position (for some amount of time).
I have solved the maths somehow, but I do not get the precision I want. As I turn around the food, the eye moves almost perfectly, but it is (1) outside the circle sometimes and (2) not perfectly positioned.
Example (left: food, right: head with eye ball with pupil outside the eye ball):
The position of the eye ball is updated on each move of the player.
Screen recording
Relevant code in MainWindow.xaml.cs
EyeBall eb = MyEyeBall;
eb.HorizontalAlignment = HorizontalAlignment.Stretch;
eb.VerticalAlignment = VerticalAlignment.Stretch;
c.Content = eb;
Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() =>
{
Cell foodCell = GetFoodCell();
// A - eye center
// B - first food center (TODO : automatically the closest food)
// A' - pupil center
// d1 - distance from center of eye to boundary of pupil
// d3 - pupil radius
// hard coded values from the proportions in EyeBall.xaml
double d1 = 6,
d3 = 9;
Point A = eb.TransformToAncestor(MyUniformGrid).Transform(new Point(eb.ActualWidth / 2, eb.ActualHeight / 2));
Point B = foodCell.TransformToAncestor(MyUniformGrid).Transform(
new Point(foodCell.ActualWidth / 2, foodCell.ActualHeight / 2));
double sum = (d1 + d3) * (((FrameworkElement)eb.Child).ActualHeight / eb.ActualHeight);
//double sum = eb.TransformToAncestor(MyUniformGrid).Transform(new Point(d1 + d3, 0)).X;
double k = sum / (DistDouble(A, B) - sum);
Point Ap = new Point(((A.X + k * B.X) / (1d + k)),
(A.Y + k * B.Y) / (1d + k));
Point Ap2 = MyUniformGrid.TransformToDescendant(eb).Transform(Ap);
Debug.WriteLine("===============================================");
Debug.WriteLine($"food cell position = {Board.Food.Pieces[0].Pos}");
Debug.WriteLine($"d1 = {d1}, d3 = {d3}");
Debug.WriteLine($"A = {A}, B = {B}");
Debug.WriteLine($"k = {k}");
Debug.WriteLine($"A': {Ap} -> {Ap2}");
Debug.WriteLine("===============================================");
eb.SetBallCenter(Ap2.X, Ap2.Y);
}));
EyeBall.xaml.cs
public partial class EyeBall : Viewbox
{
public EyeBall()
{
InitializeComponent();
}
internal void SetBallCenter(double x, double y)
{
MyBallGeometry.Center = new Point(x, y);
}
internal Point GetBallCenter()
{
return MyBallGeometry.Center;
}
}
EyeBall.xaml
<Viewbox x:Class="wpf_snake.EyeBall"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:wpf_snake"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Canvas Name="svg8" Width="61.809998" Height="60.000003">
<Canvas.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Canvas.RenderTransform>
<Canvas Name="layer1">
<Canvas.RenderTransform>
<TranslateTransform X="-46.272926" Y="-62.673704"/>
</Canvas.RenderTransform>
<Ellipse Canvas.Left="46.3" Width="61.8" Canvas.Top="62.7" Height="60" Name="ellipse971" Fill="#FF8A8EFF" StrokeThickness="0.45579806" StrokeMiterLimit="4" StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Opacity="1"/>
<Ellipse Canvas.Left="52.9" Canvas.Top="68.4" Width="48.5" Height="48.5" Name="ellipse973" Fill="#FFFFFFFF" StrokeThickness="0.49706328" StrokeMiterLimit="4" StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Opacity="1"/>
<Ellipse Canvas.Left="59.9" Canvas.Top="75.4" Width="34.5" Height="34.5" Name="circle979" Fill="#7BA9F2FF" StrokeThickness="0.07413793" StrokeMiterLimit="4" StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round" Opacity="1"/>
</Canvas>
<Path Stroke="Transparent" StrokeThickness="0" Fill="Blue" >
<Path.Data>
<EllipseGeometry Center="45,30" RadiusX="9" RadiusY="9" x:Name="MyBallGeometry"/>
</Path.Data>
</Path>
</Canvas>
</Viewbox>
Thank you.