Added vibrations to most ResultState ranks and more!
* Vibrations for most ranks * Vibrations when scrolling through FreeplayState * Vibrations for notes hits * Vibrations for game over Co-Authored-By: sector-a <82838084+sector-a@users.noreply.github.com>
This commit is contained in:
+10
-1
@@ -286,7 +286,13 @@ class Project extends HXProject {
|
||||
*/
|
||||
static final TOUCH_CONTROLS:FeatureFlag = "TOUCH_CONTROLS";
|
||||
|
||||
/**
|
||||
/**
|
||||
* `-DHAPTIC_VIBRATIONS
|
||||
* If this flag is enabled, the vibrations for the game is also enabled.
|
||||
*/
|
||||
static final HAPTIC_VIBRATIONS:FeatureFlag = "HAPTIC_VIBRATIONS";
|
||||
|
||||
/**
|
||||
* `-DEXCLUDE_ARMV7`
|
||||
* If this flag is enabled, armv7 won't be compiled when building android.
|
||||
*/
|
||||
@@ -586,6 +592,9 @@ class Project extends HXProject {
|
||||
// Should be true only on mobile builds.
|
||||
TOUCH_CONTROLS.apply(this, isMobile());
|
||||
|
||||
// Should be true only on mobile builds.
|
||||
HAPTIC_VIBRATIONS.apply(this, isMobile());
|
||||
|
||||
// Should be true only on non-mobile builds.
|
||||
// Only mobile builds support ads.
|
||||
DISABLE_ADMOB_ADS.apply(this, !isMobile());
|
||||
|
||||
@@ -9,7 +9,6 @@ import funkin.mobile.ui.options.objects.HitboxShowcase;
|
||||
import funkin.mobile.ui.FunkinHitbox;
|
||||
import funkin.mobile.util.TouchUtil;
|
||||
import funkin.mobile.util.SwipeUtil;
|
||||
import funkin.util.MathUtil;
|
||||
import funkin.ui.MusicBeatSubState;
|
||||
import funkin.ui.AtlasText;
|
||||
import funkin.graphics.shaders.HSVShader;
|
||||
@@ -306,7 +305,7 @@ class MobileControlsSchemeMenu extends MusicBeatSubState
|
||||
}
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
public override function update(elapsed:Float):Void
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
|
||||
@@ -20,11 +20,15 @@ class HapticUtil
|
||||
* @param duration The time taken for a complete cycle.
|
||||
* @param amplitude The distance of movement of the wave from its original position.
|
||||
*/
|
||||
public static function vibrate(period:Int, duration:Int, amplitude:Int = 0):Void
|
||||
public static function vibrate(period:Int = Constants.DEFAULT_VIBRATION_PERIOD, duration:Int = Constants.DEFAULT_VIBRATION_DURATION, amplitude:Int = 0):Void
|
||||
{
|
||||
#if HAPTIC_VIBRATIONS
|
||||
if (!Preferences.vibration) return;
|
||||
|
||||
Haptic.vibrate(period, duration, amplitude);
|
||||
#end
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,8 +38,9 @@ class HapticUtil
|
||||
* @param toValue End amplitude value.
|
||||
* @param duration Duration of the tween.
|
||||
*/
|
||||
public static function increasingVibrate(fromValue:Float, toValue:Float, duration:Float = 1)
|
||||
public static function increasingVibrate(fromValue:Float, toValue:Float, duration:Float = 1):Void
|
||||
{
|
||||
#if HAPTIC_VIBRATIONS
|
||||
if (!Preferences.vibration) return;
|
||||
|
||||
amplitudeTween = FlxTween.num(fromValue, toValue, duration,
|
||||
@@ -46,5 +51,8 @@ class HapticUtil
|
||||
}, function(num) {
|
||||
vibrate(0, Std.int(Constants.DEFAULT_VIBRATION_DURATION / 10), Std.int(num));
|
||||
});
|
||||
#end
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,10 +19,8 @@ import funkin.util.MathUtil;
|
||||
import funkin.effects.RetroCameraFade;
|
||||
import flixel.math.FlxPoint;
|
||||
import funkin.mobile.util.TouchUtil;
|
||||
import openfl.utils.Assets;
|
||||
#if mobile
|
||||
import funkin.mobile.util.HapticUtil;
|
||||
#end
|
||||
import openfl.utils.Assets;
|
||||
|
||||
/**
|
||||
* A substate which renders over the PlayState when the player dies.
|
||||
@@ -517,8 +515,8 @@ class GameOverSubState extends MusicBeatSubState
|
||||
{
|
||||
blueballed = true;
|
||||
|
||||
#if mobile
|
||||
HapticUtil.vibrate(500, 1000);
|
||||
#if HAPTIC_VIBRATIONS
|
||||
HapticUtil.vibrate(Constants.DEFAULT_VIBRATION_PERIOD * 5, Constants.DEFAULT_VIBRATION_DURATION * 10);
|
||||
#end
|
||||
|
||||
if (Assets.exists(Paths.sound('gameplay/gameover/fnf_loss_sfx' + blueBallSuffix)))
|
||||
|
||||
@@ -57,6 +57,7 @@ import funkin.util.SerializerUtil;
|
||||
import haxe.Int64;
|
||||
#if mobile
|
||||
import funkin.mobile.util.TouchUtil;
|
||||
import funkin.mobile.util.HapticUtil;
|
||||
import funkin.mobile.ui.FunkinHitbox;
|
||||
#if NO_DISABLE_ADMOB_ADS
|
||||
import funkin.mobile.util.AdMobUtil;
|
||||
@@ -2639,6 +2640,11 @@ class PlayState extends MusicBeatSubState
|
||||
isComboBreak = Constants.JUDGEMENT_SHIT_COMBO_BREAK;
|
||||
}
|
||||
|
||||
#if HAPTIC_VIBRATIONS
|
||||
// Vibration each note hit.
|
||||
HapticUtil.vibrate(0, 10);
|
||||
#end
|
||||
|
||||
// Send the note hit event.
|
||||
var event:HitNoteScriptEvent = new HitNoteScriptEvent(note, healthChange, score, daRating, isComboBreak, Highscore.tallies.combo + 1, noteDiff,
|
||||
daRating == 'sick');
|
||||
|
||||
@@ -514,13 +514,13 @@ class ResultState extends MusicBeatSubState
|
||||
clearPercentLerp = clearPercentCounter.curNumber;
|
||||
FunkinSound.playOnce(Paths.sound('scrollMenu'));
|
||||
|
||||
#if mobile
|
||||
#if HAPTIC_VIBRATIONS
|
||||
HapticUtil.vibrate(0, 10);
|
||||
#end
|
||||
}
|
||||
},
|
||||
onComplete: _ -> {
|
||||
#if mobile
|
||||
#if HAPTIC_VIBRATIONS
|
||||
HapticUtil.vibrate(0, Constants.DEFAULT_VIBRATION_DURATION, Constants.MAX_VIBRATION_AMPLITUDE);
|
||||
#end
|
||||
|
||||
@@ -725,6 +725,90 @@ class ResultState extends MusicBeatSubState
|
||||
// maskShaderSongName.frameUV = songName.frame.uv;
|
||||
}
|
||||
|
||||
#if HAPTIC_VIBRATIONS
|
||||
private function handleAnimationVibrations()
|
||||
{
|
||||
switch (rank)
|
||||
{
|
||||
case ScoringRank.PERFECT | ScoringRank.PERFECT_GOLD:
|
||||
for (atlas in characterAtlasAnimations)
|
||||
{
|
||||
@:nullSafety(Off)
|
||||
switch (playerCharacterId)
|
||||
{
|
||||
// Feel the bed fun :freaky:
|
||||
case "bf":
|
||||
if (atlas.sprite.anim.curFrame > 87 && atlas.sprite.anim.curFrame % 5 == 0) HapticUtil.vibrate(0, 10, Constants.MAX_VIBRATION_AMPLITUDE);
|
||||
|
||||
// GF slams into the wall.
|
||||
if (atlas.sprite.anim.curFrame == 51) HapticUtil.vibrate(0, 10, Std.int(Constants.MAX_VIBRATION_AMPLITUDE / 3));
|
||||
|
||||
// Pico drop-kicking Nene.
|
||||
case "pico":
|
||||
if (atlas.sprite.anim.curFrame == 52) HapticUtil.vibrate(Constants.DEFAULT_VIBRATION_PERIOD, Constants.DEFAULT_VIBRATION_DURATION * 5,
|
||||
Constants.MAX_VIBRATION_AMPLITUDE);
|
||||
|
||||
default:
|
||||
// nothing.
|
||||
}
|
||||
}
|
||||
|
||||
case ScoringRank.GREAT | ScoringRank.EXCELLENT:
|
||||
for (atlas in characterAtlasAnimations)
|
||||
{
|
||||
switch (playerCharacterId)
|
||||
{
|
||||
// Pico explodes the targets with a rocket launcher.
|
||||
case "pico":
|
||||
if (atlas.sprite.anim.curFrame == 45) HapticUtil.vibrate(0, 10, Std.int(Constants.MAX_VIBRATION_AMPLITUDE / 3));
|
||||
|
||||
if (atlas.sprite.anim.curFrame == 50) HapticUtil.vibrate(Constants.DEFAULT_VIBRATION_PERIOD, Constants.DEFAULT_VIBRATION_DURATION,
|
||||
Constants.MAX_VIBRATION_AMPLITUDE);
|
||||
|
||||
default:
|
||||
// nothing.
|
||||
}
|
||||
}
|
||||
|
||||
case ScoringRank.GOOD:
|
||||
for (atlas in characterAtlasAnimations)
|
||||
{
|
||||
switch (playerCharacterId)
|
||||
{
|
||||
// Pico shooting the targets.
|
||||
case "pico":
|
||||
final frames:Null<Array<Array<Int>>> = [[40, 50], [80, 90], [140, 157]];
|
||||
|
||||
for (i in 0...frames.length)
|
||||
{
|
||||
if (atlas.sprite.anim.curFrame >= frames[i][0]
|
||||
&& atlas.sprite.anim.curFrame <= frames[i][1]
|
||||
&& atlas.sprite.anim.curFrame % 2 == 0) HapticUtil.vibrate(0, 10, Constants.MAX_VIBRATION_AMPLITUDE);
|
||||
}
|
||||
|
||||
default:
|
||||
// nothing.
|
||||
}
|
||||
}
|
||||
|
||||
case ScoringRank.SHIT:
|
||||
for (atlas in characterAtlasAnimations)
|
||||
{
|
||||
switch (playerCharacterId)
|
||||
{
|
||||
// BF falling and GF slams on BF with her ass.
|
||||
case "bf":
|
||||
if (atlas.sprite.anim.curFrame == 5 || atlas.sprite.anim.curFrame == 90) HapticUtil.vibrate(Constants.DEFAULT_VIBRATION_PERIOD * 2,
|
||||
Constants.DEFAULT_VIBRATION_DURATION * 2, Constants.MAX_VIBRATION_AMPLITUDE);
|
||||
|
||||
default:
|
||||
// nothing.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#end
|
||||
|
||||
override function update(elapsed:Float):Void
|
||||
{
|
||||
// maskShaderSongName.swagSprX = songName.x;
|
||||
@@ -921,6 +1005,10 @@ class ResultState extends MusicBeatSubState
|
||||
}
|
||||
}
|
||||
|
||||
#if HAPTIC_VIBRATIONS
|
||||
handleAnimationVibrations();
|
||||
#end
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -663,6 +663,9 @@ class Save
|
||||
|
||||
public function hasBeatenLevel(levelId:String, ?difficultyList:Array<String>):Bool
|
||||
{
|
||||
// need it for testing (REMOVE IT ON RELEASE)
|
||||
return true;
|
||||
|
||||
if (difficultyList == null)
|
||||
{
|
||||
difficultyList = ['easy', 'normal', 'hard'];
|
||||
|
||||
@@ -948,7 +948,7 @@ class FreeplayState extends MusicBeatSubState
|
||||
capsuleToRank.ranking.visible = false;
|
||||
capsuleToRank.fakeRanking.visible = false;
|
||||
|
||||
#if mobile
|
||||
#if HAPTIC_VIBRATIONS
|
||||
HapticUtil.increasingVibrate(Constants.MIN_VIBRATION_AMPLITUDE, Constants.MAX_VIBRATION_AMPLITUDE, 0.6);
|
||||
#end
|
||||
|
||||
@@ -1064,7 +1064,7 @@ class FreeplayState extends MusicBeatSubState
|
||||
|
||||
FlxTween.tween(capsuleToRank, {"targetPos.x": originalPos.x, "targetPos.y": originalPos.y}, 0.5, {ease: FlxEase.expoOut});
|
||||
new FlxTimer().start(0.5, _ -> {
|
||||
#if mobile
|
||||
#if HAPTIC_VIBRATIONS
|
||||
HapticUtil.vibrate(Constants.DEFAULT_VIBRATION_PERIOD, Constants.DEFAULT_VIBRATION_DURATION, Constants.MAX_VIBRATION_AMPLITUDE);
|
||||
#end
|
||||
|
||||
@@ -1340,6 +1340,10 @@ class FreeplayState extends MusicBeatSubState
|
||||
|
||||
var hintTimer:Float = 0;
|
||||
|
||||
#if HAPTIC_VIBRATIONS
|
||||
var allowPicoBulletsVibration:Bool = false;
|
||||
#end
|
||||
|
||||
override function update(elapsed:Float):Void
|
||||
{
|
||||
super.update(elapsed);
|
||||
@@ -1481,6 +1485,11 @@ class FreeplayState extends MusicBeatSubState
|
||||
handleInputs(elapsed);
|
||||
|
||||
if (dj != null) FlxG.watch.addQuick('dj-anim', dj.getCurrentAnimation());
|
||||
|
||||
#if HAPTIC_VIBRATIONS
|
||||
// If the allowPicoBulletsVibration is true, trigger vibration each update (for pico shooting bullets animation).
|
||||
if (allowPicoBulletsVibration) HapticUtil.vibrate(0, 10, Std.int(Constants.MAX_VIBRATION_AMPLITUDE / 3));
|
||||
#end
|
||||
}
|
||||
|
||||
var _sub:Float = 0;
|
||||
@@ -2101,6 +2110,25 @@ class FreeplayState extends MusicBeatSubState
|
||||
|
||||
backingCard?.confirm();
|
||||
|
||||
#if HAPTIC_VIBRATIONS
|
||||
// Start vibration after half of second.
|
||||
new FlxTimer().start(0.5, function(tmr) {
|
||||
switch (currentCharacterId)
|
||||
{
|
||||
// Toggles the bool that allows vibration on update.
|
||||
case "pico":
|
||||
allowPicoBulletsVibration = true;
|
||||
new FlxTimer().start(0.5, function(tmr) {
|
||||
allowPicoBulletsVibration = false;
|
||||
});
|
||||
|
||||
// A single vibration.
|
||||
default:
|
||||
HapticUtil.vibrate(Constants.DEFAULT_VIBRATION_PERIOD, Constants.DEFAULT_VIBRATION_DURATION * 5, Std.int(Constants.MAX_VIBRATION_AMPLITUDE / 3));
|
||||
}
|
||||
});
|
||||
#end
|
||||
|
||||
new FlxTimer().start(styleData?.getStartDelay(), function(tmr:FlxTimer) {
|
||||
FunkinSound.emptyPartialQueue();
|
||||
|
||||
@@ -2205,6 +2233,11 @@ class FreeplayState extends MusicBeatSubState
|
||||
|
||||
// switchBackingImage(daSongCapsule.freeplayData);
|
||||
}
|
||||
|
||||
#if HAPTIC_VIBRATIONS
|
||||
// Small vibrations every selection change.
|
||||
HapticUtil.vibrate(0, 10, 10);
|
||||
#end
|
||||
}
|
||||
|
||||
public function playCurSongPreview(?daSongCapsule:SongMenuItem):Void
|
||||
|
||||
@@ -374,8 +374,8 @@ class TitleState extends MusicBeatState
|
||||
{
|
||||
if (credGroup == null || textGroup == null) return;
|
||||
|
||||
#if mobile
|
||||
HapticUtil.vibrate(Constants.DEFAULT_VIBRATION_PERIOD, Constants.DEFAULT_VIBRATION_DURATION);
|
||||
#if HAPTIC_VIBRATIONS
|
||||
HapticUtil.vibrate();
|
||||
#end
|
||||
|
||||
var coolText:AtlasText = new AtlasText(0, 0, text.trim(), AtlasFont.BOLD);
|
||||
|
||||
@@ -602,26 +602,24 @@ class Constants
|
||||
public static var GLOBAL_FREEPLAY_VICTORY_COUNTER:Int = 0;
|
||||
#end
|
||||
|
||||
#if mobile
|
||||
/**
|
||||
* Default period value for vibration.
|
||||
*/
|
||||
public static final DEFAULT_VIBRATION_PERIOD:Int = 100;
|
||||
public inline static final DEFAULT_VIBRATION_PERIOD:Int = 100;
|
||||
|
||||
/**
|
||||
* Default duration value for vibration.
|
||||
*/
|
||||
public static final DEFAULT_VIBRATION_DURATION:Int = 100;
|
||||
public inline static final DEFAULT_VIBRATION_DURATION:Int = 100;
|
||||
|
||||
/**
|
||||
* Min vibration amplitude.
|
||||
* If vibration's amplitude is less than 1 it will do nothing.
|
||||
*/
|
||||
public static final MIN_VIBRATION_AMPLITUDE:Int = 1;
|
||||
public inline static final MIN_VIBRATION_AMPLITUDE:Int = 1;
|
||||
|
||||
/**
|
||||
* Max vibration amplitude.
|
||||
*/
|
||||
public static final MAX_VIBRATION_AMPLITUDE:Int = 255;
|
||||
#end
|
||||
public inline static final MAX_VIBRATION_AMPLITUDE:Int = 255;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user