267 lines
6.3 KiB
Haxe
267 lines
6.3 KiB
Haxe
package funkin.game;
|
|
|
|
import flixel.FlxSprite;
|
|
import flixel.graphics.frames.FlxAtlasFrames;
|
|
import flixel.math.FlxMath;
|
|
import flixel.util.FlxColor;
|
|
import flixel.math.FlxRect;
|
|
import flixel.math.FlxPoint;
|
|
import funkin.system.Conductor;
|
|
#if polymod
|
|
import polymod.format.ParseRules.TargetSignatureElement;
|
|
#end
|
|
|
|
using StringTools;
|
|
|
|
class Note extends FlxSprite
|
|
{
|
|
public var strumTime:Float = 0;
|
|
|
|
public var mustPress:Bool = false;
|
|
public var noteData:Int = 0;
|
|
public var canBeHit:Bool = false;
|
|
public var tooLate:Bool = false;
|
|
public var wasGoodHit:Bool = false;
|
|
public var prevNote:Note;
|
|
|
|
public var strumID(get, never):Int;
|
|
private function get_strumID() {
|
|
var id = noteData % 4;
|
|
if (id < 0) id = 0;
|
|
return id;
|
|
}
|
|
|
|
public var sustainLength:Float = 0;
|
|
public var isSustainNote:Bool = false;
|
|
|
|
public var noteScore:Float = 1;
|
|
public var noteTypeID:Int = 0;
|
|
|
|
public var noteType(get, null):String;
|
|
private function get_noteType() {
|
|
return PlayState.instance.getNoteType(noteTypeID);
|
|
}
|
|
|
|
public static var swagWidth:Float = 160 * 0.7;
|
|
|
|
public function new(strumTime:Float, noteData:Int, noteType:Int = 0, mustPress:Bool = true, ?prevNote:Note, ?sustainNote:Bool = false)
|
|
{
|
|
super();
|
|
|
|
if (prevNote == null)
|
|
prevNote = this;
|
|
|
|
this.prevNote = prevNote;
|
|
this.mustPress = mustPress;
|
|
this.noteTypeID = noteType;
|
|
isSustainNote = sustainNote;
|
|
|
|
x += 50;
|
|
// MAKE SURE ITS DEFINITELY OFF SCREEN?
|
|
y -= 2000;
|
|
this.strumTime = strumTime;
|
|
|
|
this.noteData = noteData;
|
|
|
|
var daStage:String = PlayState.instance == null ? "stage" : PlayState.instance.curStage;
|
|
|
|
switch (daStage)
|
|
{
|
|
case 'school' | 'schoolEvil':
|
|
loadGraphic(Paths.image('weeb/pixelUI/arrows-pixels'), true, 17, 17);
|
|
|
|
animation.add('greenScroll', [6]);
|
|
animation.add('redScroll', [7]);
|
|
animation.add('blueScroll', [5]);
|
|
animation.add('purpleScroll', [4]);
|
|
|
|
if (isSustainNote)
|
|
{
|
|
loadGraphic(Paths.image('weeb/pixelUI/arrowEnds'), true, 7, 6);
|
|
|
|
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();
|
|
|
|
default:
|
|
frames = Paths.getSparrowAtlas('NOTE_assets');
|
|
|
|
animation.addByPrefix('greenScroll', 'green0');
|
|
animation.addByPrefix('redScroll', 'red0');
|
|
animation.addByPrefix('blueScroll', 'blue0');
|
|
animation.addByPrefix('purpleScroll', 'purple0');
|
|
|
|
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;
|
|
}
|
|
|
|
switch (noteData)
|
|
{
|
|
case 0:
|
|
x += swagWidth * 0;
|
|
animation.play('purpleScroll');
|
|
case 1:
|
|
x += swagWidth * 1;
|
|
animation.play('blueScroll');
|
|
case 2:
|
|
x += swagWidth * 2;
|
|
animation.play('greenScroll');
|
|
case 3:
|
|
x += swagWidth * 3;
|
|
animation.play('redScroll');
|
|
}
|
|
|
|
// trace(prevNote);
|
|
|
|
if (isSustainNote && prevNote != null)
|
|
{
|
|
noteScore * 0.2;
|
|
alpha = 0.6;
|
|
|
|
x += width / 2;
|
|
|
|
switch (noteData)
|
|
{
|
|
case 2:
|
|
animation.play('greenholdend');
|
|
case 3:
|
|
animation.play('redholdend');
|
|
case 1:
|
|
animation.play('blueholdend');
|
|
case 0:
|
|
animation.play('purpleholdend');
|
|
}
|
|
|
|
updateHitbox();
|
|
|
|
x -= width / 2;
|
|
|
|
if (daStage.startsWith('school'))
|
|
x += 30;
|
|
|
|
if (prevNote.isSustainNote)
|
|
{
|
|
switch (prevNote.noteData)
|
|
{
|
|
case 0:
|
|
prevNote.animation.play('purplehold');
|
|
case 1:
|
|
prevNote.animation.play('bluehold');
|
|
case 2:
|
|
prevNote.animation.play('greenhold');
|
|
case 3:
|
|
prevNote.animation.play('redhold');
|
|
}
|
|
|
|
prevNote.scale.y *= Conductor.stepCrochet / 100 * 1.5 * PlayState.instance.scrollSpeed;
|
|
prevNote.updateHitbox();
|
|
// prevNote.setGraphicSize();
|
|
}
|
|
}
|
|
}
|
|
|
|
public var angleOffsets:Bool = true;
|
|
|
|
override function draw() {
|
|
if (angleOffsets) {
|
|
// get default values
|
|
var oldOffset = FlxPoint.get(offset.x, offset.y);
|
|
|
|
// get offset pos without origin
|
|
var pos = FlxPoint.get(-offset.x + origin.x, -offset.y + origin.y);
|
|
|
|
// updates sin and cos values for angle
|
|
updateTrig();
|
|
|
|
// var sin = _sinAngle * _sinAngle * (_sinAngle > 0 ? 1 : -1);
|
|
// var cos = _cosAngle * _cosAngle * (_cosAngle > 0 ? 1 : -1);
|
|
var sin = _sinAngle;
|
|
var cos = _cosAngle;
|
|
|
|
var anglePos = FlxPoint.get(
|
|
(-cos * pos.x) + (-sin * pos.y),
|
|
(-sin * pos.x) + (-cos * pos.y));
|
|
|
|
// applies new values
|
|
x -= anglePos.x;
|
|
y -= anglePos.y;
|
|
offset.set((cos * origin.x) + (sin * origin.y), (sin * origin.x) + (cos * origin.y));
|
|
|
|
// draw
|
|
super.draw();
|
|
|
|
// reset values
|
|
offset.set(oldOffset.x, oldOffset.y);
|
|
x += anglePos.x;
|
|
y += anglePos.y;
|
|
|
|
// put flxpoints back in the recycling pool
|
|
oldOffset.put();
|
|
pos.put();
|
|
anglePos.put();
|
|
return;
|
|
}
|
|
super.draw();
|
|
}
|
|
|
|
override function update(elapsed:Float)
|
|
{
|
|
super.update(elapsed);
|
|
|
|
if (mustPress)
|
|
{
|
|
// The * 0.5 is so that it's easier to hit them too late, instead of too early
|
|
if (strumTime > Conductor.songPosition - Conductor.safeZoneOffset
|
|
&& strumTime < Conductor.songPosition + (Conductor.safeZoneOffset * 0.5))
|
|
canBeHit = true;
|
|
else
|
|
canBeHit = false;
|
|
|
|
if (strumTime < Conductor.songPosition - Conductor.safeZoneOffset && !wasGoodHit)
|
|
tooLate = true;
|
|
}
|
|
else
|
|
canBeHit = false;
|
|
|
|
|
|
if (tooLate)
|
|
{
|
|
if (alpha > 0.3)
|
|
alpha = 0.3;
|
|
}
|
|
}
|
|
|
|
public function updateClipRect(strum:Strum) {
|
|
var t = FlxMath.bound((Conductor.songPosition - strumTime) / (height / (0.45 * FlxMath.roundDecimal(strum.getScrollSpeed(), 2))), 0, 1);
|
|
var swagRect = new FlxRect(0, t * frameHeight, frameWidth, frameHeight);
|
|
|
|
setClipRect(swagRect);
|
|
}
|
|
|
|
public function setClipRect(rect:FlxRect) {
|
|
// TODO: Shader ClipRect like in Yoshi Engine for smoother sustains
|
|
this.clipRect = rect;
|
|
}
|
|
}
|