Skip to content

Fix Autopilot by calculating movement in the present time #32929

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: master
Choose a base branch
from

Conversation

TaterToes
Copy link
Contributor

@TaterToes TaterToes commented Apr 23, 2025

Created a pull request since I believe its in the state of feedback and debugging plus cleanup

This implementation overhauls Autopilot’s logic to eliminate both the stutter, difficult tapping. and the teleporting between HitObjects. The cursor is given a velocity calculated based on avaliable time and the distance between the cursor to the next hit object.

It also fixes some other issues given by the TODO's.

Anyways, heres a video of the implementation below.

osu.lazer.autopilot.fix.test.1.mp4

@peppy peppy self-requested a review April 24, 2025 10:53
Copy link
Member

@peppy peppy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've fixed up most of the code quality issues, and it seems to play well, but will need some further code revision.

Comment on lines 42 to 43
private const double min_start = 20;
private const double min_end = 5;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These names are nondescript and the comment doesn't really help to describe what they are doing/for.

Copy link
Contributor Author

@TaterToes TaterToes Apr 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I apologize, but let me explain this first before I update it and get approval for understanding.

My main worry about this PR was so that the cursor doesn't seemingly teleport from one hit object to the other. What min_start does is that if the currentTime is equal to the start of the hit window minus the min_start (avaliableTime is equal to min_start at this time), we gradually proportionally approach 1 ms of avaliableTime so that we can mostly avoid seemingly cursor teleportation until the end of the hitwindow minus the min_end.

The problem is that if someone tapped faster then the time interval of min_start, there would be some instances that the cursor wouldnt reach the hitcircle on time and would be considered as a miss.

Also after some thinking, since the world record for Autopilot is a map at 540 bpm 1/8 notes. The value for min_start seems to be too high.

// TODO: Implement the functionality to automatically spin spinners
double hitWindowStart = start - mehWindow - min_start;
double hitWindowEnd = start + mehWindow - min_end;
double availableTime = currentTime >= hitWindowStart
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this just be a constant value rather than constantly changing every frame? This plus moveTowards are so obfuscated in weird logic that I don't see the reason to it all. This is either due to the math in this PR being "wahtever works lol", or my knowledge of math lacking, but either way I can't follow.

Copy link
Contributor Author

@TaterToes TaterToes Apr 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I remember adding a comment here about what it does, but I might've accidentally deleted it.

My main worry was that I wanted the cursor to enter the HitObject at the time where HitWindow starts. Giving a constant value means that after we judged the last HitObject, it would take a constant value of time until the cursor reaches the HitCircle. Issue with this is that it would reach the hitObject before or after the hitwindow starts.

The other fact is that in moveTowards, the distance between the cursor and the hitobject is also changing. If we kept one of these constants, they would either accelerate or deaccelerate. (if avaliableTime was kept constant, it would never reach but infintely approach the center of the hitCircle). I wanted a constant velocity, so either we need a constant value for both avaliableTime and distance, then add to the cursorPosition, or each value has to change proportionally to each other to accurately calculate somewhat constant velocity. (well atleast until currentTime reaches hitWindow - minStart, that's basically the final guard against seemingly cursor teleportation)

Next is the logic after it passes hitWindow - minStart. The Clamped values decreases from 1 to 0 based on where currentTime between hitWindowStart and hitWindowEnd. This ensures that the cursor reaches to the hitObject on time without frequent extremely fast cursors.

I'll await edits until response.

Copy link
Contributor Author

@TaterToes TaterToes Apr 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also the logic in moveTowards is that if both currentTime and distance are constantly updating and are proportionally to each other. Velocity is calculated by how far it would go in 1 ms, and then multiply by how much time has passed between frames in ms. If you're wondering how it reaches on time, since I divided by avaliableTime, the time between frames is basically there to cancel it out ( multiply and division are like inverses) until we reach the complete distance.

basically ((distance / avaliableTime) * ElapsedFrameTime) and if ElapsedFrameTime and avaliableTime are equal then it goes the complete distance.

we also normalize it so that we multiply the unit vector by a magnitude (aka displacement)

Copy link
Contributor Author

@TaterToes TaterToes Apr 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh yeah i also forgot that sometimes hitobjects also moves, which changes distance.

@TaterToes
Copy link
Contributor Author

TaterToes commented Apr 24, 2025

the meh window isn't calculated correctly when its a slider. need its headcircle.

found a bug where replays are not spinning spinners.

@peppy
Copy link
Member

peppy commented Apr 25, 2025

@TaterToes
Copy link
Contributor Author

TaterToes commented Apr 25, 2025

place hasReplayLoaded.Value in spots that forcefully moves cursor.

why?

Extra code revise, I was thinking of putting the return function only in applyCursor and removing where I put conditions for hasReplayLoaded, but i'll explain why I did this.

Now this is the part where my knowledge lacks, but since for some reason when I was watching the replay, the spinner wasn't being automatically spun.

So I placed it in spots where it only stops the cursor from being updated to stop the weird jittery cursor trail and some other calculations, assuming that was the cause of problems.

Also sorry for so many commits, I keep changing my mind after pushing commits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants