private async void processWalkInstruction(WalkInstruction previousWalk, WalkInstruction currentWalk) { if (previousWalk != null) { await previousWalk.OnCompletion.Task; } var debugRenderers = DebugDrawWalkPath ? new List <IObject>() : null; _debugPath = debugRenderers; OnPropertyChanged(nameof(IsWalking)); float xSource = _translate.X; float ySource = _translate.Y; bool completedWalk = false; try { completedWalk = await walkAsync(currentWalk, currentWalk.Destination, currentWalk.StraightLine, debugRenderers); } finally { _faceDirection.CurrentDirectionalAnimation = _outfit.Outfit[AGSOutfit.Idle]; await _faceDirection.FaceDirectionAsync(_faceDirection.Direction); currentWalk.OnCompletion.TrySetResult(completedWalk); OnPropertyChanged(nameof(IsWalking)); } }
private async Task <bool> addNewInstructionAsync(Position destination, bool walkAnywhere, bool straightLine, bool stopOnly) { WalkInstruction newWalk = new WalkInstruction(_room?.Room, destination, walkAnywhere, straightLine, stopOnly); _incomingInstructions.Enqueue(newWalk); return(await newWalk.OnCompletion.Task); }
private WalkInstruction getWalkInstruction() { WalkInstruction instruction = _currentWalk; while (_incomingInstructions.TryDequeue(out var nextInstruction)) { if (instruction != null) { onWalkLineCompleted(instruction, instruction.CurrentLine, false); } if (nextInstruction != null) { instruction = nextInstruction; } } if (_currentWalk != instruction) { if (instruction.StopOnly) { instruction.OnCompletion.TrySetResult(false); _currentWalk = null; return(null); } var previousInstruction = _currentWalk; _currentWalk = instruction; processWalkInstruction(previousInstruction, instruction); } return(instruction); }
private void onWalkLineCompleted(WalkInstruction currentWalk, WalkLineInstruction currentLine, bool success) { currentWalk.CurrentLine = null; if (currentLine == null) { return; } currentLine.LastFrame = null; currentLine.OnCompletion.TrySetResult(success); }
private async Task <bool> walkAsync(WalkInstruction currentWalk, Position location, bool straightLine, List <IObject> debugRenderers) { Position[] walkPoints = straightLine ? new [] { location } : getWalkPoints(location); if (walkPoints.Length == 0) { return(false); } foreach (var point in walkPoints) { if (MathUtils.FloatEquals(point.X, _translate.X) && MathUtils.FloatEquals(point.Y, _translate.Y)) { continue; } if (!await walkStraightLine(currentWalk, point, debugRenderers)) { return(false); } } return(true); }
private async Task <bool> walkAsync(WalkInstruction currentWalk, Position location, bool straightLine, List <IObject> debugRenderers) { IEnumerable <Position> walkPoints = straightLine ? new List <Position> { location } : getWalkPoints(location); if (!walkPoints.Any()) { return(false); } foreach (var point in walkPoints) { if (point.X == _translate.X && point.Y == _translate.Y) { continue; } if (!await walkStraightLine(currentWalk, point, debugRenderers)) { return(false); } } return(true); }
private async Task <bool> walkStraightLine(WalkInstruction currentWalk, Position destination, List <IObject> debugRenderers) { if (_room?.Room != currentWalk.Room) { return(false); } if (debugRenderers != null) { IObject renderer = _objFactory.GetObject("Debug Line"); var line = renderer.AddComponent <GLLineRenderer>(); if (line != null) { line.X1 = _translate.X; line.Y1 = _translate.Y; line.X2 = destination.X; line.Y2 = destination.Y; } await renderer.ChangeRoomAsync(currentWalk.Room); debugRenderers.Add(renderer); } if (_cutscene.IsSkipping) { _translate.Position = destination; return(true); } if (!isDistanceVeryShort(destination)) { var lastDirection = _faceDirection.Direction; var walkAnimation = _outfit.Outfit[AGSOutfit.Walk]; bool alreadyWalking = _faceDirection.CurrentDirectionalAnimation == walkAnimation; _faceDirection.CurrentDirectionalAnimation = walkAnimation; await _faceDirection.FaceDirectionAsync(_translate.X, _translate.Y, destination.X, destination.Y); if (lastDirection != _faceDirection.Direction && alreadyWalking) { await Task.Delay(200); } } float xSteps = Math.Abs(destination.X - _translate.X); float ySteps = Math.Abs(destination.Y - _translate.Y); float numSteps = Math.Max(xSteps, ySteps); bool isBaseStepX = xSteps >= ySteps; float xStep = xSteps / numSteps; if (_translate.X > destination.X) { xStep = -xStep; } float yStep = ySteps / numSteps; if (_translate.Y > destination.Y) { yStep = -yStep; } WalkLineInstruction instruction = new WalkLineInstruction(numSteps, xStep, yStep, isBaseStepX, destination); currentWalk.CurrentLine = instruction; if (_currentWalk != currentWalk) { onWalkLineCompleted(currentWalk, instruction, false); currentWalk.CancelToken.Cancel(); return(false); } Task timeout = Task.Delay(WalkLineTimeoutInMilliseconds); Task completedTask = await Task.WhenAny(instruction.OnCompletion.Task, currentWalk.OnCompletion.Task, timeout); if (completedTask == timeout) { currentWalk.CancelToken.Cancel(); return(false); } if (completedTask == currentWalk.OnCompletion.Task) { return(false); } if (!instruction.OnCompletion.Task.Result || currentWalk.CancelToken.IsCancellationRequested || _room?.Room != currentWalk.Room || (!currentWalk.WalkAnywhere && !isWalkable(_translate.Position))) { return(false); } if (currentWalk.WalkAnywhere || isWalkable(destination)) { _translate.Position = destination; return(true); } return(false); }
private void onRepeatedlyExecute() { WalkInstruction currentWalk = getWalkInstruction(); WalkLineInstruction currentLine = currentWalk?.CurrentLine; if (currentLine == null) { return; } if (currentWalk.CancelToken.IsCancellationRequested || (!currentWalk.WalkAnywhere && !isWalkable(_translate.Position)) || _room?.Room != currentWalk.Room) { onWalkLineCompleted(currentWalk, currentLine, false); return; } if (currentLine.NumSteps <= 1f) { onWalkLineCompleted(currentWalk, currentLine, true); return; } if (_cutscene.IsSkipping) { _translate.Position = currentLine.Destination; onWalkLineCompleted(currentWalk, currentLine, true); return; } PointF walkSpeed = adjustWalkSpeed(WalkStep); float xStep = currentLine.XStep * walkSpeed.X; float yStep = currentLine.YStep * walkSpeed.Y; if (MovementLinkedToAnimation && _animation != null && _animation.Animation.Frames.Count > 1 && _animation.Animation.Sprite == currentLine.LastFrame) { //If the movement is linked to the animation and the animation speed is slower the the viewport movement, it can lead to flickering //so we do a smooth movement for this scenario. (var compensateX, var compensateY) = currentLine.Compensate; (var lastViewportX, var lastViewportY) = currentLine.Viewport; var candidateX = _translate.X + compensateForViewScrollIfNeeded(_state.Viewport.X, xStep, ref compensateX, ref lastViewportX); var candidateY = _translate.Y + compensateForViewScrollIfNeeded(_state.Viewport.Y, yStep, ref compensateY, ref lastViewportY); if (currentWalk.WalkAnywhere || isWalkable(new Position(candidateX, candidateY))) { currentLine.Compensate = (compensateX, compensateY); _translate.Position = (candidateX, candidateY); return; } } currentLine.LastFrame = _animation?.Animation.Sprite; currentLine.Viewport = (_state.Viewport.X, _state.Viewport.Y); currentLine.NumSteps -= Math.Abs(currentLine.IsBaseStepX ? xStep : yStep); if (currentLine.NumSteps >= 0f) { var candidateX = _translate.X + (xStep - currentLine.Compensate.x); var candidateY = _translate.Y + (yStep - currentLine.Compensate.y); if (currentWalk.WalkAnywhere || isWalkable(new Position(candidateX, candidateY))) { _translate.Position = (candidateX, candidateY); } else { onWalkLineCompleted(currentWalk, currentLine, false); return; } } currentLine.Compensate = (0f, 0f); }