mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2025-04-15 08:25:31 -04:00
Merge branch 'master' of https://github.com/ninjamuffin99/Funkin-secret
This commit is contained in:
commit
38e0e79bc7
42 changed files with 2971 additions and 994 deletions
CHANGELOG.mdProject.xmlREADME.md
source
ABotVis.hxCharacter.hxChartingState.hxConductor.hxControls.hxCoolUtil.hxFreeplayState.hxGameOverState.hxGameOverSubstate.hxHealthIcon.hxInitState.hxLoadingState.hxMain.hxMainMenuState.hxNote.hxNoteSplash.hxPaths.hxPauseSubState.hxPlayState.hxSong.hxSpectogramSprite.hxTitleState.hxVisShit.hxVoicesGroup.hxWiggleEffect.hx
animate
dsp
freeplayStuff
shaderslmfao
ui
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -4,13 +4,27 @@ All notable changes will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
## [UNRELEASED]
|
||||
### Added
|
||||
- Cool waveform stuff for chart editor
|
||||
- Noises in chart editor lol!
|
||||
- 3 AWESOME PICO VS. DARNELL SONGS!!
|
||||
- Character offset editor / spritesheet viewer
|
||||
## Changed
|
||||
- Lerp'd the healthbar
|
||||
- Resetting from game over and "restart song" should be faster
|
||||
- Health gain is different depending on how accurate you hit notes!
|
||||
- slight less health gained on sustain notes
|
||||
- The wave-y effect on Thorns for the school is now a shader, instead of a pre-baked animation!
|
||||
|
||||
## [0.2.8] - 2021-04-18 (note, this one is iffy cuz we slacked wit it lol!)
|
||||
### Added
|
||||
- TANKMAN! 3 NEW SONGS BY KAWAISPRITE (UGH, GUNS, STRESS)! Charting help by MtH!
|
||||
- Monster added into week 2, FINALLY (Charting help by MtH and ChaoticGamer!)
|
||||
- Can now change song difficulty mid-game.
|
||||
- Shows some song info on pause screen.
|
||||
- Cute little icons onto freeplay menu
|
||||
- Offset files for easier modification of characters
|
||||
### Changed
|
||||
- ASSET LOADING OVERHAUL, WAY FASTER LOAD TIMES ON WEB!!! (THANKS TO GEOKURELI WOKE KING)
|
||||
- Made difficulty selector on freeplay menu more apparent
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
<library name="week5" preload="true" />
|
||||
<library name="week6" preload="true" />
|
||||
<library name="week7" preload="true" />
|
||||
<library name="week8" preload="true" />
|
||||
</section>
|
||||
|
||||
<section if="NO_PRELOAD_ALL">
|
||||
|
@ -73,6 +74,7 @@
|
|||
<library name="week5" preload="false" />
|
||||
<library name="week6" preload="false" />
|
||||
<library name="week7" preload="false" />
|
||||
<library name="week8" preload="false" />
|
||||
</section>
|
||||
|
||||
<assets path="assets/songs" library="songs" exclude="*.fla|*.ogg" if="web"/>
|
||||
|
@ -95,6 +97,8 @@
|
|||
<assets path="assets/week6" library="week6" exclude="*.fla|*.mp3" unless="web"/>
|
||||
<assets path="assets/week7" library="week7" exclude="*.fla|*.ogg" if="web"/>
|
||||
<assets path="assets/week7" library="week7" exclude="*.fla|*.mp3" unless="web"/>
|
||||
<assets path="assets/week8" library="week8" exclude="*.fla|*.ogg" if="web"/>
|
||||
<assets path="assets/week8" library="week8" exclude="*.fla|*.mp3" unless="web"/>
|
||||
|
||||
<!-- <assets path='example_mods' rename='mods' embed='false'/> -->
|
||||
|
||||
|
@ -123,7 +127,8 @@
|
|||
<haxelib name="flixel-ui" />
|
||||
<!--haxelib name="newgrounds" unless="switch"/> -->
|
||||
<haxelib name="faxe" if='switch'/>
|
||||
<haxelib name="polymod"/>
|
||||
<haxelib name="polymod" if="cpp"/>
|
||||
|
||||
<!-- <haxelib name="colyseus"/> -->
|
||||
<!-- <haxelib name="colyseus-websocket" /> -->
|
||||
<!-- <haxelib name="newgrounds"/> -->
|
||||
|
|
|
@ -88,3 +88,6 @@ As for Mac, 'lime test mac -debug' should work, if not the internet surely has a
|
|||
### Additional guides
|
||||
|
||||
- [Command line basics](https://ninjamuffin99.newgrounds.com/news/post/1090480)
|
||||
|
||||
|
||||
Commits are generally signed and verified, as of September 8th, 2021! Using GPG!
|
||||
|
|
162
source/ABotVis.hx
Normal file
162
source/ABotVis.hx
Normal file
|
@ -0,0 +1,162 @@
|
|||
import dsp.FFT;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.addons.plugin.taskManager.FlxTask;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.system.FlxSound;
|
||||
import ui.PreferencesMenu.CheckboxThingie;
|
||||
|
||||
using Lambda;
|
||||
|
||||
class ABotVis extends FlxTypedSpriteGroup<FlxSprite>
|
||||
{
|
||||
public var vis:VisShit;
|
||||
|
||||
var volumes:Array<Float> = [];
|
||||
|
||||
public function new(snd:FlxSound)
|
||||
{
|
||||
super();
|
||||
|
||||
vis = new VisShit(snd);
|
||||
// vis.snd = snd;
|
||||
|
||||
var visFrms:FlxAtlasFrames = Paths.getSparrowAtlas('aBotViz');
|
||||
|
||||
for (lol in 1...8)
|
||||
{
|
||||
// pushes initial value
|
||||
volumes.push(0.0);
|
||||
|
||||
var viz:FlxSprite = new FlxSprite(50 * lol, 0);
|
||||
viz.frames = visFrms;
|
||||
add(viz);
|
||||
|
||||
var visStr = 'VIZ';
|
||||
if (lol == 5)
|
||||
visStr = 'viz'; // lol makes it lowercase, accomodates for art that I dont wanna rename!
|
||||
|
||||
viz.animation.addByPrefix('VIZ', visStr + lol, 0);
|
||||
viz.animation.play('VIZ', false, false, -1);
|
||||
}
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
// updateViz();
|
||||
|
||||
updateFFT();
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
function updateFFT()
|
||||
{
|
||||
if (vis.snd != null)
|
||||
{
|
||||
vis.checkAndSetBuffer();
|
||||
|
||||
if (vis.setBuffer)
|
||||
{
|
||||
var remappedShit:Int = 0;
|
||||
|
||||
if (vis.snd.playing)
|
||||
remappedShit = Std.int(FlxMath.remapToRange(vis.snd.time, 0, vis.snd.length, 0, vis.numSamples));
|
||||
else
|
||||
remappedShit = Std.int(FlxMath.remapToRange(Conductor.songPosition, 0, vis.snd.length, 0, vis.numSamples));
|
||||
|
||||
var fftSamples:Array<Float> = [];
|
||||
|
||||
var swagBucks = remappedShit;
|
||||
|
||||
for (i in remappedShit...remappedShit + (Std.int((44100 * (1 / 144)))))
|
||||
{
|
||||
var left = vis.audioData[swagBucks] / 32767;
|
||||
var right = vis.audioData[swagBucks + 1] / 32767;
|
||||
|
||||
var balanced = (left + right) / 2;
|
||||
|
||||
swagBucks += 2;
|
||||
|
||||
fftSamples.push(balanced);
|
||||
}
|
||||
|
||||
var freqShit = vis.funnyFFT(fftSamples);
|
||||
|
||||
for (i in 0...group.members.length)
|
||||
{
|
||||
var getSliceShit = function(s:Int)
|
||||
{
|
||||
var powShit = FlxMath.remapToRange(s, 0, group.members.length, 0, CoolUtil.coolBaseLog(10, freqShit[0].length));
|
||||
return Math.round(Math.pow(10, powShit));
|
||||
};
|
||||
|
||||
// var powShit:Float = getSliceShit(i);
|
||||
var hzSliced:Int = getSliceShit(i);
|
||||
|
||||
var sliceLength:Int = Std.int(freqShit[0].length / group.members.length);
|
||||
|
||||
var volSlice = freqShit[0].slice(hzSliced, getSliceShit(i + 1));
|
||||
|
||||
var avgVel:Float = 0;
|
||||
|
||||
for (slice in volSlice)
|
||||
{
|
||||
avgVel += slice;
|
||||
}
|
||||
|
||||
avgVel /= volSlice.length;
|
||||
|
||||
avgVel *= 10000000;
|
||||
|
||||
volumes[i] += avgVel - (FlxG.elapsed * (volumes[i] * 50));
|
||||
|
||||
var animFrame:Int = Std.int(volumes[i]);
|
||||
|
||||
animFrame = Math.floor(Math.min(5, animFrame));
|
||||
animFrame = Math.floor(Math.max(0, animFrame));
|
||||
|
||||
animFrame = Std.int(Math.abs(animFrame - 5)); // shitty dumbass flip, cuz dave got da shit backwards lol!
|
||||
|
||||
group.members[i].animation.curAnim.curFrame = animFrame;
|
||||
if (FlxG.keys.justPressed.U)
|
||||
{
|
||||
trace(avgVel);
|
||||
trace(group.members[i].animation.curAnim.curFrame);
|
||||
}
|
||||
}
|
||||
|
||||
// group.members[0].animation.curAnim.curFrame =
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function updateViz()
|
||||
{
|
||||
if (vis.snd != null)
|
||||
{
|
||||
var remappedShit:Int = 0;
|
||||
vis.checkAndSetBuffer();
|
||||
|
||||
if (vis.setBuffer)
|
||||
{
|
||||
// var startingSample:Int = Std.int(FlxMath.remapToRange)
|
||||
|
||||
if (vis.snd.playing)
|
||||
remappedShit = Std.int(FlxMath.remapToRange(vis.snd.time, 0, vis.snd.length, 0, vis.numSamples));
|
||||
|
||||
for (i in 0...group.members.length)
|
||||
{
|
||||
var sampleApprox:Int = Std.int(FlxMath.remapToRange(i, 0, group.members.length, remappedShit, remappedShit + 500));
|
||||
|
||||
var left = vis.audioData[sampleApprox] / 32767;
|
||||
|
||||
var animFrame:Int = Std.int(FlxMath.remapToRange(left, -1, 1, 0, 6));
|
||||
|
||||
group.members[i].animation.curAnim.curFrame = animFrame;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -217,26 +217,25 @@ class Character extends FlxSprite
|
|||
quickAnimAdd('idle', "Pico Idle Dance");
|
||||
quickAnimAdd('singUP', 'pico Up note0');
|
||||
quickAnimAdd('singDOWN', 'Pico Down Note0');
|
||||
if (isPlayer)
|
||||
{
|
||||
quickAnimAdd('singLEFT', 'Pico NOTE LEFT0');
|
||||
quickAnimAdd('singRIGHT', 'Pico Note Right0');
|
||||
quickAnimAdd('singRIGHTmiss', 'Pico Note Right Miss');
|
||||
quickAnimAdd('singLEFTmiss', 'Pico NOTE LEFT miss');
|
||||
}
|
||||
else
|
||||
{
|
||||
// Need to be flipped! REDO THIS LATER!
|
||||
quickAnimAdd('singLEFT', 'Pico Note Right0');
|
||||
quickAnimAdd('singRIGHT', 'Pico NOTE LEFT0');
|
||||
quickAnimAdd('singRIGHTmiss', 'Pico NOTE LEFT miss');
|
||||
quickAnimAdd('singLEFTmiss', 'Pico Note Right Miss');
|
||||
}
|
||||
|
||||
// isPlayer = true;
|
||||
|
||||
// Need to be flipped! REDO THIS LATER!
|
||||
quickAnimAdd('singLEFT', 'Pico Note Right0');
|
||||
quickAnimAdd('singRIGHT', 'Pico NOTE LEFT0');
|
||||
quickAnimAdd('singRIGHTmiss', 'Pico NOTE LEFT miss');
|
||||
quickAnimAdd('singLEFTmiss', 'Pico Note Right Miss');
|
||||
|
||||
quickAnimAdd('singUPmiss', 'pico Up note miss');
|
||||
quickAnimAdd('singDOWNmiss', 'Pico Down Note MISS');
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
// right now it loads a seperate offset file for pico, would be cool if could generalize it!
|
||||
var playerShit:String = "";
|
||||
|
||||
if (isPlayer)
|
||||
playerShit += "Player";
|
||||
|
||||
loadOffsetFile(curCharacter + playerShit);
|
||||
|
||||
playAnim('idle');
|
||||
|
||||
|
@ -486,6 +485,41 @@ class Character extends FlxSprite
|
|||
playAnim('idle');
|
||||
|
||||
flipX = true;
|
||||
case 'darnell':
|
||||
frames = Paths.getSparrowAtlas('characters/darnell');
|
||||
|
||||
quickAnimAdd('idle', 'Darnell Idle');
|
||||
quickAnimAdd('singUP', "Darnell pose up");
|
||||
quickAnimAdd('singDOWN', 'Darnell Pose Down');
|
||||
quickAnimAdd('singRIGHT', 'darnell pose left');
|
||||
quickAnimAdd('singLEFT', 'Darnell pose right'); // naming is reversed for left/right for darnell!
|
||||
quickAnimAdd('laugh', 'darnell laugh');
|
||||
|
||||
// temp
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('idle');
|
||||
|
||||
animation.finishCallback = function(animShit:String)
|
||||
{
|
||||
if (animShit.startsWith('sing'))
|
||||
{
|
||||
// loop the anim
|
||||
// this way is a little verbose, but basically sets it to the same animation, but 8 frames before finish
|
||||
playAnim(animShit, true, false, animation.getByName(animShit).frames.length - 8);
|
||||
}
|
||||
}
|
||||
case 'nene':
|
||||
// GIRLFRIEND CODE
|
||||
tex = Paths.getSparrowAtlas('characters/Nene_assets');
|
||||
frames = tex;
|
||||
|
||||
animation.addByIndices('danceLeft', 'nenebeforeyougetawoopin', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
|
||||
animation.addByIndices('danceRight', 'nenebeforeyougetawoopin', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('danceRight');
|
||||
}
|
||||
|
||||
dance();
|
||||
|
@ -627,7 +661,7 @@ class Character extends FlxSprite
|
|||
{
|
||||
switch (curCharacter)
|
||||
{
|
||||
case 'gf' | 'gf-christmas' | 'gf-car' | 'gf-pixel' | 'gf-tankmen':
|
||||
case 'gf' | 'gf-christmas' | 'gf-car' | 'gf-pixel' | 'gf-tankmen' | "nene":
|
||||
if (!animation.curAnim.name.startsWith('hair'))
|
||||
{
|
||||
danced = !danced;
|
||||
|
@ -638,10 +672,6 @@ class Character extends FlxSprite
|
|||
playAnim('danceLeft');
|
||||
}
|
||||
|
||||
case 'pico-speaker':
|
||||
// lol weed
|
||||
// playAnim('shoot' + FlxG.random.int(1, 4), true);
|
||||
|
||||
case 'tankman':
|
||||
if (!animation.curAnim.name.endsWith('DOWN-alt'))
|
||||
playAnim('idle');
|
||||
|
|
|
@ -3,7 +3,9 @@ package;
|
|||
import Conductor.BPMChangeEvent;
|
||||
import Section.SwagSection;
|
||||
import Song.SwagSong;
|
||||
import dsp.FFT;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxStrip;
|
||||
import flixel.addons.display.FlxGridOverlay;
|
||||
import flixel.addons.ui.FlxInputText;
|
||||
import flixel.addons.ui.FlxUI9SliceSprite;
|
||||
|
@ -14,6 +16,7 @@ import flixel.addons.ui.FlxUIInputText;
|
|||
import flixel.addons.ui.FlxUINumericStepper;
|
||||
import flixel.addons.ui.FlxUITabMenu;
|
||||
import flixel.addons.ui.FlxUITooltip.FlxUITooltipStyle;
|
||||
import flixel.graphics.tile.FlxDrawTrianglesItem.DrawData;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.group.FlxGroup;
|
||||
import flixel.math.FlxMath;
|
||||
|
@ -23,16 +26,22 @@ import flixel.text.FlxText;
|
|||
import flixel.ui.FlxButton;
|
||||
import flixel.ui.FlxSpriteButton;
|
||||
import flixel.util.FlxColor;
|
||||
import haxe.CallStack.StackItem;
|
||||
import haxe.Json;
|
||||
import lime.media.AudioBuffer;
|
||||
import lime.utils.Assets;
|
||||
import lime.utils.Int16Array;
|
||||
import openfl.events.Event;
|
||||
import openfl.events.IOErrorEvent;
|
||||
import openfl.media.Sound;
|
||||
import openfl.net.FileReference;
|
||||
import openfl.utils.ByteArray;
|
||||
|
||||
using Lambda;
|
||||
using StringTools;
|
||||
using flixel.util.FlxSpriteUtil;
|
||||
|
||||
// add in "compiler save" that saves the JSON directly to the debug json using File.write() stuff on windows / sys
|
||||
class ChartingState extends MusicBeatState
|
||||
{
|
||||
var _file:FileReference;
|
||||
|
@ -75,15 +84,25 @@ class ChartingState extends MusicBeatState
|
|||
|
||||
var tempBpm:Float = 0;
|
||||
|
||||
var vocals:FlxSound;
|
||||
var vocals:VoicesGroup;
|
||||
|
||||
var leftIcon:HealthIcon;
|
||||
var rightIcon:HealthIcon;
|
||||
|
||||
var audioBuf:AudioBuffer = new AudioBuffer();
|
||||
|
||||
var playheadTest:FlxSprite;
|
||||
|
||||
var staticSpecGrp:FlxTypedGroup<SpectogramSprite>;
|
||||
|
||||
override function create()
|
||||
{
|
||||
curSection = lastSection;
|
||||
|
||||
// sys.io.File.saveContent('./bitShit.txt', "swag");
|
||||
|
||||
// trace(audioBuf.sampleRate);
|
||||
|
||||
gridBG = FlxGridOverlay.create(GRID_SIZE, GRID_SIZE, GRID_SIZE * 8, GRID_SIZE * 16);
|
||||
add(gridBG);
|
||||
|
||||
|
@ -119,7 +138,8 @@ class ChartingState extends MusicBeatState
|
|||
player1: 'bf',
|
||||
player2: 'dad',
|
||||
speed: 1,
|
||||
validScore: false
|
||||
validScore: false,
|
||||
voiceList: ["BF", "BF-pixel"]
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -142,7 +162,7 @@ class ChartingState extends MusicBeatState
|
|||
bpmTxt.scrollFactor.set();
|
||||
add(bpmTxt);
|
||||
|
||||
strumLine = new FlxSprite(0, 50).makeGraphic(Std.int(FlxG.width / 2), 4);
|
||||
strumLine = new FlxSprite(0, 50).makeGraphic(Std.int(GRID_SIZE * 8), 4);
|
||||
add(strumLine);
|
||||
|
||||
dummyArrow = new FlxSprite().makeGraphic(GRID_SIZE, GRID_SIZE);
|
||||
|
@ -157,8 +177,8 @@ class ChartingState extends MusicBeatState
|
|||
UI_box = new FlxUITabMenu(null, tabs, true);
|
||||
|
||||
UI_box.resize(300, 400);
|
||||
UI_box.x = FlxG.width / 2;
|
||||
UI_box.y = 20;
|
||||
UI_box.x = (FlxG.width / 4) * 3;
|
||||
UI_box.y = 120;
|
||||
add(UI_box);
|
||||
|
||||
addSongUI();
|
||||
|
@ -203,6 +223,11 @@ class ChartingState extends MusicBeatState
|
|||
saveLevel();
|
||||
});
|
||||
|
||||
var saveCompiler:FlxButton = new FlxButton(110, 30, "Save compile", function()
|
||||
{
|
||||
saveLevel(true);
|
||||
});
|
||||
|
||||
var reloadSong:FlxButton = new FlxButton(saveButton.x + saveButton.width + 10, saveButton.y, "Reload Audio", function()
|
||||
{
|
||||
loadSong(_song.song);
|
||||
|
@ -246,6 +271,7 @@ class ChartingState extends MusicBeatState
|
|||
tab_group_song.add(check_voices);
|
||||
tab_group_song.add(check_mute_inst);
|
||||
tab_group_song.add(saveButton);
|
||||
tab_group_song.add(saveCompiler);
|
||||
tab_group_song.add(reloadSong);
|
||||
tab_group_song.add(reloadSongJson);
|
||||
tab_group_song.add(loadAutosaveBtn);
|
||||
|
@ -257,7 +283,7 @@ class ChartingState extends MusicBeatState
|
|||
UI_box.addGroup(tab_group_song);
|
||||
UI_box.scrollFactor.set();
|
||||
|
||||
FlxG.camera.follow(strumLine);
|
||||
FlxG.camera.focusOn(gridBG.getGraphicMidpoint());
|
||||
}
|
||||
|
||||
var stepperLength:FlxUINumericStepper;
|
||||
|
@ -342,6 +368,8 @@ class ChartingState extends MusicBeatState
|
|||
UI_box.addGroup(tab_group_note);
|
||||
}
|
||||
|
||||
// var spec:SpectogramSprite;
|
||||
|
||||
function loadSong(daSong:String):Void
|
||||
{
|
||||
if (FlxG.sound.music != null)
|
||||
|
@ -369,11 +397,53 @@ class ChartingState extends MusicBeatState
|
|||
|
||||
FlxG.sound.playMusic(Paths.inst(daSong), 0.6);
|
||||
|
||||
var musSpec:SpectogramSprite = new SpectogramSprite(FlxG.sound.music, FlxColor.RED);
|
||||
musSpec.x += 70;
|
||||
musSpec.daHeight = FlxG.height / 2;
|
||||
musSpec.scrollFactor.set();
|
||||
musSpec.visType = FREQUENCIES;
|
||||
add(musSpec);
|
||||
|
||||
// trace(audioBuf.data.length);
|
||||
playheadTest = new FlxSprite(0, 0).makeGraphic(2, 255, FlxColor.RED);
|
||||
playheadTest.scrollFactor.set();
|
||||
add(playheadTest);
|
||||
|
||||
// WONT WORK FOR TUTORIAL OR TEST SONG!!! REDO LATER
|
||||
vocals = new FlxSound().loadEmbedded(Paths.voices(daSong));
|
||||
FlxG.sound.list.add(vocals);
|
||||
vocals = new VoicesGroup(daSong, _song.voiceList);
|
||||
// vocals = new FlxSound().loadEmbedded(Paths.voices(daSong));
|
||||
// FlxG.sound.list.add(vocals);
|
||||
|
||||
staticSpecGrp = new FlxTypedGroup<SpectogramSprite>();
|
||||
add(staticSpecGrp);
|
||||
|
||||
var aBoy:ABotVis = new ABotVis(FlxG.sound.music);
|
||||
add(aBoy);
|
||||
|
||||
for (index => voc in vocals.members)
|
||||
{
|
||||
var vocalSpec:SpectogramSprite = new SpectogramSprite(voc, FlxG.random.color(0xFFAAAAAA, FlxColor.WHITE, 100));
|
||||
vocalSpec.x = 70 - (50 * index);
|
||||
vocalSpec.visType = FREQUENCIES;
|
||||
vocalSpec.daHeight = musSpec.daHeight;
|
||||
vocalSpec.y = vocalSpec.daHeight;
|
||||
vocalSpec.scrollFactor.set();
|
||||
add(vocalSpec);
|
||||
|
||||
var staticVocal:SpectogramSprite = new SpectogramSprite(voc, FlxG.random.color(0xFFAAAAAA, FlxColor.WHITE, 100));
|
||||
if (index == 0)
|
||||
staticVocal.x -= 150;
|
||||
|
||||
if (index == 1)
|
||||
staticVocal.x = gridBG.width;
|
||||
|
||||
staticVocal.daHeight = GRID_SIZE * 16;
|
||||
staticVocal.visType = STATIC;
|
||||
staticSpecGrp.add(staticVocal);
|
||||
}
|
||||
|
||||
FlxG.sound.music.pause();
|
||||
|
||||
vocals.pause();
|
||||
|
||||
FlxG.sound.music.onComplete = function()
|
||||
|
@ -485,15 +555,29 @@ class ChartingState extends MusicBeatState
|
|||
return daPos;
|
||||
}
|
||||
|
||||
var p1Muted:Bool = false;
|
||||
var p2Muted:Bool = false;
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
// FlxG.camera.followLerp = CoolUtil.camLerpShit(0.05);
|
||||
|
||||
curStep = recalculateSteps();
|
||||
|
||||
Conductor.songPosition = FlxG.sound.music.time;
|
||||
_song.song = typingShit.text;
|
||||
|
||||
playheadTest.x = FlxMath.remapToRange(Conductor.songPosition, 0, FlxG.sound.music.length, 0, FlxG.width);
|
||||
|
||||
strumLine.y = getYfromStrum((Conductor.songPosition - sectionStartTime()) % (Conductor.stepCrochet * _song.notes[curSection].lengthInSteps));
|
||||
|
||||
/* if (FlxG.sound.music.playing)
|
||||
{
|
||||
var normalizedShitIDK:Int = Std.int(FlxMath.remapToRange(Conductor.songPosition, 0, FlxG.sound.music.length, 0, audioBuf.data.length));
|
||||
FlxG.watch.addQuick('WEIRD AUDIO SHIT LOL', audioBuf.data[normalizedShitIDK]);
|
||||
// leftIcon.scale.x = FlxMath.remapToRange(audioBuf.data[normalizedShitIDK], 0, 255, 1, 2);
|
||||
}*/
|
||||
|
||||
if (FlxG.keys.justPressed.X)
|
||||
toggleAltAnimNote();
|
||||
|
||||
|
@ -514,35 +598,106 @@ class ChartingState extends MusicBeatState
|
|||
FlxG.watch.addQuick('daBeat', curBeat);
|
||||
FlxG.watch.addQuick('daStep', curStep);
|
||||
|
||||
if (FlxG.mouse.justPressed)
|
||||
if (FlxG.mouse.pressedMiddle)
|
||||
{
|
||||
if (FlxG.mouse.overlaps(curRenderedNotes))
|
||||
if (FlxG.sound.music.playing)
|
||||
{
|
||||
curRenderedNotes.forEach(function(note:Note)
|
||||
FlxG.sound.music.pause();
|
||||
vocals.pause();
|
||||
}
|
||||
|
||||
FlxG.sound.music.time = getStrumTime(FlxG.mouse.y) + sectionStartTime();
|
||||
vocals.time = FlxG.sound.music.time;
|
||||
}
|
||||
|
||||
if (FlxG.mouse.pressed)
|
||||
{
|
||||
if (FlxG.keys.pressed.ALT)
|
||||
{
|
||||
if (FlxG.sound.music.playing)
|
||||
{
|
||||
if (FlxG.mouse.overlaps(note))
|
||||
{
|
||||
if (FlxG.keys.pressed.CONTROL)
|
||||
{
|
||||
selectNote(note);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('tryin to delete note...');
|
||||
deleteNote(note);
|
||||
}
|
||||
}
|
||||
});
|
||||
FlxG.sound.music.pause();
|
||||
vocals.pause();
|
||||
}
|
||||
|
||||
FlxG.sound.music.time = getStrumTime(FlxG.mouse.y) + sectionStartTime();
|
||||
vocals.time = FlxG.sound.music.time;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FlxG.mouse.x > gridBG.x
|
||||
&& FlxG.mouse.x < gridBG.x + gridBG.width
|
||||
&& FlxG.mouse.y > gridBG.y
|
||||
&& FlxG.mouse.y < gridBG.y + (GRID_SIZE * _song.notes[curSection].lengthInSteps))
|
||||
if (FlxG.mouse.justPressed)
|
||||
{
|
||||
FlxG.log.add('added note');
|
||||
addNote();
|
||||
if (FlxG.mouse.overlaps(leftIcon))
|
||||
{
|
||||
if (leftIcon.char == _song.player1)
|
||||
{
|
||||
p1Muted = !p1Muted;
|
||||
leftIcon.animation.curAnim.curFrame = p1Muted ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
p2Muted = !p2Muted;
|
||||
|
||||
leftIcon.animation.curAnim.curFrame = p2Muted ? 1 : 0;
|
||||
}
|
||||
|
||||
vocals.members[0].volume = p1Muted ? 0 : 1;
|
||||
|
||||
// null check jus in case using old shit?
|
||||
if (vocals.members[1] != null)
|
||||
vocals.members[1].volume = p2Muted ? 0 : 1;
|
||||
}
|
||||
|
||||
// sloppy copypaste lol deal with it!
|
||||
if (FlxG.mouse.overlaps(rightIcon))
|
||||
{
|
||||
if (rightIcon.char == _song.player1)
|
||||
{
|
||||
p1Muted = !p1Muted;
|
||||
rightIcon.animation.curAnim.curFrame = p1Muted ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
rightIcon.animation.curAnim.curFrame = p2Muted ? 1 : 0;
|
||||
p2Muted = !p2Muted;
|
||||
}
|
||||
|
||||
vocals.members[0].volume = p1Muted ? 0 : 1;
|
||||
|
||||
// null check jus in case using old shit?
|
||||
if (vocals.members[1] != null)
|
||||
vocals.members[1].volume = p2Muted ? 0 : 1;
|
||||
}
|
||||
|
||||
if (FlxG.mouse.overlaps(curRenderedNotes))
|
||||
{
|
||||
curRenderedNotes.forEach(function(note:Note)
|
||||
{
|
||||
if (FlxG.mouse.overlaps(note))
|
||||
{
|
||||
if (FlxG.keys.pressed.CONTROL)
|
||||
{
|
||||
selectNote(note);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('tryin to delete note...');
|
||||
deleteNote(note);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FlxG.mouse.x > gridBG.x
|
||||
&& FlxG.mouse.x < gridBG.x + gridBG.width
|
||||
&& FlxG.mouse.y > gridBG.y
|
||||
&& FlxG.mouse.y < gridBG.y + (GRID_SIZE * _song.notes[curSection].lengthInSteps))
|
||||
{
|
||||
FlxG.log.add('added note');
|
||||
addNote();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -561,9 +716,15 @@ class ChartingState extends MusicBeatState
|
|||
|
||||
if (FlxG.keys.justPressed.ENTER)
|
||||
{
|
||||
autosaveSong();
|
||||
|
||||
lastSection = curSection;
|
||||
|
||||
PlayState.SONG = _song;
|
||||
|
||||
// JUST FOR DEBUG DARNELL STUFF, GENERALIZE THIS FOR BETTER LOADING ELSEWHERE TOO!
|
||||
PlayState.storyWeek = 8;
|
||||
|
||||
FlxG.sound.music.stop();
|
||||
vocals.stop();
|
||||
LoadingState.loadAndSwitchState(new PlayState());
|
||||
|
@ -624,7 +785,10 @@ class ChartingState extends MusicBeatState
|
|||
FlxG.sound.music.pause();
|
||||
vocals.pause();
|
||||
|
||||
FlxG.sound.music.time -= (FlxG.mouse.wheel * Conductor.stepCrochet * 0.4);
|
||||
var ctrlMod:Float = FlxG.keys.pressed.CONTROL ? 0.1 : 1;
|
||||
var shiftMod:Float = FlxG.keys.pressed.SHIFT ? 2 : 1;
|
||||
|
||||
FlxG.sound.music.time -= (FlxG.mouse.wheel * Conductor.stepCrochet * 0.4 * ctrlMod * shiftMod);
|
||||
vocals.time = FlxG.sound.music.time;
|
||||
}
|
||||
|
||||
|
@ -637,6 +801,9 @@ class ChartingState extends MusicBeatState
|
|||
|
||||
var daTime:Float = 700 * FlxG.elapsed;
|
||||
|
||||
if (FlxG.keys.pressed.CONTROL)
|
||||
daTime *= 0.2;
|
||||
|
||||
if (FlxG.keys.pressed.W)
|
||||
{
|
||||
FlxG.sound.music.time -= daTime;
|
||||
|
@ -683,9 +850,9 @@ class ChartingState extends MusicBeatState
|
|||
if (FlxG.keys.justPressed.LEFT || FlxG.keys.justPressed.A)
|
||||
changeSection(curSection - shiftThing);
|
||||
|
||||
bpmTxt.text = bpmTxt.text = Std.string(FlxMath.roundDecimal(Conductor.songPosition / 1000, 2))
|
||||
bpmTxt.text = bpmTxt.text = Std.string(FlxMath.roundDecimal(Conductor.songPosition / 1000, 3))
|
||||
+ " / "
|
||||
+ Std.string(FlxMath.roundDecimal(FlxG.sound.music.length / 1000, 2))
|
||||
+ Std.string(FlxMath.roundDecimal(FlxG.sound.music.length / 1000, 3))
|
||||
+ "\nSection: "
|
||||
+ curSection;
|
||||
super.update(elapsed);
|
||||
|
@ -830,11 +997,17 @@ class ChartingState extends MusicBeatState
|
|||
{
|
||||
leftIcon.changeIcon(_song.player1);
|
||||
rightIcon.changeIcon(_song.player2);
|
||||
|
||||
leftIcon.animation.curAnim.curFrame = p1Muted ? 1 : 0;
|
||||
rightIcon.animation.curAnim.curFrame = p2Muted ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
leftIcon.changeIcon(_song.player2);
|
||||
rightIcon.changeIcon(_song.player1);
|
||||
|
||||
leftIcon.animation.curAnim.curFrame = p2Muted ? 1 : 0;
|
||||
rightIcon.animation.curAnim.curFrame = p1Muted ? 1 : 0;
|
||||
}
|
||||
leftIcon.setGraphicSize(0, 45);
|
||||
rightIcon.setGraphicSize(0, 45);
|
||||
|
@ -848,6 +1021,16 @@ class ChartingState extends MusicBeatState
|
|||
|
||||
function updateGrid():Void
|
||||
{
|
||||
// null if checks jus cuz i put updateGrid() in some weird places!
|
||||
if (staticSpecGrp != null)
|
||||
{
|
||||
staticSpecGrp.forEach(function(spec)
|
||||
{
|
||||
if (spec != null)
|
||||
spec.generateSection(sectionStartTime(), (Conductor.stepCrochet * 32) / 1000);
|
||||
});
|
||||
}
|
||||
|
||||
while (curRenderedNotes.members.length > 0)
|
||||
{
|
||||
curRenderedNotes.remove(curRenderedNotes.members[0], true);
|
||||
|
@ -952,6 +1135,15 @@ class ChartingState extends MusicBeatState
|
|||
{
|
||||
if (i[0] == note.strumTime && i[1] % 4 == note.noteData)
|
||||
{
|
||||
var placeIDK:Int = Std.int(((Math.floor(dummyArrow.y / GRID_SIZE) * GRID_SIZE)) / 40);
|
||||
|
||||
placeIDK = Std.int(Math.min(placeIDK, 15));
|
||||
placeIDK = Std.int(Math.max(placeIDK, 1));
|
||||
|
||||
trace(placeIDK);
|
||||
|
||||
FlxG.sound.play(Paths.sound('funnyNoise/funnyNoise-0' + placeIDK));
|
||||
|
||||
FlxG.log.add('FOUND EVIL NUMBER');
|
||||
_song.notes[curSection].sectionNotes.remove(i);
|
||||
}
|
||||
|
@ -984,6 +1176,33 @@ class ChartingState extends MusicBeatState
|
|||
var noteSus = 0;
|
||||
var noteAlt = false;
|
||||
|
||||
// FlxG.sound.play(Paths.sound('pianoStuff/piano-00' + FlxG.random.int(1, 9)), FlxG.random.float(0.01, 0.3));
|
||||
|
||||
switch (noteData)
|
||||
{
|
||||
case 0:
|
||||
FlxG.sound.play(Paths.sound('pianoStuff/piano-015'), FlxG.random.float(0.1, 0.3));
|
||||
FlxG.sound.play(Paths.sound('pianoStuff/piano-013'), FlxG.random.float(0.1, 0.3));
|
||||
FlxG.sound.play(Paths.sound('pianoStuff/piano-009'), FlxG.random.float(0.1, 0.3));
|
||||
case 1:
|
||||
FlxG.sound.play(Paths.sound('pianoStuff/piano-015'), FlxG.random.float(0.1, 0.3));
|
||||
FlxG.sound.play(Paths.sound('pianoStuff/piano-012'), FlxG.random.float(0.1, 0.3));
|
||||
FlxG.sound.play(Paths.sound('pianoStuff/piano-009'), FlxG.random.float(0.1, 0.3));
|
||||
case 2:
|
||||
FlxG.sound.play(Paths.sound('pianoStuff/piano-015'), FlxG.random.float(0.1, 0.3));
|
||||
FlxG.sound.play(Paths.sound('pianoStuff/piano-011'), FlxG.random.float(0.1, 0.3));
|
||||
FlxG.sound.play(Paths.sound('pianoStuff/piano-009'), FlxG.random.float(0.1, 0.3));
|
||||
case 3:
|
||||
FlxG.sound.play(Paths.sound('pianoStuff/piano-014'), FlxG.random.float(0.1, 0.3));
|
||||
FlxG.sound.play(Paths.sound('pianoStuff/piano-011'), FlxG.random.float(0.1, 0.3));
|
||||
FlxG.sound.play(Paths.sound('pianoStuff/piano-010'), FlxG.random.float(0.1, 0.3));
|
||||
}
|
||||
|
||||
var bullshit:Int = Std.int((Math.floor(dummyArrow.y / GRID_SIZE) * GRID_SIZE) / 40);
|
||||
|
||||
FlxG.sound.play(Paths.sound('pianoStuff/piano-00' + Std.string((bullshit % 8) + 1)), FlxG.random.float(0.3, 0.6));
|
||||
// trace('bullshit $bullshit'); // trace(Math.floor(dummyArrow.y / GRID_SIZE) * GRID_SIZE);
|
||||
|
||||
_song.notes[curSection].sectionNotes.push([noteStrum, noteData, noteSus, noteAlt]);
|
||||
|
||||
curSelectedNote = _song.notes[curSection].sectionNotes[_song.notes[curSection].sectionNotes.length - 1];
|
||||
|
@ -1074,7 +1293,7 @@ class ChartingState extends MusicBeatState
|
|||
FlxG.save.flush();
|
||||
}
|
||||
|
||||
private function saveLevel()
|
||||
private function saveLevel(?debugSavepath:Bool = false)
|
||||
{
|
||||
var json = {
|
||||
"song": _song
|
||||
|
@ -1082,11 +1301,19 @@ class ChartingState extends MusicBeatState
|
|||
|
||||
var data:String = Json.stringify(json);
|
||||
|
||||
#if hl
|
||||
#if sys
|
||||
// quick workaround, since it easier to load into hashlink, thus quicker/nicer to test?
|
||||
// should get this auto-saved into a file or somethin
|
||||
var filename = _song.song.toLowerCase();
|
||||
sys.io.File.saveContent('./$filename.json', data);
|
||||
|
||||
if (debugSavepath)
|
||||
{
|
||||
// file path to assumingly your assets folder in your SOURCE CODE assets folder!!!
|
||||
// update this later so the save button ONLY appears when you compile in debug mode!
|
||||
sys.io.File.saveContent('../../../../assets/preload/data/$filename/$filename.json', data);
|
||||
}
|
||||
else
|
||||
sys.io.File.saveContent('./$filename.json', data);
|
||||
#else
|
||||
if ((data != null) && (data.length > 0))
|
||||
{
|
||||
|
|
|
@ -23,9 +23,6 @@ class Conductor
|
|||
public static var lastSongPos:Float;
|
||||
public static var offset:Float = 0;
|
||||
|
||||
public static var safeFrames:Int = 10;
|
||||
public static var safeZoneOffset:Float = (safeFrames / 60) * 1000; // is calculated in create(), is safeFrames in milliseconds
|
||||
|
||||
public static var bpmChangeMap:Array<BPMChangeEvent> = [];
|
||||
|
||||
public function new()
|
||||
|
|
|
@ -872,7 +872,7 @@ class FlxActionInputDigitalMobileSwipeGameplay extends FlxActionInputDigital
|
|||
|
||||
public function new(swipeDir:Int = FlxObject.ANY, Trigger:FlxInputState, ?swipeLength:Float = 90)
|
||||
{
|
||||
super(ANDROID, swipeDir, Trigger);
|
||||
super(OTHER, swipeDir, Trigger);
|
||||
|
||||
activateLength = swipeLength;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
package;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxState;
|
||||
import flixel.graphics.FlxGraphic;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.system.FlxAssets.FlxGraphicAsset;
|
||||
import flixel.tweens.FlxEase;
|
||||
import flixel.tweens.FlxTween;
|
||||
import haxe.Json;
|
||||
import haxe.format.JsonParser;
|
||||
import lime.math.Rectangle;
|
||||
import lime.utils.Assets;
|
||||
import openfl.filters.ShaderFilter;
|
||||
import shaderslmfao.ScreenWipeShader;
|
||||
|
||||
using StringTools;
|
||||
|
||||
|
@ -21,6 +28,11 @@ class CoolUtil
|
|||
return difficultyArray[PlayState.storyDifficulty];
|
||||
}
|
||||
|
||||
public static function coolBaseLog(base:Float, fin:Float):Float
|
||||
{
|
||||
return Math.log(fin) / Math.log(base);
|
||||
}
|
||||
|
||||
public static function coolTextFile(path:String):Array<String>
|
||||
{
|
||||
var daList:Array<String> = [];
|
||||
|
@ -88,6 +100,38 @@ class CoolUtil
|
|||
return lerp * (FlxG.elapsed / (1 / 60));
|
||||
}
|
||||
|
||||
public static function coolSwitchState(state:FlxState, transitionTex:String = "shaderTransitionStuff/coolDots", time:Float = 2)
|
||||
{
|
||||
var screenShit:FlxSprite = new FlxSprite().loadGraphic(Paths.image("shaderTransitionStuff/coolDots"));
|
||||
var screenWipeShit:ScreenWipeShader = new ScreenWipeShader();
|
||||
|
||||
screenWipeShit.funnyShit.input = screenShit.pixels;
|
||||
FlxTween.tween(screenWipeShit, {daAlphaShit: 1}, time, {
|
||||
ease: FlxEase.quadInOut,
|
||||
onComplete: function(twn)
|
||||
{
|
||||
screenShit.destroy();
|
||||
FlxG.switchState(new MainMenuState());
|
||||
}
|
||||
});
|
||||
FlxG.camera.setFilters([new ShaderFilter(screenWipeShit)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashlink json encoding fix for some wacky bullshit
|
||||
* https://github.com/HaxeFoundation/haxe/issues/6930#issuecomment-384570392
|
||||
*/
|
||||
public static function coolJSON(fileData:String)
|
||||
{
|
||||
var cont = fileData;
|
||||
function is(n:Int, what:Int)
|
||||
return cont.charCodeAt(n) == what;
|
||||
return JsonParser.parse(cont.substr(if (is(0, 65279)) /// looks like a HL target, skipping only first character here:
|
||||
1 else if (is(0, 239) && is(1, 187) && is(2, 191)) /// it seems to be Neko or PHP, start from position 3:
|
||||
3 else /// all other targets, that prepare the UTF string correctly
|
||||
0));
|
||||
}
|
||||
|
||||
/*
|
||||
* frame dependant lerp kinda lol
|
||||
*/
|
||||
|
|
|
@ -14,6 +14,9 @@ import flixel.math.FlxPoint;
|
|||
import flixel.text.FlxText;
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.util.FlxTimer;
|
||||
import freeplayStuff.DJBoyfriend;
|
||||
import freeplayStuff.SongMenuItem;
|
||||
import lime.app.Future;
|
||||
import lime.utils.Assets;
|
||||
|
||||
|
@ -44,10 +47,10 @@ class FreeplayState extends MusicBeatState
|
|||
];
|
||||
|
||||
private var grpSongs:FlxTypedGroup<Alphabet>;
|
||||
private var grpCapsules:FlxTypedGroup<SongMenuItem>;
|
||||
private var curPlaying:Bool = false;
|
||||
|
||||
private var iconArray:Array<HealthIcon> = [];
|
||||
var bg:FlxSprite;
|
||||
var scoreBG:FlxSprite;
|
||||
|
||||
override function create()
|
||||
|
@ -98,36 +101,51 @@ class FreeplayState extends MusicBeatState
|
|||
if (StoryMenuState.weekUnlocked[7] || isDebug)
|
||||
addWeek(['Ugh', 'Guns', 'Stress'], 7, ['tankman']);
|
||||
|
||||
addWeek(["Darnell", "lit-up", "2hot"], 8, ['darnell']);
|
||||
addWeek(["bro"], 1, ['gf']);
|
||||
|
||||
// LOAD MUSIC
|
||||
|
||||
// LOAD CHARACTERS
|
||||
|
||||
bg = new FlxSprite().loadGraphic(Paths.image('menuDesat'));
|
||||
bg.setGraphicSize(Std.int(FlxG.width));
|
||||
bg.updateHitbox();
|
||||
trace(FlxG.width);
|
||||
trace(FlxG.camera.zoom);
|
||||
trace(FlxG.camera.initialZoom);
|
||||
trace(FlxCamera.defaultZoom);
|
||||
trace(FlxG.initialZoom);
|
||||
add(bg);
|
||||
|
||||
grpSongs = new FlxTypedGroup<Alphabet>();
|
||||
add(grpSongs);
|
||||
|
||||
grpCapsules = new FlxTypedGroup<SongMenuItem>();
|
||||
add(grpCapsules);
|
||||
|
||||
for (i in 0...songs.length)
|
||||
{
|
||||
var funnyMenu:SongMenuItem = new SongMenuItem(FlxG.width, (i * 150) + 160, songs[i].songName);
|
||||
funnyMenu.targetPos.x = funnyMenu.x;
|
||||
funnyMenu.ID = i;
|
||||
|
||||
new FlxTimer().start((0.06 * i) + 0.8, function(lerpTmr)
|
||||
{
|
||||
funnyMenu.doLerp = true;
|
||||
});
|
||||
|
||||
grpCapsules.add(funnyMenu);
|
||||
|
||||
var songText:Alphabet = new Alphabet(0, (70 * i) + 30, songs[i].songName, true, false);
|
||||
songText.x += 100;
|
||||
songText.isMenuItem = true;
|
||||
songText.targetY = i;
|
||||
grpSongs.add(songText);
|
||||
|
||||
// grpSongs.add(songText);
|
||||
|
||||
var icon:HealthIcon = new HealthIcon(songs[i].songCharacter);
|
||||
icon.sprTracker = songText;
|
||||
|
||||
// using a FlxGroup is too much fuss!
|
||||
iconArray.push(icon);
|
||||
add(icon);
|
||||
// add(icon);
|
||||
|
||||
// songText.x += 40;
|
||||
// DONT PUT X IN THE FIRST PARAMETER OF new ALPHABET() !!
|
||||
|
@ -152,6 +170,9 @@ class FreeplayState extends MusicBeatState
|
|||
changeSelection();
|
||||
changeDiff();
|
||||
|
||||
var dj:DJBoyfriend = new DJBoyfriend(0, -100);
|
||||
add(dj);
|
||||
|
||||
// FlxG.sound.playMusic(Paths.music('title'), 0);
|
||||
// FlxG.sound.music.fadeIn(2, 0, 0.8);
|
||||
// selector = new FlxText();
|
||||
|
@ -226,7 +247,6 @@ class FreeplayState extends MusicBeatState
|
|||
}
|
||||
|
||||
lerpScore = CoolUtil.coolLerp(lerpScore, intendedScore, 0.4);
|
||||
bg.color = FlxColor.interpolate(bg.color, coolColors[songs[curSelected].week % coolColors.length], CoolUtil.camLerpShit(0.045));
|
||||
|
||||
scoreText.text = "PERSONAL BEST:" + Math.round(lerpScore);
|
||||
|
||||
|
@ -360,7 +380,20 @@ class FreeplayState extends MusicBeatState
|
|||
|
||||
if (accepted)
|
||||
{
|
||||
// if (Assets.exists())
|
||||
|
||||
var poop:String = Highscore.formatSong(songs[curSelected].songName.toLowerCase(), curDifficulty);
|
||||
|
||||
// does not work properly, always just accidentally sets it to normal anyways!
|
||||
/* if (!Assets.exists(Paths.json(songs[curSelected].songName + '/' + poop)))
|
||||
{
|
||||
// defaults to normal if HARD / EASY doesn't exist
|
||||
// does not account if NORMAL doesn't exist!
|
||||
FlxG.log.warn("CURRENT DIFFICULTY IS NOT CHARTED, DEFAULTING TO NORMAL!");
|
||||
poop = Highscore.formatSong(songs[curSelected].songName.toLowerCase(), 1);
|
||||
curDifficulty = 1;
|
||||
}*/
|
||||
|
||||
PlayState.SONG = Song.loadFromJson(poop, songs[curSelected].songName.toLowerCase());
|
||||
PlayState.isStoryMode = false;
|
||||
PlayState.storyDifficulty = curDifficulty;
|
||||
|
@ -441,20 +474,15 @@ class FreeplayState extends MusicBeatState
|
|||
|
||||
iconArray[curSelected].alpha = 1;
|
||||
|
||||
for (item in grpSongs.members)
|
||||
for (index => capsule in grpCapsules.members)
|
||||
{
|
||||
item.targetY = bullShit - curSelected;
|
||||
bullShit++;
|
||||
capsule.selected = false;
|
||||
|
||||
item.alpha = 0.6;
|
||||
// item.setGraphicSize(Std.int(item.width * 0.8));
|
||||
|
||||
if (item.targetY == 0)
|
||||
{
|
||||
item.alpha = 1;
|
||||
// item.setGraphicSize(Std.int(item.width));
|
||||
}
|
||||
capsule.targetPos.y = ((index - curSelected) * 150) + 160;
|
||||
capsule.targetPos.x = 270 + (60 * (Math.sin(index - curSelected)));
|
||||
}
|
||||
|
||||
grpCapsules.members[curSelected].selected = true;
|
||||
}
|
||||
|
||||
function positionHighscore()
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
package;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import flixel.addons.transition.FlxTransitionableState;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.input.gamepad.FlxGamepad;
|
||||
import flixel.tweens.FlxEase;
|
||||
import flixel.tweens.FlxTween;
|
||||
|
||||
class GameOverState extends FlxTransitionableState
|
||||
{
|
||||
var bfX:Float = 0;
|
||||
var bfY:Float = 0;
|
||||
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
super();
|
||||
|
||||
bfX = x;
|
||||
bfY = y;
|
||||
}
|
||||
|
||||
override function create()
|
||||
{
|
||||
/* var loser:FlxSprite = new FlxSprite(100, 100);
|
||||
var loseTex = FlxAtlasFrames.fromSparrow(AssetPaths.lose.png, AssetPaths.lose.xml);
|
||||
loser.frames = loseTex;
|
||||
loser.animation.addByPrefix('lose', 'lose', 24, false);
|
||||
loser.animation.play('lose');
|
||||
// add(loser); */
|
||||
|
||||
var bf:Boyfriend = new Boyfriend(bfX, bfY);
|
||||
// bf.scrollFactor.set();
|
||||
add(bf);
|
||||
bf.playAnim('firstDeath');
|
||||
|
||||
FlxG.camera.follow(bf, LOCKON, 0.001);
|
||||
/*
|
||||
var restart:FlxSprite = new FlxSprite(500, 50).loadGraphic(AssetPaths.restart.png);
|
||||
restart.setGraphicSize(Std.int(restart.width * 0.6));
|
||||
restart.updateHitbox();
|
||||
restart.alpha = 0;
|
||||
restart.antialiasing = true;
|
||||
// add(restart); */
|
||||
|
||||
FlxG.sound.music.fadeOut(2, FlxG.sound.music.volume * 0.6);
|
||||
|
||||
// FlxTween.tween(restart, {alpha: 1}, 1, {ease: FlxEase.quartInOut});
|
||||
// FlxTween.tween(restart, {y: restart.y + 40}, 7, {ease: FlxEase.quartInOut, type: PINGPONG});
|
||||
|
||||
super.create();
|
||||
}
|
||||
|
||||
private var fading:Bool = false;
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
var pressed:Bool = FlxG.keys.justPressed.ANY;
|
||||
|
||||
var gamepad:FlxGamepad = FlxG.gamepads.lastActive;
|
||||
|
||||
if (gamepad != null)
|
||||
{
|
||||
if (gamepad.justPressed.ANY)
|
||||
pressed = true;
|
||||
}
|
||||
|
||||
pressed = false;
|
||||
|
||||
if (pressed && !fading)
|
||||
{
|
||||
fading = true;
|
||||
FlxG.sound.music.fadeOut(0.5, 0, function(twn:FlxTween)
|
||||
{
|
||||
FlxG.sound.music.stop();
|
||||
LoadingState.loadAndSwitchState(new PlayState());
|
||||
});
|
||||
}
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ package;
|
|||
import flixel.FlxObject;
|
||||
import flixel.FlxSubState;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.system.FlxSound;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.util.FlxTimer;
|
||||
import haxe.display.Display.Package;
|
||||
|
@ -16,8 +17,13 @@ class GameOverSubstate extends MusicBeatSubstate
|
|||
var stageSuffix:String = "";
|
||||
var randomGameover:Int = 1;
|
||||
|
||||
var gameOverMusic:FlxSound;
|
||||
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
gameOverMusic = new FlxSound();
|
||||
FlxG.sound.list.add(gameOverMusic);
|
||||
|
||||
var daStage = PlayState.curStage;
|
||||
var daBf:String = '';
|
||||
switch (daStage)
|
||||
|
@ -48,10 +54,18 @@ class GameOverSubstate extends MusicBeatSubstate
|
|||
add(camFollow);
|
||||
|
||||
FlxG.sound.play(Paths.sound('fnf_loss_sfx' + stageSuffix));
|
||||
Conductor.changeBPM(100);
|
||||
// Conductor.changeBPM(100);
|
||||
|
||||
switch (PlayState.SONG.player1)
|
||||
{
|
||||
case 'pico':
|
||||
stageSuffix = 'Pico';
|
||||
}
|
||||
|
||||
// FlxG.camera.followLerp = 1;
|
||||
// FlxG.camera.focusOn(FlxPoint.get(FlxG.width / 2, FlxG.height / 2));
|
||||
|
||||
// commented out for now
|
||||
FlxG.camera.scroll.set();
|
||||
FlxG.camera.target = null;
|
||||
|
||||
|
@ -93,7 +107,8 @@ class GameOverSubstate extends MusicBeatSubstate
|
|||
{
|
||||
PlayState.deathCounter = 0;
|
||||
PlayState.seenCutscene = false;
|
||||
FlxG.sound.music.stop();
|
||||
// FlxG.sound.music.stop();
|
||||
gameOverMusic.stop();
|
||||
|
||||
if (PlayState.isStoryMode)
|
||||
FlxG.switchState(new StoryMenuState());
|
||||
|
@ -119,7 +134,10 @@ class GameOverSubstate extends MusicBeatSubstate
|
|||
FlxG.sound.play(Paths.sound('jeffGameover/jeffGameover-' + randomGameover), 1, false, null, true, function()
|
||||
{
|
||||
if (!isEnding)
|
||||
FlxG.sound.music.fadeIn(4, 0.2, 1);
|
||||
{
|
||||
gameOverMusic.fadeIn(4, 0.2, 1);
|
||||
}
|
||||
// FlxG.sound.music.fadeIn(4, 0.2, 1);
|
||||
});
|
||||
}
|
||||
default:
|
||||
|
@ -130,23 +148,21 @@ class GameOverSubstate extends MusicBeatSubstate
|
|||
}
|
||||
}
|
||||
|
||||
if (FlxG.sound.music.playing)
|
||||
if (gameOverMusic.playing)
|
||||
{
|
||||
Conductor.songPosition = FlxG.sound.music.time;
|
||||
Conductor.songPosition = gameOverMusic.time;
|
||||
}
|
||||
}
|
||||
|
||||
private function coolStartDeath(?vol:Float = 1):Void
|
||||
{
|
||||
if (!isEnding)
|
||||
FlxG.sound.playMusic(Paths.music('gameOver' + stageSuffix), vol);
|
||||
}
|
||||
|
||||
override function beatHit()
|
||||
{
|
||||
super.beatHit();
|
||||
|
||||
FlxG.log.add('beat');
|
||||
{
|
||||
gameOverMusic.loadEmbedded(Paths.music('gameOver' + stageSuffix));
|
||||
gameOverMusic.volume = vol;
|
||||
gameOverMusic.play();
|
||||
}
|
||||
// FlxG.sound.playMusic();
|
||||
}
|
||||
|
||||
var isEnding:Bool = false;
|
||||
|
@ -157,13 +173,17 @@ class GameOverSubstate extends MusicBeatSubstate
|
|||
{
|
||||
isEnding = true;
|
||||
bf.playAnim('deathConfirm', true);
|
||||
FlxG.sound.music.stop();
|
||||
gameOverMusic.stop();
|
||||
// FlxG.sound.music.stop();
|
||||
FlxG.sound.play(Paths.music('gameOverEnd' + stageSuffix));
|
||||
new FlxTimer().start(0.7, function(tmr:FlxTimer)
|
||||
{
|
||||
FlxG.camera.fade(FlxColor.BLACK, 2, false, function()
|
||||
{
|
||||
LoadingState.loadAndSwitchState(new PlayState());
|
||||
FlxG.camera.fade(FlxColor.BLACK, 1, true, null, true);
|
||||
PlayState.needsReset = true;
|
||||
close();
|
||||
// LoadingState.loadAndSwitchState(new PlayState());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import openfl.utils.Assets;
|
||||
|
||||
using StringTools;
|
||||
|
||||
|
@ -11,7 +12,8 @@ class HealthIcon extends FlxSprite
|
|||
*/
|
||||
public var sprTracker:FlxSprite;
|
||||
|
||||
var char:String = '';
|
||||
public var char:String = '';
|
||||
|
||||
var isPlayer:Bool = false;
|
||||
|
||||
public function new(char:String = 'bf', isPlayer:Bool = false)
|
||||
|
@ -44,6 +46,12 @@ class HealthIcon extends FlxSprite
|
|||
if (newChar != 'bf-pixel' && newChar != 'bf-old')
|
||||
newChar = newChar.split('-')[0].trim();
|
||||
|
||||
if (!Assets.exists(Paths.image('icons/icon-' + newChar)))
|
||||
{
|
||||
FlxG.log.warn('No icon with data: $newChar : using default placeholder face instead!');
|
||||
newChar = "face";
|
||||
}
|
||||
|
||||
if (newChar != char)
|
||||
{
|
||||
if (animation.getByName(newChar) == null)
|
||||
|
|
130
source/InitState.hx
Normal file
130
source/InitState.hx
Normal file
|
@ -0,0 +1,130 @@
|
|||
package;
|
||||
|
||||
import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond;
|
||||
import flixel.addons.transition.FlxTransitionableState;
|
||||
import flixel.addons.transition.TransitionData;
|
||||
import flixel.graphics.FlxGraphic;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.util.FlxColor;
|
||||
import openfl.display.BitmapData;
|
||||
import ui.PreferencesMenu;
|
||||
import ui.stageBuildShit.StageBuilderState;
|
||||
|
||||
using StringTools;
|
||||
|
||||
#if colyseus
|
||||
import io.colyseus.Client;
|
||||
import io.colyseus.Room;
|
||||
#end
|
||||
#if discord_rpc
|
||||
import Discord.DiscordClient;
|
||||
#end
|
||||
#if desktop
|
||||
import sys.FileSystem;
|
||||
import sys.io.File;
|
||||
import sys.thread.Thread;
|
||||
#end
|
||||
|
||||
class InitState extends FlxTransitionableState
|
||||
{
|
||||
override public function create():Void
|
||||
{
|
||||
#if android
|
||||
FlxG.android.preventDefaultKeys = [FlxAndroidKey.BACK];
|
||||
#end
|
||||
#if newgrounds
|
||||
NGio.init();
|
||||
#end
|
||||
#if discord_rpc
|
||||
DiscordClient.initialize();
|
||||
|
||||
Application.current.onExit.add(function(exitCode)
|
||||
{
|
||||
DiscordClient.shutdown();
|
||||
});
|
||||
#end
|
||||
|
||||
// ==== flixel shit ==== //
|
||||
|
||||
// This big obnoxious white button is for MOBILE, so that you can press it
|
||||
// easily with your finger when debug bullshit pops up during testing lol!
|
||||
FlxG.debugger.addButton(LEFT, new BitmapData(200, 200), function()
|
||||
{
|
||||
FlxG.debugger.visible = false;
|
||||
});
|
||||
|
||||
FlxG.sound.muteKeys = [ZERO];
|
||||
FlxG.game.focusLostFramerate = 60;
|
||||
|
||||
// FlxG.stage.window.borderless = true;
|
||||
// FlxG.stage.window.mouseLock = true;
|
||||
|
||||
var diamond:FlxGraphic = FlxGraphic.fromClass(GraphicTransTileDiamond);
|
||||
diamond.persist = true;
|
||||
diamond.destroyOnNoUse = false;
|
||||
|
||||
FlxTransitionableState.defaultTransIn = new TransitionData(FADE, FlxColor.BLACK, 1, new FlxPoint(0, -1), {asset: diamond, width: 32, height: 32},
|
||||
new FlxRect(-200, -200, FlxG.width * 1.4, FlxG.height * 1.4));
|
||||
FlxTransitionableState.defaultTransOut = new TransitionData(FADE, FlxColor.BLACK, 0.7, new FlxPoint(0, 1), {asset: diamond, width: 32, height: 32},
|
||||
new FlxRect(-200, -200, FlxG.width * 1.4, FlxG.height * 1.4));
|
||||
|
||||
// ===== save shit ===== //
|
||||
|
||||
FlxG.save.bind('funkin', 'ninjamuffin99');
|
||||
|
||||
// https://github.com/HaxeFlixel/flixel/pull/2396
|
||||
// IF/WHEN MY PR GOES THRU AND IT GETS INTO MAIN FLIXEL, DELETE THIS CHUNKOF CODE, AND THEN UNCOMMENT THE LINE BELOW
|
||||
// FlxG.sound.loadSavedPrefs();
|
||||
|
||||
if (FlxG.save.data.volume != null)
|
||||
FlxG.sound.volume = FlxG.save.data.volume;
|
||||
if (FlxG.save.data.mute != null)
|
||||
FlxG.sound.muted = FlxG.save.data.mute;
|
||||
|
||||
// FlxG.save.close();
|
||||
// FlxG.sound.loadSavedPrefs();
|
||||
PreferencesMenu.initPrefs();
|
||||
PlayerSettings.init();
|
||||
Highscore.load();
|
||||
|
||||
if (FlxG.save.data.weekUnlocked != null)
|
||||
{
|
||||
// FIX LATER!!!
|
||||
// WEEK UNLOCK PROGRESSION!!
|
||||
// StoryMenuState.weekUnlocked = FlxG.save.data.weekUnlocked;
|
||||
|
||||
if (StoryMenuState.weekUnlocked.length < 4)
|
||||
StoryMenuState.weekUnlocked.insert(0, true);
|
||||
|
||||
// QUICK PATCH OOPS!
|
||||
if (!StoryMenuState.weekUnlocked[0])
|
||||
StoryMenuState.weekUnlocked[0] = true;
|
||||
}
|
||||
|
||||
if (FlxG.save.data.seenVideo != null)
|
||||
VideoState.seenVideo = FlxG.save.data.seenVideo;
|
||||
|
||||
// ===== fuck outta here ===== //
|
||||
|
||||
// FlxTransitionableState.skipNextTransOut = true;
|
||||
FlxTransitionableState.skipNextTransIn = true;
|
||||
|
||||
#if FREEPLAY
|
||||
FlxG.switchState(new FreeplayState());
|
||||
#elseif ANIMATE
|
||||
FlxG.switchState(new animate.AnimTestStage());
|
||||
#elseif CHARTING
|
||||
FlxG.switchState(new ChartingState());
|
||||
#elseif STAGEBUILD
|
||||
FlxG.switchState(new StageBuilderState());
|
||||
#elseif ANIMDEBUG
|
||||
FlxG.switchState(new ui.animDebugShit.DebugBoundingState());
|
||||
#elseif NETTEST
|
||||
FlxG.switchState(new netTest.NetTest());
|
||||
#else
|
||||
FlxG.sound.cache(Paths.music('freakyMenu'));
|
||||
FlxG.switchState(new TitleState());
|
||||
#end
|
||||
}
|
||||
}
|
|
@ -57,7 +57,18 @@ class LoadingState extends MusicBeatState
|
|||
var introComplete = callbacks.add("introComplete");
|
||||
checkLoadSong(getSongPath());
|
||||
if (PlayState.SONG.needsVoices)
|
||||
checkLoadSong(getVocalPath());
|
||||
{
|
||||
var files = PlayState.SONG.voiceList;
|
||||
|
||||
if (files == null)
|
||||
files = [""]; // loads with no file name assumption, to load "Voices.ogg" or whatev normally
|
||||
|
||||
for (sndFile in files)
|
||||
{
|
||||
checkLoadSong(getVocalPath(sndFile));
|
||||
}
|
||||
}
|
||||
|
||||
checkLibrary("shared");
|
||||
if (PlayState.storyWeek > 0)
|
||||
checkLibrary("week" + PlayState.storyWeek);
|
||||
|
@ -164,9 +175,9 @@ class LoadingState extends MusicBeatState
|
|||
return Paths.inst(PlayState.SONG.song);
|
||||
}
|
||||
|
||||
static function getVocalPath()
|
||||
static function getVocalPath(?suffix:String)
|
||||
{
|
||||
return Paths.voices(PlayState.SONG.song);
|
||||
return Paths.voices(PlayState.SONG.song, suffix);
|
||||
}
|
||||
|
||||
inline static public function loadAndSwitchState(target:FlxState, stopMusic = false)
|
||||
|
|
|
@ -19,7 +19,7 @@ class Main extends Sprite
|
|||
{
|
||||
var gameWidth:Int = 1280; // Width of the game in pixels (might be less / more in actual pixels depending on your zoom).
|
||||
var gameHeight:Int = 720; // Height of the game in pixels (might be less / more in actual pixels depending on your zoom).
|
||||
var initialState:Class<FlxState> = TitleState; // The FlxState the game starts with.
|
||||
var initialState:Class<FlxState> = InitState; // The FlxState the game starts with.
|
||||
var zoom:Float = -1; // If -1, zoom is automatically calculated to fit the window dimensions.
|
||||
#if web
|
||||
var framerate:Int = 60; // How many frames per second the game should run at.
|
||||
|
@ -48,7 +48,7 @@ class Main extends Sprite
|
|||
frameworkParams: {
|
||||
assetLibraryPaths: [
|
||||
"songs" => "songs", "shared" => "shared", "tutorial" => "tutorial", "week1" => "week1", "week2" => "week2", "week3" => "week3",
|
||||
"week4" => "week4", "week5" => "week5", "week6" => "week6", "week7" => "week7", "tanky" => "tanky", "tankBG" => "tankBG"
|
||||
"week4" => "week4", "week5" => "week5", "week6" => "week6", "week7" => "week7", "week8" => "week8"
|
||||
]
|
||||
},
|
||||
framework: OPENFL,
|
||||
|
|
|
@ -16,6 +16,8 @@ import flixel.ui.FlxButton;
|
|||
import flixel.util.FlxColor;
|
||||
import flixel.util.FlxTimer;
|
||||
import lime.app.Application;
|
||||
import openfl.filters.ShaderFilter;
|
||||
import shaderslmfao.ScreenWipeShader;
|
||||
import ui.AtlasMenuList;
|
||||
import ui.MenuList;
|
||||
import ui.OptionsState;
|
||||
|
|
|
@ -34,7 +34,6 @@ class Note extends FlxSprite
|
|||
public var isSustainNote:Bool = false;
|
||||
|
||||
public var colorSwap:ColorSwap;
|
||||
public var noteScore:Float = 1;
|
||||
|
||||
public static var swagWidth:Float = 160 * 0.7;
|
||||
public static var PURP_NOTE:Int = 0;
|
||||
|
@ -42,6 +41,15 @@ class Note extends FlxSprite
|
|||
public static var BLUE_NOTE:Int = 1;
|
||||
public static var RED_NOTE:Int = 3;
|
||||
|
||||
// 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
|
||||
// anything below sick threshold is sick
|
||||
|
||||
public static var arrowColors:Array<Float> = [1, 1, 1, 1];
|
||||
|
||||
public function new(strumTime:Float, noteData:Int, ?prevNote:Note, ?sustainNote:Bool = false)
|
||||
|
@ -145,7 +153,6 @@ class Note extends FlxSprite
|
|||
|
||||
if (isSustainNote && prevNote != null)
|
||||
{
|
||||
noteScore * 0.2;
|
||||
alpha = 0.6;
|
||||
|
||||
if (PreferencesMenu.getPref('downscroll'))
|
||||
|
@ -224,9 +231,9 @@ class Note extends FlxSprite
|
|||
}
|
||||
else
|
||||
{
|
||||
if (strumTime > Conductor.songPosition - Conductor.safeZoneOffset)
|
||||
{ // The * 0.5 is so that it's easier to hit them too late, instead of too early
|
||||
if (strumTime < Conductor.songPosition + (Conductor.safeZoneOffset * 0.5))
|
||||
if (strumTime > Conductor.songPosition - HIT_WINDOW)
|
||||
{ // * 0.2 if sustain note, so u have to keep holding it closer to all the way thru!
|
||||
if (strumTime < Conductor.songPosition + (HIT_WINDOW * (isSustainNote ? 0.2 : 1)))
|
||||
canBeHit = true;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -31,17 +31,12 @@ class NoteSplash extends FlxSprite
|
|||
alpha = 0.6;
|
||||
|
||||
animation.play('note' + noteData + '-' + FlxG.random.int(0, 1), true);
|
||||
animation.curAnim.frameRate += FlxG.random.int(-2, 2);
|
||||
animation.curAnim.frameRate = 24 + FlxG.random.int(-2, 2);
|
||||
animation.finishCallback = function(name){
|
||||
kill();
|
||||
};
|
||||
updateHitbox();
|
||||
|
||||
offset.set(width * 0.3, height * 0.3);
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (animation.curAnim.finished)
|
||||
kill();
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,12 +25,12 @@ class Paths
|
|||
var levelPath = getLibraryPathForce(file, currentLevel);
|
||||
if (OpenFlAssets.exists(levelPath, type))
|
||||
return levelPath;
|
||||
|
||||
levelPath = getLibraryPathForce(file, "shared");
|
||||
if (OpenFlAssets.exists(levelPath, type))
|
||||
return levelPath;
|
||||
}
|
||||
|
||||
var levelPath = getLibraryPathForce(file, "shared");
|
||||
if (OpenFlAssets.exists(levelPath, type))
|
||||
return levelPath;
|
||||
|
||||
return getPreloadPath(file);
|
||||
}
|
||||
|
||||
|
@ -84,9 +84,12 @@ class Paths
|
|||
return getPath('music/$key.$SOUND_EXT', MUSIC, library);
|
||||
}
|
||||
|
||||
inline static public function voices(song:String)
|
||||
inline static public function voices(song:String, ?suffix:String)
|
||||
{
|
||||
return 'songs:assets/songs/${song.toLowerCase()}/Voices.$SOUND_EXT';
|
||||
if (suffix == null)
|
||||
suffix = ""; // no suffix, for a sorta backwards compatibility with older-ish voice files
|
||||
|
||||
return 'songs:assets/songs/${song.toLowerCase()}/Voices$suffix.$SOUND_EXT';
|
||||
}
|
||||
|
||||
inline static public function inst(song:String)
|
||||
|
|
|
@ -174,7 +174,10 @@ class PauseSubState extends MusicBeatSubstate
|
|||
menuItems = pauseOG;
|
||||
regenMenu();
|
||||
case "Restart Song":
|
||||
FlxG.resetState();
|
||||
PlayState.needsReset = true;
|
||||
|
||||
close();
|
||||
// FlxG.resetState();
|
||||
case "Exit to menu":
|
||||
PlayState.seenCutscene = false;
|
||||
PlayState.deathCounter = 0;
|
||||
|
|
|
@ -46,17 +46,22 @@ class PlayState extends MusicBeatState
|
|||
public static var storyDifficulty:Int = 1;
|
||||
public static var deathCounter:Int = 0;
|
||||
public static var practiceMode:Bool = false;
|
||||
public static var needsReset:Bool = false;
|
||||
|
||||
var halloweenLevel:Bool = false;
|
||||
|
||||
private var vocals:FlxSound;
|
||||
private var vocals:VoicesGroup;
|
||||
private var vocalsFinished:Bool = false;
|
||||
|
||||
private var dad:Character;
|
||||
private var gf:Character;
|
||||
private var boyfriend:Boyfriend;
|
||||
|
||||
/**
|
||||
* Notes that should be ON SCREEN and have UPDATES running on them!
|
||||
*/
|
||||
private var notes:FlxTypedGroup<Note>;
|
||||
|
||||
private var unspawnNotes:Array<Note> = [];
|
||||
|
||||
private var strumLine:FlxSprite;
|
||||
|
@ -73,6 +78,7 @@ class PlayState extends MusicBeatState
|
|||
|
||||
private var gfSpeed:Int = 1;
|
||||
private var health:Float = 1;
|
||||
private var healthDisplay:Float = 1;
|
||||
private var combo:Int = 0;
|
||||
|
||||
private var healthBarBG:FlxSprite;
|
||||
|
@ -86,7 +92,7 @@ class PlayState extends MusicBeatState
|
|||
private var camHUD:FlxCamera;
|
||||
private var camGame:FlxCamera;
|
||||
|
||||
var dialogue:Array<String> = ['blah blah blah', 'coolswag'];
|
||||
var dialogue:Array<String>;
|
||||
|
||||
public static var seenCutscene:Bool = false;
|
||||
|
||||
|
@ -120,6 +126,9 @@ class PlayState extends MusicBeatState
|
|||
var songScore:Int = 0;
|
||||
var scoreTxt:FlxText;
|
||||
|
||||
// Dunno why its called doof lol, it's just the dialogue box
|
||||
var doof:DialogueBox;
|
||||
|
||||
var grpNoteSplashes:FlxTypedGroup<NoteSplash>;
|
||||
|
||||
public static var campaignScore:Int = 0;
|
||||
|
@ -176,23 +185,6 @@ class PlayState extends MusicBeatState
|
|||
|
||||
switch (SONG.song.toLowerCase())
|
||||
{
|
||||
case 'tutorial':
|
||||
dialogue = ["Hey you're pretty cute.", 'Use the arrow keys to keep up \nwith me singing.'];
|
||||
case 'bopeebo':
|
||||
dialogue = [
|
||||
'HEY!',
|
||||
"You think you can just sing\nwith my daughter like that?",
|
||||
"If you want to date her...",
|
||||
"You're going to have to go \nthrough ME first!"
|
||||
];
|
||||
case 'fresh':
|
||||
dialogue = ["Not too shabby boy.", ""];
|
||||
case 'dadbattle':
|
||||
dialogue = [
|
||||
"gah you think you're hot stuff?",
|
||||
"If you can beat me here...",
|
||||
"Only then I will even CONSIDER letting you\ndate my daughter!"
|
||||
];
|
||||
case 'senpai':
|
||||
dialogue = CoolUtil.coolTextFile(Paths.txt('senpai/senpaiDialogue'));
|
||||
case 'roses':
|
||||
|
@ -435,7 +427,28 @@ class PlayState extends MusicBeatState
|
|||
bgGirls.updateHitbox();
|
||||
add(bgGirls);
|
||||
case 'thorns':
|
||||
loadStage('schoolEvil');
|
||||
// loadStage('schoolEvil');
|
||||
curStage = 'schoolEvil';
|
||||
|
||||
var schoolBG:FlxSprite = new FlxSprite(-200, 0).loadGraphic(Paths.image('weeb/evilSchoolBG'));
|
||||
wiggleShit.waveAmplitude = 0.017;
|
||||
wiggleShit.waveSpeed = 2;
|
||||
wiggleShit.waveFrequency = 4;
|
||||
schoolBG.shader = wiggleShit.shader;
|
||||
schoolBG.setGraphicSize(Std.int(schoolBG.width * 6));
|
||||
schoolBG.updateHitbox();
|
||||
// schoolBG.scale.set(6, 6);
|
||||
add(schoolBG);
|
||||
|
||||
schoolBG.scrollFactor.set(0.7, 1);
|
||||
|
||||
var schoolFront:FlxSprite = new FlxSprite(-250, schoolBG.y + 20).loadGraphic(Paths.image('weeb/evilSchoolFG'));
|
||||
|
||||
schoolFront.shader = wiggleShit.shader;
|
||||
|
||||
schoolFront.setGraphicSize(Std.int(schoolFront.width * 6));
|
||||
schoolFront.updateHitbox();
|
||||
add(schoolFront);
|
||||
|
||||
case 'guns' | 'stress' | 'ugh':
|
||||
loadStage('tank');
|
||||
|
@ -485,10 +498,14 @@ class PlayState extends MusicBeatState
|
|||
var fgTank3:BGSprite = new BGSprite('tank3', 1300, 1200, 3.5, 2.5, ['fg']);
|
||||
foregroundSprites.add(fgTank3);
|
||||
|
||||
case "darnell":
|
||||
loadStage('phillyStreets');
|
||||
|
||||
default:
|
||||
loadStage('stage');
|
||||
}
|
||||
|
||||
// all dis is shitty, redo later for stage shit
|
||||
var gfVersion:String = 'gf';
|
||||
|
||||
switch (curStage)
|
||||
|
@ -503,6 +520,11 @@ class PlayState extends MusicBeatState
|
|||
gfVersion = 'gf-tankmen';
|
||||
}
|
||||
|
||||
if (SONG.player1 == "pico")
|
||||
{
|
||||
gfVersion = "nene";
|
||||
}
|
||||
|
||||
if (SONG.song.toLowerCase() == 'stress')
|
||||
gfVersion = 'pico-speaker';
|
||||
|
||||
|
@ -619,6 +641,8 @@ class PlayState extends MusicBeatState
|
|||
gf.x -= 170;
|
||||
gf.y -= 75;
|
||||
}
|
||||
case 'stage' | 'phillyStreets':
|
||||
dad.y = 870 - dad.height;
|
||||
}
|
||||
|
||||
add(gf);
|
||||
|
@ -638,11 +662,13 @@ class PlayState extends MusicBeatState
|
|||
|
||||
add(foregroundSprites);
|
||||
|
||||
var doof:DialogueBox = new DialogueBox(false, dialogue);
|
||||
// doof.x += 70;
|
||||
// doof.y = FlxG.height * 0.5;
|
||||
doof.scrollFactor.set();
|
||||
doof.finishThing = startCountdown;
|
||||
if (dialogue != null)
|
||||
{
|
||||
doof = new DialogueBox(false, dialogue);
|
||||
doof.scrollFactor.set();
|
||||
doof.finishThing = startCountdown;
|
||||
doof.cameras = [camHUD];
|
||||
}
|
||||
|
||||
Conductor.songPosition = -5000;
|
||||
|
||||
|
@ -652,7 +678,6 @@ class PlayState extends MusicBeatState
|
|||
strumLine.y = FlxG.height - 150; // 150 just random ass number lol
|
||||
|
||||
strumLine.scrollFactor.set();
|
||||
|
||||
strumLineNotes = new FlxTypedGroup<FlxSprite>();
|
||||
add(strumLineNotes);
|
||||
|
||||
|
@ -684,10 +709,7 @@ class PlayState extends MusicBeatState
|
|||
|
||||
add(camFollow);
|
||||
|
||||
FlxG.camera.follow(camFollow, LOCKON, 0.04);
|
||||
// FlxG.camera.setScrollBounds(0, FlxG.width, 0, FlxG.height);
|
||||
FlxG.camera.zoom = defaultCamZoom;
|
||||
FlxG.camera.focusOn(camFollow.getPosition());
|
||||
resetCamFollow();
|
||||
|
||||
FlxG.worldBounds.set(0, 0, FlxG.width, FlxG.height);
|
||||
|
||||
|
@ -702,7 +724,7 @@ class PlayState extends MusicBeatState
|
|||
healthBarBG.y = FlxG.height * 0.1;
|
||||
|
||||
healthBar = new FlxBar(healthBarBG.x + 4, healthBarBG.y + 4, RIGHT_TO_LEFT, Std.int(healthBarBG.width - 8), Std.int(healthBarBG.height - 8), this,
|
||||
'health', 0, 2);
|
||||
'healthDisplay', 0, 2);
|
||||
healthBar.scrollFactor.set();
|
||||
healthBar.createFilledBar(0xFFFF0000, 0xFF66FF33);
|
||||
// healthBar
|
||||
|
@ -729,7 +751,6 @@ class PlayState extends MusicBeatState
|
|||
iconP1.cameras = [camHUD];
|
||||
iconP2.cameras = [camHUD];
|
||||
scoreTxt.cameras = [camHUD];
|
||||
doof.cameras = [camHUD];
|
||||
|
||||
// if (SONG.song == 'South')
|
||||
// FlxG.camera.alpha = 0.7;
|
||||
|
@ -773,7 +794,7 @@ class PlayState extends MusicBeatState
|
|||
});
|
||||
});
|
||||
case 'senpai' | 'roses' | 'thorns':
|
||||
schoolIntro(doof);
|
||||
schoolIntro(doof); // doof is assumed to be non-null, lol!
|
||||
case 'ugh':
|
||||
ughIntro();
|
||||
case 'stress':
|
||||
|
@ -1382,7 +1403,14 @@ class PlayState extends MusicBeatState
|
|||
generateStaticArrows(1);
|
||||
|
||||
talking = false;
|
||||
|
||||
restartCountdownTimer();
|
||||
}
|
||||
|
||||
function restartCountdownTimer():Void
|
||||
{
|
||||
startedCountdown = true;
|
||||
|
||||
Conductor.songPosition = 0;
|
||||
Conductor.songPosition -= Conductor.crochet * 5;
|
||||
|
||||
|
@ -1469,7 +1497,13 @@ class PlayState extends MusicBeatState
|
|||
previousFrameTime = FlxG.game.ticks;
|
||||
|
||||
if (!paused)
|
||||
FlxG.sound.playMusic(Paths.inst(SONG.song), 1, false);
|
||||
{
|
||||
if (FlxG.sound.music != null)
|
||||
FlxG.sound.music.play(true);
|
||||
else
|
||||
FlxG.sound.playMusic(Paths.inst(SONG.song), 1, false);
|
||||
}
|
||||
|
||||
FlxG.sound.music.onComplete = endSong;
|
||||
vocals.play();
|
||||
|
||||
|
@ -1486,29 +1520,44 @@ class PlayState extends MusicBeatState
|
|||
{
|
||||
// FlxG.log.add(ChartParser.parse());
|
||||
|
||||
var songData = SONG;
|
||||
Conductor.changeBPM(songData.bpm);
|
||||
Conductor.changeBPM(SONG.bpm);
|
||||
|
||||
curSong = songData.song;
|
||||
curSong = SONG.song;
|
||||
|
||||
if (SONG.needsVoices)
|
||||
vocals = new FlxSound().loadEmbedded(Paths.voices(SONG.song));
|
||||
vocals = new VoicesGroup(SONG.song, SONG.voiceList);
|
||||
else
|
||||
vocals = new FlxSound();
|
||||
vocals = new VoicesGroup(SONG.song, null, false);
|
||||
|
||||
vocals.onComplete = function()
|
||||
vocals.members[0].onComplete = function()
|
||||
{
|
||||
vocalsFinished = true;
|
||||
};
|
||||
FlxG.sound.list.add(vocals);
|
||||
|
||||
notes = new FlxTypedGroup<Note>();
|
||||
add(notes);
|
||||
|
||||
regenNoteData();
|
||||
|
||||
generatedMusic = true;
|
||||
}
|
||||
|
||||
function regenNoteData():Void
|
||||
{
|
||||
// make unspawn notes shit def empty
|
||||
unspawnNotes = [];
|
||||
|
||||
notes.forEach(function(nt)
|
||||
{
|
||||
nt.kill();
|
||||
notes.remove(nt, true);
|
||||
nt.destroy();
|
||||
});
|
||||
|
||||
var noteData:Array<SwagSection>;
|
||||
|
||||
// NEW SHIT
|
||||
noteData = songData.notes;
|
||||
noteData = SONG.notes;
|
||||
|
||||
for (section in noteData)
|
||||
{
|
||||
|
@ -1560,8 +1609,6 @@ class PlayState extends MusicBeatState
|
|||
}
|
||||
|
||||
unspawnNotes.sort(sortByShit);
|
||||
|
||||
generatedMusic = true;
|
||||
}
|
||||
|
||||
// Now you are probably wondering why I made 2 of these very similar functions
|
||||
|
@ -1765,7 +1812,7 @@ class PlayState extends MusicBeatState
|
|||
if (vocalsFinished)
|
||||
return;
|
||||
|
||||
vocals.time = Conductor.songPosition;
|
||||
vocals.time = FlxG.sound.music.time;
|
||||
vocals.play();
|
||||
}
|
||||
|
||||
|
@ -1775,16 +1822,28 @@ class PlayState extends MusicBeatState
|
|||
|
||||
override public function update(elapsed:Float)
|
||||
{
|
||||
// makes the lerp non-dependant on the framerate
|
||||
// FlxG.camera.followLerp = CoolUtil.camLerpShit(0.04);
|
||||
healthDisplay = FlxMath.lerp(healthDisplay, health, 0.15);
|
||||
|
||||
#if !debug
|
||||
perfectMode = false;
|
||||
#else
|
||||
if (FlxG.keys.justPressed.H)
|
||||
camHUD.visible = !camHUD.visible;
|
||||
if (FlxG.keys.justPressed.K)
|
||||
if (needsReset)
|
||||
{
|
||||
resetCamFollow();
|
||||
|
||||
paused = false;
|
||||
persistentUpdate = true;
|
||||
persistentDraw = true;
|
||||
|
||||
startingSong = true;
|
||||
|
||||
FlxG.sound.music.pause();
|
||||
vocals.pause();
|
||||
|
||||
FlxG.sound.music.time = 0;
|
||||
regenNoteData(); // loads the note data from start
|
||||
health = 1;
|
||||
restartCountdownTimer();
|
||||
|
||||
needsReset = false;
|
||||
|
||||
// FlxScreenGrab.grab(null, true, true);
|
||||
|
||||
/*
|
||||
|
@ -1796,6 +1855,22 @@ class PlayState extends MusicBeatState
|
|||
*/
|
||||
// sys.io.File.saveContent('./swag.png', png.readUTFBytes(png.length));
|
||||
}
|
||||
|
||||
#if !debug
|
||||
perfectMode = false;
|
||||
#else
|
||||
if (FlxG.keys.justPressed.H)
|
||||
camHUD.visible = !camHUD.visible;
|
||||
if (FlxG.keys.justPressed.K)
|
||||
{
|
||||
@:privateAccess
|
||||
var funnyData:Array<Int> = cast FlxG.sound.music._channel.__source.buffer.data;
|
||||
|
||||
funnyData.reverse();
|
||||
|
||||
@:privateAccess
|
||||
FlxG.sound.music._channel.__source.buffer.data = cast funnyData;
|
||||
}
|
||||
#end
|
||||
|
||||
// do this BEFORE super.update() so songPosition is accurate
|
||||
|
@ -1810,6 +1885,9 @@ class PlayState extends MusicBeatState
|
|||
}
|
||||
else
|
||||
{
|
||||
if (Paths.SOUND_EXT == 'mp3')
|
||||
Conductor.offset = -13; // DO NOT FORGET TO REMOVE THE HARDCODE! WHEN I MAKE BETTER OFFSET SYSTEM!
|
||||
|
||||
Conductor.songPosition = FlxG.sound.music.time + Conductor.offset; // 20 is THE MILLISECONDS??
|
||||
// Conductor.songPosition += FlxG.elapsed * 1000;
|
||||
|
||||
|
@ -1853,6 +1931,8 @@ class PlayState extends MusicBeatState
|
|||
|
||||
super.update(elapsed);
|
||||
|
||||
wiggleShit.update(elapsed);
|
||||
|
||||
scoreTxt.text = "Score:" + songScore;
|
||||
|
||||
var androidPause:Bool = false;
|
||||
|
@ -1868,6 +1948,7 @@ class PlayState extends MusicBeatState
|
|||
paused = true;
|
||||
|
||||
// 1 / 1000 chance for Gitaroo Man easter egg
|
||||
// can this please move to dying it's kinda fucked up that pausing has a 1/1000 chance ur forced to restart
|
||||
if (FlxG.random.bool(0.1))
|
||||
{
|
||||
// gitaroo man easter egg
|
||||
|
@ -1896,12 +1977,12 @@ class PlayState extends MusicBeatState
|
|||
#end
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.EIGHT)
|
||||
FlxG.switchState(new ui.animDebugShit.DebugBoundingState());
|
||||
|
||||
if (FlxG.keys.justPressed.NINE)
|
||||
iconP1.swapOldIcon();
|
||||
|
||||
// FlxG.watch.addQuick('VOL', vocals.amplitudeLeft);
|
||||
// FlxG.watch.addQuick('VOLRight', vocals.amplitudeRight);
|
||||
|
||||
iconP1.setGraphicSize(Std.int(CoolUtil.coolLerp(iconP1.width, 150, 0.15)));
|
||||
iconP2.setGraphicSize(Std.int(CoolUtil.coolLerp(iconP2.width, 150, 0.15)));
|
||||
|
||||
|
@ -1910,8 +1991,8 @@ class PlayState extends MusicBeatState
|
|||
|
||||
var iconOffset:Int = 26;
|
||||
|
||||
iconP1.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 100, 0) * 0.01) - iconOffset);
|
||||
iconP2.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 100, 0) * 0.01)) - (iconP2.width - iconOffset);
|
||||
iconP1.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.value, 0, 2, 100, 0) * 0.01) - iconOffset);
|
||||
iconP2.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.value, 0, 2, 100, 0) * 0.01)) - (iconP2.width - iconOffset);
|
||||
|
||||
if (health > 2)
|
||||
health = 2;
|
||||
|
@ -1968,24 +2049,9 @@ class PlayState extends MusicBeatState
|
|||
gfSpeed = 2;
|
||||
case 112:
|
||||
gfSpeed = 1;
|
||||
case 163:
|
||||
// FlxG.sound.music.stop();
|
||||
// FlxG.switchState(new TitleState());
|
||||
}
|
||||
}
|
||||
|
||||
if (curSong == 'Bopeebo')
|
||||
{
|
||||
switch (curBeat)
|
||||
{
|
||||
case 128, 129, 130:
|
||||
vocals.volume = 0;
|
||||
// FlxG.sound.music.stop();
|
||||
// FlxG.switchState(new PlayState());
|
||||
}
|
||||
}
|
||||
// better streaming of shit
|
||||
|
||||
if (!inCutscene && !_exiting)
|
||||
{
|
||||
// RESET = Quick Game Over Screen
|
||||
|
@ -2011,8 +2077,8 @@ class PlayState extends MusicBeatState
|
|||
persistentDraw = false;
|
||||
paused = true;
|
||||
|
||||
vocals.stop();
|
||||
FlxG.sound.music.stop();
|
||||
vocals.pause();
|
||||
FlxG.sound.music.pause();
|
||||
|
||||
// unloadAssets();
|
||||
|
||||
|
@ -2020,8 +2086,6 @@ class PlayState extends MusicBeatState
|
|||
|
||||
openSubState(new GameOverSubstate(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y));
|
||||
|
||||
// FlxG.switchState(new GameOverState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y));
|
||||
|
||||
#if discord_rpc
|
||||
// Game Over doesn't get his own variable because it's only used here
|
||||
DiscordClient.changePresence("Game Over - " + detailsText, SONG.song + " (" + storyDifficultyText + ")", iconRPC);
|
||||
|
@ -2034,7 +2098,6 @@ class PlayState extends MusicBeatState
|
|||
var dunceNote:Note = unspawnNotes[0];
|
||||
notes.add(dunceNote);
|
||||
|
||||
var index:Int = unspawnNotes.indexOf(dunceNote);
|
||||
unspawnNotes.shift();
|
||||
}
|
||||
|
||||
|
@ -2101,16 +2164,19 @@ class PlayState extends MusicBeatState
|
|||
if (daNote.altNote)
|
||||
altAnim = '-alt';
|
||||
|
||||
switch (Math.abs(daNote.noteData))
|
||||
if (!daNote.isSustainNote)
|
||||
{
|
||||
case 0:
|
||||
dad.playAnim('singLEFT' + altAnim, true);
|
||||
case 1:
|
||||
dad.playAnim('singDOWN' + altAnim, true);
|
||||
case 2:
|
||||
dad.playAnim('singUP' + altAnim, true);
|
||||
case 3:
|
||||
dad.playAnim('singRIGHT' + altAnim, true);
|
||||
switch (Math.abs(daNote.noteData))
|
||||
{
|
||||
case 0:
|
||||
dad.playAnim('singLEFT' + altAnim, true);
|
||||
case 1:
|
||||
dad.playAnim('singDOWN' + altAnim, true);
|
||||
case 2:
|
||||
dad.playAnim('singUP' + altAnim, true);
|
||||
case 3:
|
||||
dad.playAnim('singRIGHT' + altAnim, true);
|
||||
}
|
||||
}
|
||||
|
||||
dad.holdTimer = 0;
|
||||
|
@ -2149,7 +2215,7 @@ class PlayState extends MusicBeatState
|
|||
{
|
||||
if (daNote.tooLate)
|
||||
{
|
||||
health -= 0.0475;
|
||||
health -= 0.0775;
|
||||
vocals.volume = 0;
|
||||
killCombo();
|
||||
}
|
||||
|
@ -2215,6 +2281,7 @@ class PlayState extends MusicBeatState
|
|||
daPos += 4 * (1000 * 60 / daBPM);
|
||||
}
|
||||
Conductor.songPosition = FlxG.sound.music.time = daPos;
|
||||
Conductor.songPosition += Conductor.offset;
|
||||
updateCurStep();
|
||||
resyncVocals();
|
||||
}
|
||||
|
@ -2331,25 +2398,39 @@ class PlayState extends MusicBeatState
|
|||
|
||||
var isSick:Bool = true;
|
||||
|
||||
if (noteDiff > Conductor.safeZoneOffset * 0.9)
|
||||
var healthMulti:Float = 1;
|
||||
|
||||
if (daNote.noteData >= 0)
|
||||
healthMulti *= 0.033;
|
||||
else
|
||||
healthMulti *= 0.002;
|
||||
|
||||
if (noteDiff > Note.HIT_WINDOW * Note.BAD_THRESHOLD)
|
||||
{
|
||||
healthMulti *= 0; // no health on shit note
|
||||
daRating = 'shit';
|
||||
score = 50;
|
||||
isSick = false; // shitty copypaste on this literally just because im lazy and tired lol!
|
||||
}
|
||||
else if (noteDiff > Conductor.safeZoneOffset * 0.75)
|
||||
else if (noteDiff > Note.HIT_WINDOW * Note.GOOD_THRESHOLD)
|
||||
{
|
||||
healthMulti *= 0.2;
|
||||
|
||||
daRating = 'bad';
|
||||
score = 100;
|
||||
isSick = false;
|
||||
}
|
||||
else if (noteDiff > Conductor.safeZoneOffset * 0.2)
|
||||
else if (noteDiff > Note.HIT_WINDOW * Note.SICK_THRESHOLD)
|
||||
{
|
||||
healthMulti *= 0.78;
|
||||
|
||||
daRating = 'good';
|
||||
score = 200;
|
||||
isSick = false;
|
||||
}
|
||||
|
||||
health += healthMulti;
|
||||
|
||||
if (isSick)
|
||||
{
|
||||
var noteSplash:NoteSplash = grpNoteSplashes.recycle(NoteSplash);
|
||||
|
@ -2744,7 +2825,7 @@ class PlayState extends MusicBeatState
|
|||
function noteMiss(direction:Int = 1):Void
|
||||
{
|
||||
// whole function used to be encased in if (!boyfriend.stunned)
|
||||
health -= 0.04;
|
||||
health -= 0.07;
|
||||
killCombo();
|
||||
|
||||
if (!practiceMode)
|
||||
|
@ -2804,11 +2885,6 @@ class PlayState extends MusicBeatState
|
|||
popUpScore(note.strumTime, note);
|
||||
}
|
||||
|
||||
if (note.noteData >= 0)
|
||||
health += 0.023;
|
||||
else
|
||||
health += 0.004;
|
||||
|
||||
switch (note.noteData)
|
||||
{
|
||||
case 0:
|
||||
|
@ -2841,6 +2917,14 @@ class PlayState extends MusicBeatState
|
|||
}
|
||||
}
|
||||
|
||||
function resetCamFollow():Void
|
||||
{
|
||||
FlxG.camera.follow(camFollow, LOCKON, 0.04);
|
||||
// FlxG.camera.setScrollBounds(0, FlxG.width, 0, FlxG.height);
|
||||
FlxG.camera.zoom = defaultCamZoom;
|
||||
FlxG.camera.focusOn(camFollow.getPosition());
|
||||
}
|
||||
|
||||
var fastCarCanDrive:Bool = true;
|
||||
|
||||
function resetFastCar():Void
|
||||
|
@ -2955,11 +3039,6 @@ class PlayState extends MusicBeatState
|
|||
{
|
||||
resyncVocals();
|
||||
}
|
||||
|
||||
if (dad.curCharacter == 'spooky' && curStep % 4 == 2)
|
||||
{
|
||||
// dad.dance();
|
||||
}
|
||||
}
|
||||
|
||||
var lightningStrikeBeat:Int = 0;
|
||||
|
@ -2985,7 +3064,6 @@ class PlayState extends MusicBeatState
|
|||
// Conductor.changeBPM(SONG.bpm);
|
||||
}
|
||||
// FlxG.log.add('change bpm' + SONG.notes[Std.int(curStep / 16)].changeBPM);
|
||||
wiggleShit.update(Conductor.crochet);
|
||||
|
||||
// HARDCODING FOR MILF ZOOMS!
|
||||
|
||||
|
@ -3017,7 +3095,7 @@ class PlayState extends MusicBeatState
|
|||
{
|
||||
var animShit:ComboCounter = new ComboCounter(-100, 300, combo);
|
||||
animShit.scrollFactor.set(0.6, 0.6);
|
||||
add(animShit);
|
||||
// add(animShit);
|
||||
|
||||
var frameShit:Float = (1 / 24) * 2; // equals 2 frames in the animation
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ typedef SwagSong =
|
|||
var notes:Array<SwagSection>;
|
||||
var bpm:Float;
|
||||
var needsVoices:Bool;
|
||||
var voiceList:Array<String>;
|
||||
var speed:Float;
|
||||
|
||||
var player1:String;
|
||||
|
|
291
source/SpectogramSprite.hx
Normal file
291
source/SpectogramSprite.hx
Normal file
|
@ -0,0 +1,291 @@
|
|||
package;
|
||||
|
||||
import dsp.FFT;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.group.FlxGroup;
|
||||
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.math.FlxVector;
|
||||
import flixel.system.FlxSound;
|
||||
import flixel.util.FlxColor;
|
||||
import lime.utils.Int16Array;
|
||||
|
||||
using Lambda;
|
||||
using flixel.util.FlxSpriteUtil;
|
||||
|
||||
class SpectogramSprite extends FlxTypedSpriteGroup<FlxSprite>
|
||||
{
|
||||
var sampleRate:Int;
|
||||
|
||||
var lengthOfShit:Int = 500;
|
||||
|
||||
public var visType:VISTYPE = UPDATED;
|
||||
|
||||
public var col:Int = FlxColor.WHITE;
|
||||
public var daHeight:Float = FlxG.height;
|
||||
|
||||
public var vis:VisShit;
|
||||
|
||||
public function new(daSound:FlxSound, ?col:FlxColor = FlxColor.WHITE, ?height:Float = 720)
|
||||
{
|
||||
super();
|
||||
|
||||
vis = new VisShit(daSound);
|
||||
this.col = col;
|
||||
this.daHeight = height;
|
||||
|
||||
regenLineShit();
|
||||
|
||||
// makeGraphic(200, 200, FlxColor.BLACK);
|
||||
}
|
||||
|
||||
public function regenLineShit():Void
|
||||
{
|
||||
for (i in 0...lengthOfShit)
|
||||
{
|
||||
var lineShit:FlxSprite = new FlxSprite(100, i / lengthOfShit * daHeight).makeGraphic(1, 1, col);
|
||||
lineShit.active = false;
|
||||
add(lineShit);
|
||||
}
|
||||
}
|
||||
|
||||
var setBuffer:Bool = false;
|
||||
|
||||
public var audioData:Int16Array;
|
||||
|
||||
var numSamples:Int = 0;
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
switch (visType)
|
||||
{
|
||||
case UPDATED:
|
||||
updateVisulizer();
|
||||
|
||||
case FREQUENCIES:
|
||||
updateFFT();
|
||||
default:
|
||||
}
|
||||
|
||||
// if visType is static, call updateVisulizer() manually whenever you want to update it!
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param start is the start in milliseconds?
|
||||
*/
|
||||
public function generateSection(start:Float = 0, seconds:Float = 1):Void
|
||||
{
|
||||
checkAndSetBuffer();
|
||||
|
||||
// vis.checkAndSetBuffer();
|
||||
|
||||
if (setBuffer)
|
||||
{
|
||||
var samplesToGen:Int = Std.int(sampleRate * seconds);
|
||||
var startingSample:Int = Std.int(FlxMath.remapToRange(start, 0, vis.snd.length, 0, numSamples));
|
||||
|
||||
var prevLine:FlxPoint = new FlxPoint();
|
||||
|
||||
for (i in 0...group.members.length)
|
||||
{
|
||||
var sampleApprox:Int = Std.int(FlxMath.remapToRange(i, 0, group.members.length, startingSample, startingSample + samplesToGen));
|
||||
|
||||
var left = audioData[sampleApprox] / 32767;
|
||||
var right = audioData[sampleApprox + 1] / 32767;
|
||||
|
||||
var swagheight:Int = 200;
|
||||
var balanced = (left + right) / 2;
|
||||
|
||||
group.members[i].x = prevLine.x;
|
||||
group.members[i].y = prevLine.y;
|
||||
|
||||
prevLine.x = (balanced * swagheight / 2 + swagheight / 2) + x;
|
||||
prevLine.y = (i / group.members.length * daHeight) + y;
|
||||
|
||||
var line = FlxVector.get(prevLine.x - group.members[i].x, prevLine.y - group.members[i].y);
|
||||
|
||||
group.members[i].setGraphicSize(Std.int(Math.max(line.length, 1)), Std.int(1));
|
||||
group.members[i].angle = line.degrees;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function checkAndSetBuffer()
|
||||
{
|
||||
vis.checkAndSetBuffer();
|
||||
|
||||
if (vis.setBuffer)
|
||||
{
|
||||
audioData = vis.audioData;
|
||||
sampleRate = vis.sampleRate;
|
||||
setBuffer = vis.setBuffer;
|
||||
numSamples = Std.int(audioData.length / 2);
|
||||
}
|
||||
}
|
||||
|
||||
var doAnim:Bool = false;
|
||||
var frameCounter:Int = 0;
|
||||
|
||||
public function updateFFT()
|
||||
{
|
||||
if (vis.snd != null)
|
||||
{
|
||||
var remappedShit:Int = 0;
|
||||
|
||||
checkAndSetBuffer();
|
||||
|
||||
if (!doAnim)
|
||||
{
|
||||
frameCounter++;
|
||||
|
||||
if (frameCounter >= 0)
|
||||
{
|
||||
frameCounter = 0;
|
||||
doAnim = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (setBuffer && doAnim)
|
||||
{
|
||||
doAnim = false;
|
||||
|
||||
if (vis.snd.playing)
|
||||
remappedShit = Std.int(FlxMath.remapToRange(vis.snd.time, 0, vis.snd.length, 0, numSamples));
|
||||
else
|
||||
remappedShit = Std.int(FlxMath.remapToRange(Conductor.songPosition, 0, vis.snd.length, 0, numSamples));
|
||||
|
||||
var i = remappedShit;
|
||||
var prevLine:FlxPoint = new FlxPoint();
|
||||
|
||||
var swagheight:Int = 200;
|
||||
|
||||
var fftSamples:Array<Float> = [];
|
||||
|
||||
// var array:Array<Float> = cast audioData.subarray(remappedShit, remappedShit + lengthOfShit);
|
||||
|
||||
if (FlxG.keys.justPressed.M)
|
||||
{
|
||||
trace('POOP LOL');
|
||||
var funnyAud = audioData.subarray(remappedShit, remappedShit + lengthOfShit);
|
||||
|
||||
for (poop in funnyAud)
|
||||
{
|
||||
// trace("actual audio: " + poop);
|
||||
trace("win: " + poop);
|
||||
}
|
||||
|
||||
// trace(audioData.subarray(remappedShit, remappedShit + lengthOfShit).buffer);
|
||||
}
|
||||
|
||||
for (sample in remappedShit...remappedShit + (Std.int((44100 * (1 / 144)))))
|
||||
{
|
||||
var left = audioData[i] / 32767;
|
||||
var right = audioData[i + 1] / 32767;
|
||||
|
||||
var balanced = (left + right) / 2;
|
||||
|
||||
i += 2;
|
||||
|
||||
// var remappedSample:Float = FlxMath.remapToRange(sample, remappedShit, remappedShit + lengthOfShit, 0, lengthOfShit - 1);
|
||||
fftSamples.push(balanced);
|
||||
}
|
||||
|
||||
var freqShit = vis.funnyFFT(fftSamples);
|
||||
|
||||
for (i in 0...group.members.length)
|
||||
{
|
||||
// needs to be exponential growth / scaling
|
||||
// still need to optmize the FFT to run better, gets only samples needed?
|
||||
// not every frequency is built the same!
|
||||
// 20hz to 40z is a LOT of subtle low ends, but somethin like 20,000hz to 20,020hz, the difference is NOT the same!
|
||||
|
||||
var powedShit:Float = FlxMath.remapToRange(i, 0, group.members.length, 0, 4);
|
||||
|
||||
// a value between 10hz and 100Khz
|
||||
var hzPicker:Float = Math.pow(10, powedShit);
|
||||
|
||||
// var sampleApprox:Int = Std.int(FlxMath.remapToRange(i, 0, group.members.length, startingSample, startingSample + samplesToGen));
|
||||
var remappedFreq:Int = Std.int(FlxMath.remapToRange(hzPicker, 0, 10000, 0, freqShit[0].length - 1));
|
||||
|
||||
group.members[i].x = prevLine.x;
|
||||
group.members[i].y = prevLine.y;
|
||||
|
||||
var freqPower:Float = 0;
|
||||
|
||||
for (pow in 0...freqShit.length)
|
||||
freqPower += freqShit[pow][remappedFreq];
|
||||
|
||||
freqPower /= freqShit.length;
|
||||
var freqIDK:Float = FlxMath.remapToRange(freqPower, 0, 0.000005, 0, 50);
|
||||
|
||||
prevLine.x = (freqIDK * swagheight / 2 + swagheight / 2) + x;
|
||||
prevLine.y = (i / group.members.length * daHeight) + y;
|
||||
|
||||
var line = FlxVector.get(prevLine.x - group.members[i].x, prevLine.y - group.members[i].y);
|
||||
|
||||
// dont draw a line until i figure out a nicer way to view da spikes and shit idk lol!
|
||||
// group.members[i].setGraphicSize(Std.int(Math.max(line.length, 1)), Std.int(1));
|
||||
// group.members[i].angle = line.degrees;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function updateVisulizer():Void
|
||||
{
|
||||
if (vis.snd != null)
|
||||
{
|
||||
var remappedShit:Int = 0;
|
||||
|
||||
checkAndSetBuffer();
|
||||
|
||||
if (setBuffer)
|
||||
{
|
||||
if (vis.snd.playing)
|
||||
remappedShit = Std.int(FlxMath.remapToRange(vis.snd.time, 0, vis.snd.length, 0, numSamples));
|
||||
else
|
||||
remappedShit = Std.int(FlxMath.remapToRange(Conductor.songPosition, 0, vis.snd.length, 0, numSamples));
|
||||
|
||||
var i = remappedShit;
|
||||
var prevLine:FlxPoint = new FlxPoint();
|
||||
|
||||
var swagheight:Int = 200;
|
||||
|
||||
for (sample in remappedShit...remappedShit + lengthOfShit)
|
||||
{
|
||||
var left = audioData[i] / 32767;
|
||||
var right = audioData[i + 1] / 32767;
|
||||
|
||||
var balanced = (left + right) / 2;
|
||||
|
||||
i += 2;
|
||||
|
||||
var remappedSample:Float = FlxMath.remapToRange(sample, remappedShit, remappedShit + lengthOfShit, 0, lengthOfShit - 1);
|
||||
|
||||
group.members[Std.int(remappedSample)].x = prevLine.x;
|
||||
group.members[Std.int(remappedSample)].y = prevLine.y;
|
||||
// group.members[0].y = prevLine.y;
|
||||
|
||||
// FlxSpriteUtil.drawLine(this, prevLine.x, prevLine.y, width * remappedSample, left * height / 2 + height / 2);
|
||||
prevLine.x = (balanced * swagheight / 2 + swagheight / 2) + x;
|
||||
prevLine.y = (Std.int(remappedSample) / lengthOfShit * daHeight) + y;
|
||||
|
||||
var line = FlxVector.get(prevLine.x - group.members[Std.int(remappedSample)].x, prevLine.y - group.members[Std.int(remappedSample)].y);
|
||||
|
||||
group.members[Std.int(remappedSample)].setGraphicSize(Std.int(Math.max(line.length, 1)), Std.int(1));
|
||||
group.members[Std.int(remappedSample)].angle = line.degrees;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum VISTYPE
|
||||
{
|
||||
STATIC;
|
||||
UPDATED;
|
||||
FREQUENCIES;
|
||||
}
|
|
@ -1,12 +1,8 @@
|
|||
package;
|
||||
|
||||
import flixel.FlxGame;
|
||||
import flixel.FlxObject;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond;
|
||||
import flixel.addons.transition.FlxTransitionableState;
|
||||
import flixel.addons.transition.TransitionData;
|
||||
import flixel.graphics.FlxGraphic;
|
||||
import flixel.FlxState;
|
||||
import flixel.group.FlxGroup;
|
||||
import flixel.input.android.FlxAndroidKey;
|
||||
import flixel.input.android.FlxAndroidKeys;
|
||||
|
@ -14,8 +10,6 @@ import flixel.input.gamepad.FlxGamepad;
|
|||
import flixel.input.gamepad.id.SwitchJoyconLeftID;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.system.FlxAssets.FlxGraphicAsset;
|
||||
import flixel.system.FlxAssets;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.tweens.FlxEase;
|
||||
import flixel.tweens.FlxTween;
|
||||
|
@ -26,32 +20,21 @@ import lime.graphics.Image;
|
|||
import lime.media.AudioContext;
|
||||
import lime.ui.Window;
|
||||
import openfl.Assets;
|
||||
import openfl.display.BitmapData;
|
||||
import openfl.display.Sprite;
|
||||
import openfl.events.AsyncErrorEvent;
|
||||
import openfl.events.AsyncErrorEvent;
|
||||
import openfl.events.Event;
|
||||
import openfl.events.MouseEvent;
|
||||
import openfl.events.NetStatusEvent;
|
||||
import openfl.media.Video;
|
||||
import openfl.net.NetConnection;
|
||||
import openfl.net.NetStream;
|
||||
import shaderslmfao.BuildingShaders.BuildingShader;
|
||||
import shaderslmfao.BuildingShaders;
|
||||
import shaderslmfao.ColorSwap;
|
||||
import shaderslmfao.TitleOutline;
|
||||
import ui.PreferencesMenu;
|
||||
import ui.stageBuildShit.StageBuilderState;
|
||||
|
||||
using StringTools;
|
||||
|
||||
#if colyseus
|
||||
import io.colyseus.Client;
|
||||
import io.colyseus.Room;
|
||||
#end
|
||||
#if discord_rpc
|
||||
import Discord.DiscordClient;
|
||||
#end
|
||||
#if desktop
|
||||
import sys.FileSystem;
|
||||
import sys.io.File;
|
||||
|
@ -62,20 +45,15 @@ class TitleState extends MusicBeatState
|
|||
{
|
||||
public static var initialized:Bool = false;
|
||||
|
||||
var startedIntro:Bool;
|
||||
|
||||
var blackScreen:FlxSprite;
|
||||
var credGroup:FlxGroup;
|
||||
var credTextShit:Alphabet;
|
||||
var textGroup:FlxGroup;
|
||||
var ngSpr:FlxSprite;
|
||||
|
||||
var curWacky:Array<String> = [];
|
||||
var wackyImage:FlxSprite;
|
||||
var lastBeat:Int = 0;
|
||||
var swagShader:ColorSwap;
|
||||
var alphaShader:BuildingShaders;
|
||||
var thingie:FlxSprite;
|
||||
|
||||
var video:Video;
|
||||
var netStream:NetStream;
|
||||
|
@ -83,24 +61,9 @@ class TitleState extends MusicBeatState
|
|||
|
||||
override public function create():Void
|
||||
{
|
||||
#if android
|
||||
FlxG.android.preventDefaultKeys = [FlxAndroidKey.BACK];
|
||||
#end
|
||||
|
||||
FlxG.debugger.addButton(LEFT, new BitmapData(200, 200), function()
|
||||
{
|
||||
FlxG.debugger.visible = false;
|
||||
});
|
||||
|
||||
startedIntro = false;
|
||||
|
||||
FlxG.game.focusLostFramerate = 60;
|
||||
|
||||
swagShader = new ColorSwap();
|
||||
alphaShader = new BuildingShaders();
|
||||
|
||||
FlxG.sound.muteKeys = [ZERO];
|
||||
|
||||
curWacky = FlxG.random.getObject(getIntroTextShit());
|
||||
FlxG.sound.cache(Paths.music('freakyMenu'));
|
||||
|
||||
|
@ -108,57 +71,6 @@ class TitleState extends MusicBeatState
|
|||
|
||||
super.create();
|
||||
|
||||
FlxG.save.bind('funkin', 'ninjamuffin99');
|
||||
|
||||
// https://github.com/HaxeFlixel/flixel/pull/2396
|
||||
// IF/WHEN MY PR GOES THRU AND IT GETS INTO MAIN FLIXEL, DELETE THIS CHUNKOF CODE, AND THEN UNCOMMENT THE LINE BELOW
|
||||
// FlxG.sound.loadSavedPrefs();
|
||||
|
||||
if (FlxG.save.data.volume != null)
|
||||
{
|
||||
FlxG.sound.volume = FlxG.save.data.volume;
|
||||
}
|
||||
|
||||
if (FlxG.save.data.mute != null)
|
||||
{
|
||||
FlxG.sound.muted = FlxG.save.data.mute;
|
||||
}
|
||||
|
||||
// FlxG.save.close();
|
||||
// FlxG.sound.loadSavedPrefs();
|
||||
PreferencesMenu.initPrefs();
|
||||
PlayerSettings.init();
|
||||
Highscore.load();
|
||||
|
||||
#if newgrounds
|
||||
NGio.init();
|
||||
#end
|
||||
|
||||
if (FlxG.save.data.weekUnlocked != null)
|
||||
{
|
||||
// FIX LATER!!!
|
||||
// WEEK UNLOCK PROGRESSION!!
|
||||
// StoryMenuState.weekUnlocked = FlxG.save.data.weekUnlocked;
|
||||
|
||||
if (StoryMenuState.weekUnlocked.length < 4)
|
||||
StoryMenuState.weekUnlocked.insert(0, true);
|
||||
|
||||
// QUICK PATCH OOPS!
|
||||
if (!StoryMenuState.weekUnlocked[0])
|
||||
StoryMenuState.weekUnlocked[0] = true;
|
||||
}
|
||||
|
||||
if (FlxG.save.data.seenVideo != null)
|
||||
{
|
||||
VideoState.seenVideo = FlxG.save.data.seenVideo;
|
||||
}
|
||||
|
||||
#if FREEPLAY
|
||||
FlxG.switchState(new FreeplayState());
|
||||
#elseif ANIMATE
|
||||
FlxG.switchState(new animate.AnimTestStage());
|
||||
#elseif CHARTING
|
||||
FlxG.switchState(new ChartingState());
|
||||
/*
|
||||
#elseif web
|
||||
|
||||
|
@ -190,30 +102,10 @@ class TitleState extends MusicBeatState
|
|||
*/
|
||||
|
||||
// netConnection.addEventListener(MouseEvent.MOUSE_DOWN, overlay_onMouseDown);
|
||||
#elseif STAGEBUILD
|
||||
FlxG.switchState(new StageBuilderState());
|
||||
#elseif ANIMDEBUG
|
||||
FlxG.switchState(new ui.animDebugShit.DebugBoundingState());
|
||||
#elseif NETTEST
|
||||
FlxG.switchState(new netTest.NetTest());
|
||||
#else
|
||||
new FlxTimer().start(1, function(tmr:FlxTimer)
|
||||
{
|
||||
startIntro();
|
||||
});
|
||||
#end
|
||||
|
||||
#if discord_rpc
|
||||
DiscordClient.initialize();
|
||||
|
||||
Application.current.onExit.add(function(exitCode)
|
||||
{
|
||||
DiscordClient.shutdown();
|
||||
});
|
||||
#end
|
||||
|
||||
// FlxG.stage.window.borderless = true;
|
||||
// FlxG.stage.window.mouseLock = true;
|
||||
}
|
||||
|
||||
private function client_onMetaData(metaData:Dynamic)
|
||||
|
@ -261,18 +153,6 @@ class TitleState extends MusicBeatState
|
|||
|
||||
function startIntro()
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
var diamond:FlxGraphic = FlxGraphic.fromClass(GraphicTransTileDiamond);
|
||||
diamond.persist = true;
|
||||
diamond.destroyOnNoUse = false;
|
||||
|
||||
FlxTransitionableState.defaultTransIn = new TransitionData(FADE, FlxColor.BLACK, 1, new FlxPoint(0, -1), {asset: diamond, width: 32, height: 32},
|
||||
new FlxRect(-200, -200, FlxG.width * 1.4, FlxG.height * 1.4));
|
||||
FlxTransitionableState.defaultTransOut = new TransitionData(FADE, FlxColor.BLACK, 0.7, new FlxPoint(0, 1),
|
||||
{asset: diamond, width: 32, height: 32}, new FlxRect(-200, -200, FlxG.width * 1.4, FlxG.height * 1.4));
|
||||
}
|
||||
|
||||
if (FlxG.sound.music == null || !FlxG.sound.music.playing)
|
||||
{
|
||||
FlxG.sound.playMusic(Paths.music('freakyMenu'), 0);
|
||||
|
@ -283,10 +163,6 @@ class TitleState extends MusicBeatState
|
|||
persistentUpdate = true;
|
||||
|
||||
var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
|
||||
// bg.antialiasing = true;
|
||||
// bg.setGraphicSize(Std.int(bg.width * 0.6));
|
||||
// bg.updateHitbox();
|
||||
|
||||
add(bg);
|
||||
|
||||
logoBl = new FlxSprite(-150, -100);
|
||||
|
@ -334,34 +210,18 @@ class TitleState extends MusicBeatState
|
|||
// titleText.screenCenter(X);
|
||||
add(titleText);
|
||||
|
||||
var logo:FlxSprite = new FlxSprite().loadGraphic(Paths.image('logo'));
|
||||
logo.screenCenter();
|
||||
logo.antialiasing = true;
|
||||
// add(logo);
|
||||
|
||||
// FlxTween.tween(logoBl, {y: logoBl.y + 50}, 0.6, {ease: FlxEase.quadInOut, type: PINGPONG});
|
||||
// FlxTween.tween(logo, {y: logoBl.y + 50}, 0.6, {ease: FlxEase.quadInOut, type: PINGPONG, startDelay: 0.1});
|
||||
var animShit:ComboCounter = new ComboCounter(200, 200, 1423);
|
||||
// add(animShit);
|
||||
credGroup = new FlxGroup();
|
||||
add(credGroup);
|
||||
|
||||
textGroup = new FlxGroup();
|
||||
|
||||
blackScreen = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
|
||||
blackScreen = bg.clone();
|
||||
credGroup.add(blackScreen);
|
||||
|
||||
// var atlasBullShit:FlxSprite = new FlxSprite();
|
||||
// atlasBullShit.frames = CoolUtil.fromAnimate(Paths.image('money'), Paths.file('images/money.json'));
|
||||
// credGroup.add(atlasBullShit);
|
||||
|
||||
credTextShit = new Alphabet(0, 0, "ninjamuffin99\nPhantomArcade\nkawaisprite\nevilsk8er", true);
|
||||
credTextShit.screenCenter();
|
||||
|
||||
// credTextShit.alignment = CENTER;
|
||||
|
||||
credTextShit.visible = false;
|
||||
|
||||
ngSpr = new FlxSprite(0, FlxG.height * 0.52);
|
||||
|
||||
if (FlxG.random.bool(1))
|
||||
|
@ -388,8 +248,6 @@ class TitleState extends MusicBeatState
|
|||
ngSpr.screenCenter(X);
|
||||
ngSpr.antialiasing = true;
|
||||
|
||||
FlxTween.tween(credTextShit, {y: credTextShit.y + 20}, 2.9, {ease: FlxEase.quadInOut, type: PINGPONG});
|
||||
|
||||
FlxG.mouse.visible = false;
|
||||
|
||||
if (initialized)
|
||||
|
@ -399,9 +257,6 @@ class TitleState extends MusicBeatState
|
|||
|
||||
if (FlxG.sound.music != null)
|
||||
FlxG.sound.music.onComplete = function() FlxG.switchState(new VideoState());
|
||||
|
||||
startedIntro = true;
|
||||
// credGroup.add(credTextShit);
|
||||
}
|
||||
|
||||
function getIntroTextShit():Array<Array<String>>
|
||||
|
@ -421,9 +276,6 @@ class TitleState extends MusicBeatState
|
|||
|
||||
var transitioning:Bool = false;
|
||||
|
||||
var fnfShit:String = "Friday Night Funkin'";
|
||||
var thingOffset:Int = 0;
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
/* if (FlxG.onMobile)
|
||||
|
@ -501,9 +353,10 @@ class TitleState extends MusicBeatState
|
|||
|
||||
if (FlxG.sound.music != null)
|
||||
Conductor.songPosition = FlxG.sound.music.time;
|
||||
// FlxG.watch.addQuick('amp', FlxG.sound.music.amplitude);
|
||||
if (FlxG.keys.justPressed.F)
|
||||
FlxG.fullscreen = !FlxG.fullscreen;
|
||||
|
||||
// do controls.PAUSE | controls.ACCEPT instead?
|
||||
var pressedEnter:Bool = FlxG.keys.justPressed.ENTER;
|
||||
|
||||
if (FlxG.onMobile)
|
||||
|
@ -542,13 +395,8 @@ class TitleState extends MusicBeatState
|
|||
FlxG.camera.flash(FlxColor.WHITE, 1);
|
||||
FlxG.sound.play(Paths.sound('confirmMenu'), 0.7);
|
||||
transitioning = true;
|
||||
// FlxG.sound.music.stop();
|
||||
|
||||
// These assets are very unlikely to be used for the rest of gameplay, so it unloads them from cache/memory
|
||||
// Saves about 50mb of RAM or so???
|
||||
Assets.cache.clear(Paths.image('gfDanceTitle'));
|
||||
Assets.cache.clear(Paths.image('logoBumpin'));
|
||||
Assets.cache.clear(Paths.image('titleEnter'));
|
||||
var targetState:FlxState = new MainMenuState();
|
||||
|
||||
#if newgrounds
|
||||
if (!OutdatedSubState.leftState)
|
||||
|
@ -561,19 +409,26 @@ class TitleState extends MusicBeatState
|
|||
if (version.trim() != onlineVersion)
|
||||
{
|
||||
trace('OLD VERSION!');
|
||||
// FlxG.switchState(new OutdatedSubState());
|
||||
// targetState = new OutdatedSubState();
|
||||
}
|
||||
else
|
||||
{
|
||||
// FlxG.switchState(new MainMenuState());
|
||||
// targetState = new MainMenuState();
|
||||
}
|
||||
// REDO FOR ITCH/FINAL SHIT
|
||||
FlxG.switchState(new MainMenuState());
|
||||
});
|
||||
}
|
||||
#else
|
||||
FlxG.switchState(new MainMenuState());
|
||||
#end
|
||||
new FlxTimer().start(2, function(tmr:FlxTimer)
|
||||
{
|
||||
// These assets are very unlikely to be used for the rest of gameplay, so it unloads them from cache/memory
|
||||
// Saves about 50mb of RAM or so???
|
||||
Assets.cache.clear(Paths.image('gfDanceTitle'));
|
||||
Assets.cache.clear(Paths.image('logoBumpin'));
|
||||
Assets.cache.clear(Paths.image('titleEnter'));
|
||||
// ngSpr??
|
||||
FlxG.switchState(targetState);
|
||||
});
|
||||
// FlxG.sound.play(Paths.music('titleShoot'), 0.7);
|
||||
}
|
||||
if (pressedEnter && !skippedIntro && initialized)
|
||||
|
@ -591,8 +446,6 @@ class TitleState extends MusicBeatState
|
|||
#end
|
||||
*/
|
||||
|
||||
// if (FlxG.keys.justPressed.SPACE)
|
||||
// swagShader.hasOutline = !swagShader.hasOutline;
|
||||
if (controls.UI_LEFT)
|
||||
swagShader.update(-elapsed * 0.1);
|
||||
if (controls.UI_RIGHT)
|
||||
|
@ -640,6 +493,10 @@ class TitleState extends MusicBeatState
|
|||
cheatActive = true;
|
||||
|
||||
FlxG.sound.playMusic(Paths.music('tutorialTitle'), 1);
|
||||
|
||||
var spec:SpectogramSprite = new SpectogramSprite(FlxG.sound.music);
|
||||
add(spec);
|
||||
|
||||
Conductor.changeBPM(190);
|
||||
FlxG.camera.flash(FlxColor.WHITE, 1);
|
||||
FlxG.sound.play(Paths.sound('confirmMenu'), 0.7);
|
||||
|
@ -678,11 +535,56 @@ class TitleState extends MusicBeatState
|
|||
}
|
||||
|
||||
var isRainbow:Bool = false;
|
||||
var skippedIntro:Bool = false;
|
||||
|
||||
override function beatHit()
|
||||
{
|
||||
super.beatHit();
|
||||
|
||||
if (!skippedIntro)
|
||||
{
|
||||
FlxG.log.add(curBeat);
|
||||
// if the user is draggin the window some beats will
|
||||
// be missed so this is just to compensate
|
||||
if (curBeat > lastBeat)
|
||||
{
|
||||
for (i in lastBeat...curBeat)
|
||||
{
|
||||
switch (i + 1)
|
||||
{
|
||||
case 1:
|
||||
createCoolText(['ninjamuffin99', 'phantomArcade', 'kawaisprite', 'evilsk8er']);
|
||||
case 3:
|
||||
addMoreText('present');
|
||||
case 4:
|
||||
deleteCoolText();
|
||||
case 5:
|
||||
createCoolText(['In association', 'with']);
|
||||
case 7:
|
||||
addMoreText('newgrounds');
|
||||
ngSpr.visible = true;
|
||||
case 8:
|
||||
deleteCoolText();
|
||||
ngSpr.visible = false;
|
||||
case 9:
|
||||
createCoolText([curWacky[0]]);
|
||||
case 11:
|
||||
addMoreText(curWacky[1]);
|
||||
case 12:
|
||||
deleteCoolText();
|
||||
case 13:
|
||||
addMoreText('Friday');
|
||||
case 14:
|
||||
addMoreText('Night');
|
||||
case 15:
|
||||
addMoreText('Funkin');
|
||||
case 16:
|
||||
skipIntro();
|
||||
}
|
||||
}
|
||||
}
|
||||
lastBeat = curBeat;
|
||||
}
|
||||
if (skippedIntro)
|
||||
{
|
||||
if (cheatActive && curBeat % 2 == 0)
|
||||
|
@ -697,73 +599,8 @@ class TitleState extends MusicBeatState
|
|||
else
|
||||
gfDance.animation.play('danceLeft');
|
||||
}
|
||||
else
|
||||
{
|
||||
FlxG.log.add(curBeat);
|
||||
// if the user is draggin the window some beats will
|
||||
// be missed so this is just to compensate
|
||||
if (curBeat > lastBeat)
|
||||
{
|
||||
for (i in lastBeat...curBeat)
|
||||
{
|
||||
switch (i + 1)
|
||||
{
|
||||
case 1:
|
||||
createCoolText(['ninjamuffin99', 'phantomArcade', 'kawaisprite', 'evilsk8er']);
|
||||
// credTextShit.visible = true;
|
||||
case 3:
|
||||
addMoreText('present');
|
||||
// credTextShit.text += '\npresent...';
|
||||
// credTextShit.addText();
|
||||
case 4:
|
||||
deleteCoolText();
|
||||
// credTextShit.visible = false;
|
||||
// credTextShit.text = 'In association \nwith';
|
||||
// credTextShit.screenCenter();
|
||||
case 5:
|
||||
createCoolText(['In association', 'with']);
|
||||
case 7:
|
||||
addMoreText('newgrounds');
|
||||
ngSpr.visible = true;
|
||||
// credTextShit.text += '\nNewgrounds';
|
||||
case 8:
|
||||
deleteCoolText();
|
||||
ngSpr.visible = false;
|
||||
// credTextShit.visible = false;
|
||||
|
||||
// credTextShit.text = 'Shoutouts Tom Fulp';
|
||||
// credTextShit.screenCenter();
|
||||
case 9:
|
||||
createCoolText([curWacky[0]]);
|
||||
// credTextShit.visible = true;
|
||||
case 11:
|
||||
addMoreText(curWacky[1]);
|
||||
// credTextShit.text += '\nlmao';
|
||||
case 12:
|
||||
deleteCoolText();
|
||||
// credTextShit.visible = false;
|
||||
// credTextShit.text = "Friday";
|
||||
// credTextShit.screenCenter();
|
||||
case 13:
|
||||
addMoreText('Friday');
|
||||
// credTextShit.visible = true;
|
||||
case 14:
|
||||
addMoreText('Night');
|
||||
// credTextShit.text += '\nNight';
|
||||
case 15:
|
||||
addMoreText('Funkin'); // credTextShit.text += '\nFunkin';
|
||||
|
||||
case 16:
|
||||
skipIntro();
|
||||
}
|
||||
}
|
||||
}
|
||||
lastBeat = curBeat;
|
||||
}
|
||||
}
|
||||
|
||||
var skippedIntro:Bool = false;
|
||||
|
||||
function skipIntro():Void
|
||||
{
|
||||
if (!skippedIntro)
|
||||
|
|
131
source/VisShit.hx
Normal file
131
source/VisShit.hx
Normal file
|
@ -0,0 +1,131 @@
|
|||
package;
|
||||
|
||||
import dsp.FFT;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.system.FlxSound;
|
||||
import lime.utils.Int16Array;
|
||||
|
||||
using Lambda;
|
||||
|
||||
class VisShit
|
||||
{
|
||||
public var snd:FlxSound;
|
||||
public var setBuffer:Bool = false;
|
||||
public var audioData:Int16Array;
|
||||
public var sampleRate:Int = 44100; // default, ez?
|
||||
public var numSamples:Int = 0;
|
||||
|
||||
public function new(snd:FlxSound)
|
||||
{
|
||||
this.snd = snd;
|
||||
}
|
||||
|
||||
public function funnyFFT(samples:Array<Float>, ?skipped:Int = 1):Array<Array<Float>>
|
||||
{
|
||||
// nab multiple samples at once in while / for loops?
|
||||
|
||||
var fs:Float = 44100 / skipped; // sample rate shit?
|
||||
|
||||
final fftN = 1024;
|
||||
final halfN = Std.int(fftN / 2);
|
||||
final overlap = 0.5;
|
||||
final hop = Std.int(fftN * (1 - overlap));
|
||||
|
||||
// window function to compensate for overlapping
|
||||
final a0 = 0.5; // => Hann(ing) window
|
||||
final window = (n:Int) -> a0 - (1 - a0) * Math.cos(2 * Math.PI * n / fftN);
|
||||
|
||||
// NOTE TO SELF FOR WHEN I WAKE UP
|
||||
|
||||
// helpers, note that spectrum indexes suppose non-negative frequencies
|
||||
final binSize = fs / fftN;
|
||||
final indexToFreq = function(k:Int)
|
||||
{
|
||||
var powShit:Float = FlxMath.remapToRange(k, 0, halfN, 0, CoolUtil.coolBaseLog(10, halfN)); // 4.3 is almost the log of 20Khz or so. Close enuf lol
|
||||
|
||||
return 1.0 * (Math.pow(10, powShit)); // we need the `1.0` to avoid overflows
|
||||
};
|
||||
|
||||
// "melodic" band-pass filter
|
||||
final minFreq = 20.70;
|
||||
final maxFreq = 4000.01;
|
||||
final melodicBandPass = function(k:Int, s:Float)
|
||||
{
|
||||
// final freq = indexToFreq(k);
|
||||
// final filter = freq > minFreq - binSize && freq < maxFreq + binSize ? 1 : 0;
|
||||
return s;
|
||||
};
|
||||
|
||||
var freqOutput:Array<Array<Float>> = [];
|
||||
|
||||
var c = 0; // index where each chunk begins
|
||||
var indexOfArray:Int = 0;
|
||||
while (c < samples.length)
|
||||
{
|
||||
// take a chunk (zero-padded if needed) and apply the window
|
||||
final chunk = [
|
||||
for (n in 0...fftN)
|
||||
(c + n < samples.length ? samples[c + n] : 0.0) * window(n)
|
||||
];
|
||||
|
||||
// compute positive spectrum with sampling correction and BP filter
|
||||
final freqs = FFT.rfft(chunk).map(z -> z.scale(1 / fftN).magnitude).mapi(melodicBandPass);
|
||||
|
||||
freqOutput.push([]);
|
||||
|
||||
// if (FlxG.keys.justPressed.M)
|
||||
// trace(FFT.rfft(chunk).map(z -> z.scale(1 / fs).magnitude));
|
||||
|
||||
// find spectral peaks and their instantaneous frequencies
|
||||
for (k => s in freqs)
|
||||
{
|
||||
final time = c / fs;
|
||||
final freq = indexToFreq(k);
|
||||
final power = s * s;
|
||||
if (FlxG.keys.justPressed.I)
|
||||
{
|
||||
trace(k);
|
||||
|
||||
haxe.Log.trace('${time};${freq};${power}', null);
|
||||
}
|
||||
if (freq < maxFreq)
|
||||
freqOutput[indexOfArray].push(power);
|
||||
//
|
||||
}
|
||||
// haxe.Log.trace("", null);
|
||||
|
||||
indexOfArray++;
|
||||
// move to next (overlapping) chunk
|
||||
c += hop;
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.C)
|
||||
trace(freqOutput.length);
|
||||
|
||||
return freqOutput;
|
||||
}
|
||||
|
||||
public function checkAndSetBuffer()
|
||||
{
|
||||
if (snd != null && snd.playing)
|
||||
{
|
||||
if (!setBuffer)
|
||||
{
|
||||
// Math.pow3
|
||||
@:privateAccess
|
||||
var buf = snd._channel.__source.buffer;
|
||||
|
||||
// @:privateAccess
|
||||
audioData = cast buf.data; // jank and hacky lol! kinda busted on HTML5 also!!
|
||||
sampleRate = buf.sampleRate;
|
||||
|
||||
trace('got audio buffer shit');
|
||||
trace(sampleRate);
|
||||
trace(buf.bitsPerSample);
|
||||
|
||||
setBuffer = true;
|
||||
numSamples = Std.int(audioData.length / 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
83
source/VoicesGroup.hx
Normal file
83
source/VoicesGroup.hx
Normal file
|
@ -0,0 +1,83 @@
|
|||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.system.FlxSound;
|
||||
|
||||
// different than FlxSoundGroup cuz this can control all the sounds time and shit
|
||||
// when needed
|
||||
class VoicesGroup extends FlxTypedGroup<FlxSound>
|
||||
{
|
||||
public var time(default, set):Float = 0;
|
||||
|
||||
public var volume(default, set):Float = 1;
|
||||
|
||||
// make it a group that you add to?
|
||||
public function new(song:String, ?files:Array<String>, ?needsVoices:Bool = true)
|
||||
{
|
||||
super();
|
||||
|
||||
if (!needsVoices)
|
||||
{
|
||||
// simply adds an empty sound? fills it in moreso for easier backwards compatibility
|
||||
add(new FlxSound());
|
||||
// FlxG.sound.list.add(snd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (files == null)
|
||||
files = [""]; // loads with no file name assumption, to load "Voices.ogg" or whatev normally
|
||||
|
||||
for (sndFile in files)
|
||||
{
|
||||
var snd:FlxSound = new FlxSound().loadEmbedded(Paths.voices(song, '$sndFile'));
|
||||
FlxG.sound.list.add(snd); // adds it to sound group for proper volumes
|
||||
add(snd); // adds it to main group for other shit
|
||||
}
|
||||
}
|
||||
|
||||
// prob a better / cleaner way to do all these forEach stuff?
|
||||
public function pause()
|
||||
{
|
||||
forEachAlive(function(snd)
|
||||
{
|
||||
snd.pause();
|
||||
});
|
||||
}
|
||||
|
||||
public function play()
|
||||
{
|
||||
forEachAlive(function(snd)
|
||||
{
|
||||
snd.play();
|
||||
});
|
||||
}
|
||||
|
||||
public function stop()
|
||||
{
|
||||
forEachAlive(function(snd)
|
||||
{
|
||||
snd.stop();
|
||||
});
|
||||
}
|
||||
|
||||
function set_time(time:Float):Float
|
||||
{
|
||||
forEachAlive(function(snd)
|
||||
{
|
||||
// account for different offsets per sound?
|
||||
snd.time = time;
|
||||
});
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
// in PlayState, adjust the code so that it only mutes the player1 vocal tracks?
|
||||
function set_volume(volume:Float):Float
|
||||
{
|
||||
forEachAlive(function(snd)
|
||||
{
|
||||
snd.volume = volume;
|
||||
});
|
||||
|
||||
return volume;
|
||||
}
|
||||
}
|
|
@ -96,8 +96,25 @@ class WiggleShader extends FlxShader
|
|||
|
||||
if (effectType == EFFECT_TYPE_DREAMY)
|
||||
{
|
||||
float offsetX = sin(pt.y * uFrequency + uTime * uSpeed) * uWaveAmplitude;
|
||||
pt.x += offsetX; // * (pt.y - 1.0); // <- Uncomment to stop bottom part of the screen from moving
|
||||
|
||||
float w = 1 / openfl_TextureSize.y;
|
||||
float h = 1 / openfl_TextureSize.x;
|
||||
|
||||
// look mom, I know how to write shaders now
|
||||
|
||||
pt.x = floor(pt.x / h) * h;
|
||||
|
||||
float offsetX = sin(pt.x * uFrequency + uTime * uSpeed) * uWaveAmplitude;
|
||||
pt.y += floor(offsetX / w) * w; // * (pt.y - 1.0); // <- Uncomment to stop bottom part of the screen from moving
|
||||
|
||||
|
||||
pt.y = floor(pt.y / w) * w;
|
||||
|
||||
float offsetY = sin(pt.y * (uFrequency / 2.0) + uTime * (uSpeed / 2.0)) * (uWaveAmplitude / 2.0);
|
||||
pt.x += floor(offsetY / h) * h; // * (pt.y - 1.0); // <- Uncomment to stop bottom part of the screen from moving
|
||||
|
||||
|
||||
|
||||
}
|
||||
else if (effectType == EFFECT_TYPE_WAVY)
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package animate;
|
||||
|
||||
import animate.FlxSymbol.Parsed;
|
||||
import animate.FlxSymbol.Timeline;
|
||||
// import animate.FlxSymbol.Parsed;
|
||||
// import animate.FlxSymbol.Timeline;
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
|
@ -13,7 +13,7 @@ import lime.utils.Assets;
|
|||
|
||||
class AnimateTimeline extends FlxTypedGroup<FlxSprite>
|
||||
{
|
||||
var coolParsed:Parsed;
|
||||
// var coolParsed:Parsed;
|
||||
var playhead:FlxSprite;
|
||||
|
||||
public var curFrame(default, set):Int;
|
||||
|
@ -31,45 +31,47 @@ class AnimateTimeline extends FlxTypedGroup<FlxSprite>
|
|||
{
|
||||
super();
|
||||
|
||||
hudCamShit = new FlxCamera();
|
||||
hudCamShit.bgColor = FlxColor.TRANSPARENT;
|
||||
FlxG.cameras.add(hudCamShit, false);
|
||||
/* hudCamShit = new FlxCamera();
|
||||
hudCamShit.bgColor = FlxColor.TRANSPARENT;
|
||||
FlxG.cameras.add(hudCamShit, false);
|
||||
|
||||
playhead = new FlxSprite(0, -12).makeGraphic(2, 10, FlxColor.MAGENTA);
|
||||
add(playhead);
|
||||
playhead = new FlxSprite(0, -12).makeGraphic(2, 10, FlxColor.MAGENTA);
|
||||
add(playhead);
|
||||
|
||||
hudCamShit.follow(playhead);
|
||||
hudCamShit.setScrollBounds(0, null, -14, null);
|
||||
hudCamShit.follow(playhead);
|
||||
hudCamShit.setScrollBounds(0, null, -14, null);
|
||||
|
||||
curFrame = 0;
|
||||
curFrame = 0;
|
||||
|
||||
coolParsed = cast Json.parse(Assets.getText(parsed));
|
||||
coolParsed = cast Json.parse(Assets.getText(parsed));
|
||||
|
||||
var layerNum:Int = 0;
|
||||
for (layer in coolParsed.AN.TL.L)
|
||||
{
|
||||
var frameNum:Int = 0;
|
||||
var layerNum:Int = 0;
|
||||
for (layer in coolParsed.AN.TL.L)
|
||||
{
|
||||
var frameNum:Int = 0;
|
||||
|
||||
for (frame in layer.FR)
|
||||
{
|
||||
var coolFrame:TimelineFrame = new TimelineFrame((frame.I * 12) + 12 * 5, layerNum * 12, frame.DU, frame);
|
||||
add(coolFrame);
|
||||
frameNum++;
|
||||
}
|
||||
for (frame in layer.FR)
|
||||
{
|
||||
var coolFrame:TimelineFrame = new TimelineFrame((frame.I * 12) + 12 * 5, layerNum * 12, frame.DU, frame);
|
||||
add(coolFrame);
|
||||
frameNum++;
|
||||
}
|
||||
|
||||
var layerName:FlxText = new FlxText(0, layerNum * 12, 0, layer.LN, 10);
|
||||
layerName.color = FlxColor.PURPLE;
|
||||
layerName.scrollFactor.x = 0;
|
||||
var layerName:FlxText = new FlxText(0, layerNum * 12, 0, layer.LN, 10);
|
||||
layerName.color = FlxColor.PURPLE;
|
||||
layerName.scrollFactor.x = 0;
|
||||
|
||||
var layerBG:FlxSprite = new FlxSprite(0, layerNum * 12).makeGraphic(12 * 4, 12);
|
||||
layerBG.scrollFactor.x = 0;
|
||||
var layerBG:FlxSprite = new FlxSprite(0, layerNum * 12).makeGraphic(12 * 4, 12);
|
||||
layerBG.scrollFactor.x = 0;
|
||||
|
||||
add(layerBG);
|
||||
add(layerName);
|
||||
add(layerBG);
|
||||
add(layerName);
|
||||
|
||||
layerNum++;
|
||||
}
|
||||
layerNum++;
|
||||
}
|
||||
|
||||
|
||||
this.cameras = [hudCamShit];
|
||||
this.cameras = [hudCamShit];
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,69 +2,182 @@ package animate;
|
|||
|
||||
// import animateAtlasPlayer.assets.AssetManager;
|
||||
// import animateAtlasPlayer.core.Animation;
|
||||
import animate.FlxSymbol.Parsed;
|
||||
import animate.ParseAnimate.AnimJson;
|
||||
import animate.ParseAnimate.Sprite;
|
||||
import animate.ParseAnimate.Spritemap;
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.FlxGraphic;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.graphics.frames.FlxFrame.FlxFrameAngle;
|
||||
import flixel.group.FlxGroup;
|
||||
import flixel.math.FlxMatrix;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.system.FlxAssets.FlxGraphicAsset;
|
||||
import haxe.Json;
|
||||
import haxe.Utf8;
|
||||
import haxe.format.JsonParser;
|
||||
import lime.text.UTF8String;
|
||||
import openfl.Assets;
|
||||
import openfl.display.BitmapData;
|
||||
import openfl.geom.Matrix;
|
||||
import openfl.geom.Rectangle;
|
||||
|
||||
class FlxAnimate extends FlxSymbol
|
||||
{
|
||||
// var myAnim:Animation;
|
||||
// var animBitmap:BitmapData;
|
||||
var loadedQueue:Bool = false;
|
||||
var jsonAnim:AnimJson;
|
||||
|
||||
var swagFrames:Array<BitmapData> = [];
|
||||
var sprGrp:FlxTypedGroup<FlxSymbol>;
|
||||
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
var folder:String = 'tightBarsLol';
|
||||
coolParse = cast Json.parse(Assets.getText(Paths.file('images/' + folder + '/Animation.json')));
|
||||
super(x, y);
|
||||
|
||||
// reverses the layers, for proper rendering!
|
||||
coolParse.AN.TL.L.reverse();
|
||||
super(x, y, coolParse);
|
||||
sprGrp = new FlxTypedGroup<FlxSymbol>();
|
||||
|
||||
var tests:Array<String> = ['tightBarsLol', 'tightestBars'];
|
||||
|
||||
var folder:String = tests[1];
|
||||
|
||||
frames = FlxAnimate.fromAnimate(Paths.file('images/' + folder + "/spritemap1.png"), Paths.file('images/$folder/spritemap1.json'));
|
||||
|
||||
jsonAnim = cast CoolUtil.coolJSON(Assets.getText(Paths.file('images/$folder/Animation.json')));
|
||||
ParseAnimate.generateSymbolmap(jsonAnim.SD.S);
|
||||
ParseAnimate.resetFrameList();
|
||||
|
||||
ParseAnimate.parseTimeline(jsonAnim.AN.TL, 0, 0);
|
||||
|
||||
generateSpriteShit();
|
||||
|
||||
/* var folder:String = 'tightestBars';
|
||||
coolParse = cast Json.parse(Assets.getText(Paths.file('images/' + folder + '/Animation.json')));
|
||||
|
||||
// reverses the layers, for proper rendering!
|
||||
coolParse.AN.TL.L.reverse();
|
||||
super(x, y, coolParse);
|
||||
|
||||
frames = FlxAnimate.fromAnimate(Paths.file('images/' + folder + '/spritemap1.png'), Paths.file('images/' + folder + '/spritemap1.json'));
|
||||
*/
|
||||
|
||||
frames = FlxAnimate.fromAnimate(Paths.file('images/' + folder + '/spritemap1.png'), Paths.file('images/' + folder + '/spritemap1.json'));
|
||||
// frames
|
||||
}
|
||||
|
||||
override function draw()
|
||||
{
|
||||
// having this commented out fixes some wacky scaling bullshit?
|
||||
// or fixes drawing it twice?
|
||||
// super.draw();
|
||||
|
||||
if (FlxG.keys.justPressed.ONE)
|
||||
{
|
||||
trace("-------------------------------------");
|
||||
trace('CUR FRAME: ' + daFrame);
|
||||
trace('--------------');
|
||||
}
|
||||
// renderFrame(coolParse.AN.TL, coolParse, true);
|
||||
|
||||
renderFrame(coolParse.AN.TL, coolParse, true);
|
||||
actualFrameRender();
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.E)
|
||||
/**
|
||||
* Puts all the needed sprites into a FlxTypedGroup, and properly recycles them?
|
||||
**/
|
||||
function generateSpriteShit()
|
||||
{
|
||||
sprGrp.kill(); // kills group, maybe dont need to do this one so broadly? ehh whatev
|
||||
|
||||
for (frameSorted in ParseAnimate.frameList)
|
||||
{
|
||||
for (shit in FlxSymbol.nestedShit.keys())
|
||||
for (i in frameSorted)
|
||||
{
|
||||
for (spr in FlxSymbol.nestedShit.get(shit))
|
||||
{
|
||||
trace(shit);
|
||||
spr.draw();
|
||||
}
|
||||
}
|
||||
// instead of making them every frame, regenerate when needed?
|
||||
var spr:FlxSymbol = sprGrp.recycle(FlxSymbol); // redo this to recycle from a list later
|
||||
spr.frames = frames;
|
||||
spr.frame = spr.frames.getByName(i.frameName); // this one is fine
|
||||
spr.updateHitbox();
|
||||
|
||||
FlxSymbol.nestedShit.clear();
|
||||
// move this? wont work here!
|
||||
if (FlxG.keys.justPressed.I)
|
||||
{
|
||||
trace(i.frameName);
|
||||
trace(i.depthString);
|
||||
// trace("random lol: " + i.randomLol);
|
||||
}
|
||||
|
||||
// cuz its in group, gets a lil fuckie when animated, need to go thru and properly reset each thing for shit like matrix!
|
||||
// merely resets the matrix to normal ass one!
|
||||
spr.transformMatrix.identity();
|
||||
spr.setPosition();
|
||||
|
||||
/* for (swagMatrix in i.matrixArray)
|
||||
{
|
||||
var alsoSwag:FlxMatrix = new FlxMatrix(swagMatrix[0], swagMatrix[1], swagMatrix[4], swagMatrix[5], swagMatrix[12], swagMatrix[13]);
|
||||
spr.matrixExposed = true;
|
||||
spr.transformMatrix.concat(alsoSwag);
|
||||
}*/
|
||||
|
||||
// i.fullMatrix.concat
|
||||
|
||||
spr.matrixExposed = true;
|
||||
|
||||
// trace(i.fullMatrix);
|
||||
|
||||
if (i.fullMatrix.a < 0)
|
||||
{
|
||||
trace('negative?');
|
||||
trace(i.fullMatrix);
|
||||
}
|
||||
|
||||
spr.transformMatrix.concat(i.fullMatrix);
|
||||
|
||||
if (i.fullMatrix.a < 0)
|
||||
{
|
||||
trace('negative?');
|
||||
trace(i.fullMatrix);
|
||||
trace(spr.transformMatrix);
|
||||
}
|
||||
|
||||
// trace(spr.transformMatrix);
|
||||
|
||||
spr.origin.set();
|
||||
|
||||
/* for (trpShit in i.trpArray)
|
||||
{
|
||||
spr.origin.x -= trpShit[0];
|
||||
spr.origin.y -= trpShit[1];
|
||||
}
|
||||
*/
|
||||
// spr.alpha = 0.3;
|
||||
|
||||
spr.antialiasing = true;
|
||||
sprGrp.add(spr);
|
||||
spr.alpha = 0.5;
|
||||
|
||||
/* if (i == "0225")
|
||||
{
|
||||
trace('FUNNY MATRIX!');
|
||||
trace(spr._matrix);
|
||||
trace("\n\n MATRIX MAP");
|
||||
for (m in ParseAnimate.matrixMap.get("0225"))
|
||||
{
|
||||
trace(m);
|
||||
}
|
||||
|
||||
trace('\n\n');
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
// trace(sprGrp.length);
|
||||
}
|
||||
|
||||
// fix render order of ALL layers!
|
||||
// seperate frameList into layers
|
||||
// go thru animate file to see how it should all be ordered
|
||||
// per frame symbol stuff to fix lip sync (in ParseAnimate?)
|
||||
// definitely need to dig through Animate.json stuff
|
||||
// something with TRP stuff, look through tighterBars (GF scene)
|
||||
// redo map stuff incase there's multiple assets
|
||||
// ONE CENTRAL THING FOR THIS DUMBASS BULLSHIT
|
||||
// sorted framelist put it all in there, then make i actually mean something
|
||||
|
||||
function actualFrameRender()
|
||||
{
|
||||
sprGrp.draw();
|
||||
}
|
||||
|
||||
// notes to self
|
||||
|
@ -73,6 +186,8 @@ class FlxAnimate extends FlxSymbol
|
|||
var frameTickTypeShit:Float = 0;
|
||||
var animFrameRate:Int = 24;
|
||||
|
||||
// redo all the matrix animation stuff
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
@ -89,16 +204,29 @@ class FlxAnimate extends FlxSymbol
|
|||
{
|
||||
changeFrame(1);
|
||||
frameTickTypeShit = 0;
|
||||
ParseAnimate.resetFrameList();
|
||||
ParseAnimate.parseTimeline(jsonAnim.AN.TL, 0, daFrame);
|
||||
|
||||
generateSpriteShit();
|
||||
}
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.RIGHT)
|
||||
{
|
||||
changeFrame(1);
|
||||
|
||||
ParseAnimate.resetFrameList();
|
||||
ParseAnimate.parseTimeline(jsonAnim.AN.TL, 0, daFrame);
|
||||
|
||||
generateSpriteShit();
|
||||
}
|
||||
if (FlxG.keys.justPressed.LEFT)
|
||||
changeFrame(-1);
|
||||
}
|
||||
|
||||
// This stuff is u
|
||||
/**
|
||||
* PARSES THE 'spritemap1.png' or whatever into a FlxAtlasFrames!!!
|
||||
*/
|
||||
public static function fromAnimate(Source:FlxGraphicAsset, Description:String):FlxAtlasFrames
|
||||
{
|
||||
var graphic:FlxGraphic = FlxG.bitmap.add(Source);
|
||||
|
@ -114,11 +242,11 @@ class FlxAnimate extends FlxSymbol
|
|||
|
||||
frames = new FlxAtlasFrames(graphic);
|
||||
|
||||
var data:AnimateObject;
|
||||
var data:Spritemap;
|
||||
|
||||
var json:String = Description;
|
||||
|
||||
trace(json);
|
||||
// trace(json);
|
||||
|
||||
var funnyJson:Dynamic = {};
|
||||
if (Assets.exists(json))
|
||||
|
@ -126,12 +254,14 @@ class FlxAnimate extends FlxSymbol
|
|||
|
||||
// trace(json);
|
||||
|
||||
data = cast funnyJson.ATLAS;
|
||||
// data = c
|
||||
|
||||
for (sprite in data.SPRITES)
|
||||
data = cast funnyJson;
|
||||
|
||||
for (sprite in data.ATLAS.SPRITES)
|
||||
{
|
||||
// probably nicer way to do this? Oh well
|
||||
var swagSprite:AnimateSprite = sprite.SPRITE;
|
||||
var swagSprite:Sprite = sprite.SPRITE;
|
||||
|
||||
var rect = FlxRect.get(swagSprite.x, swagSprite.y, swagSprite.w, swagSprite.h);
|
||||
|
||||
|
@ -147,10 +277,7 @@ class FlxAnimate extends FlxSymbol
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HL json encoding fix for some wacky bullshit
|
||||
* https://github.com/HaxeFoundation/haxe/issues/6930#issuecomment-384570392
|
||||
*/
|
||||
// handy json function that has some hashlink fix, see the thing in CoolUtils file to see the link / where i stole it from
|
||||
class JaySon
|
||||
{
|
||||
public static function parseFile(name:String)
|
||||
|
@ -164,18 +291,3 @@ class JaySon
|
|||
0));
|
||||
}
|
||||
}
|
||||
|
||||
typedef AnimateObject =
|
||||
{
|
||||
SPRITES:Array<Dynamic>
|
||||
}
|
||||
|
||||
typedef AnimateSprite =
|
||||
{
|
||||
var name:String;
|
||||
var x:Int;
|
||||
var y:Int;
|
||||
var w:Int;
|
||||
var h:Int;
|
||||
var rotated:Bool;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
package animate;
|
||||
|
||||
import animate.ParseAnimate.AnimJson;
|
||||
import animate.ParseAnimate.Animation;
|
||||
import animate.ParseAnimate.Frame;
|
||||
import animate.ParseAnimate.Sprite;
|
||||
import animate.ParseAnimate.Spritemap;
|
||||
import animate.ParseAnimate.SymbolDictionary;
|
||||
import animate.ParseAnimate.Timeline;
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxFrame.FlxFrameAngle;
|
||||
|
@ -8,251 +15,41 @@ import flixel.math.FlxMath;
|
|||
import flixel.math.FlxMatrix;
|
||||
import flixel.math.FlxPoint;
|
||||
import lime.system.System;
|
||||
import openfl.Assets;
|
||||
import openfl.geom.Matrix;
|
||||
|
||||
class FlxSymbol extends FlxSprite
|
||||
{
|
||||
public var coolParse:Parsed;
|
||||
public var oldMatrix:Array<Float> = [];
|
||||
|
||||
// Loop types shit
|
||||
public static inline var LOOP:String = 'LP';
|
||||
public static inline var PLAY_ONCE:String = 'PO';
|
||||
public static inline var SINGLE_FRAME:String = 'SF';
|
||||
|
||||
/**
|
||||
* This gets set in some nest animation bullshit in animation render code
|
||||
*/
|
||||
public var firstFrame:Int = 0;
|
||||
|
||||
public var transformMatrix:Matrix = new Matrix();
|
||||
public var daLoopType:String = 'LP'; // LP by default, is set below!!!
|
||||
|
||||
public function new(x:Float, y:Float, coolParsed:Parsed)
|
||||
/**
|
||||
* Bool flag showing whether transformMatrix is used for rendering or not.
|
||||
* False by default, which means that transformMatrix isn't used for rendering
|
||||
*/
|
||||
public var matrixExposed:Bool = true;
|
||||
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
// trace(System.deviceModel);
|
||||
// trace(System.deviceVendor);
|
||||
// trace(System.platformLabel);
|
||||
// trace(System.platformName);
|
||||
|
||||
this.coolParse = coolParsed;
|
||||
|
||||
var hasSymbolDictionary:Bool = Reflect.hasField(coolParse, "SD");
|
||||
|
||||
if (hasSymbolDictionary)
|
||||
symbolAtlasShit = parseSymbolDictionary(coolParse);
|
||||
}
|
||||
|
||||
var symbolAtlasShit:Map<String, String> = new Map();
|
||||
|
||||
public static var nestedShit:Map<Int, Array<FlxSymbol>> = new Map();
|
||||
|
||||
var symbolMap:Map<String, Animation> = new Map();
|
||||
|
||||
public var daFrame:Int = 0;
|
||||
|
||||
public var transformMatrix:Matrix = new Matrix();
|
||||
|
||||
function renderFrame(TL:Timeline, coolParsed:Parsed, ?traceShit:Bool = false)
|
||||
{
|
||||
for (layer in TL.L)
|
||||
{
|
||||
if (FlxG.keys.justPressed.TWO)
|
||||
trace(layer.LN);
|
||||
|
||||
// layer.FR.reverse();
|
||||
|
||||
// for (frame in layer.FR)
|
||||
// {
|
||||
|
||||
var keyFrames:Array<Int> = [];
|
||||
var keyFrameMap:Map<Int, Frame> = new Map();
|
||||
|
||||
// probably dumb to generate this every single frame for every layer?
|
||||
// prob want to generate it first when loading
|
||||
for (frm in layer.FR)
|
||||
{
|
||||
keyFrameMap[frm.I] = frm;
|
||||
keyFrames.push(frm.I);
|
||||
|
||||
for (thing in 0...frm.DU - 1)
|
||||
keyFrames.push(frm.I);
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.THREE)
|
||||
{
|
||||
trace(layer.LN);
|
||||
trace(keyFrames);
|
||||
}
|
||||
|
||||
var newFrameNum:Int = daFrame;
|
||||
|
||||
// need to account for movie clip / Graphic bullshit?
|
||||
|
||||
switch (daLoopType)
|
||||
{
|
||||
case LOOP:
|
||||
var tempFrame = layer.FR[newFrameNum + firstFrame % layer.FR.length];
|
||||
// trace(tempFrame);
|
||||
// newFrameNum += firstFrame;
|
||||
// newFrameNum = newFrameNum % (tempFrame.I + tempFrame.DU);
|
||||
// newFrameNum = FlxMath.wrap(newFrameNum, tempFrame.I, tempFrame.I + tempFrame.DU);
|
||||
|
||||
// trace(newFrameNum % keyFrames.length);
|
||||
// trace(newFrameNum);
|
||||
// trace(keyFrames);
|
||||
newFrameNum = keyFrames[newFrameNum % keyFrames.length]; // temp, fix later for good looping
|
||||
case PLAY_ONCE:
|
||||
// trace(newFrameNum);
|
||||
// trace(keyFrames.length - 1);
|
||||
// trace(keyFrameMap.get(newFrameNum + firstFrame));
|
||||
// trace(keyFrameMap.get(keyFrames[keyFrames.length - 1]));
|
||||
// trace(layer.LN);
|
||||
// trace(keyFrames);
|
||||
newFrameNum = Std.int(Math.min(newFrameNum + firstFrame, keyFrames.length - 1));
|
||||
case SINGLE_FRAME:
|
||||
// trace(layer);
|
||||
// trace(firstFrame);
|
||||
// trace(newFrameNum);
|
||||
// trace(layer.LN);
|
||||
// trace(keyFrames);
|
||||
newFrameNum = keyFrames[firstFrame];
|
||||
}
|
||||
|
||||
// trace(daLoopType);
|
||||
// trace(newFrameNum);
|
||||
// trace(layer.FR.length);
|
||||
|
||||
// trace(newFrameNum % layer.FR.length);
|
||||
|
||||
// var swagFrame:Frame = layer.FR[newFrameNum % layer.FR.length]; // has modulo just in case????
|
||||
// doesnt actually use position in the array?3
|
||||
var swagFrame:Frame = keyFrameMap.get(newFrameNum);
|
||||
|
||||
// get frame by going through
|
||||
|
||||
// if (newFrameNum >= frame.I && newFrameNum < frame.I + frame.DU)
|
||||
// {
|
||||
// trace(daLoopType);
|
||||
for (element in swagFrame.E)
|
||||
{
|
||||
if (Reflect.hasField(element, 'ASI'))
|
||||
{
|
||||
var m3d = element.ASI.M3D;
|
||||
var dumbassMatrix:Matrix = new Matrix(m3d[0], m3d[1], m3d[4], m3d[5], m3d[12], m3d[13]);
|
||||
|
||||
var spr:FlxSymbol = new FlxSymbol(0, 0, coolParsed);
|
||||
spr.setPosition(x, y);
|
||||
matrixExposed = true;
|
||||
spr.frames = frames;
|
||||
spr.frame = spr.frames.getByName(element.ASI.N);
|
||||
|
||||
// dumbassMatrix.translate(origin.x, origin.y);
|
||||
|
||||
dumbassMatrix.concat(_matrix);
|
||||
spr.matrixExposed = true;
|
||||
spr.transformMatrix.concat(dumbassMatrix);
|
||||
// spr._matrix.concat(spr.transformMatrix);
|
||||
|
||||
spr.origin.set();
|
||||
// Prob dont need these offset thingies???
|
||||
// spr.origin.x += origin.x;
|
||||
// spr.origin.y += origin.y;
|
||||
|
||||
// spr.antialiasing = true;
|
||||
spr.draw();
|
||||
|
||||
if (FlxG.keys.justPressed.ONE)
|
||||
{
|
||||
trace("ASI - " + layer.LN + ": " + element.ASI.N);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var nestedSymbol = symbolMap.get(element.SI.SN);
|
||||
var nestedShit:FlxSymbol = new FlxSymbol(x, y, coolParse);
|
||||
nestedShit.frames = frames;
|
||||
|
||||
var swagMatrix:FlxMatrix = new FlxMatrix(element.SI.M3D[0], element.SI.M3D[1], element.SI.M3D[4], element.SI.M3D[5], element.SI.M3D[12],
|
||||
element.SI.M3D[13]);
|
||||
|
||||
swagMatrix.concat(_matrix);
|
||||
|
||||
nestedShit._matrix.concat(swagMatrix);
|
||||
nestedShit.origin.set(element.SI.TRP.x, element.SI.TRP.y);
|
||||
// nestedShit.angle += ((180 / Math.PI) * Math.atan2(swagMatrix.b, swagMatrix.a));
|
||||
// nestedShit.angle += angle;
|
||||
|
||||
if (symbolAtlasShit.exists(nestedSymbol.SN))
|
||||
{
|
||||
// nestedShit.frames.getByName(symbolAtlasShit.get(nestedSymbol.SN));
|
||||
// nestedShit.draw();
|
||||
}
|
||||
|
||||
// scale.y = Math.sqrt(_matrix.c * _matrix.c + _matrix.d * _matrix.d);
|
||||
// scale.x = Math.sqrt(_matrix.a * _matrix.a + _matrix.b * _matrix.b);
|
||||
|
||||
// nestedShit.oldMatrix = element.SI.M3D;
|
||||
|
||||
if (FlxG.keys.justPressed.ONE)
|
||||
{
|
||||
trace("SI - " + layer.LN + ": " + element.SI.SN + " - LOOP TYPE: " + element.SI.LP);
|
||||
}
|
||||
|
||||
nestedShit.firstFrame = element.SI.FF;
|
||||
// nestedShit.daFrame += nestedShit.firstFrame;
|
||||
|
||||
nestedShit.daLoopType = element.SI.LP;
|
||||
nestedShit.daFrame = daFrame;
|
||||
nestedShit.scrollFactor.set(1, 1);
|
||||
nestedShit.renderFrame(nestedSymbol.TL, coolParsed);
|
||||
|
||||
// renderFrame(nestedSymbol.TL, coolParsed);
|
||||
}
|
||||
}
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
function changeFrame(frameChange:Int = 0):Void
|
||||
{
|
||||
daFrame += frameChange;
|
||||
}
|
||||
|
||||
function parseSymbolDictionary(coolParsed:Parsed):Map<String, String>
|
||||
{
|
||||
var awesomeMap:Map<String, String> = new Map();
|
||||
for (symbol in coolParsed.SD.S)
|
||||
{
|
||||
symbolMap.set(symbol.SN, symbol);
|
||||
|
||||
var symbolName = symbol.SN;
|
||||
|
||||
// one time reverse?
|
||||
symbol.TL.L.reverse();
|
||||
|
||||
for (layer in symbol.TL.L)
|
||||
{
|
||||
for (frame in layer.FR)
|
||||
{
|
||||
for (element in frame.E)
|
||||
{
|
||||
if (Reflect.hasField(element, 'ASI'))
|
||||
{
|
||||
awesomeMap.set(symbolName, element.ASI.N);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return awesomeMap;
|
||||
}
|
||||
|
||||
function getFrame() {}
|
||||
|
||||
/**
|
||||
* custom "homemade" (nabbed from FlxSkewSprite) draw function, to make having a matrix transform slightly
|
||||
* less painful
|
||||
*/
|
||||
override function drawComplex(camera:FlxCamera):Void
|
||||
{
|
||||
_frame.prepareMatrix(_matrix, FlxFrameAngle.ANGLE_0, checkFlipX(), checkFlipY());
|
||||
|
@ -263,155 +60,23 @@ class FlxSymbol extends FlxSprite
|
|||
{
|
||||
_matrix.concat(transformMatrix);
|
||||
}
|
||||
else
|
||||
|
||||
if (bakedRotationAngle <= 0)
|
||||
{
|
||||
if (bakedRotationAngle <= 0)
|
||||
{
|
||||
updateTrig();
|
||||
updateTrig();
|
||||
|
||||
if (angle != 0)
|
||||
_matrix.rotateWithTrig(_cosAngle, _sinAngle);
|
||||
}
|
||||
|
||||
// updateSkewMatrix();
|
||||
_matrix.concat(_skewMatrix);
|
||||
if (angle != 0)
|
||||
_matrix.rotateWithTrig(_cosAngle, _sinAngle);
|
||||
}
|
||||
|
||||
_point.addPoint(origin);
|
||||
if (isPixelPerfectRender(camera))
|
||||
_point.floor();
|
||||
|
||||
_matrix.translate(_point.x, _point.y);
|
||||
camera.drawPixels(_frame, framePixels, _matrix, colorTransform, blend, antialiasing);
|
||||
}
|
||||
|
||||
var _skewMatrix:Matrix = new Matrix();
|
||||
|
||||
// public var transformMatrix(default, null):Matrix = new Matrix();
|
||||
|
||||
/**
|
||||
* Bool flag showing whether transformMatrix is used for rendering or not.
|
||||
* False by default, which means that transformMatrix isn't used for rendering
|
||||
*/
|
||||
public var matrixExposed:Bool = false;
|
||||
|
||||
public var skew(default, null):FlxPoint = FlxPoint.get();
|
||||
|
||||
function updateSkewMatrix():Void
|
||||
{
|
||||
_skewMatrix.identity();
|
||||
|
||||
if (skew.x != 0 || skew.y != 0)
|
||||
if (isPixelPerfectRender(camera))
|
||||
{
|
||||
_skewMatrix.b = Math.tan(skew.y * FlxAngle.TO_RAD);
|
||||
_skewMatrix.c = Math.tan(skew.x * FlxAngle.TO_RAD);
|
||||
_matrix.tx = Math.floor(_matrix.tx);
|
||||
_matrix.ty = Math.floor(_matrix.ty);
|
||||
}
|
||||
camera.drawPixels(_frame, framePixels, _matrix, colorTransform, blend, antialiasing, shader);
|
||||
}
|
||||
}
|
||||
|
||||
// TYPEDEFS FOR ANIMATION.JSON PARSING
|
||||
|
||||
typedef Parsed =
|
||||
{
|
||||
var MD:Metadata;
|
||||
var AN:Animation;
|
||||
var SD:SymbolDictionary; // Doesn't always have symbol dictionary!!
|
||||
}
|
||||
|
||||
typedef Metadata =
|
||||
{
|
||||
/** Framerate */
|
||||
var FRT:Int;
|
||||
}
|
||||
|
||||
/** Basically treated like one big symbol*/
|
||||
typedef Animation =
|
||||
{
|
||||
/** symbolName */
|
||||
var SN:String;
|
||||
|
||||
var TL:Timeline;
|
||||
|
||||
/** IDK what STI stands for, Symbole Type Instance?
|
||||
Anyways, it is NOT used in SYMBOLS, only the main AN animation
|
||||
*/
|
||||
var STI:Dynamic;
|
||||
}
|
||||
|
||||
/** DISCLAIMER, MAY NOT ACTUALLY BE CALLED
|
||||
SYMBOL TYPE ISNTANCE, IM JUST MAKING ASSUMPTION!! */
|
||||
typedef SymbolTypeInstance =
|
||||
{
|
||||
// var TL:Timeline;
|
||||
// var SN:String;
|
||||
}
|
||||
|
||||
typedef SymbolDictionary =
|
||||
{
|
||||
var S:Array<Animation>;
|
||||
}
|
||||
|
||||
typedef Timeline =
|
||||
{
|
||||
/** Layers */
|
||||
var L:Array<Layer>;
|
||||
}
|
||||
|
||||
// Singular layer, not to be confused with LAYERS
|
||||
typedef Layer =
|
||||
{
|
||||
var LN:String;
|
||||
|
||||
/** Frames */
|
||||
var FR:Array<Frame>;
|
||||
}
|
||||
|
||||
typedef Frame =
|
||||
{
|
||||
/** Frame index*/
|
||||
var I:Int;
|
||||
|
||||
/** Duration, in frames*/
|
||||
var DU:Int;
|
||||
|
||||
/** Elements*/
|
||||
var E:Array<Element>;
|
||||
}
|
||||
|
||||
typedef Element =
|
||||
{
|
||||
var SI:SymbolInstance;
|
||||
var ASI:AtlasSymbolInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
Symbol instance, for SYMBOLS and refers to SYMBOLS
|
||||
*/
|
||||
typedef SymbolInstance =
|
||||
{
|
||||
var SN:String;
|
||||
|
||||
/** SymbolType (Graphic, Movieclip, Button)*/
|
||||
var ST:String;
|
||||
|
||||
/** First frame*/
|
||||
var FF:Int;
|
||||
|
||||
/** Loop type (Loop, play once, single frame)*/
|
||||
var LP:String;
|
||||
|
||||
var TRP:TransformationPoint;
|
||||
var M3D:Array<Float>;
|
||||
}
|
||||
|
||||
typedef AtlasSymbolInstance =
|
||||
{
|
||||
var N:String;
|
||||
var M3D:Array<Float>;
|
||||
}
|
||||
|
||||
typedef TransformationPoint =
|
||||
{
|
||||
var x:Float;
|
||||
var y:Float;
|
||||
}
|
||||
|
|
515
source/animate/ParseAnimate.hx
Normal file
515
source/animate/ParseAnimate.hx
Normal file
|
@ -0,0 +1,515 @@
|
|||
package animate;
|
||||
|
||||
import haxe.format.JsonParser;
|
||||
import openfl.Assets;
|
||||
import openfl.geom.Matrix3D;
|
||||
import openfl.geom.Matrix;
|
||||
import sys.io.File;
|
||||
|
||||
/**
|
||||
* Generally designed / written in a way that can be easily taken out of FNF and used elsewhere
|
||||
* I don't think it even has ties to OpenFL? Could probably just use it for ANY haxe
|
||||
* project if needed, DOES NEED A LOT OF CLEANUP THOUGH!
|
||||
*/
|
||||
class ParseAnimate
|
||||
{
|
||||
// make list of frames needed to render (with ASI)
|
||||
// make GIANT list of all the frames ever and have them in order?
|
||||
public static var symbolMap:Map<String, Symbol> = new Map();
|
||||
public static var actualSprites:Map<String, Sprite> = new Map();
|
||||
|
||||
private var _atlas:Map<String, Sprite>;
|
||||
private var _symbolData:Map<String, Symbol>;
|
||||
private var _defaultSymbolName:String;
|
||||
|
||||
public function new(data:AnimJson, atlas:Spritemap)
|
||||
{
|
||||
// bitmap data could prob be instead
|
||||
// this code is mostly nabbed from https://github.com/miltoncandelero/OpenFLAnimateAtlas/blob/master/Source/animateatlas/displayobject/SpriteAnimationLibrary.hx
|
||||
parseAnimationData(data);
|
||||
parseAtlasData(atlas);
|
||||
}
|
||||
|
||||
private function parseAnimationData(data:AnimJson):Void
|
||||
{
|
||||
_symbolData = new Map();
|
||||
|
||||
var symbols = data.SD.S;
|
||||
for (symbol in symbols)
|
||||
_symbolData[symbol.SN] = preprocessSymbolData(symbol);
|
||||
|
||||
var defaultSymbol:Symbol = preprocessSymbolData(data.AN);
|
||||
_defaultSymbolName = defaultSymbol.SN;
|
||||
_symbolData.set(_defaultSymbolName, defaultSymbol);
|
||||
}
|
||||
|
||||
// at little redundant, does exactly the same thing as genSpritemap()
|
||||
private function parseAtlasData(atlas:Spritemap):Void
|
||||
{
|
||||
_atlas = new Map<String, Sprite>();
|
||||
if (atlas.ATLAS != null && atlas.ATLAS.SPRITES != null)
|
||||
{
|
||||
for (s in atlas.ATLAS.SPRITES)
|
||||
_atlas.set(s.SPRITE.name, s.SPRITE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Not used, was used for testing stuff though!
|
||||
*/
|
||||
public static function init()
|
||||
{
|
||||
// Main.gids
|
||||
var folder:String = 'tightestBars';
|
||||
|
||||
// var spritemap:Spritemap =
|
||||
// var spritemap:Spritemap = genSpritemap('test/$folder/spritemap1.json');
|
||||
|
||||
actualSprites = genSpritemap('test/$folder/spritemap1.json');
|
||||
|
||||
var animation:AnimJson = cast CoolUtil.coolJSON(Assets.getText('src/$folder/Animation.json'));
|
||||
|
||||
generateSymbolmap(animation.SD.S);
|
||||
|
||||
trace("\n\nANIMATION SHIT\n");
|
||||
|
||||
var timelineLength:Int = 0;
|
||||
for (lyr in animation.AN.TL.L)
|
||||
timelineLength = Std.int(Math.max(lyr.FR.length, timelineLength));
|
||||
|
||||
var content:String = animation.AN.TL.L[0].LN;
|
||||
content += "TOTAL FRAMES NEEDED: " + timelineLength + "\n";
|
||||
|
||||
for (frm in 0...timelineLength)
|
||||
{
|
||||
trace('FRAME NUMBER ' + frm);
|
||||
try
|
||||
{
|
||||
parseTimeline(animation.AN.TL, 1, frm);
|
||||
content += 'Good write on frame: ' + frm + "\n";
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
content += "BAD WRITE : " + frm + "\n";
|
||||
content += "\t" + e + "\n";
|
||||
trace(e);
|
||||
}
|
||||
|
||||
// File.saveContent("output.txt", content);
|
||||
}
|
||||
|
||||
parseTimeline(animation.AN.TL, 1, 0);
|
||||
trace(actualSprites);
|
||||
}
|
||||
|
||||
/**
|
||||
* a MAP of SPRITES, not to be confused with Spritemap... lol
|
||||
*/
|
||||
public static function genSpritemap(json:String):Map<String, Sprite>
|
||||
{
|
||||
var sprShitty:Spritemap = cast CoolUtil.coolJSON(json);
|
||||
var sprMap:Map<String, Sprite> = new Map();
|
||||
|
||||
for (spr in sprShitty.ATLAS.SPRITES)
|
||||
sprMap.set(spr.SPRITE.name, spr.SPRITE);
|
||||
return sprMap;
|
||||
}
|
||||
|
||||
// should change dis to all private?
|
||||
public static function generateSymbolmap(symbols:Array<Symbol>)
|
||||
{
|
||||
for (symbol in symbols)
|
||||
{
|
||||
// trace(symbol.SN + "has: " + symbol.TL.L.length + " LAYERS");
|
||||
|
||||
symbolMap.set(symbol.SN, symbol);
|
||||
// parseTimeline(symbol.TL);
|
||||
}
|
||||
}
|
||||
|
||||
public static function preprocessSymbolData(anim:Symbol):Symbol
|
||||
{
|
||||
var timelineData:Timeline = anim.TL;
|
||||
var layerData:Array<Layer> = timelineData.L;
|
||||
|
||||
if (!timelineData.sortedForRender)
|
||||
{
|
||||
timelineData.sortedForRender = true;
|
||||
layerData.reverse();
|
||||
}
|
||||
|
||||
for (layerStuff in layerData)
|
||||
{
|
||||
var frames:Array<Frame> = layerStuff.FR;
|
||||
|
||||
for (frame in frames)
|
||||
{
|
||||
var elements:Array<Element> = frame.E;
|
||||
for (e in 0...elements.length)
|
||||
{
|
||||
var element:Element = elements[e];
|
||||
if (element.ASI != null)
|
||||
{
|
||||
element = elements[e] = {
|
||||
SI: {
|
||||
SN: "ATLAS_SYMBOL_SPRITE",
|
||||
LP: "LP",
|
||||
TRP: {x: 0, y: 0},
|
||||
M3D: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],
|
||||
FF: 0,
|
||||
ST: "G",
|
||||
ASI: element.ASI
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return anim;
|
||||
}
|
||||
|
||||
public static var curLoopType:String;
|
||||
|
||||
/**
|
||||
* Stuff for debug parsing
|
||||
*/
|
||||
public static var depthTypeBeat:String = "";
|
||||
|
||||
/**
|
||||
* Array of bullshit that will eventually be RENDERED by whoever wanna use it!
|
||||
*/
|
||||
public static var frameList:Array<Array<VALIDFRAME>> = [];
|
||||
|
||||
// for loop stuf
|
||||
|
||||
/**
|
||||
* Similar to frameList, keeps track of shit according to framess?
|
||||
* That amount of arrays within arrays is fuckin dumb
|
||||
* but innermost array is basically just x and y value, cuz im dum
|
||||
*/
|
||||
public static var matrixHelp:Array<Array<Array<Float>>> = [];
|
||||
|
||||
public static var trpHelpIDK:Array<Array<Array<Float>>> = [];
|
||||
|
||||
public static var loopedFrameShit:Int = 0;
|
||||
|
||||
public static var funnyMatrix:Matrix = new Matrix();
|
||||
public static var matrixFlipper:Array<Matrix> = [];
|
||||
|
||||
// clean up all the crazy ass arrays
|
||||
|
||||
public static function resetFrameList()
|
||||
{
|
||||
// funnyMatrix.identity();
|
||||
|
||||
frameList = [];
|
||||
frameList.push([]);
|
||||
matrixHelp = [];
|
||||
matrixHelp.push([]);
|
||||
|
||||
trpHelpIDK = [];
|
||||
trpHelpIDK.push([]);
|
||||
}
|
||||
|
||||
public static var isFlipped:Bool = false;
|
||||
|
||||
public static function parseTimeline(TL:Timeline, tabbed:Int = 0, ?frameInput:Int)
|
||||
{
|
||||
var strTab:String = "";
|
||||
for (i in 0...tabbed)
|
||||
strTab += '\t';
|
||||
|
||||
for (layer in TL.L)
|
||||
{
|
||||
var frameArray:Array<Int> = [];
|
||||
var frameMap:Map<Int, Frame> = new Map();
|
||||
|
||||
for (frms in layer.FR)
|
||||
{
|
||||
for (i in 0...frms.DU)
|
||||
frameArray.push(frms.I);
|
||||
|
||||
frameMap.set(frms.I, frms);
|
||||
}
|
||||
|
||||
if (frameInput == null)
|
||||
frameInput = 0;
|
||||
|
||||
var oldFrm:Int = frameInput;
|
||||
/*
|
||||
if (curLoopType == "SF")
|
||||
{
|
||||
trace(layer.LN);
|
||||
|
||||
trace(frameArray);
|
||||
trace(frameInput);
|
||||
trace(curLoopType);
|
||||
}*/
|
||||
|
||||
if (curLoopType == "LP")
|
||||
frameInput = frameArray[frameInput % frameArray.length];
|
||||
else if (curLoopType == "SF")
|
||||
{
|
||||
frameInput = frameArray[loopedFrameShit];
|
||||
|
||||
// see what happens when something has more than 2 layer?
|
||||
// single frame stuff isn't fully implemented
|
||||
}
|
||||
else
|
||||
frameInput = frameArray[frameInput];
|
||||
|
||||
// trace(frameMap.get(frameInput));
|
||||
|
||||
var frame:Frame = frameMap.get(frameInput);
|
||||
|
||||
// get somethin sorted per element list, which would essentially be per symbol things properly sorted
|
||||
// seperate data types if symbol or atlassymbolinstance? would probably be maybe slightly less memory intensive? i dunno
|
||||
|
||||
// goes thru each layer, and then each element
|
||||
// after it gets thru each element it adds to the layer frame stuff.
|
||||
// make somethin that works recursively, maybe thats the symbol dictionary type shit?
|
||||
|
||||
for (element in frame.E)
|
||||
{
|
||||
if (Reflect.hasField(element, "ASI"))
|
||||
{
|
||||
matrixHelp[matrixHelp.length - 1].push(element.ASI.M3D);
|
||||
|
||||
var m3D = element.ASI.M3D;
|
||||
var lilMatrix:Matrix = new Matrix(m3D[0], m3D[1], m3D[4], m3D[5], m3D[12], m3D[13]);
|
||||
matrixFlipper.push(lilMatrix);
|
||||
|
||||
// matrixFlipper.reverse();
|
||||
|
||||
// funnyMatrix.identity();
|
||||
|
||||
// for (m in matrixFlipper)
|
||||
// funnyMatrix.concat(m);
|
||||
|
||||
if (isFlipped)
|
||||
{
|
||||
trace("MORE FLIPPED SHIT");
|
||||
trace("MORE FLIPPED SHIT");
|
||||
trace("MORE FLIPPED SHIT");
|
||||
trace(funnyMatrix);
|
||||
trace(matrixFlipper);
|
||||
}
|
||||
|
||||
// trace(funnyMatrix);
|
||||
|
||||
funnyMatrix.concat(lilMatrix);
|
||||
// trace(funnyMatrix);
|
||||
|
||||
frameList[frameList.length - 1].push({
|
||||
frameName: element.ASI.N,
|
||||
depthString: depthTypeBeat,
|
||||
matrixArray: matrixHelp[matrixHelp.length - 1],
|
||||
trpArray: trpHelpIDK[trpHelpIDK.length - 1],
|
||||
fullMatrix: funnyMatrix.clone()
|
||||
});
|
||||
|
||||
// flips the matrix once?? I cant remember exactly why it needs to be flipped
|
||||
// matrixHelp[matrixHelp.length - 1].reverse();
|
||||
|
||||
// trpHelpIDK = [];
|
||||
|
||||
// push the matrix array after each symbol?
|
||||
|
||||
funnyMatrix.identity();
|
||||
matrixFlipper = [];
|
||||
|
||||
depthTypeBeat = "";
|
||||
curLoopType = "";
|
||||
loopedFrameShit = 0;
|
||||
|
||||
isFlipped = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var m3D = element.SI.M3D;
|
||||
var lilMatrix:Matrix = new Matrix(m3D[0], m3D[1], m3D[4], m3D[5], m3D[12], m3D[13]);
|
||||
|
||||
if (lilMatrix.a == -1)
|
||||
{
|
||||
isFlipped = true;
|
||||
|
||||
trace('IS THE NEGATIVE ONE');
|
||||
}
|
||||
|
||||
if (isFlipped)
|
||||
trace(lilMatrix);
|
||||
|
||||
funnyMatrix.concat(lilMatrix);
|
||||
matrixFlipper.push(lilMatrix);
|
||||
// trace(funnyMatrix);
|
||||
|
||||
matrixHelp[matrixHelp.length - 1].push(element.SI.M3D);
|
||||
trpHelpIDK[trpHelpIDK.length - 1].push([element.SI.TRP.x, element.SI.TRP.y]); // trpHelpIDK.push();
|
||||
depthTypeBeat += "->" + element.SI.SN;
|
||||
curLoopType = element.SI.LP;
|
||||
|
||||
var inputFrame:Int = element.SI.FF;
|
||||
|
||||
// JANKY FIX, MAY NOT ACCOUNT FOR ALL SCENARIOS OF SINGLE FRAME ANIMATIONS!!
|
||||
if (curLoopType == "SF")
|
||||
{
|
||||
// trace("LOOP SHIT: " + inputFrame);
|
||||
loopedFrameShit = inputFrame;
|
||||
}
|
||||
|
||||
// condense the animation code, so it automatically already fills up animation shit per symbol
|
||||
|
||||
parseTimeline(symbolMap.get(element.SI.SN).TL, tabbed + 1, inputFrame);
|
||||
}
|
||||
|
||||
// idk if this should go per layer or per element / object?
|
||||
|
||||
matrixHelp.push([]);
|
||||
trpHelpIDK.push([]);
|
||||
}
|
||||
|
||||
if (tabbed == 0)
|
||||
{
|
||||
frameList[frameList.length - 1].reverse();
|
||||
frameList.push([]); // new layer essentially
|
||||
}
|
||||
}
|
||||
|
||||
frameList.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
typedef VALIDFRAME =
|
||||
{
|
||||
frameName:String,
|
||||
depthString:String,
|
||||
matrixArray:Array<Array<Float>>,
|
||||
trpArray:Array<Array<Float>>,
|
||||
fullMatrix:Matrix
|
||||
}
|
||||
|
||||
typedef AnimJson =
|
||||
{
|
||||
AN:Animation,
|
||||
SD:SymbolDictionary,
|
||||
MD:MetaData
|
||||
}
|
||||
|
||||
typedef Animation =
|
||||
{
|
||||
N:String,
|
||||
SN:String,
|
||||
TL:Timeline
|
||||
}
|
||||
|
||||
typedef SymbolDictionary =
|
||||
{
|
||||
S:Array<Symbol>
|
||||
}
|
||||
|
||||
typedef Symbol =
|
||||
{
|
||||
/**Symbol name*/
|
||||
SN:String,
|
||||
|
||||
TL:Timeline
|
||||
}
|
||||
|
||||
typedef Timeline =
|
||||
{
|
||||
?sortedForRender:Bool,
|
||||
L:Array<Layer>
|
||||
}
|
||||
|
||||
typedef Layer =
|
||||
{
|
||||
LN:String,
|
||||
FR:Array<Frame>
|
||||
}
|
||||
|
||||
typedef Frame =
|
||||
{
|
||||
E:Array<Element>,
|
||||
I:Int,
|
||||
DU:Int
|
||||
// maybe need to implement names if it has frame labels?
|
||||
}
|
||||
|
||||
typedef Element =
|
||||
{
|
||||
SI:SymbolInstance,
|
||||
?ASI:AlsoSymbolInstance
|
||||
// lmfao idk what ASI stands for lmfaoo, i dont think its "also"
|
||||
}
|
||||
|
||||
typedef SymbolInstance =
|
||||
{
|
||||
SN:String,
|
||||
ASI:AlsoSymbolInstance,
|
||||
|
||||
/**Symbol type, prob either G (graphic), or movie clip?*/ ST:String,
|
||||
|
||||
/**First frame*/ FF:Int,
|
||||
|
||||
/**Loop type, loop ping pong, etc.*/ LP:String,
|
||||
|
||||
/**3D matrix*/ M3D:Array<Float>,
|
||||
|
||||
TRP:
|
||||
{
|
||||
x:Float, y:Float
|
||||
}
|
||||
}
|
||||
|
||||
typedef AlsoSymbolInstance =
|
||||
{
|
||||
N:String,
|
||||
M3D:Array<Float>
|
||||
}
|
||||
|
||||
typedef MetaData =
|
||||
{
|
||||
/**
|
||||
* Framerate
|
||||
*/
|
||||
FRT:Int
|
||||
}
|
||||
|
||||
// SPRITEMAP BULLSHIT
|
||||
typedef Spritemap =
|
||||
{
|
||||
ATLAS:
|
||||
{
|
||||
SPRITES:Array<SpriteBullshit>
|
||||
},
|
||||
meta:Meta
|
||||
}
|
||||
|
||||
typedef SpriteBullshit =
|
||||
{
|
||||
SPRITE:Sprite
|
||||
}
|
||||
|
||||
typedef Sprite =
|
||||
{
|
||||
name:String,
|
||||
x:Int,
|
||||
y:Int,
|
||||
w:Int,
|
||||
h:Int,
|
||||
rotated:Bool
|
||||
}
|
||||
|
||||
typedef Meta =
|
||||
{
|
||||
app:String,
|
||||
verstion:String,
|
||||
image:String,
|
||||
format:String,
|
||||
size:
|
||||
{
|
||||
w:Int, h:Float
|
||||
},
|
||||
resolution:Float
|
||||
}
|
80
source/dsp/Complex.hx
Normal file
80
source/dsp/Complex.hx
Normal file
|
@ -0,0 +1,80 @@
|
|||
package dsp;
|
||||
|
||||
/**
|
||||
Complex number representation.
|
||||
**/
|
||||
@:forward(real, imag) @:notNull @:pure
|
||||
abstract Complex({
|
||||
final real:Float;
|
||||
final imag:Float;
|
||||
})
|
||||
{
|
||||
public inline function new(real:Float, imag:Float)
|
||||
this = {real: real, imag: imag};
|
||||
|
||||
/**
|
||||
Makes a Complex number with the given Float as its real part and a zero imag part.
|
||||
**/
|
||||
@:from
|
||||
public static inline function fromReal(r:Float)
|
||||
return new Complex(r, 0);
|
||||
|
||||
/**
|
||||
Complex argument, in radians.
|
||||
**/
|
||||
public var angle(get, never):Float;
|
||||
|
||||
inline function get_angle()
|
||||
return Math.atan2(this.imag, this.real);
|
||||
|
||||
/**
|
||||
Complex module.
|
||||
**/
|
||||
public var magnitude(get, never):Float;
|
||||
|
||||
inline function get_magnitude()
|
||||
return Math.sqrt(this.real * this.real + this.imag * this.imag);
|
||||
|
||||
@:op(A + B)
|
||||
public inline function add(rhs:Complex):Complex
|
||||
return new Complex(this.real + rhs.real, this.imag + rhs.imag);
|
||||
|
||||
@:op(A - B)
|
||||
public inline function sub(rhs:Complex):Complex
|
||||
return new Complex(this.real - rhs.real, this.imag - rhs.imag);
|
||||
|
||||
@:op(A * B)
|
||||
public inline function mult(rhs:Complex):Complex
|
||||
return new Complex(this.real * rhs.real - this.imag * rhs.imag, this.real * rhs.imag + this.imag * rhs.real);
|
||||
|
||||
/**
|
||||
Returns the complex conjugate, does not modify this object.
|
||||
**/
|
||||
public inline function conj():Complex
|
||||
return new Complex(this.real, -this.imag);
|
||||
|
||||
/**
|
||||
Multiplication by a real factor, does not modify this object.
|
||||
**/
|
||||
public inline function scale(k:Float):Complex
|
||||
return new Complex(this.real * k, this.imag * k);
|
||||
|
||||
public inline function copy():Complex
|
||||
return new Complex(this.real, this.imag);
|
||||
|
||||
/**
|
||||
The imaginary unit.
|
||||
**/
|
||||
public static final im = new Complex(0, 1);
|
||||
|
||||
/**
|
||||
The complex zero.
|
||||
**/
|
||||
public static final zero = new Complex(0, 0);
|
||||
|
||||
/**
|
||||
Computes the complex exponential `e^(iw)`.
|
||||
**/
|
||||
public static inline function exp(w:Float)
|
||||
return new Complex(Math.cos(w), Math.sin(w));
|
||||
}
|
154
source/dsp/FFT.hx
Normal file
154
source/dsp/FFT.hx
Normal file
|
@ -0,0 +1,154 @@
|
|||
package dsp;
|
||||
|
||||
import dsp.Complex;
|
||||
|
||||
// these are only used for testing, down in FFT.main()
|
||||
using dsp.OffsetArray;
|
||||
using dsp.Signal;
|
||||
|
||||
|
||||
/**
|
||||
Fast/Finite Fourier Transforms.
|
||||
**/
|
||||
class FFT {
|
||||
/**
|
||||
Computes the Discrete Fourier Transform (DFT) of a `Complex` sequence.
|
||||
|
||||
If the input has N data points (N should be a power of 2 or padding will be added)
|
||||
from a signal sampled at intervals of 1/Fs, the result will be a sequence of N
|
||||
samples from the Discrete-Time Fourier Transform (DTFT) - which is Fs-periodic -
|
||||
with a spacing of Fs/N Hz between them and a scaling factor of Fs.
|
||||
**/
|
||||
public static function fft(input:Array<Complex>) : Array<Complex>
|
||||
return do_fft(input, false);
|
||||
|
||||
/**
|
||||
Like `fft`, but for a real (Float) sequence input.
|
||||
|
||||
Since the input time signal is real, its frequency representation is
|
||||
Hermitian-symmetric so we only return the positive frequencies.
|
||||
**/
|
||||
public static function rfft(input:Array<Float>) : Array<Complex> {
|
||||
final s = fft(input.map(Complex.fromReal));
|
||||
return s.slice(0, Std.int(s.length / 2) + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
Computes the Inverse DFT of a periodic input sequence.
|
||||
|
||||
If the input contains N (a power of 2) DTFT samples, each spaced Fs/N Hz
|
||||
from each other, the result will consist of N data points as sampled
|
||||
from a time signal at intervals of 1/Fs with a scaling factor of 1/Fs.
|
||||
**/
|
||||
public static function ifft(input:Array<Complex>) : Array<Complex>
|
||||
return do_fft(input, true);
|
||||
|
||||
// Handles padding and scaling for forwards and inverse FFTs.
|
||||
private static function do_fft(input:Array<Complex>, inverse:Bool) : Array<Complex> {
|
||||
final n = nextPow2(input.length);
|
||||
var ts = [for (i in 0...n) if (i < input.length) input[i] else Complex.zero];
|
||||
var fs = [for (_ in 0...n) Complex.zero];
|
||||
ditfft2(ts, 0, fs, 0, n, 1, inverse);
|
||||
return inverse ? fs.map(z -> z.scale(1 / n)) : fs;
|
||||
return fs;
|
||||
}
|
||||
|
||||
// Radix-2 Decimation-In-Time variant of Cooley–Tukey's FFT, recursive.
|
||||
private static function ditfft2(
|
||||
time:Array<Complex>, t:Int,
|
||||
freq:Array<Complex>, f:Int,
|
||||
n:Int, step:Int, inverse: Bool
|
||||
) : Void {
|
||||
if (n == 1) {
|
||||
freq[f] = time[t].copy();
|
||||
} else {
|
||||
final halfLen = Std.int(n / 2);
|
||||
ditfft2(time, t, freq, f, halfLen, step * 2, inverse);
|
||||
ditfft2(time, t + step, freq, f + halfLen, halfLen, step * 2, inverse);
|
||||
for (k in 0...halfLen) {
|
||||
final twiddle = Complex.exp((inverse ? 1 : -1) * 2 * Math.PI * k / n);
|
||||
final even = freq[f + k].copy();
|
||||
final odd = freq[f + k + halfLen].copy();
|
||||
freq[f + k] = even + twiddle * odd;
|
||||
freq[f + k + halfLen] = even - twiddle * odd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Naive O(n^2) DFT, used for testing purposes.
|
||||
private static function dft(ts:Array<Complex>, ?inverse:Bool) : Array<Complex> {
|
||||
if (inverse == null) inverse = false;
|
||||
final n = ts.length;
|
||||
var fs = new Array<Complex>();
|
||||
fs.resize(n);
|
||||
for (f in 0...n) {
|
||||
var sum = Complex.zero;
|
||||
for (t in 0...n) {
|
||||
sum += ts[t] * Complex.exp((inverse ? 1 : -1) * 2 * Math.PI * f * t / n);
|
||||
}
|
||||
fs[f] = inverse ? sum.scale(1 / n) : sum;
|
||||
}
|
||||
return fs;
|
||||
}
|
||||
|
||||
/**
|
||||
Finds the power of 2 that is equal to or greater than the given natural.
|
||||
**/
|
||||
static function nextPow2(x:Int) : Int {
|
||||
if (x < 2) return 1;
|
||||
else if ((x & (x-1)) == 0) return x;
|
||||
var pow = 2;
|
||||
x--;
|
||||
while ((x >>= 1) != 0) pow <<= 1;
|
||||
return pow;
|
||||
}
|
||||
|
||||
// testing, but also acts like an example
|
||||
static function main() {
|
||||
// sampling and buffer parameters
|
||||
final Fs = 44100.0;
|
||||
final N = 512;
|
||||
final halfN = Std.int(N / 2);
|
||||
|
||||
// build a time signal as a sum of sinusoids
|
||||
final freqs = [5919.911];
|
||||
final ts = [for (n in 0...N) freqs.map(f -> Math.sin(2 * Math.PI * f * n / Fs)).sum()];
|
||||
|
||||
// get positive spectrum and use its symmetry to reconstruct negative domain
|
||||
final fs_pos = rfft(ts);
|
||||
final fs_fft = new OffsetArray(
|
||||
[for (k in -(halfN - 1) ... 0) fs_pos[-k].conj()].concat(fs_pos),
|
||||
-(halfN - 1)
|
||||
);
|
||||
|
||||
// double-check with naive DFT
|
||||
final fs_dft = new OffsetArray(
|
||||
dft(ts.map(Complex.fromReal)).circShift(halfN - 1),
|
||||
-(halfN - 1)
|
||||
);
|
||||
final fs_err = [for (k in -(halfN - 1) ... halfN) fs_fft[k] - fs_dft[k]];
|
||||
final max_fs_err = fs_err.map(z -> z.magnitude).max();
|
||||
if (max_fs_err > 1e-6) haxe.Log.trace('FT Error: ${max_fs_err}', null);
|
||||
// else for (k => s in fs_fft) haxe.Log.trace('${k * Fs / N};${s.scale(1 / Fs).magnitude}', null);
|
||||
|
||||
// find spectral peaks to detect signal frequencies
|
||||
final freqis = fs_fft.array.map(z -> z.magnitude)
|
||||
.findPeaks()
|
||||
.map(k -> (k - (halfN - 1)) * Fs / N)
|
||||
.filter(f -> f >= 0);
|
||||
if (freqis.length != freqs.length) {
|
||||
trace('Found frequencies: ${freqis}');
|
||||
} else {
|
||||
final freqs_err = [for (i in 0...freqs.length) freqis[i] - freqs[i]];
|
||||
final max_freqs_err = freqs_err.map(Math.abs).max();
|
||||
if (max_freqs_err > Fs / N) trace('Frequency Errors: ${freqs_err}');
|
||||
}
|
||||
|
||||
// recover time signal from the frequency domain
|
||||
final ts_ifft = ifft(fs_fft.array.circShift(-(halfN - 1)).map(z -> z.scale(1 / Fs)));
|
||||
final ts_err = [for (n in 0...N) ts_ifft[n].scale(Fs).real - ts[n]];
|
||||
final max_ts_err = ts_err.map(Math.abs).max();
|
||||
if (max_ts_err > 1e-6) haxe.Log.trace('IFT Error: ${max_ts_err}', null);
|
||||
// else for (n in 0...ts_ifft.length) haxe.Log.trace('${n / Fs};${ts_ifft[n].scale(Fs).real}', null);
|
||||
}
|
||||
}
|
78
source/dsp/OffsetArray.hx
Normal file
78
source/dsp/OffsetArray.hx
Normal file
|
@ -0,0 +1,78 @@
|
|||
package dsp;
|
||||
|
||||
/**
|
||||
A view into an Array with an indexing offset.
|
||||
|
||||
Usages include 1-indexed sequences or zero-centered buffers with negative indexing.
|
||||
**/
|
||||
@:forward(array, offset)
|
||||
abstract OffsetArray<T>({
|
||||
final array : Array<T>;
|
||||
final offset : Int;
|
||||
}) {
|
||||
public inline function new(array:Array<T>, offset:Int)
|
||||
this = { array: array, offset: offset };
|
||||
|
||||
public var length(get,never) : Int;
|
||||
inline function get_length()
|
||||
return this.array.length;
|
||||
|
||||
@:arrayAccess
|
||||
public inline function get(index:Int) : T
|
||||
return this.array[index - this.offset];
|
||||
|
||||
@:arrayAccess
|
||||
public inline function set(index:Int, value:T) : Void
|
||||
this.array[index - this.offset] = value;
|
||||
|
||||
/**
|
||||
Iterates through items in their original order while providing the altered indexes as keys.
|
||||
**/
|
||||
public inline function keyValueIterator() : KeyValueIterator<Int,T>
|
||||
return new OffsetArrayIterator(this.array, this.offset);
|
||||
|
||||
@:from
|
||||
static inline function fromArray<T>(array:Array<T>)
|
||||
return new OffsetArray(array, 0);
|
||||
|
||||
@:to
|
||||
inline function toArray()
|
||||
return this.array;
|
||||
|
||||
/**
|
||||
Makes a shifted version of the given `array`, where elements are in the
|
||||
same order but shifted by `n` positions (to the right if positive and to
|
||||
the left if negative) in **circular** fashion (no elements discarded).
|
||||
**/
|
||||
public static function circShift<T>(array:Array<T>, n:Int) : Array<T> {
|
||||
if (n < 0) return circShift(array, array.length + n);
|
||||
|
||||
var shifted = new Array<T>();
|
||||
|
||||
n = n % array.length;
|
||||
for (i in array.length - n ... array.length) shifted.push(array[i]);
|
||||
for (i in 0 ... array.length - n) shifted.push(array[i]);
|
||||
|
||||
return shifted;
|
||||
}
|
||||
}
|
||||
|
||||
private class OffsetArrayIterator<T> {
|
||||
private final array : Array<T>;
|
||||
private final offset : Int;
|
||||
private var enumeration : Int;
|
||||
|
||||
public inline function new(array:Array<T>, offset:Int) {
|
||||
this.array = array;
|
||||
this.offset = offset;
|
||||
this.enumeration = 0;
|
||||
}
|
||||
|
||||
public inline function next() : {key:Int, value:T} {
|
||||
final i = this.enumeration++;
|
||||
return { key: i + this.offset, value: this.array[i] };
|
||||
}
|
||||
|
||||
public inline function hasNext() : Bool
|
||||
return this.enumeration < this.array.length;
|
||||
}
|
110
source/dsp/Signal.hx
Normal file
110
source/dsp/Signal.hx
Normal file
|
@ -0,0 +1,110 @@
|
|||
package dsp;
|
||||
|
||||
using Lambda;
|
||||
|
||||
|
||||
/**
|
||||
Signal processing miscellaneous utilities.
|
||||
**/
|
||||
class Signal {
|
||||
/**
|
||||
Returns a smoothed version of the input array using a moving average.
|
||||
**/
|
||||
public static function smooth(y:Array<Float>, n:Int) : Array<Float> {
|
||||
if (n <= 0) {
|
||||
return null;
|
||||
} else if (n == 1) {
|
||||
return y.copy();
|
||||
} else {
|
||||
var smoothed = new Array<Float>();
|
||||
smoothed.resize(y.length);
|
||||
for (i in 0...y.length) {
|
||||
var m = i + 1 < n ? i : n - 1;
|
||||
smoothed[i] = sum(y.slice(i - m, i + 1));
|
||||
}
|
||||
return smoothed;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Finds indexes of peaks in the order they appear in the input sequence.
|
||||
|
||||
@param threshold Minimal peak height wrt. its neighbours, defaults to 0.
|
||||
@param minHeight Minimal peak height wrt. the whole input, defaults to global minimum.
|
||||
**/
|
||||
public static function findPeaks(
|
||||
y:Array<Float>,
|
||||
?threshold:Float,
|
||||
?minHeight:Float
|
||||
) : Array<Int> {
|
||||
threshold = threshold == null ? 0.0 : Math.abs(threshold);
|
||||
minHeight = minHeight == null ? Signal.min(y) : minHeight;
|
||||
|
||||
var peaks = new Array<Int>();
|
||||
|
||||
final dy = [for (i in 1...y.length) y[i] - y[i-1]];
|
||||
for (i in 1...dy.length) {
|
||||
// peak: function growth positive to its left and negative to its right
|
||||
if (
|
||||
dy[i-1] > threshold && dy[i] < -threshold &&
|
||||
y[i] > minHeight
|
||||
) {
|
||||
peaks.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
return peaks;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the sum of all the elements of a given array.
|
||||
|
||||
This function tries to minimize floating-point precision errors.
|
||||
**/
|
||||
public static function sum(array:Array<Float>) : Float {
|
||||
// Neumaier's "improved Kahan-Babuska algorithm":
|
||||
|
||||
var sum = 0.0;
|
||||
var c = 0.0; // running compensation for lost precision
|
||||
|
||||
for (v in array) {
|
||||
var t = sum + v;
|
||||
c += Math.abs(sum) >= Math.abs(v)
|
||||
? (sum - t) + v // sum is bigger => low-order digits of v are lost
|
||||
: (v - t) + sum; // v is bigger => low-order digits of sum are lost
|
||||
sum = t;
|
||||
}
|
||||
|
||||
return sum + c; // correction only applied at the very end
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the average value of an array.
|
||||
**/
|
||||
public static function mean(y:Array<Float>) : Float
|
||||
return sum(y) / y.length;
|
||||
|
||||
/**
|
||||
Returns the global maximum.
|
||||
**/
|
||||
public static function max(y:Array<Float>) : Float
|
||||
return y.fold(Math.max, y[0]);
|
||||
|
||||
/**
|
||||
Returns the global maximum's index.
|
||||
**/
|
||||
public static function maxi(y:Array<Float>) : Int
|
||||
return y.foldi((yi, m, i) -> yi > y[m] ? i : m, 0);
|
||||
|
||||
/**
|
||||
Returns the global minimum.
|
||||
**/
|
||||
public static function min(y:Array<Float>) : Float
|
||||
return y.fold(Math.min, y[0]);
|
||||
|
||||
/**
|
||||
Returns the global minimum's index.
|
||||
**/
|
||||
public static function mini(y:Array<Float>) : Int
|
||||
return y.foldi((yi, m, i) -> yi < y[m] ? i : m, 0);
|
||||
}
|
52
source/freeplayStuff/DJBoyfriend.hx
Normal file
52
source/freeplayStuff/DJBoyfriend.hx
Normal file
|
@ -0,0 +1,52 @@
|
|||
package freeplayStuff;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
|
||||
class DJBoyfriend extends FlxSprite
|
||||
{
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
animOffsets = new Map<String, Array<Dynamic>>();
|
||||
|
||||
frames = Paths.getSparrowAtlas('freeplay/bfFreeplay');
|
||||
animation.addByPrefix('intro', "boyfriend dj intro", 24, false);
|
||||
animation.addByPrefix('idle', "Boyfriend DJ0", 24);
|
||||
animation.addByPrefix('confirm', "Boyfriend DJ confirm", 24);
|
||||
|
||||
addOffset('intro', 0, 0);
|
||||
addOffset('idle', -4, -426);
|
||||
|
||||
playAnim('intro');
|
||||
animation.finishCallback = function(anim)
|
||||
{
|
||||
switch (anim)
|
||||
{
|
||||
case "intro":
|
||||
playAnim('idle'); // plays idle anim after playing intro
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// playAnim stolen from Character.hx, cuz im lazy lol!
|
||||
public var animOffsets:Map<String, Array<Dynamic>>;
|
||||
|
||||
public function playAnim(AnimName:String, Force:Bool = false, Reversed:Bool = false, Frame:Int = 0):Void
|
||||
{
|
||||
animation.play(AnimName, Force, Reversed, Frame);
|
||||
|
||||
var daOffset = animOffsets.get(AnimName);
|
||||
if (animOffsets.exists(AnimName))
|
||||
{
|
||||
offset.set(daOffset[0], daOffset[1]);
|
||||
}
|
||||
else
|
||||
offset.set(0, 0);
|
||||
}
|
||||
|
||||
public function addOffset(name:String, x:Float = 0, y:Float = 0)
|
||||
{
|
||||
animOffsets[name] = [x, y];
|
||||
}
|
||||
}
|
71
source/freeplayStuff/SongMenuItem.hx
Normal file
71
source/freeplayStuff/SongMenuItem.hx
Normal file
|
@ -0,0 +1,71 @@
|
|||
package freeplayStuff;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
||||
import flixel.group.FlxSpriteGroup;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.text.FlxText;
|
||||
|
||||
class SongMenuItem extends FlxSpriteGroup
|
||||
{
|
||||
var capsule:FlxSprite;
|
||||
|
||||
public var selected(default, set):Bool = false;
|
||||
|
||||
public var songTitle:String = "Test";
|
||||
|
||||
var songText:FlxText;
|
||||
|
||||
public var targetPos:FlxPoint = new FlxPoint();
|
||||
public var doLerp:Bool = false;
|
||||
|
||||
public function new(x:Float, y:Float, song:String)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
this.songTitle = song;
|
||||
|
||||
capsule = new FlxSprite();
|
||||
capsule.frames = Paths.getSparrowAtlas('freeplay/freeplayCapsule');
|
||||
capsule.animation.addByPrefix('selected', 'mp3 capsule w backing0', 24);
|
||||
capsule.animation.addByPrefix('unselected', 'mp3 capsule w backing NOT SELECTED', 24);
|
||||
// capsule.animation
|
||||
add(capsule);
|
||||
|
||||
songText = new FlxText(120, 40, 0, songTitle, 40);
|
||||
songText.font = "5by7";
|
||||
songText.color = 0xFF43C1EA;
|
||||
add(songText);
|
||||
|
||||
selected = selected; // just to kickstart the set_selected
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (doLerp)
|
||||
{
|
||||
x = CoolUtil.coolLerp(x, targetPos.x, 0.3);
|
||||
y = CoolUtil.coolLerp(y, targetPos.y, 0.4);
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.ALT)
|
||||
selected = false;
|
||||
if (FlxG.keys.justPressed.CONTROL)
|
||||
selected = true;
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
function set_selected(value:Bool):Bool
|
||||
{
|
||||
trace(value);
|
||||
|
||||
// cute one liners, lol!
|
||||
songText.alpha = value ? 1 : 0.6;
|
||||
capsule.offset.x = value ? 0 : -5;
|
||||
capsule.animation.play(value ? "selected" : "unselected");
|
||||
return value;
|
||||
}
|
||||
}
|
72
source/shaderslmfao/ScreenWipeShader.hx
Normal file
72
source/shaderslmfao/ScreenWipeShader.hx
Normal file
|
@ -0,0 +1,72 @@
|
|||
package shaderslmfao;
|
||||
|
||||
import flixel.system.FlxAssets.FlxShader;
|
||||
|
||||
class ScreenWipeShader extends FlxShader
|
||||
{
|
||||
public var daAlphaShit(default, set):Float = 0;
|
||||
|
||||
function set_daAlphaShit(alpha:Float):Float
|
||||
{
|
||||
alphaShit.value[0] = alpha;
|
||||
|
||||
return alpha;
|
||||
}
|
||||
|
||||
@:glFragmentSource('
|
||||
#pragma header
|
||||
|
||||
uniform float alphaShit;
|
||||
uniform float yPos;
|
||||
uniform float xPos;
|
||||
|
||||
uniform sampler2D funnyShit;
|
||||
|
||||
|
||||
vec3 rgb2hsv(vec3 c)
|
||||
{
|
||||
vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
||||
vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
|
||||
vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
|
||||
|
||||
float d = q.x - min(q.w, q.y);
|
||||
float e = 1.0e-10;
|
||||
return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
||||
}
|
||||
|
||||
vec3 hsv2rgb(vec3 c)
|
||||
{
|
||||
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
||||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 funnyUv = openfl_TextureCoordv;
|
||||
vec4 color = flixel_texture2D(bitmap, funnyUv);
|
||||
|
||||
vec2 reallyFunnyUv = vec2(vec2(0.0, 0.0) - gl_FragCoord.xy / openfl_TextureSize.xy);
|
||||
|
||||
vec4 gf = flixel_texture2D(funnyShit, openfl_TextureCoordv);
|
||||
|
||||
|
||||
vec3 hsvTypeBeat = rgb2hsv(vec3(gf.r, gf.g, gf.b));
|
||||
|
||||
vec4 output = color;
|
||||
|
||||
// .b here actually means value?
|
||||
if (hsvTypeBeat.b <= alphaShit)
|
||||
color = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
')
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
|
||||
alphaShit.value = [0];
|
||||
}
|
||||
}
|
22
source/shaderslmfao/WaveShader.hx
Normal file
22
source/shaderslmfao/WaveShader.hx
Normal file
|
@ -0,0 +1,22 @@
|
|||
package shaderslmfao;
|
||||
|
||||
import flixel.system.FlxAssets.FlxShader;
|
||||
|
||||
class WaveShader extends FlxShader
|
||||
{
|
||||
@:glFragmentSource('
|
||||
#pragma header
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color = flixel_texture2D(bitmap, openfl_TextureCoordv);
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
|
||||
')
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
}
|
||||
}
|
|
@ -3,10 +3,8 @@ package ui;
|
|||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.util.FlxColor;
|
||||
#if cpp
|
||||
import polymod.Polymod;
|
||||
import sys.FileSystem;
|
||||
#end
|
||||
|
||||
class ModMenu extends ui.OptionsState.Page
|
||||
{
|
||||
|
|
|
@ -32,7 +32,7 @@ class OptionsState extends MusicBeatState
|
|||
var controls = addPage(Controls, new ControlsMenu());
|
||||
// var colors = addPage(Colors, new ColorsMenu());
|
||||
|
||||
#if cpp
|
||||
#if polymod
|
||||
var mods = addPage(Mods, new ModMenu());
|
||||
#end
|
||||
|
||||
|
@ -43,7 +43,7 @@ class OptionsState extends MusicBeatState
|
|||
// colors.onExit.add(switchPage.bind(Options));
|
||||
preferences.onExit.add(switchPage.bind(Options));
|
||||
|
||||
#if cpp
|
||||
#if polymod
|
||||
mods.onExit.add(switchPage.bind(Options));
|
||||
#end
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ class OptionsMenu extends Page
|
|||
createItem('preferences', function() switchPage(Preferences));
|
||||
createItem("controls", function() switchPage(Controls));
|
||||
// createItem('colors', function() switchPage(Colors));
|
||||
#if cpp
|
||||
#if polymod
|
||||
createItem('mods', function() switchPage(Mods));
|
||||
#end
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue