c# AntiSocial Robots 소스 분석
Robot 클래스 정의
namespace AntisocialRobots
{
/// <summary>Represents one robot.</summary>
internal class Robot
{
/// <summary>The visual element used to represent the robot on the screen.</summary>
public Ellipse Element;
/// <summary>The current location of the robot within the room.</summary>
public RoomPoint Location;
/// <summary>The game frame in which this robot was last moved.</summary>
public int LastMovedFrame;
}
}
RoomPosition 클래스 정의
namespace AntisocialRobots
{
internal struct RoomPoint
{
public int X;
public int Y;
public RoomPoint(int x, int y)
{
X = x;
Y = y;
}
public double DistanceTo(RoomPoint other) { return Math.Sqrt(Square(other.X-X)+Square(other.Y-Y));}
public double AngleTo(RoomPoint other) { return Math.Atan2(other.Y - Y, other.X - X); }
public static double Square(double n) { return n*n; }
}
}
마우스 클릭 위치를 캔버스 위치로 전환
RoomPoint MousePositionToRoomPoint(MouseEventArgs e)
{
Point pt = e.GetPosition(Room);
return new RoomPoint((int)(pt.X * ROOM_SIZE), (int)(pt.Y * ROOM_SIZE));
}
아날로그 로보트가 한 위치를 이동하는 것을 모의한다. 로보트 대상에게 로보트 대상의 실제 위치를 알 필요가 없다. 로보트 대상의 실제 위치만 알 수 있기 때문에 로보트 대상의 로보트 Position만 바꾸어야 한다.
void SimulateOneStep(Robot r)
{
RoomPoint ptR = r.Location;
double vectorX = 0, vectorY = 0;
foreach (Robot s in _robots)
{
if (r == s) continue;
RoomPoint ptS = s.Location;
double inverseSquareDistance = 1.0 / RoomPoint.Square(ptR.DistanceTo(ptS));
double angle = ptR.AngleTo(ptS);
vectorX -= inverseSquareDistance * Math.Cos(angle);
vectorY -= inverseSquareDistance * Math.Sin(angle);
}
double degrees = Math.Atan2(vectorY, vectorX) * 180 / Math.PI;
degrees += 22.5;
while (degrees < 0) degrees += 360;
while (degrees >= 360) degrees -= 360;
int direction = (int)(degrees * 8 / 360);
if ((direction == 7) || (direction == 0) || (direction == 1))
ptR.X = Math.Min(ptR.X + 1, ROOM_SIZE - 1);
else if ((direction == 3) || (direction == 4) || (direction == 5))
ptR.X = Math.Max(ptR.X - 1, 0);
if ((direction == 1) || (direction == 2) || (direction == 3))
ptR.Y = Math.Min(ptR.Y + 1, ROOM_SIZE - 1);
else if ((direction == 5) || (direction == 6) || (direction == 7))
ptR.Y = Math.Max(ptR.Y - 1, 0);
if (((ptR.X != r.Location.X) || (ptR.Y != r.Location.Y)) && _roomCells[ptR.X, ptR.Y] == null)
{
_roomCells[r.Location.X, r.Location.Y] = null;
_roomCells[ptR.X, ptR.Y] = r;
r.Location = new RoomPoint(ptR.X, ptR.Y);
}
}
Robot의 화면 위치는 주 프로그램이 제어하고 RoomPosition에 따라 변환합니다.이렇게 두 차례의 위치 전환을 진행했지만 업무와 실현 간의 결합을 박리하여 코드를 더욱 간결하게 했다.
Robot 화면 위치 계산:
4
void SetRobotElementPosition(Robot robot, RoomPoint pt)
{
Canvas.SetLeft(robot.Element,((double)pt.X)/ROOM_SIZE);
Canvas.SetTop(robot.Element,((double)pt.Y)/ROOM_SIZE);
}
현재 문제는 로보트가 캔버스에 그려진 후에 스스로 위치를 계산하고 캔버스에 새로운 위치를 그릴 수 있도록 백엔드 계산을 계속 실행해야 한다는 것이다.로봇이라는 동작이 완성될 때만 위치를 계산할 수 없고, 프로그램이 실행되는 동안 모든 로봇의 위치를 계산해야 한다는 것이다.스레드를 사용하여 다음 작업을 수행할 수 있습니다.Action recomputeAndRedraw = null;
recomputeAndRedraw = delegate
{
Dispatcher.BeginInvoke((Action)delegate
{
PerformSimulationStep();
recomputeAndRedraw();
}, DispatcherPriority.Background);
};
Loaded += delegate
{
_framesPerSecondStopwatch.Start();
recomputeAndRedraw();
};
인터페이스가 불러오면 액션은 백엔드에서 계속 실행되고 로보트의 위치를 계산하여 인터페이스에 그려집니다.
기술:
private TaskFactory _uiTasks;
_uiTasks=new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
//Action에서 비동기식 작업을 수행합니다.
_uiTasks.StartNew(()=>{});
_uiTasks.StartNew(delegate{});
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.