Fixed a few issues with touch controls & flicks

Co-Authored-By: MoonDroid <81515012+moondroidcoder@users.noreply.github.com>
This commit is contained in:
KarimAkra
2025-04-15 23:39:17 +03:00
co-authored by MoonDroid
parent 5c9d76791b
commit d80afc35b4
4 changed files with 129 additions and 37 deletions
+5 -3
View File
@@ -4,6 +4,7 @@ package funkin.mobile.ui;
// Also this adds pixelOverlap to TouchUtil so, hell yeah !!
// W.I.P DONT TOUCH.
// TODO: Replace all the touchBuddy littered around the game's code with the ACTUAL touchBuddy.
// Thnk u agua and toffee <3
import openfl.display.Bitmap;
import flixel.util.FlxDestroyUtil;
import flixel.FlxG;
@@ -73,12 +74,13 @@ class TouchPointer extends FlxSprite
var _pointTime:Int = -1;
var _calcAngle:Float = 0;
var _pointId:Int;
var offsetX:Int = 0;
var offsetY:Int = 0;
public var offsetX:Int = -50;
public var offsetY:Int = -50;
public function new(xPos:Float, yPos:Float, touch:Int, pId:Int)
{
super(xPos, yPos, "assets/images/cursor/michael.png");
super(xPos + offsetX, yPos + offsetY, "assets/images/cursor/michael.png");
touchId = touch;
_pointId = pId;
scrollFactor.set(0, 0);
+35 -5
View File
@@ -380,6 +380,7 @@ class SwipeUtil
// Calling a function for each check might be eh, but I think its clean enough.
// TODO: Add mouse support to this somehow? for now just keep it.
// TODO: Rework handleFlick.
/**
* Handles flick checks depending on the direction given.
@@ -393,26 +394,39 @@ class SwipeUtil
static function handleFlick(direction:SwipingDirection):Bool
{
#if TOUCH_CONTROLS
#if mobile
var touches = FlxG.touches;
#else
var touches = FlxG.mouse;
#end
if (TouchUtil.pressed)
{
_velocityX = 0;
_velocityY = 0;
return false;
}
// Update velocities based on touch input if no touch is pressed
final vertical:Bool = direction == Up || direction == Down;
final horizontal:Bool = direction == Left || direction == Right;
if (TouchUtil.pressed) return false;
if (vertical && FlxG.touches.velocityY == 0)
if (vertical && touches.velocityY == 0)
{
_velocityY = 0;
return false;
}
if (horizontal && FlxG.touches.velocityX == 0)
if (horizontal && touches.velocityX == 0)
{
_velocityX = 0;
return false;
}
if (vertical) _velocityY += FlxG.touches.velocityY;
final framerateRatio:Float = (1 / FlxG.elapsed) / FlxG.updateFramerate;
if (horizontal) _velocityX += FlxG.touches.velocityX;
// Apply frame-rate scaling using the ratio
if (vertical) _velocityY += touches.velocityY / framerateRatio;
if (horizontal) _velocityX += touches.velocityX / framerateRatio;
// Check if a swipe matches the specified direction
final swiped:Bool = switch (direction)
@@ -437,6 +451,22 @@ class SwipeUtil
#end
}
public static inline function resetSwipeVelocity():Void
{
#if mobile
var touches = FlxG.touches;
#else
var touches = FlxG.mouse;
#end
@:privateAccess
touches.velocityY = 0;
@:privateAccess
touches.velocityX = 0;
_velocityY = 0;
_velocityX = 0;
}
/**
* Handles swipe gestures and detects the direction of the swipe based on the input.
* The function starts tracking the swipe when a touch is pressed and compares the
+46 -10
View File
@@ -421,8 +421,6 @@ class PauseSubState extends MusicBeatSubState
// Doing this just so it'd look better i guess.
final upP:Bool = controls.UI_UP_P || SwipeUtil.swipeUp;
final downP:Bool = controls.UI_DOWN_P || SwipeUtil.swipeDown;
final accept:Bool = controls.ACCEPT
|| (TouchUtil.overlapsComplex(menuEntryText.members[currentEntry], camera) && TouchUtil.justReleased && !SwipeUtil.swipeAny);
if (upP)
{
@@ -433,15 +431,26 @@ class PauseSubState extends MusicBeatSubState
changeSelection(1);
}
if (accept && !justOpened)
if (TouchUtil.justReleased && !SwipeUtil.swipeAny && !justOpened)
{
// Remove banner ad when game is unpaused.
#if NO_DISABLE_ADMOB_ADS
if (currentMenuEntries[currentEntry].text != "Change Difficulty"
&& currentMenuEntries[currentEntry].text != "Enable Practice Mode"
&& currentMenuEntries[currentEntry].text != "Back") AdMobUtil.removeBanner();
#end
for (i in 0...menuEntryText.members.length)
{
if (!TouchUtil.overlaps(menuEntryText.members[i], camera)) continue;
if (i == currentEntry)
{
currentMenuEntries[currentEntry].callback(this);
break;
}
changeSelection(i - currentEntry);
break;
}
}
if (controls.ACCEPT)
{
currentMenuEntries[currentEntry].callback(this);
}
else if (controls.PAUSE && !justOpened)
@@ -644,7 +653,9 @@ class PauseSubState extends MusicBeatSubState
{
// Resume a paused video if it exists.
VideoCutscene.resumeVideo();
#if NO_DISABLE_ADMOB_ADS
AdMobUtil.removeBanner();
#end
state.close();
}
@@ -679,6 +690,9 @@ class PauseSubState extends MusicBeatSubState
PlayState.instance.needsReset = true;
#if NO_DISABLE_ADMOB_ADS
AdMobUtil.removeBanner();
#end
state.close();
}
@@ -689,6 +703,9 @@ class PauseSubState extends MusicBeatSubState
static function restartPlayState(state:PauseSubState):Void
{
PlayState.instance.needsReset = true;
#if NO_DISABLE_ADMOB_ADS
AdMobUtil.removeBanner();
#end
state.close();
}
@@ -711,6 +728,9 @@ class PauseSubState extends MusicBeatSubState
static function restartVideoCutscene(state:PauseSubState):Void
{
VideoCutscene.restartVideo();
#if NO_DISABLE_ADMOB_ADS
AdMobUtil.removeBanner();
#end
state.close();
}
@@ -721,6 +741,9 @@ class PauseSubState extends MusicBeatSubState
static function skipVideoCutscene(state:PauseSubState):Void
{
VideoCutscene.finishVideo();
#if NO_DISABLE_ADMOB_ADS
AdMobUtil.removeBanner();
#end
state.close();
}
@@ -733,6 +756,9 @@ class PauseSubState extends MusicBeatSubState
if (PlayState.instance?.currentConversation == null) return;
PlayState.instance.currentConversation.resetConversation();
#if NO_DISABLE_ADMOB_ADS
AdMobUtil.removeBanner();
#end
state.close();
}
@@ -745,6 +771,9 @@ class PauseSubState extends MusicBeatSubState
if (PlayState.instance?.currentConversation == null) return;
PlayState.instance.currentConversation.skipConversation();
#if NO_DISABLE_ADMOB_ADS
AdMobUtil.removeBanner();
#end
state.close();
}
@@ -765,6 +794,10 @@ class PauseSubState extends MusicBeatSubState
FreeplayState.build(sticker);
// Do this AFTER because this resets the value of isStoryMode!
#if NO_DISABLE_ADMOB_ADS
AdMobUtil.removeBanner();
#end
if (PlayStatePlaylist.isStoryMode)
{
PlayStatePlaylist.reset();
@@ -788,6 +821,9 @@ class PauseSubState extends MusicBeatSubState
*/
static function quitToChartEditor(state:PauseSubState):Void
{
#if NO_DISABLE_ADMOB_ADS
AdMobUtil.removeBanner();
#end
state.close();
if (FlxG.sound.music != null) FlxG.sound.music.pause(); // Don't reset song position!
PlayState.instance.close(); // This only works because PlayState is a substate!
+43 -19
View File
@@ -1504,9 +1504,16 @@ class FreeplayState extends MusicBeatSubState
final downP:Bool = controls.UI_DOWN_P || SwipeUtil.swipeDown;
final accepted:Bool = controls.ACCEPT;
#if TOUCH_CONTROLS
#if mobile
var touches = FlxG.touches;
#else
var touches = FlxG.mouse;
#end
// Nested as fuck
@:nullSafety(Off)
if (TouchUtil.justReleased && !SwipeUtil.swipeAny && !TouchUtil.overlapsComplex(diffSelRight))
if (TouchUtil.justReleased && !SwipeUtil.swipeAny && !TouchUtil.overlapsComplex(diffSelRight) && touches.velocityY == 0)
{
for (i in 0...grpCapsules.members.length)
{
@@ -1519,6 +1526,7 @@ class FreeplayState extends MusicBeatSubState
break;
}
}
#end
if (TouchUtil.justPressed)
{
@@ -1571,7 +1579,7 @@ class FreeplayState extends MusicBeatSubState
final wheelAmount:Float = #if !html5 FlxG.mouse.wheel #else FlxG.mouse.wheel / 8 #end;
#elseif mobile
final wheelAmount:Float = 0 / 2;
final wheelAmount:Float = FlxG.touches.horizontalWheel / 2;
#end
if (wheelAmount != 0 #if mobile && !TouchUtil.pressed #end)
@@ -1583,13 +1591,28 @@ class FreeplayState extends MusicBeatSubState
// TODO: This is a tad too heavy on phones. Find a way to keep it changing selections without all the redundant loading.
if (SwipeUtil.flickUp)
{
dj?.resetAFKTimer();
changeSelection(-1);
if (curSelected - 1 >= 0)
{
dj?.resetAFKTimer();
changeSelection(-1);
}
else
{
SwipeUtil.resetSwipeVelocity();
}
}
else if (SwipeUtil.flickDown)
if (SwipeUtil.flickDown)
{
dj?.resetAFKTimer();
changeSelection(1);
if (curSelected + 1 < grpCapsules.countLiving())
{
dj?.resetAFKTimer();
changeSelection(1);
}
else
{
SwipeUtil.resetSwipeVelocity();
}
}
// FORGIVE ME FOR NOT PLACING THESE IN DifficultySelector BUT IT JUST DIDN'T WORK RIGHT
@@ -1631,7 +1654,7 @@ class FreeplayState extends MusicBeatSubState
if (_pressedOn)
{
if (TouchUtil.touch != null && TouchUtil.touch.ticksDeltaSincePress >= 1000)
if (TouchUtil.touch != null && TouchUtil.touch.ticksDeltaSincePress >= 700)
{
_toggled = true;
_pressedOn = false;
@@ -1706,15 +1729,7 @@ class FreeplayState extends MusicBeatSubState
break;
}
}
else
{
for (diff in grpDifficulties.group.members)
{
if (diff == null || diff.difficultyId != currentDifficulty) continue;
if (diff.x != 90) diff.x = 90 + (CUTOUT_WIDTH * DJ_POS_MULTI);
}
}
FlxG.mouse.visible = true;
#end
if (controls.BACK)
@@ -2195,8 +2210,17 @@ class FreeplayState extends MusicBeatSubState
curSelected += change;
if (curSelected < 0) curSelected = (SwipeUtil.flickUp) ? 0 : grpCapsules.countLiving() - 1;
if (curSelected >= grpCapsules.countLiving()) curSelected = (SwipeUtil.flickDown) ? grpCapsules.countLiving() - 1 : 0;
// Doesn't go beyond the last/first capsule if there's a flick, and resets the swipe velocity to be extra safe.
if (curSelected < 0)
{
curSelected = (SwipeUtil.flickUp) ? 0 : grpCapsules.countLiving() - 1;
SwipeUtil.resetSwipeVelocity();
}
if (curSelected >= grpCapsules.countLiving())
{
curSelected = (SwipeUtil.flickDown) ? grpCapsules.countLiving() - 1 : 0;
SwipeUtil.resetSwipeVelocity();
}
if (!prepForNewRank && curSelected != prevSelected) FunkinSound.playOnce(Paths.sound('scrollMenu'), 0.4);