Funkin/source/Note.hx

413 lines
10 KiB
Haxe
Raw Normal View History

2020-10-03 02:50:15 -04:00
package;
import flixel.FlxSprite;
2020-10-04 02:42:58 -04:00
import flixel.graphics.frames.FlxAtlasFrames;
2021-01-25 04:18:44 -05:00
import flixel.math.FlxMath;
2020-10-03 02:50:15 -04:00
import flixel.util.FlxColor;
import flixel.util.FlxTimer;
import shaderslmfao.ColorSwap;
2021-03-30 18:10:15 -04:00
import ui.PreferencesMenu;
2021-03-20 01:03:42 -04:00
using StringTools;
#if polymod
2021-01-25 04:18:44 -05:00
import polymod.format.ParseRules.TargetSignatureElement;
#end
2020-10-03 02:50:15 -04:00
class Note extends FlxSprite
{
2022-02-09 20:31:36 -05:00
public var data = new NoteData();
2020-10-03 02:50:15 -04:00
/**
* code colors for.... code....
* i think goes in order of left to right
*
* left 0
* down 1
* up 2
* right 3
*/
public static var codeColors:Array<Int> = [0xFFFF22AA, 0xFF00EEFF, 0xFF00CC00, 0xFFCC1111];
2020-10-03 02:50:15 -04:00
public var mustPress:Bool = false;
2021-12-06 22:35:14 -05:00
public var followsTime:Bool = true; // used if you want the note to follow the time shit!
2020-10-03 13:36:39 -04:00
public var canBeHit:Bool = false;
public var tooLate:Bool = false;
public var wasGoodHit:Bool = false;
public var prevNote:Note;
2021-04-10 18:23:56 -04:00
private var willMiss:Bool = false;
2020-10-03 02:50:15 -04:00
2021-04-10 18:23:56 -04:00
public var invisNote:Bool = false;
2020-10-19 21:59:00 -04:00
public var isSustainNote:Bool = false;
2020-10-18 20:59:53 -04:00
2021-03-21 14:45:46 -04:00
public var colorSwap:ColorSwap;
2022-02-09 20:31:36 -05:00
/** the lowercase name of the note, for anim control, i.e. left right up down */
public var dirName(get, never):String;
inline function get_dirName() return data.dirName;
/** the uppercase name of the note, for anim control, i.e. left right up down */
public var dirNameUpper(get, never):String;
inline function get_dirNameUpper() return data.dirNameUpper;
/** the lowercase name of the note's color, for anim control, i.e. purple blue green red */
public var colorName(get, never):String;
inline function get_colorName() return data.colorName;
/** the lowercase name of the note's color, for anim control, i.e. purple blue green red */
public var colorNameUpper(get, never):String;
inline function get_colorNameUpper() return data.colorNameUpper;
public var highStakes(get, never):Bool;
inline function get_highStakes() return data.highStakes;
public var lowStakes(get, never):Bool;
inline function get_lowStakes() return data.lowStakes;
2020-10-04 04:38:21 -04:00
public static var swagWidth:Float = 160 * 0.7;
2020-10-13 22:12:31 -04:00
public static var PURP_NOTE:Int = 0;
public static var GREEN_NOTE:Int = 2;
public static var BLUE_NOTE:Int = 1;
public static var RED_NOTE:Int = 3;
2020-10-04 04:38:21 -04:00
// SCORING STUFF
public static var safeFrames:Int = 10;
public static var HIT_WINDOW:Float = (safeFrames / 60) * 1000; // 166.67 ms hit window
// anything above bad threshold is shit
public static var BAD_THRESHOLD:Float = 0.8; // 125ms , 8 frames
public static var GOOD_THRESHOLD:Float = 0.55; // 91.67ms , 5.5 frames
public static var SICK_THRESHOLD:Float = 0.2; // 33.33ms , 2 frames
public var noteSpeedMulti:Float = 1;
public var pastHalfWay:Bool = false;
// anything below sick threshold is sick
2021-03-21 14:45:46 -04:00
public static var arrowColors:Array<Float> = [1, 1, 1, 1];
2022-02-09 20:31:36 -05:00
public function new(strumTime:Float = 0, noteData:NoteType, ?prevNote:Note, ?sustainNote:Bool = false)
2020-10-03 02:50:15 -04:00
{
super();
2020-10-06 21:56:14 -04:00
if (prevNote == null)
prevNote = this;
2020-10-05 01:13:12 -04:00
this.prevNote = prevNote;
2020-10-19 21:59:00 -04:00
isSustainNote = sustainNote;
2020-10-05 01:13:12 -04:00
2020-10-04 04:38:21 -04:00
x += 50;
2020-11-10 21:07:56 -05:00
// MAKE SURE ITS DEFINITELY OFF SCREEN?
y -= 2000;
2022-01-22 16:53:38 -05:00
data.strumTime = strumTime;
2020-10-03 13:36:39 -04:00
data.noteData = noteData;
2020-10-03 02:50:15 -04:00
2021-01-25 04:18:44 -05:00
var daStage:String = PlayState.curStage;
2020-10-04 02:42:58 -04:00
2021-01-25 04:18:44 -05:00
switch (daStage)
{
2021-02-13 17:39:31 -05:00
case 'school' | 'schoolEvil':
2021-02-08 16:34:48 -05:00
loadGraphic(Paths.image('weeb/pixelUI/arrows-pixels'), true, 17, 17);
2021-02-02 00:48:22 -05:00
animation.add('greenScroll', [6]);
animation.add('redScroll', [7]);
animation.add('blueScroll', [5]);
animation.add('purpleScroll', [4]);
if (isSustainNote)
{
2021-02-08 16:34:48 -05:00
loadGraphic(Paths.image('weeb/pixelUI/arrowEnds'), true, 7, 6);
2021-02-02 00:48:22 -05:00
animation.add('purpleholdend', [4]);
animation.add('greenholdend', [6]);
animation.add('redholdend', [7]);
animation.add('blueholdend', [5]);
animation.add('purplehold', [0]);
animation.add('greenhold', [2]);
animation.add('redhold', [3]);
animation.add('bluehold', [1]);
}
setGraphicSize(Std.int(width * PlayState.daPixelZoom));
updateHitbox();
2021-01-25 04:18:44 -05:00
default:
2021-02-08 16:34:48 -05:00
frames = Paths.getSparrowAtlas('NOTE_assets');
2020-10-05 01:13:12 -04:00
2021-03-20 01:03:42 -04:00
animation.addByPrefix('greenScroll', 'green instance');
animation.addByPrefix('redScroll', 'red instance');
animation.addByPrefix('blueScroll', 'blue instance');
animation.addByPrefix('purpleScroll', 'purple instance');
2020-10-05 01:13:12 -04:00
2021-01-25 04:18:44 -05:00
animation.addByPrefix('purpleholdend', 'pruple end hold');
animation.addByPrefix('greenholdend', 'green hold end');
animation.addByPrefix('redholdend', 'red hold end');
animation.addByPrefix('blueholdend', 'blue hold end');
animation.addByPrefix('purplehold', 'purple hold piece');
animation.addByPrefix('greenhold', 'green hold piece');
animation.addByPrefix('redhold', 'red hold piece');
animation.addByPrefix('bluehold', 'blue hold piece');
setGraphicSize(Std.int(width * 0.7));
updateHitbox();
antialiasing = true;
// colorSwap.colorToReplace = 0xFFF9393F;
// colorSwap.newColor = 0xFF00FF00;
// color = FlxG.random.color();
// color.saturation *= 4;
// replaceColor(0xFFC1C1C1, FlxColor.RED);
2021-01-25 04:18:44 -05:00
}
2020-10-03 02:50:15 -04:00
2021-03-21 14:45:46 -04:00
colorSwap = new ColorSwap();
shader = colorSwap.shader;
updateColors();
2021-03-21 14:45:46 -04:00
2022-02-09 20:31:36 -05:00
x += swagWidth * data.int;
animation.play(data.colorName + 'Scroll');
2020-10-03 02:50:15 -04:00
2020-10-24 05:36:50 -04:00
// trace(prevNote);
2020-10-05 01:13:12 -04:00
2020-10-19 21:59:00 -04:00
if (isSustainNote && prevNote != null)
2020-10-03 15:32:15 -04:00
{
2020-10-03 02:50:15 -04:00
alpha = 0.6;
2020-10-05 01:13:12 -04:00
2021-03-30 18:10:15 -04:00
if (PreferencesMenu.getPref('downscroll'))
angle = 180;
2020-10-05 01:13:12 -04:00
x += width / 2;
2022-02-09 20:31:36 -05:00
animation.play(data.colorName + 'holdend');
2020-10-05 01:13:12 -04:00
updateHitbox();
x -= width / 2;
2021-02-02 00:48:22 -05:00
if (PlayState.curStage.startsWith('school'))
2021-02-01 05:52:10 -05:00
x += 30;
2020-10-19 21:59:00 -04:00
if (prevNote.isSustainNote)
2020-10-05 01:13:12 -04:00
{
2022-02-09 20:31:36 -05:00
prevNote.animation.play(prevNote.colorName + 'hold');
2021-02-13 17:39:31 -05:00
prevNote.updateHitbox();
var scaleThing:Float = Math.round((Conductor.stepCrochet) * (0.45 * FlxMath.roundDecimal(SongLoad.getSpeed(), 2)));
// get them a LIL closer together cuz the antialiasing blurs the edges
if (antialiasing)
scaleThing *= 1.0 + (1.0 / prevNote.frameHeight);
prevNote.scale.y = scaleThing / prevNote.frameHeight;
prevNote.updateHitbox();
2020-10-05 01:13:12 -04:00
}
2020-10-03 15:32:15 -04:00
}
2020-10-03 02:50:15 -04:00
}
2020-10-03 13:36:39 -04:00
2021-06-07 21:14:50 -04:00
override function destroy()
{
prevNote = null;
super.destroy();
}
2021-03-21 14:45:46 -04:00
public function updateColors():Void
{
colorSwap.update(arrowColors[data.noteData]);
2021-03-21 14:45:46 -04:00
}
2020-10-03 13:36:39 -04:00
override function update(elapsed:Float)
{
super.update(elapsed);
if (mustPress)
{
// miss on the NEXT frame so lag doesnt make u miss notes
2021-04-08 07:33:36 -04:00
if (willMiss && !wasGoodHit)
{
2020-10-03 13:36:39 -04:00
tooLate = true;
canBeHit = false;
}
else
{
2022-01-22 16:53:38 -05:00
if (!pastHalfWay && data.strumTime <= Conductor.songPosition)
{
pastHalfWay = true;
noteSpeedMulti *= 2;
}
2022-01-22 16:53:38 -05:00
if (data.strumTime > Conductor.songPosition - HIT_WINDOW)
2021-12-05 18:51:31 -05:00
{ // * 0.5 if sustain note, so u have to keep holding it closer to all the way thru!
2022-01-22 16:53:38 -05:00
if (data.strumTime < Conductor.songPosition + (HIT_WINDOW * (isSustainNote ? 0.5 : 1)))
canBeHit = true;
}
2021-04-10 18:23:56 -04:00
else
{
canBeHit = true;
willMiss = true;
}
}
2020-10-03 13:36:39 -04:00
}
else
2020-10-04 02:42:58 -04:00
{
2020-10-03 13:36:39 -04:00
canBeHit = false;
2022-01-22 16:53:38 -05:00
if (data.strumTime <= Conductor.songPosition)
2020-10-04 02:42:58 -04:00
wasGoodHit = true;
}
if (tooLate)
{
if (alpha > 0.3)
alpha = 0.3;
}
2020-10-03 13:36:39 -04:00
}
2022-02-09 20:31:36 -05:00
static public function fromData(data:NoteData, prevNote:Note, isSustainNote = false)
{
return new Note(data.strumTime, data.noteData, prevNote, isSustainNote);
}
2020-10-03 02:50:15 -04:00
}
2022-01-22 16:53:38 -05:00
2022-02-09 20:31:36 -05:00
typedef RawNoteData =
2022-01-22 16:53:38 -05:00
{
var strumTime:Float;
2022-02-09 20:31:36 -05:00
var noteData:NoteType;
2022-01-22 16:53:38 -05:00
var sustainLength:Float;
var altNote:Bool;
}
2022-02-09 20:31:36 -05:00
@:forward
abstract NoteData(RawNoteData)
{
public function new (strumTime = 0.0, noteData:NoteType = 0, sustainLength = 0.0, altNote = false)
{
this =
{ strumTime : strumTime
, noteData : noteData
, sustainLength : sustainLength
, altNote : altNote
}
}
public var note(get, never):NoteType;
inline function get_note() return this.noteData.value;
public var int(get, never):Int;
inline function get_int() return this.noteData.int;
public var dir(get, never):NoteDir;
inline function get_dir() return this.noteData.value;
public var dirName(get, never):String;
inline function get_dirName() return dir.name;
public var dirNameUpper(get, never):String;
inline function get_dirNameUpper() return dir.nameUpper;
public var color(get, never):NoteColor;
inline function get_color() return this.noteData.value;
public var colorName(get, never):String;
inline function get_colorName() return color.name;
public var colorNameUpper(get, never):String;
inline function get_colorNameUpper() return color.nameUpper;
public var highStakes(get, never):Bool;
inline function get_highStakes() return this.noteData.highStakes;
public var lowStakes(get, never):Bool;
inline function get_lowStakes() return this.noteData.lowStakes;
}
enum abstract NoteType(Int) from Int to Int
{
// public var raw(get, never):Int;
// inline function get_raw() return this;
public var int(get, never):Int;
inline function get_int() return this < 0 ? -this : this % 4;
public var value(get, never):NoteType;
inline function get_value() return int;
public var highStakes(get, never):Bool;
inline function get_highStakes() return this > 3;
public var lowStakes(get, never):Bool;
inline function get_lowStakes() return this < 0;
}
@:forward
enum abstract NoteDir(NoteType) from Int to Int from NoteType
{
var LEFT = 0;
var DOWN = 1;
var UP = 2;
var RIGHT = 3;
var value(get, never):NoteDir;
inline function get_value() return this.value;
public var name(get, never):String;
function get_name()
{
return switch(value)
{
case LEFT : "left" ;
case DOWN : "down" ;
case UP : "up" ;
case RIGHT: "right";
}
}
public var nameUpper(get, never):String;
function get_nameUpper()
{
return switch(value)
{
case LEFT : "LEFT" ;
case DOWN : "DOWN" ;
case UP : "UP" ;
case RIGHT: "RIGHT";
}
}
}
@:forward
enum abstract NoteColor(NoteType) from Int to Int from NoteType
{
var PURPLE = 0;
var BLUE = 1;
var GREEN = 2;
var RED = 3;
var value(get, never):NoteColor;
inline function get_value() return this.value;
public var name(get, never):String;
function get_name()
{
return switch(value)
{
case PURPLE: "purple";
case BLUE : "blue" ;
case GREEN : "green" ;
case RED : "red" ;
}
}
public var nameUpper(get, never):String;
function get_nameUpper()
{
return switch(value)
{
case PURPLE: "PURPLE";
case BLUE : "BLUE" ;
case GREEN : "GREEN" ;
case RED : "RED" ;
}
}
}