Add files via upload
This commit is contained in:
parent
0e5fe03b78
commit
f919a81e18
|
@ -0,0 +1,73 @@
|
|||
package;
|
||||
|
||||
import flixel.FlxG;
|
||||
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 haxe.Json;
|
||||
import lime.math.Rectangle;
|
||||
import lime.utils.Assets;
|
||||
|
||||
import game.state.*;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class CoolUtil
|
||||
{
|
||||
public static var difficultyArray:Array<String> = ['EASY', "NORMAL", "HARD"];
|
||||
|
||||
public static function difficultyString():String
|
||||
{
|
||||
return difficultyArray[PlayState.storyDifficulty];
|
||||
}
|
||||
|
||||
public static function coolTextFile(path:String):Array<String>
|
||||
{
|
||||
var daList:Array<String> = Assets.getText(path).trim().split('\n');
|
||||
|
||||
for (i in 0...daList.length)
|
||||
{
|
||||
daList[i] = daList[i].trim();
|
||||
}
|
||||
|
||||
return daList;
|
||||
}
|
||||
|
||||
public static function numberArray(max:Int, ?min = 0):Array<Int>
|
||||
{
|
||||
var dumbArray:Array<Int> = [];
|
||||
for (i in min...max)
|
||||
{
|
||||
dumbArray.push(i);
|
||||
}
|
||||
return dumbArray;
|
||||
}
|
||||
|
||||
// Robbed From Psych lmfao
|
||||
inline public static function boundTo(value:Float, min:Float, max:Float):Float {
|
||||
return Math.max(min, Math.min(max, value));
|
||||
}
|
||||
|
||||
/**
|
||||
Lerps camera, but accountsfor framerate shit?
|
||||
Right now it's simply for use to change the followLerp variable of a camera during update
|
||||
TODO LATER MAYBE:
|
||||
Actually make and modify the scroll and lerp shit in it's own function
|
||||
instead of solely relying on changing the lerp on the fly
|
||||
*/
|
||||
public static function camLerpShit(lerp:Float):Float
|
||||
{
|
||||
return lerp * (FlxG.elapsed / (1 / 60));
|
||||
}
|
||||
|
||||
/*
|
||||
* just lerp that does camLerpShit for u so u dont have to do it every time
|
||||
*/
|
||||
public static function coolLerp(a:Float, b:Float, ratio:Float):Float
|
||||
{
|
||||
return FlxMath.lerp(a, b, camLerpShit(ratio));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
package;
|
||||
|
||||
import flixel.FlxGame;
|
||||
import flixel.FlxState;
|
||||
import openfl.Assets;
|
||||
import openfl.Lib;
|
||||
import openfl.display.FPS;
|
||||
import openfl.display.Sprite;
|
||||
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 game.state.menus.*;
|
||||
|
||||
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 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.
|
||||
#else
|
||||
var framerate:Int = 120; // How many frames per second the game should run at.
|
||||
|
||||
#end
|
||||
var skipSplash:Bool = true; // Whether to skip the flixel splash screen that appears in release mode.
|
||||
var startFullscreen:Bool = false; // Whether to start the game in fullscreen on desktop targets
|
||||
|
||||
// You can pretty much ignore everything from here on - your code should go in your states.
|
||||
|
||||
public static function main():Void
|
||||
{
|
||||
Lib.current.addChild(new Main());
|
||||
}
|
||||
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
|
||||
if (stage != null)
|
||||
{
|
||||
init();
|
||||
}
|
||||
else
|
||||
{
|
||||
addEventListener(Event.ADDED_TO_STAGE, init);
|
||||
}
|
||||
}
|
||||
|
||||
private function init(?E:Event):Void
|
||||
{
|
||||
if (hasEventListener(Event.ADDED_TO_STAGE))
|
||||
{
|
||||
removeEventListener(Event.ADDED_TO_STAGE, init);
|
||||
}
|
||||
|
||||
setupGame();
|
||||
}
|
||||
|
||||
var video:Video;
|
||||
var netStream:NetStream;
|
||||
private var overlay:Sprite;
|
||||
|
||||
public static var fpsCounter:FPS;
|
||||
|
||||
private function setupGame():Void
|
||||
{
|
||||
var stageWidth:Int = Lib.current.stage.stageWidth;
|
||||
var stageHeight:Int = Lib.current.stage.stageHeight;
|
||||
|
||||
if (zoom == -1)
|
||||
{
|
||||
var ratioX:Float = stageWidth / gameWidth;
|
||||
var ratioY:Float = stageHeight / gameHeight;
|
||||
zoom = Math.min(ratioX, ratioY);
|
||||
gameWidth = Math.ceil(stageWidth / zoom);
|
||||
gameHeight = Math.ceil(stageHeight / zoom);
|
||||
}
|
||||
|
||||
#if !debug
|
||||
initialState = TitleState;
|
||||
#end
|
||||
|
||||
addChild(new FlxGame(gameWidth, gameHeight, initialState, #if (flixel < "5.0.0") zoom, #end framerate, framerate, skipSplash, startFullscreen));
|
||||
|
||||
#if !mobile
|
||||
fpsCounter = new FPS(10, 3, 0xFFFFFF);
|
||||
addChild(fpsCounter);
|
||||
#end
|
||||
/*
|
||||
video = new Video();
|
||||
addChild(video);
|
||||
|
||||
var netConnection = new NetConnection();
|
||||
netConnection.connect(null);
|
||||
|
||||
netStream = new NetStream(netConnection);
|
||||
netStream.client = {onMetaData: client_onMetaData};
|
||||
netStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, netStream_onAsyncError);
|
||||
|
||||
#if (js && html5)
|
||||
overlay = new Sprite();
|
||||
overlay.graphics.beginFill(0, 0.5);
|
||||
overlay.graphics.drawRect(0, 0, 560, 320);
|
||||
overlay.addEventListener(MouseEvent.MOUSE_DOWN, overlay_onMouseDown);
|
||||
overlay.buttonMode = true;
|
||||
addChild(overlay);
|
||||
|
||||
netConnection.addEventListener(NetStatusEvent.NET_STATUS, netConnection_onNetStatus);
|
||||
#else
|
||||
netStream.play("assets/preload/music/dredd.mp4");
|
||||
#end
|
||||
*/
|
||||
}
|
||||
/*
|
||||
private function client_onMetaData(metaData:Dynamic)
|
||||
{
|
||||
video.attachNetStream(netStream);
|
||||
|
||||
video.width = video.videoWidth;
|
||||
video.height = video.videoHeight;
|
||||
}
|
||||
|
||||
private function netStream_onAsyncError(event:AsyncErrorEvent):Void
|
||||
{
|
||||
trace("Error loading video");
|
||||
}
|
||||
|
||||
private function netConnection_onNetStatus(event:NetStatusEvent):Void
|
||||
{
|
||||
}
|
||||
|
||||
private function overlay_onMouseDown(event:MouseEvent):Void
|
||||
{
|
||||
netStream.play("assets/preload/music/dredd.mp4");
|
||||
}
|
||||
*/
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import openfl.utils.AssetType;
|
||||
import openfl.utils.Assets as OpenFlAssets;
|
||||
|
||||
class Paths
|
||||
{
|
||||
inline public static var SOUND_EXT = #if web "mp3" #else "ogg" #end;
|
||||
|
||||
static var currentLevel:String;
|
||||
|
||||
static public function setCurrentLevel(name:String)
|
||||
{
|
||||
currentLevel = name.toLowerCase();
|
||||
}
|
||||
|
||||
static function getPath(file:String, type:AssetType, library:Null<String>)
|
||||
{
|
||||
if (library != null)
|
||||
return getLibraryPath(file, library);
|
||||
|
||||
if (currentLevel != null)
|
||||
{
|
||||
var levelPath = getLibraryPathForce(file, currentLevel);
|
||||
if (OpenFlAssets.exists(levelPath, type))
|
||||
return levelPath;
|
||||
|
||||
levelPath = getLibraryPathForce(file, "shared");
|
||||
if (OpenFlAssets.exists(levelPath, type))
|
||||
return levelPath;
|
||||
}
|
||||
|
||||
return getPreloadPath(file);
|
||||
}
|
||||
|
||||
static public function getLibraryPath(file:String, library = "preload")
|
||||
{
|
||||
return if (library == "preload" || library == "default") getPreloadPath(file); else getLibraryPathForce(file, library);
|
||||
}
|
||||
|
||||
inline static function getLibraryPathForce(file:String, library:String)
|
||||
{
|
||||
return '$library:assets/$library/$file';
|
||||
}
|
||||
|
||||
inline static function getPreloadPath(file:String)
|
||||
{
|
||||
return 'assets/$file';
|
||||
}
|
||||
|
||||
inline static public function file(file:String, type:AssetType = TEXT, ?library:String)
|
||||
{
|
||||
return getPath(file, type, library);
|
||||
}
|
||||
|
||||
inline static public function txt(key:String, ?library:String)
|
||||
{
|
||||
return getPath('data/$key.txt', TEXT, library);
|
||||
}
|
||||
|
||||
inline static public function xml(key:String, ?library:String)
|
||||
{
|
||||
return getPath('data/$key.xml', TEXT, library);
|
||||
}
|
||||
|
||||
inline static public function json(key:String, ?library:String)
|
||||
{
|
||||
return getPath('data/$key.json', TEXT, library);
|
||||
}
|
||||
|
||||
static public function sound(key:String, ?library:String)
|
||||
{
|
||||
return getPath('sounds/$key.$SOUND_EXT', SOUND, library);
|
||||
}
|
||||
|
||||
inline static public function soundRandom(key:String, min:Int, max:Int, ?library:String)
|
||||
{
|
||||
return sound(key + FlxG.random.int(min, max), library);
|
||||
}
|
||||
|
||||
inline static public function music(key:String, ?library:String)
|
||||
{
|
||||
return getPath('music/$key.$SOUND_EXT', MUSIC, library);
|
||||
}
|
||||
|
||||
inline static public function voices(song:String)
|
||||
{
|
||||
return 'songs:assets/songs/${song.toLowerCase()}/Voices.$SOUND_EXT';
|
||||
}
|
||||
|
||||
inline static public function inst(song:String)
|
||||
{
|
||||
return 'songs:assets/songs/${song.toLowerCase()}/Inst.$SOUND_EXT';
|
||||
}
|
||||
|
||||
inline static public function image(key:String, ?library:String)
|
||||
{
|
||||
return getPath('images/$key.png', IMAGE, library);
|
||||
}
|
||||
|
||||
inline static public function font(key:String)
|
||||
{
|
||||
return 'assets/fonts/$key';
|
||||
}
|
||||
|
||||
inline static public function getSparrowAtlas(key:String, ?library:String)
|
||||
{
|
||||
return FlxAtlasFrames.fromSparrow(image(key, library), file('images/$key.xml', library));
|
||||
}
|
||||
|
||||
inline static public function getPackerAtlas(key:String, ?library:String)
|
||||
{
|
||||
return FlxAtlasFrames.fromSpriteSheetPacker(image(key, library), file('images/$key.txt', library));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
package animate;
|
||||
|
||||
// import animateAtlasPlayer.assets.AssetManager;
|
||||
// import animateAtlasPlayer.core.Animation;
|
||||
import animate.FlxSymbol.Parsed;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.FlxGraphic;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.system.FlxAssets.FlxGraphicAsset;
|
||||
import haxe.Json;
|
||||
import openfl.Assets;
|
||||
import openfl.display.BitmapData;
|
||||
import openfl.geom.Rectangle;
|
||||
|
||||
class FlxAnimate extends FlxSymbol
|
||||
{
|
||||
// var myAnim:Animation;
|
||||
// var animBitmap:BitmapData;
|
||||
var loadedQueue:Bool = false;
|
||||
|
||||
var swagFrames:Array<BitmapData> = [];
|
||||
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
var folder:String = 'tightBars';
|
||||
coolParse = cast Json.parse(Assets.getText(Paths.file('images/' + folder + '/Animation.json')));
|
||||
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
|
||||
}
|
||||
|
||||
override function draw()
|
||||
{
|
||||
super.draw();
|
||||
|
||||
renderFrame(coolParse.AN.TL, coolParse, true);
|
||||
|
||||
if (FlxG.keys.justPressed.E)
|
||||
{
|
||||
for (shit in FlxSymbol.nestedShit.keys())
|
||||
{
|
||||
for (spr in FlxSymbol.nestedShit.get(shit))
|
||||
{
|
||||
spr.draw();
|
||||
}
|
||||
}
|
||||
|
||||
FlxSymbol.nestedShit.clear();
|
||||
}
|
||||
}
|
||||
|
||||
var curFrame:Int = 0;
|
||||
|
||||
// notes to self
|
||||
// account for different layers
|
||||
var playingAnim:Bool = false;
|
||||
var frameTickTypeShit:Float = 0;
|
||||
var animFrameRate:Int = 24;
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
if (FlxG.keys.justPressed.SPACE)
|
||||
playingAnim = !playingAnim;
|
||||
|
||||
if (playingAnim)
|
||||
{
|
||||
frameTickTypeShit += elapsed;
|
||||
|
||||
// prob fix this framerate thing for higher framerates?
|
||||
if (frameTickTypeShit >= 1 / 24)
|
||||
{
|
||||
changeFrame(1);
|
||||
frameTickTypeShit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.RIGHT)
|
||||
changeFrame(1);
|
||||
if (FlxG.keys.justPressed.LEFT)
|
||||
changeFrame(-1);
|
||||
}
|
||||
|
||||
// This stuff is u
|
||||
public static function fromAnimate(Source:FlxGraphicAsset, Description:String):FlxAtlasFrames
|
||||
{
|
||||
var graphic:FlxGraphic = FlxG.bitmap.add(Source);
|
||||
if (graphic == null)
|
||||
return null;
|
||||
|
||||
var frames:FlxAtlasFrames = FlxAtlasFrames.findFrame(graphic);
|
||||
if (frames != null)
|
||||
return frames;
|
||||
|
||||
if (graphic == null || Description == null)
|
||||
return null;
|
||||
|
||||
frames = new FlxAtlasFrames(graphic);
|
||||
|
||||
var data:AnimateObject;
|
||||
|
||||
var json:String = Description;
|
||||
|
||||
trace(json);
|
||||
|
||||
if (Assets.exists(json))
|
||||
json = Assets.getText(json);
|
||||
|
||||
data = cast Json.parse(json).ATLAS;
|
||||
|
||||
for (sprite in data.SPRITES)
|
||||
{
|
||||
// probably nicer way to do this? Oh well
|
||||
var swagSprite:AnimateSprite = sprite.SPRITE;
|
||||
|
||||
var rect = FlxRect.get(swagSprite.x, swagSprite.y, swagSprite.w, swagSprite.h);
|
||||
|
||||
var size = new Rectangle(0, 0, rect.width, rect.height);
|
||||
|
||||
var offset = FlxPoint.get(-size.left, -size.top);
|
||||
var sourceSize = FlxPoint.get(size.width, size.height);
|
||||
|
||||
frames.addAtlasFrame(rect, sourceSize, offset, swagSprite.name);
|
||||
}
|
||||
|
||||
return frames;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,324 @@
|
|||
package animate;
|
||||
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxFrame.FlxFrameAngle;
|
||||
import flixel.math.FlxAngle;
|
||||
import flixel.math.FlxMatrix;
|
||||
import flixel.math.FlxPoint;
|
||||
import openfl.geom.Matrix;
|
||||
|
||||
class FlxSymbol extends FlxSprite
|
||||
{
|
||||
public var coolParse:Parsed;
|
||||
public var oldMatrix:Array<Float> = [];
|
||||
|
||||
private var hasFrameByPass:Bool = false;
|
||||
|
||||
public function new(x:Float, y:Float, coolParsed:Parsed)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
this.coolParse = coolParsed;
|
||||
|
||||
var hasSymbolDictionary:Bool = Reflect.hasField(coolParse, "SD");
|
||||
|
||||
if (hasSymbolDictionary)
|
||||
symbolAtlasShit = parseSymbolDictionary(coolParse);
|
||||
}
|
||||
|
||||
var symbolAtlasShit:Map<String, String> = new Map();
|
||||
|
||||
override function draw()
|
||||
{
|
||||
super.draw();
|
||||
}
|
||||
|
||||
public static var nestedShit:Map<Int, Array<FlxSymbol>> = new Map();
|
||||
|
||||
var symbolMap:Map<String, Animation> = new Map();
|
||||
|
||||
var drawQueue:Array<FlxSymbol> = [];
|
||||
|
||||
public var daFrame:Int = 0;
|
||||
public var nestDepth:Int = 0;
|
||||
|
||||
public var transformMatrix:Matrix = new Matrix();
|
||||
|
||||
function renderFrame(TL:Timeline, coolParsed:Parsed, ?isMainLoop:Bool = false)
|
||||
{
|
||||
drawQueue = [];
|
||||
|
||||
for (layer in TL.L)
|
||||
{
|
||||
// layer.FR.reverse();
|
||||
// var frame = layer.FR[0]
|
||||
|
||||
for (frame in layer.FR)
|
||||
{
|
||||
if (daFrame >= frame.I && daFrame < frame.I + frame.DU)
|
||||
{
|
||||
for (element in frame.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);
|
||||
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();
|
||||
spr.origin.x += origin.x;
|
||||
spr.origin.y += origin.y;
|
||||
|
||||
spr.antialiasing = true;
|
||||
spr.draw();
|
||||
}
|
||||
else
|
||||
{
|
||||
var nestedSymbol = symbolMap.get(element.SI.SN);
|
||||
var nestedShit:FlxSymbol = new FlxSymbol(0, 0, 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;
|
||||
|
||||
nestedShit.hasFrameByPass = true;
|
||||
nestedShit.nestDepth = nestDepth + 1;
|
||||
nestedShit.renderFrame(nestedSymbol.TL, coolParsed);
|
||||
|
||||
// renderFrame(nestedSymbol.TL, coolParsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// drawQueue.reverse();
|
||||
//
|
||||
// for (thing in drawQueue)
|
||||
// thing.draw();
|
||||
}
|
||||
|
||||
function setDaMap(spr:FlxSymbol):Void
|
||||
{
|
||||
if (!nestedShit.exists(nestDepth))
|
||||
nestedShit.set(nestDepth, [spr]);
|
||||
else
|
||||
nestedShit.get(nestDepth).push(spr);
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
override function drawComplex(camera:FlxCamera):Void
|
||||
{
|
||||
_frame.prepareMatrix(_matrix, FlxFrameAngle.ANGLE_0, checkFlipX(), checkFlipY());
|
||||
_matrix.translate(-origin.x, -origin.y);
|
||||
_matrix.scale(scale.x, scale.y);
|
||||
|
||||
if (matrixExposed)
|
||||
{
|
||||
_matrix.concat(transformMatrix);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bakedRotationAngle <= 0)
|
||||
{
|
||||
updateTrig();
|
||||
|
||||
if (angle != 0)
|
||||
_matrix.rotateWithTrig(_cosAngle, _sinAngle);
|
||||
}
|
||||
|
||||
// updateSkewMatrix();
|
||||
_matrix.concat(_skewMatrix);
|
||||
}
|
||||
|
||||
_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)
|
||||
{
|
||||
_skewMatrix.b = Math.tan(skew.y * FlxAngle.TO_RAD);
|
||||
_skewMatrix.c = Math.tan(skew.x * FlxAngle.TO_RAD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 =
|
||||
{
|
||||
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;
|
||||
|
||||
var TRP:TransformationPoint;
|
||||
var M3D:Array<Float>;
|
||||
}
|
||||
|
||||
typedef AtlasSymbolInstance =
|
||||
{
|
||||
var N:String;
|
||||
var M3D:Array<Float>;
|
||||
}
|
||||
|
||||
typedef TransformationPoint =
|
||||
{
|
||||
var x:Float;
|
||||
var y:Float;
|
||||
}
|
|
@ -0,0 +1,253 @@
|
|||
package game.data;
|
||||
|
||||
import game.state.menus.options.controls.Controls;
|
||||
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxG;
|
||||
import flixel.input.actions.FlxActionInput;
|
||||
import flixel.input.gamepad.FlxGamepad;
|
||||
import flixel.util.FlxSignal;
|
||||
|
||||
// import ui.DeviceManager;
|
||||
// import props.Player;
|
||||
class PlayerSettings
|
||||
{
|
||||
static public var numPlayers(default, null) = 0;
|
||||
static public var numAvatars(default, null) = 0;
|
||||
static public var player1(default, null):PlayerSettings;
|
||||
static public var player2(default, null):PlayerSettings;
|
||||
|
||||
static public var onAvatarAdd(default, null) = new FlxTypedSignal<PlayerSettings->Void>();
|
||||
static public var onAvatarRemove(default, null) = new FlxTypedSignal<PlayerSettings->Void>();
|
||||
|
||||
public var id(default, null):Int;
|
||||
|
||||
public var controls(default, null):Controls;
|
||||
|
||||
// public var avatar:Player;
|
||||
// public var camera(get, never):PlayCamera;
|
||||
|
||||
function new(id)
|
||||
{
|
||||
this.id = id;
|
||||
this.controls = new Controls('player$id', None);
|
||||
|
||||
#if CLEAR_INPUT_SAVE
|
||||
FlxG.save.data.controls = null;
|
||||
FlxG.save.flush();
|
||||
#end
|
||||
|
||||
var useDefault = true;
|
||||
var controlData = FlxG.save.data.controls;
|
||||
if (controlData != null)
|
||||
{
|
||||
var keyData:Dynamic = null;
|
||||
if (id == 0 && controlData.p1 != null && controlData.p1.keys != null)
|
||||
keyData = controlData.p1.keys;
|
||||
else if (id == 1 && controlData.p2 != null && controlData.p2.keys != null)
|
||||
keyData = controlData.p2.keys;
|
||||
|
||||
if (keyData != null)
|
||||
{
|
||||
useDefault = false;
|
||||
trace("loaded key data: " + haxe.Json.stringify(keyData));
|
||||
controls.fromSaveData(keyData, Keys);
|
||||
}
|
||||
}
|
||||
|
||||
if (useDefault)
|
||||
controls.setKeyboardScheme(Solo);
|
||||
}
|
||||
|
||||
function addGamepad(gamepad:FlxGamepad)
|
||||
{
|
||||
var useDefault = true;
|
||||
var controlData = FlxG.save.data.controls;
|
||||
if (controlData != null)
|
||||
{
|
||||
var padData:Dynamic = null;
|
||||
if (id == 0 && controlData.p1 != null && controlData.p1.pad != null)
|
||||
padData = controlData.p1.pad;
|
||||
else if (id == 1 && controlData.p2 != null && controlData.p2.pad != null)
|
||||
padData = controlData.p2.pad;
|
||||
|
||||
if (padData != null)
|
||||
{
|
||||
useDefault = false;
|
||||
trace("loaded pad data: " + haxe.Json.stringify(padData));
|
||||
controls.addGamepadWithSaveData(gamepad.id, padData);
|
||||
}
|
||||
}
|
||||
|
||||
if (useDefault)
|
||||
controls.addDefaultGamepad(gamepad.id);
|
||||
}
|
||||
|
||||
public function saveControls()
|
||||
{
|
||||
if (FlxG.save.data.controls == null)
|
||||
FlxG.save.data.controls = {};
|
||||
|
||||
var playerData:{ ?keys:Dynamic, ?pad:Dynamic }
|
||||
if (id == 0)
|
||||
{
|
||||
if (FlxG.save.data.controls.p1 == null)
|
||||
FlxG.save.data.controls.p1 = {};
|
||||
playerData = FlxG.save.data.controls.p1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FlxG.save.data.controls.p2 == null)
|
||||
FlxG.save.data.controls.p2 = {};
|
||||
playerData = FlxG.save.data.controls.p2;
|
||||
}
|
||||
|
||||
var keyData = controls.createSaveData(Keys);
|
||||
if (keyData != null)
|
||||
{
|
||||
playerData.keys = keyData;
|
||||
trace("saving key data: " + haxe.Json.stringify(keyData));
|
||||
}
|
||||
|
||||
if (controls.gamepadsAdded.length > 0)
|
||||
{
|
||||
var padData = controls.createSaveData(Gamepad(controls.gamepadsAdded[0]));
|
||||
if (padData != null)
|
||||
{
|
||||
trace("saving pad data: " + haxe.Json.stringify(padData));
|
||||
playerData.pad = padData;
|
||||
}
|
||||
}
|
||||
|
||||
FlxG.save.flush();
|
||||
}
|
||||
|
||||
static public function init():Void
|
||||
{
|
||||
if (player1 == null)
|
||||
{
|
||||
player1 = new PlayerSettings(0);
|
||||
++numPlayers;
|
||||
}
|
||||
|
||||
FlxG.gamepads.deviceConnected.add(onGamepadAdded);
|
||||
|
||||
var numGamepads = FlxG.gamepads.numActiveGamepads;
|
||||
for (i in 0...numGamepads)
|
||||
{
|
||||
var gamepad = FlxG.gamepads.getByID(i);
|
||||
if (gamepad != null)
|
||||
onGamepadAdded(gamepad);
|
||||
}
|
||||
|
||||
// player1.controls.addDefaultGamepad(0);
|
||||
// }
|
||||
|
||||
// if (numGamepads > 1)
|
||||
// {
|
||||
// if (player2 == null)
|
||||
// {
|
||||
// player2 = new PlayerSettings(1, None);
|
||||
// ++numPlayers;
|
||||
// }
|
||||
|
||||
// var gamepad = FlxG.gamepads.getByID(1);
|
||||
// if (gamepad == null)
|
||||
// throw 'Unexpected null gamepad. id:0';
|
||||
|
||||
// player2.controls.addDefaultGamepad(1);
|
||||
// }
|
||||
|
||||
// DeviceManager.init();
|
||||
}
|
||||
|
||||
static function onGamepadAdded(gamepad:FlxGamepad)
|
||||
{
|
||||
player1.addGamepad(gamepad);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
public function setKeyboardScheme(scheme)
|
||||
{
|
||||
controls.setKeyboardScheme(scheme);
|
||||
}
|
||||
|
||||
static public function addAvatar(avatar:Player):PlayerSettings
|
||||
{
|
||||
var settings:PlayerSettings;
|
||||
|
||||
if (player1 == null)
|
||||
{
|
||||
player1 = new PlayerSettings(0, Solo);
|
||||
++numPlayers;
|
||||
}
|
||||
|
||||
if (player1.avatar == null)
|
||||
settings = player1;
|
||||
else
|
||||
{
|
||||
if (player2 == null)
|
||||
{
|
||||
if (player1.controls.keyboardScheme.match(Duo(true)))
|
||||
player2 = new PlayerSettings(1, Duo(false));
|
||||
else
|
||||
player2 = new PlayerSettings(1, None);
|
||||
++numPlayers;
|
||||
}
|
||||
|
||||
if (player2.avatar == null)
|
||||
settings = player2;
|
||||
else
|
||||
throw throw 'Invalid number of players: ${numPlayers + 1}';
|
||||
}
|
||||
++numAvatars;
|
||||
settings.avatar = avatar;
|
||||
avatar.settings = settings;
|
||||
|
||||
splitCameras();
|
||||
|
||||
onAvatarAdd.dispatch(settings);
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
static public function removeAvatar(avatar:Player):Void
|
||||
{
|
||||
var settings:PlayerSettings;
|
||||
|
||||
if (player1 != null && player1.avatar == avatar)
|
||||
settings = player1;
|
||||
else if (player2 != null && player2.avatar == avatar)
|
||||
{
|
||||
settings = player2;
|
||||
if (player1.controls.keyboardScheme.match(Duo(_)))
|
||||
player1.setKeyboardScheme(Solo);
|
||||
}
|
||||
else
|
||||
throw "Cannot remove avatar that is not for a player";
|
||||
|
||||
settings.avatar = null;
|
||||
while (settings.controls.gamepadsAdded.length > 0)
|
||||
{
|
||||
final id = settings.controls.gamepadsAdded.shift();
|
||||
settings.controls.removeGamepad(id);
|
||||
DeviceManager.releaseGamepad(FlxG.gamepads.getByID(id));
|
||||
}
|
||||
|
||||
--numAvatars;
|
||||
|
||||
splitCameras();
|
||||
|
||||
onAvatarRemove.dispatch(avatar.settings);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
static public function reset()
|
||||
{
|
||||
player1 = null;
|
||||
player2 = null;
|
||||
numPlayers = 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package game.data.backend;
|
||||
|
||||
import game.data.backend.*;
|
||||
import game.data.backend.Song.SwagSong;
|
||||
|
||||
/**
|
||||
* ...
|
||||
* @author
|
||||
*/
|
||||
|
||||
typedef BPMChangeEvent =
|
||||
{
|
||||
var stepTime:Int;
|
||||
var songTime:Float;
|
||||
var bpm:Float;
|
||||
}
|
||||
|
||||
class Conductor
|
||||
{
|
||||
public static var bpm:Float = 100;
|
||||
public static var crochet:Float = ((60 / bpm) * 1000); // beats in milliseconds
|
||||
public static var stepCrochet:Float = crochet / 4; // steps in milliseconds
|
||||
public static var songPosition:Float;
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
||||
public static function findRating(diff:Float)
|
||||
{
|
||||
var ratingData:Array<Dynamic> = [['sick', 45], ['good', 90], ['bad', 135]];
|
||||
for (i in 0...ratingData.length)
|
||||
{
|
||||
if (diff <= ratingData[i][1])
|
||||
{
|
||||
return ratingData[i][0];
|
||||
}
|
||||
}
|
||||
return 'shit';
|
||||
}
|
||||
|
||||
public static function getRatingScore(diff:Float)
|
||||
{
|
||||
return (findRating(diff) == 'sick' ? 350 : findRating(diff) == 'good' ? 200 :
|
||||
findRating(diff) == 'bad' ? 100 : findRating(diff) == 'shit' ? 50 : 0);
|
||||
}
|
||||
|
||||
public static function mapBPMChanges(song:SwagSong)
|
||||
{
|
||||
bpmChangeMap = [];
|
||||
|
||||
var curBPM:Float = song.bpm;
|
||||
var totalSteps:Int = 0;
|
||||
var totalPos:Float = 0;
|
||||
for (i in 0...song.notes.length)
|
||||
{
|
||||
if(song.notes[i].changeBPM && song.notes[i].bpm != curBPM)
|
||||
{
|
||||
curBPM = song.notes[i].bpm;
|
||||
var event:BPMChangeEvent = {
|
||||
stepTime: totalSteps,
|
||||
songTime: totalPos,
|
||||
bpm: curBPM
|
||||
};
|
||||
bpmChangeMap.push(event);
|
||||
}
|
||||
|
||||
var deltaSteps:Int = song.notes[i].lengthInSteps;
|
||||
totalSteps += deltaSteps;
|
||||
totalPos += ((60 / curBPM) * 1000 / 4) * deltaSteps;
|
||||
}
|
||||
trace("new BPM map BUDDY " + bpmChangeMap);
|
||||
}
|
||||
|
||||
public static function changeBPM(newBpm:Float)
|
||||
{
|
||||
bpm = newBpm;
|
||||
|
||||
crochet = ((60 / bpm) * 1000);
|
||||
stepCrochet = crochet / 4;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package;
|
||||
|
||||
import Sys.sleep;
|
||||
|
||||
using StringTools;
|
||||
|
||||
#if discord_rpc
|
||||
import discord_rpc.DiscordRpc;
|
||||
#end
|
||||
|
||||
class DiscordClient
|
||||
{
|
||||
#if discord_rpc
|
||||
public function new()
|
||||
{
|
||||
trace("Discord Client starting...");
|
||||
DiscordRpc.start({
|
||||
clientID: "814588678700924999",
|
||||
onReady: onReady,
|
||||
onError: onError,
|
||||
onDisconnected: onDisconnected
|
||||
});
|
||||
trace("Discord Client started.");
|
||||
|
||||
while (true)
|
||||
{
|
||||
DiscordRpc.process();
|
||||
sleep(2);
|
||||
// trace("Discord Client Update");
|
||||
}
|
||||
|
||||
DiscordRpc.shutdown();
|
||||
}
|
||||
|
||||
public static function shutdown()
|
||||
{
|
||||
DiscordRpc.shutdown();
|
||||
}
|
||||
|
||||
static function onReady()
|
||||
{
|
||||
DiscordRpc.presence({
|
||||
details: "In the Menus",
|
||||
state: null,
|
||||
largeImageKey: 'icon',
|
||||
largeImageText: "Friday Night Funkin'"
|
||||
});
|
||||
}
|
||||
|
||||
static function onError(_code:Int, _message:String)
|
||||
{
|
||||
trace('Error! $_code : $_message');
|
||||
}
|
||||
|
||||
static function onDisconnected(_code:Int, _message:String)
|
||||
{
|
||||
trace('Disconnected! $_code : $_message');
|
||||
}
|
||||
|
||||
public static function initialize()
|
||||
{
|
||||
var DiscordDaemon = sys.thread.Thread.create(() ->
|
||||
{
|
||||
new DiscordClient();
|
||||
});
|
||||
trace("Discord Client initialized");
|
||||
}
|
||||
|
||||
public static function changePresence(details:String, state:Null<String>, ?smallImageKey:String, ?hasStartTimestamp:Bool, ?endTimestamp:Float)
|
||||
{
|
||||
var startTimestamp:Float = if (hasStartTimestamp) Date.now().getTime() else 0;
|
||||
|
||||
if (endTimestamp > 0)
|
||||
{
|
||||
endTimestamp = startTimestamp + endTimestamp;
|
||||
}
|
||||
|
||||
DiscordRpc.presence({
|
||||
details: details,
|
||||
state: state,
|
||||
largeImageKey: 'icon',
|
||||
largeImageText: "Friday Night Funkin'",
|
||||
smallImageKey: smallImageKey,
|
||||
// Obtained times are in milliseconds so they are divided so Discord can use it
|
||||
startTimestamp: Std.int(startTimestamp / 1000),
|
||||
endTimestamp: Std.int(endTimestamp / 1000)
|
||||
});
|
||||
|
||||
// trace('Discord RPC Updated. Arguments: $details, $state, $smallImageKey, $hasStartTimestamp, $endTimestamp');
|
||||
}
|
||||
#end
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package game.data.backend;
|
||||
|
||||
import flixel.FlxG;
|
||||
|
||||
class Highscore
|
||||
{
|
||||
#if (haxe >= "4.0.0")
|
||||
public static var songScores:Map<String, Int> = new Map();
|
||||
#else
|
||||
public static var songScores:Map<String, Int> = new Map<String, Int>();
|
||||
#end
|
||||
|
||||
|
||||
public static function saveScore(song:String, score:Int = 0, ?diff:Int = 0):Void
|
||||
{
|
||||
var formattedSong:String = formatSong(song, diff);
|
||||
|
||||
#if newgrounds
|
||||
// NGio.postScore(score, song);
|
||||
#end
|
||||
|
||||
if (songScores.exists(formattedSong))
|
||||
{
|
||||
if (songScores.get(formattedSong) < score)
|
||||
setScore(formattedSong, score);
|
||||
}
|
||||
else
|
||||
setScore(formattedSong, score);
|
||||
}
|
||||
|
||||
public static function saveWeekScore(week:Int = 1, score:Int = 0, ?diff:Int = 0):Void
|
||||
{
|
||||
#if newgrounds
|
||||
// NGio.postScore(score, "Week " + week);
|
||||
#end
|
||||
|
||||
var formattedSong:String = formatSong('week' + week, diff);
|
||||
|
||||
if (songScores.exists(formattedSong))
|
||||
{
|
||||
if (songScores.get(formattedSong) < score)
|
||||
setScore(formattedSong, score);
|
||||
}
|
||||
else
|
||||
setScore(formattedSong, score);
|
||||
}
|
||||
|
||||
/**
|
||||
* YOU SHOULD FORMAT SONG WITH formatSong() BEFORE TOSSING IN SONG VARIABLE
|
||||
*/
|
||||
static function setScore(formattedSong:String, score:Int):Void
|
||||
{
|
||||
/** GeoKureli
|
||||
* References to Highscore were wrapped in `#if !switch` blocks. I wasn't sure if this
|
||||
* is because switch doesn't use NGio, or because switch has a different saving method.
|
||||
* I moved the compiler flag here, rather than using it everywhere else.
|
||||
*/
|
||||
#if !switch
|
||||
|
||||
// Reminder that I don't need to format this song, it should come formatted!
|
||||
songScores.set(formattedSong, score);
|
||||
FlxG.save.data.songScores = songScores;
|
||||
FlxG.save.flush();
|
||||
#end
|
||||
}
|
||||
|
||||
public static function formatSong(song:String, diff:Int):String
|
||||
{
|
||||
var daSong:String = song;
|
||||
|
||||
if (diff == 0)
|
||||
daSong += '-easy';
|
||||
else if (diff == 2)
|
||||
daSong += '-hard';
|
||||
|
||||
return daSong;
|
||||
}
|
||||
|
||||
public static function getScore(song:String, diff:Int):Int
|
||||
{
|
||||
if (!songScores.exists(formatSong(song, diff)))
|
||||
setScore(formatSong(song, diff), 0);
|
||||
|
||||
return songScores.get(formatSong(song, diff));
|
||||
}
|
||||
|
||||
public static function getWeekScore(week:Int, diff:Int):Int
|
||||
{
|
||||
if (!songScores.exists(formatSong('week' + week, diff)))
|
||||
setScore(formatSong('week' + week, diff), 0);
|
||||
|
||||
return songScores.get(formatSong('week' + week, diff));
|
||||
}
|
||||
|
||||
public static function load():Void
|
||||
{
|
||||
if (FlxG.save.data.songScores != null)
|
||||
{
|
||||
songScores = FlxG.save.data.songScores;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package game.data.backend;
|
||||
|
||||
typedef SwagSection =
|
||||
{
|
||||
var sectionNotes:Array<Dynamic>;
|
||||
var lengthInSteps:Int;
|
||||
var typeOfSection:Int;
|
||||
var mustHitSection:Bool;
|
||||
var bpm:Float;
|
||||
var changeBPM:Bool;
|
||||
var altAnim:Bool;
|
||||
}
|
||||
|
||||
class Section
|
||||
{
|
||||
public var sectionNotes:Array<Dynamic> = [];
|
||||
|
||||
public var lengthInSteps:Int = 16;
|
||||
public var typeOfSection:Int = 0;
|
||||
public var mustHitSection:Bool = true;
|
||||
|
||||
/**
|
||||
* Copies the first section into the second section!
|
||||
*/
|
||||
public static var COPYCAT:Int = 0;
|
||||
|
||||
public function new(lengthInSteps:Int = 16)
|
||||
{
|
||||
this.lengthInSteps = lengthInSteps;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package game.data.backend;
|
||||
|
||||
import game.data.backend.Section.SwagSection;
|
||||
import haxe.Json;
|
||||
import haxe.format.JsonParser;
|
||||
import lime.utils.Assets;
|
||||
|
||||
using StringTools;
|
||||
|
||||
typedef SwagSong =
|
||||
{
|
||||
var song:String;
|
||||
var notes:Array<SwagSection>;
|
||||
var bpm:Float;
|
||||
var needsVoices:Bool;
|
||||
var speed:Float;
|
||||
|
||||
var player1:String;
|
||||
var player2:String;
|
||||
var validScore:Bool;
|
||||
}
|
||||
|
||||
class Song
|
||||
{
|
||||
public var song:String;
|
||||
public var notes:Array<SwagSection>;
|
||||
public var bpm:Float;
|
||||
public var needsVoices:Bool = true;
|
||||
public var speed:Float = 1;
|
||||
|
||||
public var player1:String = 'bf';
|
||||
public var player2:String = 'dad';
|
||||
|
||||
public function new(song, notes, bpm)
|
||||
{
|
||||
this.song = song;
|
||||
this.notes = notes;
|
||||
this.bpm = bpm;
|
||||
}
|
||||
|
||||
public static function loadFromJson(jsonInput:String, ?folder:String):SwagSong
|
||||
{
|
||||
var rawJson = Assets.getText(Paths.json(folder.toLowerCase() + '/' + jsonInput.toLowerCase())).trim();
|
||||
|
||||
while (!rawJson.endsWith("}"))
|
||||
{
|
||||
rawJson = rawJson.substr(0, rawJson.length - 1);
|
||||
// LOL GOING THROUGH THE BULLSHIT TO CLEAN IDK WHATS STRANGE
|
||||
}
|
||||
|
||||
// FIX THE CASTING ON WINDOWS/NATIVE
|
||||
// Windows???
|
||||
// trace(songData);
|
||||
|
||||
// trace('LOADED FROM JSON: ' + songData.notes);
|
||||
/*
|
||||
for (i in 0...songData.notes.length)
|
||||
{
|
||||
trace('LOADED FROM JSON: ' + songData.notes[i].sectionNotes);
|
||||
// songData.notes[i].sectionNotes = songData.notes[i].sectionNotes
|
||||
}
|
||||
|
||||
daNotes = songData.notes;
|
||||
daSong = songData.song;
|
||||
daBpm = songData.bpm; */
|
||||
|
||||
return parseJSONshit(rawJson);
|
||||
}
|
||||
|
||||
public static function parseJSONshit(rawJson:String):SwagSong
|
||||
{
|
||||
var swagShit:SwagSong = cast Json.parse(rawJson).song;
|
||||
swagShit.validScore = true;
|
||||
return swagShit;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package game.data.backend;
|
||||
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.math.FlxPoint;
|
||||
|
||||
class SwagCamera extends FlxCamera
|
||||
{
|
||||
/**
|
||||
* properly follow framerate
|
||||
* most of this just copied from FlxCamera,
|
||||
* only lines 96 and 97 are changed
|
||||
*/
|
||||
override public function updateFollow():Void
|
||||
{
|
||||
// Either follow the object closely,
|
||||
// or double check our deadzone and update accordingly.
|
||||
if (deadzone == null)
|
||||
{
|
||||
target.getMidpoint(_point);
|
||||
_point.addPoint(targetOffset);
|
||||
focusOn(_point);
|
||||
}
|
||||
else
|
||||
{
|
||||
var edge:Float;
|
||||
var targetX:Float = target.x + targetOffset.x;
|
||||
var targetY:Float = target.y + targetOffset.y;
|
||||
|
||||
if (style == SCREEN_BY_SCREEN)
|
||||
{
|
||||
if (targetX >= (scroll.x + width))
|
||||
{
|
||||
_scrollTarget.x += width;
|
||||
}
|
||||
else if (targetX < scroll.x)
|
||||
{
|
||||
_scrollTarget.x -= width;
|
||||
}
|
||||
|
||||
if (targetY >= (scroll.y + height))
|
||||
{
|
||||
_scrollTarget.y += height;
|
||||
}
|
||||
else if (targetY < scroll.y)
|
||||
{
|
||||
_scrollTarget.y -= height;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
edge = targetX - deadzone.x;
|
||||
if (_scrollTarget.x > edge)
|
||||
{
|
||||
_scrollTarget.x = edge;
|
||||
}
|
||||
edge = targetX + target.width - deadzone.x - deadzone.width;
|
||||
if (_scrollTarget.x < edge)
|
||||
{
|
||||
_scrollTarget.x = edge;
|
||||
}
|
||||
|
||||
edge = targetY - deadzone.y;
|
||||
if (_scrollTarget.y > edge)
|
||||
{
|
||||
_scrollTarget.y = edge;
|
||||
}
|
||||
edge = targetY + target.height - deadzone.y - deadzone.height;
|
||||
if (_scrollTarget.y < edge)
|
||||
{
|
||||
_scrollTarget.y = edge;
|
||||
}
|
||||
}
|
||||
|
||||
if ((target is FlxSprite))
|
||||
{
|
||||
if (_lastTargetPosition == null)
|
||||
{
|
||||
_lastTargetPosition = FlxPoint.get(target.x, target.y); // Creates this point.
|
||||
}
|
||||
_scrollTarget.x += (target.x - _lastTargetPosition.x) * followLead.x;
|
||||
_scrollTarget.y += (target.y - _lastTargetPosition.y) * followLead.y;
|
||||
|
||||
_lastTargetPosition.x = target.x;
|
||||
_lastTargetPosition.y = target.y;
|
||||
}
|
||||
|
||||
if (followLerp >= 60 / FlxG.updateFramerate)
|
||||
{
|
||||
scroll.copyFrom(_scrollTarget); // no easing
|
||||
}
|
||||
else
|
||||
{
|
||||
// THIS THE PART THAT ACTUALLY MATTERS LOL
|
||||
scroll.x += (_scrollTarget.x - scroll.x) * CoolUtil.camLerpShit(followLerp);
|
||||
scroll.y += (_scrollTarget.y - scroll.y) * CoolUtil.camLerpShit(followLerp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,261 @@
|
|||
package game.data.debug;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxObject;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxState;
|
||||
import flixel.addons.display.FlxGridOverlay;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.util.FlxColor;
|
||||
import openfl.events.Event;
|
||||
import openfl.events.IOErrorEvent;
|
||||
import openfl.net.FileReference;
|
||||
|
||||
import game.objects.*;
|
||||
|
||||
using StringTools;
|
||||
|
||||
/**
|
||||
*DEBUG MODE
|
||||
*/
|
||||
class AnimationDebug extends FlxState
|
||||
{
|
||||
var bf:Boyfriend;
|
||||
var dad:Character;
|
||||
var char:Character;
|
||||
var textAnim:FlxText;
|
||||
var dumbTexts:FlxTypedGroup<FlxText>;
|
||||
var animList:Array<String> = [];
|
||||
var curAnim:Int = 0;
|
||||
var isDad:Bool = true;
|
||||
var daAnim:String = 'spooky';
|
||||
var camFollow:FlxObject;
|
||||
|
||||
public function new(daAnim:String = 'spooky')
|
||||
{
|
||||
super();
|
||||
this.daAnim = daAnim;
|
||||
}
|
||||
|
||||
override function create()
|
||||
{
|
||||
FlxG.sound.music.stop();
|
||||
|
||||
var gridBG:FlxSprite = FlxGridOverlay.create(10, 10);
|
||||
gridBG.scrollFactor.set(0.5, 0.5);
|
||||
add(gridBG);
|
||||
|
||||
if (daAnim == 'bf')
|
||||
isDad = false;
|
||||
|
||||
if (isDad)
|
||||
{
|
||||
dad = new Character(0, 0, daAnim);
|
||||
dad.screenCenter();
|
||||
dad.debugMode = true;
|
||||
add(dad);
|
||||
|
||||
char = dad;
|
||||
dad.flipX = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
bf = new Boyfriend(0, 0);
|
||||
bf.screenCenter();
|
||||
bf.debugMode = true;
|
||||
add(bf);
|
||||
|
||||
char = bf;
|
||||
bf.flipX = false;
|
||||
}
|
||||
|
||||
dumbTexts = new FlxTypedGroup<FlxText>();
|
||||
add(dumbTexts);
|
||||
|
||||
textAnim = new FlxText(300, 16);
|
||||
textAnim.size = 26;
|
||||
textAnim.scrollFactor.set();
|
||||
add(textAnim);
|
||||
|
||||
genBoyOffsets();
|
||||
|
||||
camFollow = new FlxObject(0, 0, 2, 2);
|
||||
camFollow.screenCenter();
|
||||
add(camFollow);
|
||||
|
||||
FlxG.camera.follow(camFollow);
|
||||
|
||||
super.create();
|
||||
}
|
||||
|
||||
function genBoyOffsets(pushList:Bool = true):Void
|
||||
{
|
||||
var daLoop:Int = 0;
|
||||
|
||||
for (anim => offsets in char.animOffsets)
|
||||
{
|
||||
var text:FlxText = new FlxText(10, 20 + (18 * daLoop), 0, anim + ": " + offsets, 15);
|
||||
text.scrollFactor.set();
|
||||
text.color = FlxColor.BLUE;
|
||||
dumbTexts.add(text);
|
||||
|
||||
if (pushList)
|
||||
animList.push(anim);
|
||||
|
||||
daLoop++;
|
||||
}
|
||||
}
|
||||
|
||||
function updateTexts():Void
|
||||
{
|
||||
dumbTexts.forEach(function(text:FlxText)
|
||||
{
|
||||
text.kill();
|
||||
dumbTexts.remove(text, true);
|
||||
});
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
textAnim.text = char.animation.curAnim.name;
|
||||
|
||||
if (FlxG.keys.justPressed.E)
|
||||
FlxG.camera.zoom += 0.25;
|
||||
if (FlxG.keys.justPressed.Q)
|
||||
FlxG.camera.zoom -= 0.25;
|
||||
|
||||
if (FlxG.keys.pressed.I || FlxG.keys.pressed.J || FlxG.keys.pressed.K || FlxG.keys.pressed.L)
|
||||
{
|
||||
if (FlxG.keys.pressed.I)
|
||||
camFollow.velocity.y = -90;
|
||||
else if (FlxG.keys.pressed.K)
|
||||
camFollow.velocity.y = 90;
|
||||
else
|
||||
camFollow.velocity.y = 0;
|
||||
|
||||
if (FlxG.keys.pressed.J)
|
||||
camFollow.velocity.x = -90;
|
||||
else if (FlxG.keys.pressed.L)
|
||||
camFollow.velocity.x = 90;
|
||||
else
|
||||
camFollow.velocity.x = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
camFollow.velocity.set();
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.W)
|
||||
{
|
||||
curAnim -= 1;
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.S)
|
||||
{
|
||||
curAnim += 1;
|
||||
}
|
||||
|
||||
if (curAnim < 0)
|
||||
curAnim = animList.length - 1;
|
||||
|
||||
if (curAnim >= animList.length)
|
||||
curAnim = 0;
|
||||
|
||||
if (FlxG.keys.justPressed.S || FlxG.keys.justPressed.W || FlxG.keys.justPressed.SPACE)
|
||||
{
|
||||
char.playAnim(animList[curAnim]);
|
||||
|
||||
updateTexts();
|
||||
genBoyOffsets(false);
|
||||
}
|
||||
|
||||
var upP = FlxG.keys.anyJustPressed([UP]);
|
||||
var rightP = FlxG.keys.anyJustPressed([RIGHT]);
|
||||
var downP = FlxG.keys.anyJustPressed([DOWN]);
|
||||
var leftP = FlxG.keys.anyJustPressed([LEFT]);
|
||||
|
||||
var holdShift = FlxG.keys.pressed.SHIFT;
|
||||
var multiplier = 1;
|
||||
if (holdShift)
|
||||
multiplier = 10;
|
||||
|
||||
if (upP || rightP || downP || leftP)
|
||||
{
|
||||
updateTexts();
|
||||
if (upP)
|
||||
char.animOffsets.get(animList[curAnim])[1] += 1 * multiplier;
|
||||
if (downP)
|
||||
char.animOffsets.get(animList[curAnim])[1] -= 1 * multiplier;
|
||||
if (leftP)
|
||||
char.animOffsets.get(animList[curAnim])[0] += 1 * multiplier;
|
||||
if (rightP)
|
||||
char.animOffsets.get(animList[curAnim])[0] -= 1 * multiplier;
|
||||
|
||||
updateTexts();
|
||||
genBoyOffsets(false);
|
||||
char.playAnim(animList[curAnim]);
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.ESCAPE)
|
||||
{
|
||||
var outputString:String = "";
|
||||
|
||||
for (swagAnim in animList)
|
||||
{
|
||||
outputString += swagAnim + " " + char.animOffsets.get(swagAnim)[0] + " " + char.animOffsets.get(swagAnim)[1] + "\n";
|
||||
}
|
||||
|
||||
outputString.trim();
|
||||
saveOffsets(outputString);
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
var _file:FileReference;
|
||||
|
||||
private function saveOffsets(saveString:String)
|
||||
{
|
||||
if ((saveString != null) && (saveString.length > 0))
|
||||
{
|
||||
_file = new FileReference();
|
||||
_file.addEventListener(Event.COMPLETE, onSaveComplete);
|
||||
_file.addEventListener(Event.CANCEL, onSaveCancel);
|
||||
_file.addEventListener(IOErrorEvent.IO_ERROR, onSaveError);
|
||||
_file.save(saveString, daAnim + "Offsets.txt");
|
||||
}
|
||||
}
|
||||
|
||||
function onSaveComplete(_):Void
|
||||
{
|
||||
_file.removeEventListener(Event.COMPLETE, onSaveComplete);
|
||||
_file.removeEventListener(Event.CANCEL, onSaveCancel);
|
||||
_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
|
||||
_file = null;
|
||||
FlxG.log.notice("Successfully saved LEVEL DATA.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the save file dialog is cancelled.
|
||||
*/
|
||||
function onSaveCancel(_):Void
|
||||
{
|
||||
_file.removeEventListener(Event.COMPLETE, onSaveComplete);
|
||||
_file.removeEventListener(Event.CANCEL, onSaveCancel);
|
||||
_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
|
||||
_file = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called if there is an error while saving the gameplay recording.
|
||||
*/
|
||||
function onSaveError(_):Void
|
||||
{
|
||||
_file.removeEventListener(Event.COMPLETE, onSaveComplete);
|
||||
_file.removeEventListener(Event.CANCEL, onSaveCancel);
|
||||
_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
|
||||
_file = null;
|
||||
FlxG.log.error("Problem saving Level data");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxState;
|
||||
import openfl.Assets;
|
||||
import sys.io.File;
|
||||
|
||||
class DebugBoundingState extends FlxState
|
||||
{
|
||||
override function create()
|
||||
{
|
||||
var bf:FlxSprite = new FlxSprite().loadGraphic(Paths.image('characters/temp'));
|
||||
add(bf);
|
||||
|
||||
FlxG.stage.window.onDropFile.add(function(path:String)
|
||||
{
|
||||
trace("DROPPED FILE FROM: " + Std.string(path));
|
||||
var newPath = "./" + Paths.image('characters/temp');
|
||||
File.copy(path, newPath);
|
||||
|
||||
var swag = Paths.image('characters/temp');
|
||||
|
||||
if (bf != null)
|
||||
remove(bf);
|
||||
FlxG.bitmap.removeByKey(Paths.image('characters/temp'));
|
||||
Assets.cache.clear();
|
||||
|
||||
bf.loadGraphic(Paths.image('characters/temp'));
|
||||
add(bf);
|
||||
});
|
||||
|
||||
super.create();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
package game.data.format;
|
||||
|
||||
import game.state.menus.options.controls.Controls;
|
||||
import game.state.menus.options.controls.Controls.Device;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.input.gamepad.FlxGamepad;
|
||||
import flixel.input.gamepad.FlxGamepadInputID;
|
||||
import flixel.input.keyboard.FlxKey;
|
||||
|
||||
using flixel.util.FlxStringUtil;
|
||||
|
||||
class InputFormatter
|
||||
{
|
||||
static public function format(id:Int, device:Device):String
|
||||
{
|
||||
return switch (device)
|
||||
{
|
||||
case Keys: getKeyName(id);
|
||||
case Gamepad(gamepadID): getButtonName(id, FlxG.gamepads.getByID(gamepadID));
|
||||
}
|
||||
}
|
||||
|
||||
static public function getKeyName(id:Int):String
|
||||
{
|
||||
return switch(id)
|
||||
{
|
||||
case ZERO : "0";
|
||||
case ONE : "1";
|
||||
case TWO : "2";
|
||||
case THREE : "3";
|
||||
case FOUR : "4";
|
||||
case FIVE : "5";
|
||||
case SIX : "6";
|
||||
case SEVEN : "7";
|
||||
case EIGHT : "8";
|
||||
case NINE : "9";
|
||||
case PAGEUP : "PgUp";
|
||||
case PAGEDOWN : "PgDown";
|
||||
// case HOME : "Hm";
|
||||
// case END : "End";
|
||||
// case INSERT : "Ins";
|
||||
// case ESCAPE : "Esc";
|
||||
// case MINUS : "-";
|
||||
// case PLUS : "+";
|
||||
// case DELETE : "Del";
|
||||
case BACKSPACE : "BckSpc";
|
||||
case LBRACKET : "[";
|
||||
case RBRACKET : "]";
|
||||
case BACKSLASH : "\\";
|
||||
case CAPSLOCK : "Caps";
|
||||
case SEMICOLON : ";";
|
||||
case QUOTE : "'";
|
||||
// case ENTER : "Ent";
|
||||
// case SHIFT : "Shf";
|
||||
case COMMA : ",";
|
||||
case PERIOD : ".";
|
||||
case SLASH : "/";
|
||||
case GRAVEACCENT : "`";
|
||||
case CONTROL : "Ctrl";
|
||||
case ALT : "Alt";
|
||||
// case SPACE : "Spc";
|
||||
// case UP : "Up";
|
||||
// case DOWN : "Dn";
|
||||
// case LEFT : "Lf";
|
||||
// case RIGHT : "Rt";
|
||||
// case TAB : "Tab";
|
||||
case PRINTSCREEN : "PrtScrn";
|
||||
case NUMPADZERO : "#0";
|
||||
case NUMPADONE : "#1";
|
||||
case NUMPADTWO : "#2";
|
||||
case NUMPADTHREE : "#3";
|
||||
case NUMPADFOUR : "#4";
|
||||
case NUMPADFIVE : "#5";
|
||||
case NUMPADSIX : "#6";
|
||||
case NUMPADSEVEN : "#7";
|
||||
case NUMPADEIGHT : "#8";
|
||||
case NUMPADNINE : "#9";
|
||||
case NUMPADMINUS : "#-";
|
||||
case NUMPADPLUS : "#+";
|
||||
case NUMPADPERIOD : "#.";
|
||||
case NUMPADMULTIPLY: "#*";
|
||||
default: titleCase(FlxKey.toStringMap[id]);
|
||||
}
|
||||
}
|
||||
|
||||
static var dirReg = ~/^(l|r).?-(left|right|down|up)$/;
|
||||
inline static public function getButtonName(id:Int, gamepad:FlxGamepad):String
|
||||
{
|
||||
return switch(gamepad.getInputLabel(id))
|
||||
{
|
||||
// case null | "": shortenButtonName(FlxGamepadInputID.toStringMap[id]);
|
||||
case label: shortenButtonName(label);
|
||||
}
|
||||
}
|
||||
|
||||
static function shortenButtonName(name:String)
|
||||
{
|
||||
return switch (name == null ? "" : name.toLowerCase())
|
||||
{
|
||||
case "": "[?]";
|
||||
// case "square" : "[]";
|
||||
// case "circle" : "()";
|
||||
// case "triangle": "/\\";
|
||||
// case "plus" : "+";
|
||||
// case "minus" : "-";
|
||||
// case "home" : "Hm";
|
||||
// case "guide" : "Gd";
|
||||
// case "back" : "Bk";
|
||||
// case "select" : "Bk";
|
||||
// case "start" : "St";
|
||||
// case "left" : "Lf";
|
||||
// case "right" : "Rt";
|
||||
// case "down" : "Dn";
|
||||
// case "up" : "Up";
|
||||
case dir if (dirReg.match(dir)):
|
||||
dirReg.matched(1).toUpperCase() + " " + titleCase(dirReg.matched(2));
|
||||
case label: titleCase(label);
|
||||
}
|
||||
}
|
||||
|
||||
inline static function titleCaseTrim(str:String, length = 8)
|
||||
{
|
||||
return str.charAt(0).toUpperCase() + str.substr(1, length - 1).toLowerCase();
|
||||
}
|
||||
|
||||
inline static function titleCase(str:String)
|
||||
{
|
||||
return str.charAt(0).toUpperCase() + str.substr(1).toLowerCase();
|
||||
}
|
||||
|
||||
inline static public function parsePadName(name:String):ControllerName
|
||||
{
|
||||
return ControllerName.parseName(name);
|
||||
}
|
||||
|
||||
inline static public function getPadName(gamepad:FlxGamepad):ControllerName
|
||||
{
|
||||
return ControllerName.getName(gamepad);
|
||||
}
|
||||
|
||||
inline static public function getPadNameById(id:Int):ControllerName
|
||||
{
|
||||
return ControllerName.getNameById(id);
|
||||
}
|
||||
}
|
||||
|
||||
@:forward
|
||||
@:enum abstract ControllerName(String) from String to String
|
||||
{
|
||||
var OUYA = "Ouya" ;
|
||||
var PS4 = "PS4" ;
|
||||
var LOGI = "Logi" ;
|
||||
var XBOX = "XBox" ;
|
||||
var XINPUT = "XInput" ;
|
||||
var WII = "Wii" ;
|
||||
var PRO_CON = "Pro_Con" ;
|
||||
var JOYCONS = "Joycons" ;
|
||||
var JOYCON_L = "Joycon_L";
|
||||
var JOYCON_R = "Joycon_R";
|
||||
var MFI = "MFI" ;
|
||||
var PAD = "Pad" ;
|
||||
|
||||
static public function getAssetByDevice(device:Device):String
|
||||
{
|
||||
return switch (device)
|
||||
{
|
||||
case Keys: getAsset(null);
|
||||
case Gamepad(id): getAsset(FlxG.gamepads.getByID(id));
|
||||
}
|
||||
}
|
||||
|
||||
static public function getAsset(gamepad:FlxGamepad):String
|
||||
{
|
||||
if (gamepad == null)
|
||||
return 'assets/images/ui/devices/Keys.png';
|
||||
|
||||
final name = parseName(gamepad.name);
|
||||
var path = 'assets/images/ui/devices/$name.png';
|
||||
if (openfl.utils.Assets.exists(path))
|
||||
return path;
|
||||
|
||||
return 'assets/images/ui/devices/Pad.png';
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline static public function getNameById(id:Int):ControllerName return getName(FlxG.gamepads.getByID(id));
|
||||
inline static public function getName(gamepad:FlxGamepad):ControllerName return parseName(gamepad.name);
|
||||
static public function parseName(name:String):ControllerName
|
||||
{
|
||||
name = name.toLowerCase().remove("-").remove("_");
|
||||
return
|
||||
if (name.contains("ouya"))
|
||||
OUYA;
|
||||
else if (name.contains("wireless controller") || name.contains("ps4"))
|
||||
PS4;
|
||||
else if (name.contains("logitech"))
|
||||
LOGI;
|
||||
else if (name.contains("xbox"))
|
||||
XBOX
|
||||
else if (name.contains("xinput"))
|
||||
XINPUT;
|
||||
else if (name.contains("nintendo rvlcnt01tr") || name.contains("nintendo rvlcnt01"))
|
||||
WII;
|
||||
else if (name.contains("mayflash wiimote pc adapter"))
|
||||
WII;
|
||||
else if (name.contains("pro controller"))
|
||||
PRO_CON;
|
||||
else if (name.contains("joycon l+r"))
|
||||
JOYCONS;
|
||||
else if (name.contains("joycon (l)"))
|
||||
JOYCON_L;
|
||||
else if (name.contains("joycon (r)"))
|
||||
JOYCON_R;
|
||||
else if (name.contains("mfi"))
|
||||
MFI;
|
||||
else
|
||||
PAD;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package game.objects;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.util.FlxTimer;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class Boyfriend extends Character
|
||||
{
|
||||
// public var stunned:Bool = false;
|
||||
|
||||
public function new(x:Float, y:Float, ?char:String = 'bf')
|
||||
{
|
||||
super(x, y, char, true);
|
||||
}
|
||||
|
||||
public var startedDeath:Bool = false;
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (!debugMode)
|
||||
{
|
||||
if (animation.curAnim.name.startsWith('sing'))
|
||||
{
|
||||
holdTimer += elapsed;
|
||||
}
|
||||
else
|
||||
holdTimer = 0;
|
||||
|
||||
if (animation.curAnim.name.endsWith('miss') && animation.curAnim.finished && !debugMode)
|
||||
{
|
||||
playAnim('idle', true, false, 10);
|
||||
}
|
||||
|
||||
if (animation.curAnim.name == 'firstDeath' && animation.curAnim.finished && startedDeath)
|
||||
{
|
||||
playAnim('deathLoop');
|
||||
}
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,701 @@
|
|||
package game.objects;
|
||||
|
||||
import game.data.backend.Section.SwagSection;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.animation.FlxBaseAnimation;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.util.FlxSort;
|
||||
import haxe.io.Path;
|
||||
|
||||
import game.state.*;
|
||||
import game.data.backend.*;
|
||||
import game.objects.stages.background.*;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class Character extends FlxSprite
|
||||
{
|
||||
public var animOffsets:Map<String, Array<Dynamic>>;
|
||||
public var debugMode:Bool = false;
|
||||
|
||||
public var isPlayer:Bool = false;
|
||||
public var curCharacter:String = 'bf';
|
||||
|
||||
public var holdTimer:Float = 0;
|
||||
|
||||
public var animationNotes:Array<Dynamic> = [];
|
||||
|
||||
public function new(x:Float, y:Float, ?character:String = "bf", ?isPlayer:Bool = false)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
animOffsets = new Map<String, Array<Dynamic>>();
|
||||
curCharacter = character;
|
||||
this.isPlayer = isPlayer;
|
||||
|
||||
var tex:FlxAtlasFrames;
|
||||
antialiasing = true;
|
||||
|
||||
switch (curCharacter)
|
||||
{
|
||||
case 'gf':
|
||||
// GIRLFRIEND CODE
|
||||
tex = Paths.getSparrowAtlas('characters/GF_assets');
|
||||
frames = tex;
|
||||
quickAnimAdd('cheer', 'GF Cheer');
|
||||
quickAnimAdd('singLEFT', 'GF left note');
|
||||
quickAnimAdd('singRIGHT', 'GF Right Note');
|
||||
quickAnimAdd('singUP', 'GF Up Note');
|
||||
quickAnimAdd('singDOWN', 'GF Down Note');
|
||||
animation.addByIndices('sad', 'gf sad', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], "", 24, true);
|
||||
animation.addByIndices('danceLeft', 'GF Dancing Beat', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
|
||||
animation.addByIndices('danceRight', 'GF Dancing Beat', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
|
||||
animation.addByIndices('hairBlow', "GF Dancing Beat Hair blowing", [0, 1, 2, 3], "", 24);
|
||||
animation.addByIndices('hairFall', "GF Dancing Beat Hair Landing", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], "", 24, false);
|
||||
animation.addByPrefix('scared', 'GF FEAR', 24, true);
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('danceRight');
|
||||
|
||||
case 'gf-christmas':
|
||||
tex = Paths.getSparrowAtlas('characters/gfChristmas');
|
||||
frames = tex;
|
||||
quickAnimAdd('cheer', 'GF Cheer');
|
||||
quickAnimAdd('singLEFT', 'GF left note');
|
||||
quickAnimAdd('singRIGHT', 'GF Right Note');
|
||||
quickAnimAdd('singUP', 'GF Up Note');
|
||||
quickAnimAdd('singDOWN', 'GF Down Note');
|
||||
animation.addByIndices('sad', 'gf sad', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], "", 24, false);
|
||||
animation.addByIndices('danceLeft', 'GF Dancing Beat', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
|
||||
animation.addByIndices('danceRight', 'GF Dancing Beat', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
|
||||
animation.addByIndices('hairBlow', "GF Dancing Beat Hair blowing", [0, 1, 2, 3], "", 24);
|
||||
animation.addByIndices('hairFall', "GF Dancing Beat Hair Landing", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], "", 24, false);
|
||||
animation.addByPrefix('scared', 'GF FEAR', 24, true);
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('danceRight');
|
||||
case 'gf-tankmen':
|
||||
frames = Paths.getSparrowAtlas('characters/gfTankmen');
|
||||
animation.addByIndices('sad', 'GF Crying at Gunpoint', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], "", 24, true);
|
||||
animation.addByIndices('danceLeft', 'GF Dancing at Gunpoint', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
|
||||
animation.addByIndices('danceRight', 'GF Dancing at Gunpoint', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
|
||||
|
||||
loadOffsetFile('gf');
|
||||
playAnim('danceRight');
|
||||
|
||||
case 'bf-holding-gf':
|
||||
frames = Paths.getSparrowAtlas('characters/bfAndGF');
|
||||
quickAnimAdd('idle', 'BF idle dance');
|
||||
quickAnimAdd('singDOWN', 'BF NOTE DOWN0');
|
||||
quickAnimAdd('singLEFT', 'BF NOTE LEFT0');
|
||||
quickAnimAdd('singRIGHT', 'BF NOTE RIGHT0');
|
||||
quickAnimAdd('singUP', 'BF NOTE UP0');
|
||||
|
||||
quickAnimAdd('singDOWNmiss', 'BF NOTE DOWN MISS');
|
||||
quickAnimAdd('singLEFTmiss', 'BF NOTE LEFT MISS');
|
||||
quickAnimAdd('singRIGHTmiss', 'BF NOTE RIGHT MISS');
|
||||
quickAnimAdd('singUPmiss', 'BF NOTE UP MISS');
|
||||
quickAnimAdd('bfCatch', 'BF catches GF');
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('idle');
|
||||
|
||||
flipX = true;
|
||||
|
||||
case 'gf-car':
|
||||
tex = Paths.getSparrowAtlas('characters/gfCar');
|
||||
frames = tex;
|
||||
animation.addByIndices('singUP', 'GF Dancing Beat Hair blowing CAR', [0], "", 24, false);
|
||||
animation.addByIndices('danceLeft', 'GF Dancing Beat Hair blowing CAR', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
|
||||
animation.addByIndices('danceRight', 'GF Dancing Beat Hair blowing CAR', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24,
|
||||
false);
|
||||
animation.addByIndices('idleHair', 'GF Dancing Beat Hair blowing CAR', [10, 11, 12, 25, 26, 27], "", 24, true);
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('danceRight');
|
||||
|
||||
case 'gf-pixel':
|
||||
tex = Paths.getSparrowAtlas('characters/gfPixel');
|
||||
frames = tex;
|
||||
animation.addByIndices('singUP', 'GF IDLE', [2], "", 24, false);
|
||||
animation.addByIndices('danceLeft', 'GF IDLE', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
|
||||
animation.addByIndices('danceRight', 'GF IDLE', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('danceRight');
|
||||
|
||||
setGraphicSize(Std.int(width * PlayState.daPixelZoom));
|
||||
updateHitbox();
|
||||
antialiasing = false;
|
||||
|
||||
case 'dad':
|
||||
// DAD ANIMATION LOADING CODE
|
||||
tex = Paths.getSparrowAtlas('characters/DADDY_DEAREST');
|
||||
frames = tex;
|
||||
quickAnimAdd('idle', 'Dad idle dance');
|
||||
quickAnimAdd('singUP', 'Dad Sing Note UP');
|
||||
quickAnimAdd('singRIGHT', 'Dad Sing Note RIGHT');
|
||||
quickAnimAdd('singDOWN', 'Dad Sing Note DOWN');
|
||||
quickAnimAdd('singLEFT', 'Dad Sing Note LEFT');
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('idle');
|
||||
case 'spooky':
|
||||
tex = Paths.getSparrowAtlas('characters/spooky_kids_assets');
|
||||
frames = tex;
|
||||
quickAnimAdd('singUP', 'spooky UP NOTE');
|
||||
quickAnimAdd('singDOWN', 'spooky DOWN note');
|
||||
quickAnimAdd('singLEFT', 'note sing left');
|
||||
quickAnimAdd('singRIGHT', 'spooky sing right');
|
||||
animation.addByIndices('danceLeft', 'spooky dance idle', [0, 2, 6], "", 12, false);
|
||||
animation.addByIndices('danceRight', 'spooky dance idle', [8, 10, 12, 14], "", 12, false);
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('danceRight');
|
||||
case 'mom':
|
||||
tex = Paths.getSparrowAtlas('characters/Mom_Assets');
|
||||
frames = tex;
|
||||
|
||||
quickAnimAdd('idle', "Mom Idle");
|
||||
quickAnimAdd('singUP', "Mom Up Pose");
|
||||
quickAnimAdd('singDOWN', "MOM DOWN POSE");
|
||||
quickAnimAdd('singLEFT', 'Mom Left Pose');
|
||||
// ANIMATION IS CALLED MOM LEFT POSE BUT ITS FOR THE RIGHT
|
||||
// CUZ DAVE IS DUMB!
|
||||
quickAnimAdd('singRIGHT', 'Mom Pose Left');
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('idle');
|
||||
|
||||
case 'mom-car':
|
||||
tex = Paths.getSparrowAtlas('characters/momCar');
|
||||
frames = tex;
|
||||
|
||||
quickAnimAdd('idle', "Mom Idle");
|
||||
quickAnimAdd('singUP', "Mom Up Pose");
|
||||
quickAnimAdd('singDOWN', "MOM DOWN POSE");
|
||||
quickAnimAdd('singLEFT', 'Mom Left Pose');
|
||||
// ANIMATION IS CALLED MOM LEFT POSE BUT ITS FOR THE RIGHT
|
||||
// CUZ DAVE IS DUMB!
|
||||
quickAnimAdd('singRIGHT', 'Mom Pose Left');
|
||||
animation.addByIndices('idleHair', "Mom Idle", [10, 11, 12, 13], "", 24, true);
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('idle');
|
||||
case 'monster':
|
||||
tex = Paths.getSparrowAtlas('characters/Monster_Assets');
|
||||
frames = tex;
|
||||
quickAnimAdd('idle', 'monster idle');
|
||||
quickAnimAdd('singUP', 'monster up note');
|
||||
quickAnimAdd('singDOWN', 'monster down');
|
||||
quickAnimAdd('singLEFT', 'Monster left note');
|
||||
quickAnimAdd('singRIGHT', 'Monster Right note');
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('idle');
|
||||
case 'monster-christmas':
|
||||
tex = Paths.getSparrowAtlas('characters/monsterChristmas');
|
||||
frames = tex;
|
||||
quickAnimAdd('idle', 'monster idle');
|
||||
quickAnimAdd('singUP', 'monster up note');
|
||||
quickAnimAdd('singDOWN', 'monster down');
|
||||
quickAnimAdd('singLEFT', 'Monster left note');
|
||||
quickAnimAdd('singRIGHT', 'Monster Right note');
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('idle');
|
||||
case 'pico':
|
||||
tex = Paths.getSparrowAtlas('characters/Pico_FNF_assetss');
|
||||
frames = tex;
|
||||
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');
|
||||
}
|
||||
|
||||
quickAnimAdd('singUPmiss', 'pico Up note miss');
|
||||
quickAnimAdd('singDOWNmiss', 'Pico Down Note MISS');
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('idle');
|
||||
|
||||
flipX = true;
|
||||
|
||||
case 'pico-speaker':
|
||||
frames = Paths.getSparrowAtlas('characters/picoSpeaker');
|
||||
|
||||
quickAnimAdd('shoot1', "Pico shoot 1");
|
||||
quickAnimAdd('shoot2', "Pico shoot 2");
|
||||
quickAnimAdd('shoot3', "Pico shoot 3");
|
||||
quickAnimAdd('shoot4', "Pico shoot 4");
|
||||
|
||||
// here for now, will be replaced later for less copypaste
|
||||
loadOffsetFile(curCharacter);
|
||||
playAnim('shoot1');
|
||||
|
||||
loadMappedAnims();
|
||||
|
||||
case 'bf':
|
||||
var tex = Paths.getSparrowAtlas('characters/BOYFRIEND');
|
||||
frames = tex;
|
||||
quickAnimAdd('idle', 'BF idle dance');
|
||||
quickAnimAdd('singUP', 'BF NOTE UP0');
|
||||
quickAnimAdd('singLEFT', 'BF NOTE LEFT0');
|
||||
quickAnimAdd('singRIGHT', 'BF NOTE RIGHT0');
|
||||
quickAnimAdd('singDOWN', 'BF NOTE DOWN0');
|
||||
quickAnimAdd('singUPmiss', 'BF NOTE UP MISS');
|
||||
quickAnimAdd('singLEFTmiss', 'BF NOTE LEFT MISS');
|
||||
quickAnimAdd('singRIGHTmiss', 'BF NOTE RIGHT MISS');
|
||||
quickAnimAdd('singDOWNmiss', 'BF NOTE DOWN MISS');
|
||||
quickAnimAdd('hey', 'BF HEY');
|
||||
|
||||
quickAnimAdd('firstDeath', "BF dies");
|
||||
animation.addByPrefix('deathLoop', "BF Dead Loop", 24, true);
|
||||
quickAnimAdd('deathConfirm', "BF Dead confirm");
|
||||
|
||||
animation.addByPrefix('scared', 'BF idle shaking', 24, true);
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('idle');
|
||||
|
||||
flipX = true;
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
case 'bf-christmas':
|
||||
var tex = Paths.getSparrowAtlas('characters/bfChristmas');
|
||||
frames = tex;
|
||||
quickAnimAdd('idle', 'BF idle dance');
|
||||
quickAnimAdd('singUP', 'BF NOTE UP0');
|
||||
quickAnimAdd('singLEFT', 'BF NOTE LEFT0');
|
||||
quickAnimAdd('singRIGHT', 'BF NOTE RIGHT0');
|
||||
quickAnimAdd('singDOWN', 'BF NOTE DOWN0');
|
||||
quickAnimAdd('singUPmiss', 'BF NOTE UP MISS');
|
||||
quickAnimAdd('singLEFTmiss', 'BF NOTE LEFT MISS');
|
||||
quickAnimAdd('singRIGHTmiss', 'BF NOTE RIGHT MISS');
|
||||
quickAnimAdd('singDOWNmiss', 'BF NOTE DOWN MISS');
|
||||
quickAnimAdd('hey', 'BF HEY');
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('idle');
|
||||
|
||||
flipX = true;
|
||||
case 'bf-car':
|
||||
var tex = Paths.getSparrowAtlas('characters/bfCar');
|
||||
frames = tex;
|
||||
quickAnimAdd('idle', 'BF idle dance');
|
||||
quickAnimAdd('singUP', 'BF NOTE UP0');
|
||||
quickAnimAdd('singLEFT', 'BF NOTE LEFT0');
|
||||
quickAnimAdd('singRIGHT', 'BF NOTE RIGHT0');
|
||||
quickAnimAdd('singDOWN', 'BF NOTE DOWN0');
|
||||
quickAnimAdd('singUPmiss', 'BF NOTE UP MISS');
|
||||
quickAnimAdd('singLEFTmiss', 'BF NOTE LEFT MISS');
|
||||
quickAnimAdd('singRIGHTmiss', 'BF NOTE RIGHT MISS');
|
||||
quickAnimAdd('singDOWNmiss', 'BF NOTE DOWN MISS');
|
||||
animation.addByIndices('idleHair', 'BF idle dance', [10, 11, 12, 13], "", 24, true);
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('idle');
|
||||
|
||||
flipX = true;
|
||||
case 'bf-pixel':
|
||||
frames = Paths.getSparrowAtlas('characters/bfPixel');
|
||||
quickAnimAdd('idle', 'BF IDLE');
|
||||
quickAnimAdd('singUP', 'BF UP NOTE');
|
||||
quickAnimAdd('singLEFT', 'BF LEFT NOTE');
|
||||
quickAnimAdd('singRIGHT', 'BF RIGHT NOTE');
|
||||
quickAnimAdd('singDOWN', 'BF DOWN NOTE');
|
||||
quickAnimAdd('singUPmiss', 'BF UP MISS');
|
||||
quickAnimAdd('singLEFTmiss', 'BF LEFT MISS');
|
||||
quickAnimAdd('singRIGHTmiss', 'BF RIGHT MISS');
|
||||
quickAnimAdd('singDOWNmiss', 'BF DOWN MISS');
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
setGraphicSize(Std.int(width * 6));
|
||||
updateHitbox();
|
||||
|
||||
playAnim('idle');
|
||||
|
||||
width -= 100;
|
||||
height -= 100;
|
||||
|
||||
antialiasing = false;
|
||||
|
||||
flipX = true;
|
||||
case 'bf-pixel-dead':
|
||||
frames = Paths.getSparrowAtlas('characters/bfPixelsDEAD');
|
||||
quickAnimAdd('singUP', "BF Dies pixel");
|
||||
quickAnimAdd('firstDeath', "BF Dies pixel");
|
||||
animation.addByPrefix('deathLoop', "Retry Loop", 24, true);
|
||||
quickAnimAdd('deathConfirm', "RETRY CONFIRM");
|
||||
animation.play('firstDeath');
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('firstDeath');
|
||||
// pixel bullshit
|
||||
setGraphicSize(Std.int(width * 6));
|
||||
updateHitbox();
|
||||
antialiasing = false;
|
||||
flipX = true;
|
||||
|
||||
case 'bf-holding-gf-dead':
|
||||
frames = Paths.getSparrowAtlas('characters/bfHoldingGF-DEAD');
|
||||
quickAnimAdd('singUP', 'BF Dead with GF Loop');
|
||||
quickAnimAdd('firstDeath', 'BF Dies with GF');
|
||||
animation.addByPrefix('deathLoop', 'BF Dead with GF Loop', 24, true);
|
||||
quickAnimAdd('deathConfirm', 'RETRY confirm holding gf');
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('firstDeath');
|
||||
|
||||
flipX = true;
|
||||
|
||||
case 'senpai':
|
||||
frames = Paths.getSparrowAtlas('characters/senpai');
|
||||
quickAnimAdd('idle', 'Senpai Idle');
|
||||
// at framerate 16.8 animation plays over 2 beats at 144bpm,
|
||||
// but if the game lags or the bpm is > 144 (mods etc.)
|
||||
// he may miss his next dance
|
||||
// animation.getByName('idle').frameRate = 16.8;
|
||||
|
||||
quickAnimAdd('singUP', 'SENPAI UP NOTE');
|
||||
quickAnimAdd('singLEFT', 'SENPAI LEFT NOTE');
|
||||
quickAnimAdd('singRIGHT', 'SENPAI RIGHT NOTE');
|
||||
quickAnimAdd('singDOWN', 'SENPAI DOWN NOTE');
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('idle');
|
||||
|
||||
setGraphicSize(Std.int(width * 6));
|
||||
updateHitbox();
|
||||
|
||||
antialiasing = false;
|
||||
case 'senpai-angry':
|
||||
frames = Paths.getSparrowAtlas('characters/senpai');
|
||||
quickAnimAdd('idle', 'Angry Senpai Idle');
|
||||
quickAnimAdd('singUP', 'Angry Senpai UP NOTE');
|
||||
quickAnimAdd('singLEFT', 'Angry Senpai LEFT NOTE');
|
||||
quickAnimAdd('singRIGHT', 'Angry Senpai RIGHT NOTE');
|
||||
quickAnimAdd('singDOWN', 'Angry Senpai DOWN NOTE');
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('idle');
|
||||
|
||||
setGraphicSize(Std.int(width * 6));
|
||||
updateHitbox();
|
||||
|
||||
antialiasing = false;
|
||||
|
||||
case 'spirit':
|
||||
frames = Paths.getPackerAtlas('characters/spirit');
|
||||
quickAnimAdd('idle', "idle spirit_");
|
||||
quickAnimAdd('singUP', "up_");
|
||||
quickAnimAdd('singRIGHT', "right_");
|
||||
quickAnimAdd('singLEFT', "left_");
|
||||
quickAnimAdd('singDOWN', "spirit down_");
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
setGraphicSize(Std.int(width * 6));
|
||||
updateHitbox();
|
||||
|
||||
playAnim('idle');
|
||||
|
||||
antialiasing = false;
|
||||
|
||||
case 'parents-christmas':
|
||||
frames = Paths.getSparrowAtlas('characters/mom_dad_christmas_assets');
|
||||
quickAnimAdd('idle', 'Parent Christmas Idle');
|
||||
quickAnimAdd('singUP', 'Parent Up Note Dad');
|
||||
quickAnimAdd('singDOWN', 'Parent Down Note Dad');
|
||||
quickAnimAdd('singLEFT', 'Parent Left Note Dad');
|
||||
quickAnimAdd('singRIGHT', 'Parent Right Note Dad');
|
||||
|
||||
quickAnimAdd('singUP-alt', 'Parent Up Note Mom');
|
||||
|
||||
quickAnimAdd('singDOWN-alt', 'Parent Down Note Mom');
|
||||
quickAnimAdd('singLEFT-alt', 'Parent Left Note Mom');
|
||||
quickAnimAdd('singRIGHT-alt', 'Parent Right Note Mom');
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('idle');
|
||||
case 'tankman':
|
||||
frames = Paths.getSparrowAtlas('characters/tankmanCaptain');
|
||||
|
||||
quickAnimAdd('idle', "Tankman Idle Dance");
|
||||
|
||||
if (isPlayer)
|
||||
{
|
||||
quickAnimAdd('singLEFT', 'Tankman Note Left ');
|
||||
quickAnimAdd('singRIGHT', 'Tankman Right Note ');
|
||||
quickAnimAdd('singLEFTmiss', 'Tankman Note Left MISS');
|
||||
quickAnimAdd('singRIGHTmiss', 'Tankman Right Note MISS');
|
||||
}
|
||||
else
|
||||
{
|
||||
// Need to be flipped! REDO THIS LATER
|
||||
quickAnimAdd('singLEFT', 'Tankman Right Note ');
|
||||
quickAnimAdd('singRIGHT', 'Tankman Note Left ');
|
||||
quickAnimAdd('singLEFTmiss', 'Tankman Right Note MISS');
|
||||
quickAnimAdd('singRIGHTmiss', 'Tankman Note Left MISS');
|
||||
}
|
||||
|
||||
quickAnimAdd('singUP', 'Tankman UP note ');
|
||||
quickAnimAdd('singDOWN', 'Tankman DOWN note ');
|
||||
quickAnimAdd('singUPmiss', 'Tankman UP note MISS');
|
||||
quickAnimAdd('singDOWNmiss', 'Tankman DOWN note MISS');
|
||||
|
||||
// PRETTY GOOD tankman
|
||||
// TANKMAN UGH instanc
|
||||
|
||||
quickAnimAdd('singDOWN-alt', 'PRETTY GOOD');
|
||||
quickAnimAdd('singUP-alt', 'TANKMAN UGH');
|
||||
|
||||
loadOffsetFile(curCharacter);
|
||||
|
||||
playAnim('idle');
|
||||
|
||||
flipX = true;
|
||||
}
|
||||
|
||||
dance();
|
||||
animation.finish();
|
||||
|
||||
if (isPlayer)
|
||||
{
|
||||
flipX = !flipX;
|
||||
|
||||
// Doesn't flip for BF, since his are already in the right place???
|
||||
if (!curCharacter.startsWith('bf'))
|
||||
{
|
||||
// var animArray
|
||||
var oldRight = animation.getByName('singRIGHT').frames;
|
||||
animation.getByName('singRIGHT').frames = animation.getByName('singLEFT').frames;
|
||||
animation.getByName('singLEFT').frames = oldRight;
|
||||
|
||||
// IF THEY HAVE MISS ANIMATIONS??
|
||||
if (animation.getByName('singRIGHTmiss') != null)
|
||||
{
|
||||
var oldMiss = animation.getByName('singRIGHTmiss').frames;
|
||||
animation.getByName('singRIGHTmiss').frames = animation.getByName('singLEFTmiss').frames;
|
||||
animation.getByName('singLEFTmiss').frames = oldMiss;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function loadMappedAnims()
|
||||
{
|
||||
var swagshit = Song.loadFromJson('picospeaker', 'stress');
|
||||
|
||||
var notes = swagshit.notes;
|
||||
|
||||
for (section in notes)
|
||||
{
|
||||
for (idk in section.sectionNotes)
|
||||
{
|
||||
animationNotes.push(idk);
|
||||
}
|
||||
}
|
||||
|
||||
TankmenBG.animationNotes = animationNotes;
|
||||
|
||||
trace(animationNotes);
|
||||
animationNotes.sort(sortAnims);
|
||||
}
|
||||
|
||||
function sortAnims(val1:Array<Dynamic>, val2:Array<Dynamic>):Int
|
||||
{
|
||||
return FlxSort.byValues(FlxSort.ASCENDING, val1[0], val2[0]);
|
||||
}
|
||||
|
||||
function quickAnimAdd(name:String, prefix:String)
|
||||
{
|
||||
animation.addByPrefix(name, prefix, 24, false);
|
||||
}
|
||||
|
||||
private function loadOffsetFile(offsetCharacter:String)
|
||||
{
|
||||
var daFile:Array<String> = CoolUtil.coolTextFile(Paths.file("images/characters/" + offsetCharacter + "Offsets.txt"));
|
||||
|
||||
for (i in daFile)
|
||||
{
|
||||
var splitWords:Array<String> = i.split(" ");
|
||||
addOffset(splitWords[0], Std.parseInt(splitWords[1]), Std.parseInt(splitWords[2]));
|
||||
}
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (!curCharacter.startsWith('bf'))
|
||||
{
|
||||
if (animation.curAnim.name.startsWith('sing'))
|
||||
{
|
||||
holdTimer += elapsed;
|
||||
}
|
||||
|
||||
var dadVar:Float = 4;
|
||||
|
||||
if (curCharacter == 'dad')
|
||||
dadVar = 6.1;
|
||||
if (holdTimer >= Conductor.stepCrochet * dadVar * 0.001)
|
||||
{
|
||||
dance();
|
||||
holdTimer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (curCharacter.endsWith('-car'))
|
||||
{
|
||||
// looping hair anims after idle finished
|
||||
if (!animation.curAnim.name.startsWith('sing') && animation.curAnim.finished)
|
||||
playAnim('idleHair');
|
||||
}
|
||||
|
||||
switch (curCharacter)
|
||||
{
|
||||
case 'gf':
|
||||
if (animation.curAnim.name == 'hairFall' && animation.curAnim.finished)
|
||||
playAnim('danceRight');
|
||||
case "pico-speaker":
|
||||
// for pico??
|
||||
if (animationNotes.length > 0)
|
||||
{
|
||||
if (Conductor.songPosition > animationNotes[0][0])
|
||||
{
|
||||
trace('played shoot anim' + animationNotes[0][1]);
|
||||
|
||||
var shootAnim:Int = 1;
|
||||
|
||||
if (animationNotes[0][1] >= 2)
|
||||
shootAnim = 3;
|
||||
|
||||
shootAnim += FlxG.random.int(0, 1);
|
||||
|
||||
playAnim('shoot' + shootAnim, true);
|
||||
animationNotes.shift();
|
||||
}
|
||||
}
|
||||
|
||||
if (animation.curAnim.finished)
|
||||
{
|
||||
playAnim(animation.curAnim.name, false, false, animation.curAnim.numFrames - 3);
|
||||
}
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
private var danced:Bool = false;
|
||||
|
||||
/**
|
||||
* FOR GF DANCING SHIT
|
||||
*/
|
||||
public function dance()
|
||||
{
|
||||
if (!debugMode)
|
||||
{
|
||||
switch (curCharacter)
|
||||
{
|
||||
case 'gf' | 'gf-christmas' | 'gf-car' | 'gf-pixel' | 'gf-tankmen':
|
||||
if (!animation.curAnim.name.startsWith('hair'))
|
||||
{
|
||||
danced = !danced;
|
||||
|
||||
if (danced)
|
||||
playAnim('danceRight');
|
||||
else
|
||||
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');
|
||||
|
||||
case 'spooky':
|
||||
danced = !danced;
|
||||
|
||||
if (danced)
|
||||
playAnim('danceRight');
|
||||
else
|
||||
playAnim('danceLeft');
|
||||
default:
|
||||
playAnim('idle');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (curCharacter == 'gf')
|
||||
{
|
||||
if (AnimName == 'singLEFT')
|
||||
{
|
||||
danced = true;
|
||||
}
|
||||
else if (AnimName == 'singRIGHT')
|
||||
{
|
||||
danced = false;
|
||||
}
|
||||
|
||||
if (AnimName == 'singUP' || AnimName == 'singDOWN')
|
||||
{
|
||||
danced = !danced;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function addOffset(name:String, x:Float = 0, y:Float = 0)
|
||||
{
|
||||
animOffsets[name] = [x, y];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package game.objects;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
|
||||
import game.state.PlayState;
|
||||
|
||||
/*
|
||||
Pulled a Forever Engine and moved the ratings, combo numbers n stuff into
|
||||
a separate class
|
||||
|
||||
- Zyflx
|
||||
*/
|
||||
|
||||
class JudgeSpr
|
||||
{
|
||||
public static function spawnJudgeSpr(rating:String, isPixel:Bool = false)
|
||||
{
|
||||
var ratingSpr:FlxSprite = new FlxSprite().loadGraphic(Paths.image(rating));
|
||||
|
||||
ratingSpr.x = FlxG.width * 0.55 - 40;
|
||||
if (ratingSpr.x < FlxG.camera.scroll.x)
|
||||
ratingSpr.x = FlxG.camera.scroll.x;
|
||||
else if (ratingSpr.x > FlxG.camera.scroll.x + FlxG.camera.width - ratingSpr.width)
|
||||
ratingSpr.x = FlxG.camera.scroll.x + FlxG.camera.width - ratingSpr.width;
|
||||
|
||||
ratingSpr.y = FlxG.camera.scroll.y + FlxG.camera.height * 0.4 - 60;
|
||||
ratingSpr.acceleration.y = 550;
|
||||
ratingSpr.velocity.y -= FlxG.random.int(140, 175);
|
||||
ratingSpr.velocity.x -= FlxG.random.int(0, 10);
|
||||
|
||||
if (isPixel)
|
||||
{
|
||||
ratingSpr.setGraphicSize(Std.int(ratingSpr.width * PlayState.daPixelZoom * 0.7));
|
||||
}
|
||||
else
|
||||
{
|
||||
ratingSpr.setGraphicSize(Std.int(ratingSpr.width * 0.7));
|
||||
ratingSpr.antialiasing = true;
|
||||
}
|
||||
ratingSpr.updateHitbox();
|
||||
|
||||
return ratingSpr;
|
||||
}
|
||||
|
||||
public static function spawnComboNum(path:String, isPixel:Bool = false)
|
||||
{
|
||||
var comboNum:FlxSprite = new FlxSprite().loadGraphic(Paths.image(path));
|
||||
|
||||
if (isPixel)
|
||||
{
|
||||
comboNum.setGraphicSize(Std.int(comboNum.width * PlayState.daPixelZoom));
|
||||
}
|
||||
else
|
||||
{
|
||||
comboNum.setGraphicSize(Std.int(comboNum.width * 0.5));
|
||||
}
|
||||
comboNum.updateHitbox();
|
||||
|
||||
comboNum.acceleration.y = FlxG.random.int(200, 300);
|
||||
comboNum.velocity.y -= FlxG.random.int(140, 160);
|
||||
comboNum.velocity.x = FlxG.random.float(-5, 5);
|
||||
|
||||
return comboNum;
|
||||
}
|
||||
|
||||
public static function spawnComboSpr(path:String, isPixel:Bool = false)
|
||||
{
|
||||
var comboSpr:FlxSprite = new FlxSprite();
|
||||
comboSpr.loadGraphic(Paths.image(path));
|
||||
|
||||
comboSpr.y = FlxG.camera.scroll.y + FlxG.camera.height * 0.4 + 80;
|
||||
comboSpr.x = FlxG.width * 0.55;
|
||||
if (comboSpr.x < FlxG.camera.scroll.x + 194)
|
||||
comboSpr.x = FlxG.camera.scroll.x + 194;
|
||||
else if (comboSpr.x > FlxG.camera.scroll.x + FlxG.camera.width - comboSpr.width)
|
||||
comboSpr.x = FlxG.camera.scroll.x + FlxG.camera.width - comboSpr.width;
|
||||
|
||||
comboSpr.acceleration.y = 600;
|
||||
comboSpr.velocity.y -= 150;
|
||||
comboSpr.velocity.x += FlxG.random.int(1, 10);
|
||||
|
||||
if (isPixel)
|
||||
{
|
||||
comboSpr.setGraphicSize(Std.int(comboSpr.width * PlayState.daPixelZoom * 0.7));
|
||||
}
|
||||
else
|
||||
{
|
||||
comboSpr.setGraphicSize(Std.int(comboSpr.width * 0.7));
|
||||
comboSpr.antialiasing = true;
|
||||
}
|
||||
comboSpr.updateHitbox();
|
||||
|
||||
return comboSpr;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package game.objects.cutscene;
|
||||
|
||||
import animate.FlxAnimate;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxState;
|
||||
import flixel.addons.display.FlxGridOverlay;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.util.FlxColor;
|
||||
import openfl.display.BitmapData;
|
||||
|
||||
// import animateAtlasPlayer.assets.AssetManager;
|
||||
// import animateAtlasPlayer.core.Animation;
|
||||
class CutsceneAnimTestState extends FlxState
|
||||
{
|
||||
var cutsceneGroup:CutsceneCharacter;
|
||||
|
||||
var curSelected:Int = 0;
|
||||
var debugTxt:FlxText;
|
||||
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
|
||||
var gridBG:FlxSprite = FlxGridOverlay.create(10, 10);
|
||||
gridBG.scrollFactor.set(0.5, 0.5);
|
||||
add(gridBG);
|
||||
|
||||
debugTxt = new FlxText(900, 20, 0, "", 20);
|
||||
debugTxt.color = FlxColor.BLUE;
|
||||
add(debugTxt);
|
||||
|
||||
var animated:FlxAnimate = new FlxAnimate(600, 200);
|
||||
add(animated);
|
||||
|
||||
// createCutscene(0);
|
||||
// createCutscene(1);
|
||||
// createCutscene(2);
|
||||
// createCutscene(3);
|
||||
// createCutscene(4);
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
/* if (FlxG.keys.pressed.SHIFT)
|
||||
{
|
||||
if (FlxG.keys.justPressed.UP)
|
||||
curSelected -= 1;
|
||||
if (FlxG.keys.justPressed.DOWN)
|
||||
curSelected += 1;
|
||||
|
||||
if (curSelected < 0)
|
||||
curSelected = cutsceneGroup.members.length - 1;
|
||||
if (curSelected >= cutsceneGroup.members.length)
|
||||
curSelected = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
var valueMulti:Float = 1;
|
||||
|
||||
if (FlxG.keys.pressed.SPACE)
|
||||
valueMulti = 10;
|
||||
|
||||
if (FlxG.keys.justPressed.UP)
|
||||
cutsceneGroup.members[curSelected].y -= valueMulti;
|
||||
if (FlxG.keys.justPressed.DOWN)
|
||||
cutsceneGroup.members[curSelected].y += valueMulti;
|
||||
if (FlxG.keys.justPressed.LEFT)
|
||||
cutsceneGroup.members[curSelected].x -= valueMulti;
|
||||
if (FlxG.keys.justPressed.RIGHT)
|
||||
cutsceneGroup.members[curSelected].x += valueMulti;
|
||||
}
|
||||
|
||||
debugTxt.text = curSelected + " : " + cutsceneGroup.members[curSelected].getPosition();
|
||||
*/
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package game.objects.cutscene;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.math.FlxPoint;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class CutsceneCharacter extends FlxTypedGroup<FlxSprite>
|
||||
{
|
||||
public var coolPos:FlxPoint = FlxPoint.get();
|
||||
public var animShit:Map<String, FlxPoint> = new Map();
|
||||
|
||||
private var imageShit:String;
|
||||
|
||||
public function new(x:Float, y:Float, imageShit:String)
|
||||
{
|
||||
super();
|
||||
|
||||
coolPos.set(x, y);
|
||||
|
||||
this.imageShit = imageShit;
|
||||
parseOffsets();
|
||||
createCutscene(0);
|
||||
}
|
||||
|
||||
// shitshow, oh well
|
||||
var arrayLMFAOOOO:Array<String> = [];
|
||||
|
||||
function parseOffsets()
|
||||
{
|
||||
var splitShit:Array<String> = CoolUtil.coolTextFile(Paths.file('images/cutsceneStuff/' + imageShit + "CutsceneOffsets.txt"));
|
||||
|
||||
for (i in splitShit)
|
||||
{
|
||||
var xAndY:FlxPoint = FlxPoint.get();
|
||||
var dumbSplit:Array<String> = i.split('---')[1].trim().split(' ');
|
||||
trace('cool split: ' + i.split('---')[1]);
|
||||
trace(dumbSplit);
|
||||
xAndY.set(Std.parseFloat(dumbSplit[0]), Std.parseFloat(dumbSplit[1]));
|
||||
|
||||
animShit.set(i.split('---')[0].trim(), xAndY);
|
||||
arrayLMFAOOOO.push(i.split('---')[0].trim());
|
||||
}
|
||||
|
||||
trace(animShit);
|
||||
}
|
||||
|
||||
public function createCutscene(daNum:Int = 0)
|
||||
{
|
||||
var cutScene:FlxSprite = new FlxSprite(coolPos.x + animShit.get(arrayLMFAOOOO[daNum]).x, coolPos.y + animShit.get(arrayLMFAOOOO[daNum]).y);
|
||||
cutScene.frames = Paths.getSparrowAtlas('cutsceneStuff/' + imageShit + "-" + daNum);
|
||||
cutScene.animation.addByPrefix('weed', arrayLMFAOOOO[daNum], 24, false);
|
||||
cutScene.animation.play('weed');
|
||||
cutScene.antialiasing = true;
|
||||
|
||||
cutScene.animation.finishCallback = function(anim:String)
|
||||
{
|
||||
cutScene.kill();
|
||||
cutScene.destroy();
|
||||
cutScene = null;
|
||||
|
||||
if (daNum + 1 < arrayLMFAOOOO.length)
|
||||
createCutscene(daNum + 1);
|
||||
else
|
||||
ended();
|
||||
};
|
||||
|
||||
add(cutScene);
|
||||
}
|
||||
|
||||
public var onFinish:Void->Void;
|
||||
|
||||
public function ended():Void
|
||||
{
|
||||
if (onFinish != null)
|
||||
onFinish();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package game.objects.cutscene;
|
||||
|
||||
import flixel.FlxBasic;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import openfl.events.NetStatusEvent;
|
||||
import openfl.media.Video;
|
||||
import openfl.net.NetConnection;
|
||||
import openfl.net.NetStream;
|
||||
|
||||
class FlxVideo extends FlxBasic
|
||||
{
|
||||
var video:Video;
|
||||
var netStream:NetStream;
|
||||
|
||||
public var finishCallback:Void->Void;
|
||||
|
||||
/**
|
||||
* Doesn't actually interact with Flixel shit, only just a pleasant to use class
|
||||
*/
|
||||
public function new(vidSrc:String)
|
||||
{
|
||||
super();
|
||||
|
||||
video = new Video();
|
||||
video.x = 0;
|
||||
video.y = 0;
|
||||
|
||||
FlxG.addChildBelowMouse(video);
|
||||
|
||||
var netConnection = new NetConnection();
|
||||
netConnection.connect(null);
|
||||
|
||||
netStream = new NetStream(netConnection);
|
||||
netStream.client = {onMetaData: client_onMetaData};
|
||||
netConnection.addEventListener(NetStatusEvent.NET_STATUS, netConnection_onNetStatus);
|
||||
netStream.play(Paths.file(vidSrc));
|
||||
}
|
||||
|
||||
public function finishVideo():Void
|
||||
{
|
||||
netStream.dispose();
|
||||
FlxG.removeChild(video);
|
||||
|
||||
if (finishCallback != null)
|
||||
finishCallback();
|
||||
}
|
||||
|
||||
public function client_onMetaData(metaData:Dynamic)
|
||||
{
|
||||
video.attachNetStream(netStream);
|
||||
|
||||
video.width = FlxG.width;
|
||||
video.height = FlxG.height;
|
||||
}
|
||||
|
||||
private function netConnection_onNetStatus(event:NetStatusEvent):Void
|
||||
{
|
||||
if (event.info.code == 'NetStream.Play.Complete')
|
||||
finishVideo();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import flixel.system.FlxSound;
|
||||
|
||||
class TankCutscene extends FlxSprite
|
||||
{
|
||||
public var startSyncAudio:FlxSound;
|
||||
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
super(x, y);
|
||||
}
|
||||
|
||||
var startedPlayingSound:Bool = false;
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (animation.curAnim.curFrame >= 1 && !startedPlayingSound)
|
||||
{
|
||||
startSyncAudio.play();
|
||||
startedPlayingSound = true;
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package game.objects.shaders;
|
||||
|
||||
import flixel.util.FlxColor;
|
||||
import openfl.display.ShaderParameter;
|
||||
|
||||
typedef BlendModeShader =
|
||||
{
|
||||
var uBlendColor:ShaderParameter<Float>;
|
||||
}
|
||||
|
||||
class BlendModeEffect
|
||||
{
|
||||
public var shader(default, null):BlendModeShader;
|
||||
|
||||
@:isVar
|
||||
public var color(default, set):FlxColor;
|
||||
|
||||
public function new(shader:BlendModeShader, color:FlxColor):Void
|
||||
{
|
||||
shader.uBlendColor.value = [];
|
||||
this.shader = shader;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
function set_color(color:FlxColor):FlxColor
|
||||
{
|
||||
shader.uBlendColor.value[0] = color.redFloat;
|
||||
shader.uBlendColor.value[1] = color.greenFloat;
|
||||
shader.uBlendColor.value[2] = color.blueFloat;
|
||||
shader.uBlendColor.value[3] = color.alphaFloat;
|
||||
|
||||
return this.color = color;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package game.objects.shaders;
|
||||
|
||||
import flixel.system.FlxAssets.FlxShader;
|
||||
|
||||
class BuildingShaders
|
||||
{
|
||||
public var shader(default, null):BuildingShader;
|
||||
public var daAlpha:Float = 1;
|
||||
|
||||
public function new():Void
|
||||
{
|
||||
shader = new BuildingShader();
|
||||
shader.alphaShit.value = [0];
|
||||
}
|
||||
|
||||
public function update(elapsed:Float):Void
|
||||
{
|
||||
shader.alphaShit.value[0] += elapsed;
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
shader.alphaShit.value[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
class BuildingShader extends FlxShader
|
||||
{
|
||||
@:glFragmentSource('
|
||||
#pragma header
|
||||
|
||||
uniform float alphaShit;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color = flixel_texture2D(bitmap, openfl_TextureCoordv);
|
||||
|
||||
if (color.a > 0.0)
|
||||
color -= alphaShit;
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
|
||||
')
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
package game.objects.shaders;
|
||||
|
||||
import flixel.system.FlxAssets.FlxShader;
|
||||
import flixel.util.FlxColor;
|
||||
|
||||
class ColorSwap
|
||||
{
|
||||
public var shader(default, null):ColorSwapShader;
|
||||
public var colorToReplace(default, set):FlxColor;
|
||||
public var newColor(default, set):FlxColor;
|
||||
public var daTime(default, set):Float;
|
||||
|
||||
public var hasOutline(default, set):Bool = false;
|
||||
|
||||
public var hueShit:Float = 0;
|
||||
|
||||
public function new():Void
|
||||
{
|
||||
shader = new ColorSwapShader();
|
||||
shader.uTime.value = [0];
|
||||
shader.money.value = [0];
|
||||
shader.awesomeOutline.value = [hasOutline];
|
||||
}
|
||||
|
||||
public function update(elapsed:Float):Void
|
||||
{
|
||||
shader.uTime.value[0] += elapsed;
|
||||
hueShit += elapsed;
|
||||
// trace(shader.money.value[0]);
|
||||
}
|
||||
|
||||
function set_colorToReplace(color:FlxColor):FlxColor
|
||||
{
|
||||
colorToReplace = color;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
function set_hasOutline(lol:Bool):Bool
|
||||
{
|
||||
shader.awesomeOutline.value = [lol];
|
||||
return lol;
|
||||
}
|
||||
|
||||
function set_daTime(daTime:Float):Float
|
||||
{
|
||||
return daTime;
|
||||
}
|
||||
|
||||
function set_newColor(color:FlxColor):FlxColor
|
||||
{
|
||||
newColor = color;
|
||||
|
||||
return color;
|
||||
}
|
||||
}
|
||||
|
||||
class ColorSwapShader extends FlxShader
|
||||
{
|
||||
@:glFragmentSource('
|
||||
#pragma header
|
||||
|
||||
uniform float uTime;
|
||||
uniform float money;
|
||||
uniform bool awesomeOutline;
|
||||
|
||||
|
||||
const float offset = 1.0 / 128.0;
|
||||
|
||||
|
||||
|
||||
vec3 normalizeColor(vec3 color)
|
||||
{
|
||||
return vec3(
|
||||
color[0] / 255.0,
|
||||
color[1] / 255.0,
|
||||
color[2] / 255.0
|
||||
);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
vec4 color = flixel_texture2D(bitmap, openfl_TextureCoordv);
|
||||
|
||||
vec4 swagColor = vec4(rgb2hsv(vec3(color[0], color[1], color[2])), color[3]);
|
||||
|
||||
// [0] is the hue???
|
||||
swagColor[0] += uTime;
|
||||
// swagColor[1] += uTime;
|
||||
|
||||
// money += swagColor[0];
|
||||
|
||||
color = vec4(hsv2rgb(vec3(swagColor[0], swagColor[1], swagColor[2])), swagColor[3]);
|
||||
|
||||
|
||||
if (awesomeOutline)
|
||||
{
|
||||
// Outline bullshit?
|
||||
vec2 size = vec2(3, 3);
|
||||
|
||||
if (color.a <= 0.5) {
|
||||
float w = size.x / openfl_TextureSize.x;
|
||||
float h = size.y / openfl_TextureSize.y;
|
||||
|
||||
if (flixel_texture2D(bitmap, vec2(openfl_TextureCoordv.x + w, openfl_TextureCoordv.y)).a != 0.
|
||||
|| flixel_texture2D(bitmap, vec2(openfl_TextureCoordv.x - w, openfl_TextureCoordv.y)).a != 0.
|
||||
|| flixel_texture2D(bitmap, vec2(openfl_TextureCoordv.x, openfl_TextureCoordv.y + h)).a != 0.
|
||||
|| flixel_texture2D(bitmap, vec2(openfl_TextureCoordv.x, openfl_TextureCoordv.y - h)).a != 0.)
|
||||
color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
gl_FragColor = color;
|
||||
|
||||
|
||||
/*
|
||||
if (color.a > 0.5)
|
||||
gl_FragColor = color;
|
||||
else
|
||||
{
|
||||
float a = flixel_texture2D(bitmap, vec2(openfl_TextureCoordv + offset, openfl_TextureCoordv.y)).a +
|
||||
flixel_texture2D(bitmap, vec2(openfl_TextureCoordv, openfl_TextureCoordv.y - offset)).a +
|
||||
flixel_texture2D(bitmap, vec2(openfl_TextureCoordv - offset, openfl_TextureCoordv.y)).a +
|
||||
flixel_texture2D(bitmap, vec2(openfl_TextureCoordv, openfl_TextureCoordv.y + offset)).a;
|
||||
if (color.a < 1.0 && a > 0.0)
|
||||
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.8);
|
||||
else
|
||||
gl_FragColor = color;
|
||||
} */
|
||||
}
|
||||
|
||||
')
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package game.objects.shaders;
|
||||
|
||||
import flixel.system.FlxAssets.FlxShader;
|
||||
|
||||
class OverlayShader extends FlxShader
|
||||
{
|
||||
@:glFragmentSource('
|
||||
#pragma header
|
||||
uniform vec4 uBlendColor;
|
||||
|
||||
vec3 blendLighten(base:Vec3, blend:Vec3) : Vec3 {
|
||||
return mix(
|
||||
1.0 - 2.0 * (1.0 - base) * (1.0 - blend),
|
||||
2.0 * base * blend,
|
||||
step( base, vec3(0.5) )
|
||||
);
|
||||
}
|
||||
|
||||
vec4 blendLighten(vec4 base, vec4 blend, float opacity)
|
||||
{
|
||||
return (blendLighten(base, blend) * opacity + base * (1.0 - opacity));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 base = texture2D(bitmap, openfl_TextureCoordv);
|
||||
gl_FragColor = blendLighten(base, uBlendColor, uBlendColor.a);
|
||||
}')
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
package game.objects.shaders;
|
||||
|
||||
// STOLEN FROM HAXEFLIXEL DEMO LOL
|
||||
import flixel.system.FlxAssets.FlxShader;
|
||||
|
||||
enum WiggleEffectType
|
||||
{
|
||||
DREAMY;
|
||||
WAVY;
|
||||
HEAT_WAVE_HORIZONTAL;
|
||||
HEAT_WAVE_VERTICAL;
|
||||
FLAG;
|
||||
}
|
||||
|
||||
class WiggleEffect
|
||||
{
|
||||
public var shader(default, null):WiggleShader = new WiggleShader();
|
||||
public var effectType(default, set):WiggleEffectType = DREAMY;
|
||||
public var waveSpeed(default, set):Float = 0;
|
||||
public var waveFrequency(default, set):Float = 0;
|
||||
public var waveAmplitude(default, set):Float = 0;
|
||||
|
||||
public function new():Void
|
||||
{
|
||||
shader.uTime.value = [0];
|
||||
}
|
||||
|
||||
public function update(elapsed:Float):Void
|
||||
{
|
||||
shader.uTime.value[0] += elapsed;
|
||||
}
|
||||
|
||||
function set_effectType(v:WiggleEffectType):WiggleEffectType
|
||||
{
|
||||
effectType = v;
|
||||
shader.effectType.value = [WiggleEffectType.getConstructors().indexOf(Std.string(v))];
|
||||
return v;
|
||||
}
|
||||
|
||||
function set_waveSpeed(v:Float):Float
|
||||
{
|
||||
waveSpeed = v;
|
||||
shader.uSpeed.value = [waveSpeed];
|
||||
return v;
|
||||
}
|
||||
|
||||
function set_waveFrequency(v:Float):Float
|
||||
{
|
||||
waveFrequency = v;
|
||||
shader.uFrequency.value = [waveFrequency];
|
||||
return v;
|
||||
}
|
||||
|
||||
function set_waveAmplitude(v:Float):Float
|
||||
{
|
||||
waveAmplitude = v;
|
||||
shader.uWaveAmplitude.value = [waveAmplitude];
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
class WiggleShader extends FlxShader
|
||||
{
|
||||
@:glFragmentSource('
|
||||
#pragma header
|
||||
//uniform float tx, ty; // x,y waves phase
|
||||
uniform float uTime;
|
||||
|
||||
const int EFFECT_TYPE_DREAMY = 0;
|
||||
const int EFFECT_TYPE_WAVY = 1;
|
||||
const int EFFECT_TYPE_HEAT_WAVE_HORIZONTAL = 2;
|
||||
const int EFFECT_TYPE_HEAT_WAVE_VERTICAL = 3;
|
||||
const int EFFECT_TYPE_FLAG = 4;
|
||||
|
||||
uniform int effectType;
|
||||
|
||||
/**
|
||||
* How fast the waves move over time
|
||||
*/
|
||||
uniform float uSpeed;
|
||||
|
||||
/**
|
||||
* Number of waves over time
|
||||
*/
|
||||
uniform float uFrequency;
|
||||
|
||||
/**
|
||||
* How much the pixels are going to stretch over the waves
|
||||
*/
|
||||
uniform float uWaveAmplitude;
|
||||
|
||||
vec2 sineWave(vec2 pt)
|
||||
{
|
||||
float x = 0.0;
|
||||
float y = 0.0;
|
||||
|
||||
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
|
||||
}
|
||||
else if (effectType == EFFECT_TYPE_WAVY)
|
||||
{
|
||||
float offsetY = sin(pt.x * uFrequency + uTime * uSpeed) * uWaveAmplitude;
|
||||
pt.y += offsetY; // * (pt.y - 1.0); // <- Uncomment to stop bottom part of the screen from moving
|
||||
}
|
||||
else if (effectType == EFFECT_TYPE_HEAT_WAVE_HORIZONTAL)
|
||||
{
|
||||
x = sin(pt.x * uFrequency + uTime * uSpeed) * uWaveAmplitude;
|
||||
}
|
||||
else if (effectType == EFFECT_TYPE_HEAT_WAVE_VERTICAL)
|
||||
{
|
||||
y = sin(pt.y * uFrequency + uTime * uSpeed) * uWaveAmplitude;
|
||||
}
|
||||
else if (effectType == EFFECT_TYPE_FLAG)
|
||||
{
|
||||
y = sin(pt.y * uFrequency + 10.0 * pt.x + uTime * uSpeed) * uWaveAmplitude;
|
||||
x = sin(pt.x * uFrequency + 5.0 * pt.y + uTime * uSpeed) * uWaveAmplitude;
|
||||
}
|
||||
|
||||
return vec2(pt.x + x, pt.y + y);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 uv = sineWave(openfl_TextureCoordv);
|
||||
gl_FragColor = texture2D(bitmap, uv);
|
||||
}')
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,672 @@
|
|||
package game.objects.stages;
|
||||
|
||||
import flixel.FlxBasic;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxG;
|
||||
import flixel.math.FlxAngle;
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.util.FlxTimer;
|
||||
import flixel.system.FlxSound;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.addons.effects.FlxTrail;
|
||||
import flixel.addons.effects.chainable.FlxWaveEffect;
|
||||
import game.data.backend.*;
|
||||
import game.objects.*;
|
||||
import game.objects.stages.background.*;
|
||||
import game.state.PlayState;
|
||||
|
||||
import game.objects.shaders.BuildingShaders;
|
||||
import game.objects.shaders.BuildingShaders.BuildingShader;
|
||||
|
||||
/*
|
||||
If it wasn't obvious already, this class is heavily based off of
|
||||
Forever Engines "Stage.hx"
|
||||
|
||||
Forever Engine by beloved
|
||||
*/
|
||||
|
||||
class GameStage extends FlxTypedGroup<FlxBasic>
|
||||
{
|
||||
var pixelZoom = PlayState.daPixelZoom;
|
||||
|
||||
// Spooky Stage Stuff
|
||||
var halloweenBG:FlxSprite;
|
||||
var lightningStrikeBeat:Int = 0;
|
||||
var lightningOffset:Int = 8;
|
||||
|
||||
// Philly Stage Stuff
|
||||
// I love philly cheesesteaks
|
||||
var phillyTrain:FlxSprite;
|
||||
var trainSound:FlxSound;
|
||||
var phillyCityLights:FlxTypedGroup<FlxSprite>;
|
||||
var lightFadeShader:BuildingShaders;
|
||||
|
||||
// Limo Stage Stuff
|
||||
public var limo:FlxSprite;
|
||||
var fastCar:FlxSprite;
|
||||
var grpLimoDancers:FlxTypedGroup<BackgroundDancer>;
|
||||
|
||||
// Mall Stage Stuff
|
||||
var upperBoppers:FlxSprite;
|
||||
var bottomBoppers:FlxSprite;
|
||||
var santa:FlxSprite;
|
||||
|
||||
// School Stuff
|
||||
var bgGirls:BackgroundGirls;
|
||||
|
||||
// Tank Stage Stuff
|
||||
var tankWatchtower:BGSprite;
|
||||
var tankGround:BGSprite;
|
||||
public var tankmanRun:FlxTypedGroup<TankmenBG>;
|
||||
public var foregroundSprites:FlxTypedGroup<BGSprite>;
|
||||
|
||||
// For if you want to have sprites in front of the characters
|
||||
public var fgSprites:FlxTypedGroup<FlxBasic>;
|
||||
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
|
||||
foregroundSprites = new FlxTypedGroup<BGSprite>();
|
||||
fgSprites = new FlxTypedGroup<FlxBasic>();
|
||||
|
||||
switch (getStage())
|
||||
{
|
||||
case 'stage':
|
||||
PlayState.defaultCamZoom = 0.9;
|
||||
|
||||
var bg:BGSprite = new BGSprite('stageback', -600, -200, 0.9, 0.9);
|
||||
add(bg);
|
||||
|
||||
var stageFront:FlxSprite = new FlxSprite(-650, 600).loadGraphic(Paths.image('stagefront'));
|
||||
stageFront.setGraphicSize(Std.int(stageFront.width * 1.1));
|
||||
stageFront.updateHitbox();
|
||||
stageFront.antialiasing = true;
|
||||
stageFront.scrollFactor.set(0.9, 0.9);
|
||||
stageFront.active = false;
|
||||
add(stageFront);
|
||||
|
||||
var stageCurtains:FlxSprite = new FlxSprite(-500, -300).loadGraphic(Paths.image('stagecurtains'));
|
||||
stageCurtains.setGraphicSize(Std.int(stageCurtains.width * 0.9));
|
||||
stageCurtains.updateHitbox();
|
||||
stageCurtains.antialiasing = true;
|
||||
stageCurtains.scrollFactor.set(1.3, 1.3);
|
||||
stageCurtains.active = false;
|
||||
add(stageCurtains);
|
||||
|
||||
case 'spooky':
|
||||
var hallowTex = Paths.getSparrowAtlas('halloween_bg');
|
||||
|
||||
halloweenBG = new FlxSprite(-200, -100);
|
||||
halloweenBG.frames = hallowTex;
|
||||
halloweenBG.animation.addByPrefix('idle', 'halloweem bg0');
|
||||
halloweenBG.animation.addByPrefix('lightning', 'halloweem bg lightning strike', 24, false);
|
||||
halloweenBG.animation.play('idle');
|
||||
halloweenBG.antialiasing = true;
|
||||
add(halloweenBG);
|
||||
|
||||
case 'philly':
|
||||
var bg:FlxSprite = new FlxSprite(-100).loadGraphic(Paths.image('philly/sky'));
|
||||
bg.scrollFactor.set(0.1, 0.1);
|
||||
add(bg);
|
||||
|
||||
var city:FlxSprite = new FlxSprite(-10).loadGraphic(Paths.image('philly/city'));
|
||||
city.scrollFactor.set(0.3, 0.3);
|
||||
city.setGraphicSize(Std.int(city.width * 0.85));
|
||||
city.updateHitbox();
|
||||
add(city);
|
||||
|
||||
lightFadeShader = new BuildingShaders();
|
||||
phillyCityLights = new FlxTypedGroup<FlxSprite>();
|
||||
|
||||
add(phillyCityLights);
|
||||
|
||||
for (i in 0...5)
|
||||
{
|
||||
var light:FlxSprite = new FlxSprite(city.x).loadGraphic(Paths.image('philly/win' + i));
|
||||
light.scrollFactor.set(0.3, 0.3);
|
||||
light.visible = false;
|
||||
light.setGraphicSize(Std.int(light.width * 0.85));
|
||||
light.updateHitbox();
|
||||
light.antialiasing = true;
|
||||
light.shader = lightFadeShader.shader;
|
||||
phillyCityLights.add(light);
|
||||
}
|
||||
|
||||
var streetBehind:FlxSprite = new FlxSprite(-40, 50).loadGraphic(Paths.image('philly/behindTrain'));
|
||||
add(streetBehind);
|
||||
|
||||
phillyTrain = new FlxSprite(2000, 360).loadGraphic(Paths.image('philly/train'));
|
||||
add(phillyTrain);
|
||||
|
||||
var street:FlxSprite = new FlxSprite(-40, streetBehind.y).loadGraphic(Paths.image('philly/street'));
|
||||
add(street);
|
||||
|
||||
trainSound = new FlxSound().loadEmbedded(Paths.sound('train_passes'));
|
||||
FlxG.sound.list.add(trainSound);
|
||||
|
||||
case 'limo':
|
||||
var skyBG:FlxSprite = new FlxSprite(-120, -50).loadGraphic(Paths.image('limo/limoSunset'));
|
||||
skyBG.scrollFactor.set(0.1, 0.1);
|
||||
add(skyBG);
|
||||
|
||||
var bgLimo:FlxSprite = new FlxSprite(-200, 480);
|
||||
bgLimo.frames = Paths.getSparrowAtlas('limo/bgLimo');
|
||||
bgLimo.animation.addByPrefix('drive', "background limo pink", 24);
|
||||
bgLimo.animation.play('drive');
|
||||
bgLimo.scrollFactor.set(0.4, 0.4);
|
||||
add(bgLimo);
|
||||
|
||||
grpLimoDancers = new FlxTypedGroup<BackgroundDancer>();
|
||||
add(grpLimoDancers);
|
||||
|
||||
for (i in 0...5)
|
||||
{
|
||||
var dancer:BackgroundDancer = new BackgroundDancer((370 * i) + 130, bgLimo.y - 400);
|
||||
dancer.scrollFactor.set(0.4, 0.4);
|
||||
grpLimoDancers.add(dancer);
|
||||
}
|
||||
|
||||
var overlayShit:FlxSprite = new FlxSprite(-500, -600).loadGraphic(Paths.image('limo/limoOverlay'));
|
||||
overlayShit.alpha = 0.5;
|
||||
|
||||
limo = new FlxSprite(-120, 550);
|
||||
limo.frames = Paths.getSparrowAtlas('limo/limoDrive');
|
||||
limo.animation.addByPrefix('drive', "Limo stage", 24);
|
||||
limo.animation.play('drive');
|
||||
limo.antialiasing = true;
|
||||
|
||||
fastCar = new FlxSprite(-300, 160).loadGraphic(Paths.image('limo/fastCarLol'));
|
||||
|
||||
case 'mall':
|
||||
PlayState.defaultCamZoom = 0.80;
|
||||
|
||||
var bg:FlxSprite = new FlxSprite(-1000, -500).loadGraphic(Paths.image('christmas/bgWalls'));
|
||||
bg.antialiasing = true;
|
||||
bg.scrollFactor.set(0.2, 0.2);
|
||||
bg.active = false;
|
||||
bg.setGraphicSize(Std.int(bg.width * 0.8));
|
||||
bg.updateHitbox();
|
||||
add(bg);
|
||||
|
||||
upperBoppers = new FlxSprite(-240, -90);
|
||||
upperBoppers.frames = Paths.getSparrowAtlas('christmas/upperBop');
|
||||
upperBoppers.animation.addByPrefix('bop', "Upper Crowd Bob", 24, false);
|
||||
upperBoppers.antialiasing = true;
|
||||
upperBoppers.scrollFactor.set(0.33, 0.33);
|
||||
upperBoppers.setGraphicSize(Std.int(upperBoppers.width * 0.85));
|
||||
upperBoppers.updateHitbox();
|
||||
add(upperBoppers);
|
||||
|
||||
var bgEscalator:FlxSprite = new FlxSprite(-1100, -600).loadGraphic(Paths.image('christmas/bgEscalator'));
|
||||
bgEscalator.antialiasing = true;
|
||||
bgEscalator.scrollFactor.set(0.3, 0.3);
|
||||
bgEscalator.active = false;
|
||||
bgEscalator.setGraphicSize(Std.int(bgEscalator.width * 0.9));
|
||||
bgEscalator.updateHitbox();
|
||||
add(bgEscalator);
|
||||
|
||||
var tree:FlxSprite = new FlxSprite(370, -250).loadGraphic(Paths.image('christmas/christmasTree'));
|
||||
tree.antialiasing = true;
|
||||
tree.scrollFactor.set(0.40, 0.40);
|
||||
add(tree);
|
||||
|
||||
bottomBoppers = new FlxSprite(-300, 140);
|
||||
bottomBoppers.frames = Paths.getSparrowAtlas('christmas/bottomBop');
|
||||
bottomBoppers.animation.addByPrefix('bop', 'Bottom Level Boppers', 24, false);
|
||||
bottomBoppers.antialiasing = true;
|
||||
bottomBoppers.scrollFactor.set(0.9, 0.9);
|
||||
bottomBoppers.setGraphicSize(Std.int(bottomBoppers.width * 1));
|
||||
bottomBoppers.updateHitbox();
|
||||
add(bottomBoppers);
|
||||
|
||||
var fgSnow:FlxSprite = new FlxSprite(-600, 700).loadGraphic(Paths.image('christmas/fgSnow'));
|
||||
fgSnow.active = false;
|
||||
fgSnow.antialiasing = true;
|
||||
add(fgSnow);
|
||||
|
||||
santa = new FlxSprite(-840, 150);
|
||||
santa.frames = Paths.getSparrowAtlas('christmas/santa');
|
||||
santa.animation.addByPrefix('idle', 'santa idle in fear', 24, false);
|
||||
santa.antialiasing = true;
|
||||
add(santa);
|
||||
|
||||
case 'mallEvil':
|
||||
var bg:FlxSprite = new FlxSprite(-400, -500).loadGraphic(Paths.image('christmas/evilBG'));
|
||||
bg.antialiasing = true;
|
||||
bg.scrollFactor.set(0.2, 0.2);
|
||||
bg.active = false;
|
||||
bg.setGraphicSize(Std.int(bg.width * 0.8));
|
||||
bg.updateHitbox();
|
||||
add(bg);
|
||||
|
||||
var evilTree:FlxSprite = new FlxSprite(300, -300).loadGraphic(Paths.image('christmas/evilTree'));
|
||||
evilTree.antialiasing = true;
|
||||
evilTree.scrollFactor.set(0.2, 0.2);
|
||||
add(evilTree);
|
||||
|
||||
var evilSnow:FlxSprite = new FlxSprite(-200, 700).loadGraphic(Paths.image("christmas/evilSnow"));
|
||||
evilSnow.antialiasing = true;
|
||||
add(evilSnow);
|
||||
|
||||
case 'school':
|
||||
PlayState.isPixel = true;
|
||||
|
||||
var bgSky = new FlxSprite().loadGraphic(Paths.image('weeb/weebSky'));
|
||||
bgSky.scrollFactor.set(0.1, 0.1);
|
||||
add(bgSky);
|
||||
|
||||
var repositionShit = -200;
|
||||
|
||||
var bgSchool:FlxSprite = new FlxSprite(repositionShit, 0).loadGraphic(Paths.image('weeb/weebSchool'));
|
||||
bgSchool.scrollFactor.set(0.6, 0.90);
|
||||
add(bgSchool);
|
||||
|
||||
var bgStreet:FlxSprite = new FlxSprite(repositionShit).loadGraphic(Paths.image('weeb/weebStreet'));
|
||||
bgStreet.scrollFactor.set(0.95, 0.95);
|
||||
add(bgStreet);
|
||||
|
||||
var fgTrees:FlxSprite = new FlxSprite(repositionShit + 170, 130).loadGraphic(Paths.image('weeb/weebTreesBack'));
|
||||
fgTrees.scrollFactor.set(0.9, 0.9);
|
||||
add(fgTrees);
|
||||
|
||||
var bgTrees:FlxSprite = new FlxSprite(repositionShit - 380, -800);
|
||||
var treetex = Paths.getPackerAtlas('weeb/weebTrees');
|
||||
bgTrees.frames = treetex;
|
||||
bgTrees.animation.add('treeLoop', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18], 12);
|
||||
bgTrees.animation.play('treeLoop');
|
||||
bgTrees.scrollFactor.set(0.85, 0.85);
|
||||
add(bgTrees);
|
||||
|
||||
var treeLeaves:FlxSprite = new FlxSprite(repositionShit, -40);
|
||||
treeLeaves.frames = Paths.getSparrowAtlas('weeb/petals');
|
||||
treeLeaves.animation.addByPrefix('leaves', 'PETALS ALL', 24, true);
|
||||
treeLeaves.animation.play('leaves');
|
||||
treeLeaves.scrollFactor.set(0.85, 0.85);
|
||||
add(treeLeaves);
|
||||
|
||||
var widShit = Std.int(bgSky.width * 6);
|
||||
|
||||
bgSky.setGraphicSize(widShit);
|
||||
bgSchool.setGraphicSize(widShit);
|
||||
bgStreet.setGraphicSize(widShit);
|
||||
bgTrees.setGraphicSize(Std.int(widShit * 1.4));
|
||||
fgTrees.setGraphicSize(Std.int(widShit * 0.8));
|
||||
treeLeaves.setGraphicSize(widShit);
|
||||
|
||||
fgTrees.updateHitbox();
|
||||
bgSky.updateHitbox();
|
||||
bgSchool.updateHitbox();
|
||||
bgStreet.updateHitbox();
|
||||
bgTrees.updateHitbox();
|
||||
treeLeaves.updateHitbox();
|
||||
|
||||
bgGirls = new BackgroundGirls(-100, 190);
|
||||
bgGirls.scrollFactor.set(0.9, 0.9);
|
||||
|
||||
if (PlayState.SONG.song.toLowerCase() == 'roses') bgGirls.getScared();
|
||||
|
||||
bgGirls.setGraphicSize(Std.int(bgGirls.width * pixelZoom));
|
||||
bgGirls.updateHitbox();
|
||||
add(bgGirls);
|
||||
|
||||
case 'schoolEvil':
|
||||
PlayState.isPixel = true;
|
||||
|
||||
var waveEffectBG = new FlxWaveEffect(FlxWaveMode.ALL, 2, -1, 3, 2);
|
||||
var waveEffectFG = new FlxWaveEffect(FlxWaveMode.ALL, 2, -1, 5, 2);
|
||||
|
||||
var posX = 400;
|
||||
var posY = 200;
|
||||
|
||||
var bg:FlxSprite = new FlxSprite(posX, posY);
|
||||
bg.frames = Paths.getSparrowAtlas('weeb/animatedEvilSchool');
|
||||
bg.animation.addByPrefix('idle', 'background 2', 24);
|
||||
bg.animation.play('idle');
|
||||
bg.scrollFactor.set(0.8, 0.9);
|
||||
bg.scale.set(6, 6);
|
||||
add(bg);
|
||||
|
||||
case 'tank':
|
||||
PlayState.defaultCamZoom = 0.90;
|
||||
|
||||
var bg:BGSprite = new BGSprite('tankSky', -400, -400, 0, 0);
|
||||
add(bg);
|
||||
|
||||
var tankSky:BGSprite = new BGSprite('tankClouds', FlxG.random.int(-700, -100), FlxG.random.int(-20, 20), 0.1, 0.1);
|
||||
tankSky.active = true;
|
||||
tankSky.velocity.x = FlxG.random.float(5, 15);
|
||||
add(tankSky);
|
||||
|
||||
var tankMountains:BGSprite = new BGSprite('tankMountains', -300, -20, 0.2, 0.2);
|
||||
tankMountains.setGraphicSize(Std.int(tankMountains.width * 1.2));
|
||||
tankMountains.updateHitbox();
|
||||
add(tankMountains);
|
||||
|
||||
var tankBuildings:BGSprite = new BGSprite('tankBuildings', -200, 0, 0.30, 0.30);
|
||||
tankBuildings.setGraphicSize(Std.int(tankBuildings.width * 1.1));
|
||||
tankBuildings.updateHitbox();
|
||||
add(tankBuildings);
|
||||
|
||||
var tankRuins:BGSprite = new BGSprite('tankRuins', -200, 0, 0.35, 0.35);
|
||||
tankRuins.setGraphicSize(Std.int(tankRuins.width * 1.1));
|
||||
tankRuins.updateHitbox();
|
||||
add(tankRuins);
|
||||
|
||||
var smokeLeft:BGSprite = new BGSprite('smokeLeft', -200, -100, 0.4, 0.4, ['SmokeBlurLeft'], true);
|
||||
add(smokeLeft);
|
||||
|
||||
var smokeRight:BGSprite = new BGSprite('smokeRight', 1100, -100, 0.4, 0.4, ['SmokeRight'], true);
|
||||
add(smokeRight);
|
||||
|
||||
// tankGround.
|
||||
|
||||
tankWatchtower = new BGSprite('tankWatchtower', 100, 50, 0.5, 0.5, ['watchtower gradient color']);
|
||||
add(tankWatchtower);
|
||||
|
||||
tankGround = new BGSprite('tankRolling', 300, 300, 0.5, 0.5, ['BG tank w lighting'], true);
|
||||
add(tankGround);
|
||||
// tankGround.active = false;
|
||||
|
||||
tankmanRun = new FlxTypedGroup<TankmenBG>();
|
||||
add(tankmanRun);
|
||||
|
||||
var tankGround:BGSprite = new BGSprite('tankGround', -420, -150);
|
||||
tankGround.setGraphicSize(Std.int(tankGround.width * 1.15));
|
||||
tankGround.updateHitbox();
|
||||
add(tankGround);
|
||||
|
||||
moveTank();
|
||||
|
||||
// smokeLeft.screenCenter();
|
||||
|
||||
var fgTank0:BGSprite = new BGSprite('tank0', -500, 650, 1.7, 1.5, ['fg']);
|
||||
foregroundSprites.add(fgTank0);
|
||||
|
||||
var fgTank1:BGSprite = new BGSprite('tank1', -300, 750, 2, 0.2, ['fg']);
|
||||
foregroundSprites.add(fgTank1);
|
||||
|
||||
// just called 'foreground' just cuz small inconsistency no bbiggei
|
||||
var fgTank2:BGSprite = new BGSprite('tank2', 450, 940, 1.5, 1.5, ['foreground']);
|
||||
foregroundSprites.add(fgTank2);
|
||||
|
||||
var fgTank4:BGSprite = new BGSprite('tank4', 1300, 900, 1.5, 1.5, ['fg']);
|
||||
foregroundSprites.add(fgTank4);
|
||||
|
||||
var fgTank5:BGSprite = new BGSprite('tank5', 1620, 700, 1.5, 1.5, ['fg']);
|
||||
foregroundSprites.add(fgTank5);
|
||||
|
||||
var fgTank3:BGSprite = new BGSprite('tank3', 1300, 1200, 3.5, 2.5, ['fg']);
|
||||
foregroundSprites.add(fgTank3);
|
||||
}
|
||||
}
|
||||
|
||||
// Define Your Songs Stage Here
|
||||
public function getStage()
|
||||
{
|
||||
var curStage:String = 'stage';
|
||||
switch (PlayState.SONG.song.toLowerCase())
|
||||
{
|
||||
case 'spookeez' | 'south' | 'monster': curStage = 'spooky';
|
||||
case 'pico' | 'philly' | 'blammed': curStage = 'philly';
|
||||
case 'satin-panties' | 'high' | 'milf': curStage = 'limo';
|
||||
case 'coca' | 'eggnog': curStage = 'mall';
|
||||
case 'winter-horrorland': curStage = 'mallEvil';
|
||||
case 'senpai' | 'roses': curStage = 'school';
|
||||
case 'thorns': curStage = 'schoolEvil';
|
||||
case 'ugh' | 'guns' | 'stress': curStage = 'tank';
|
||||
}
|
||||
return curStage;
|
||||
}
|
||||
|
||||
public function getGF()
|
||||
{
|
||||
var GF:String = 'gf';
|
||||
switch (getStage())
|
||||
{
|
||||
case 'limo': GF = 'gf-car';
|
||||
case 'mall' | 'mallEvil': GF = 'gf-christmas';
|
||||
case 'tank': GF = 'gf-tankmen';
|
||||
}
|
||||
if (PlayState.isPixel) GF = 'gf-pixel';
|
||||
if (PlayState.SONG.song.toLowerCase() == 'stress') GF = 'pico-speaker';
|
||||
return GF;
|
||||
}
|
||||
|
||||
// Put Character Positions Here
|
||||
public function positionChars(bf:Character, dad:Character, gf:Character)
|
||||
{
|
||||
switch (getStage())
|
||||
{
|
||||
case 'limo':
|
||||
bf.y -= 220;
|
||||
bf.x += 260;
|
||||
|
||||
resetFastCar();
|
||||
add(fastCar);
|
||||
|
||||
case 'mall':
|
||||
bf.x += 200;
|
||||
|
||||
case 'mallEvil':
|
||||
bf.x += 320;
|
||||
dad.y -= 80;
|
||||
|
||||
case 'school':
|
||||
bf.x += 200;
|
||||
bf.y += 220;
|
||||
gf.x += 180;
|
||||
gf.y += 300;
|
||||
|
||||
case 'schoolEvil':
|
||||
var evilTrail = new FlxTrail(dad, null, 4, 24, 0.3, 0.069);
|
||||
add(evilTrail);
|
||||
|
||||
bf.x += 200;
|
||||
bf.y += 220;
|
||||
gf.x += 180;
|
||||
gf.y += 300;
|
||||
|
||||
case "tank":
|
||||
gf.y += 10;
|
||||
gf.x -= 30;
|
||||
bf.x += 40;
|
||||
bf.y += 0;
|
||||
dad.y += 60;
|
||||
dad.x -= 80;
|
||||
|
||||
if (getGF() != 'pico-speaker')
|
||||
{
|
||||
gf.x -= 170;
|
||||
gf.y -= 75;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function updateStage(elapsed:Float, bf:Character, dad:Character, gf:Character)
|
||||
{
|
||||
switch (getStage())
|
||||
{
|
||||
case 'philly':
|
||||
if (trainMoving)
|
||||
{
|
||||
trainFrameTiming += elapsed;
|
||||
|
||||
if (trainFrameTiming >= 1 / 24)
|
||||
{
|
||||
updateTrainPos(gf);
|
||||
trainFrameTiming = 0;
|
||||
}
|
||||
}
|
||||
|
||||
lightFadeShader.update((Conductor.crochet / 1000) * FlxG.elapsed * 1.5);
|
||||
|
||||
case 'tank': moveTank();
|
||||
}
|
||||
}
|
||||
|
||||
// Stage Events eg: bgChar bopping etc.
|
||||
public function beatHit(beat:Int, bf:Character, dad:Character, gf:Character)
|
||||
{
|
||||
switch (getStage())
|
||||
{
|
||||
case 'spooky':
|
||||
if (FlxG.random.bool(10) && beat > lightningStrikeBeat + lightningOffset) {
|
||||
FlxG.sound.play(Paths.soundRandom('thunder_', 1, 2));
|
||||
halloweenBG.animation.play('lightning');
|
||||
|
||||
lightningStrikeBeat = beat;
|
||||
lightningOffset = FlxG.random.int(8, 24);
|
||||
|
||||
bf.playAnim('scared', true);
|
||||
gf.playAnim('scared', true);
|
||||
}
|
||||
|
||||
case 'philly':
|
||||
if (!trainMoving) trainCooldown += 1;
|
||||
if (beat % 4 == 0)
|
||||
{
|
||||
lightFadeShader.reset();
|
||||
|
||||
phillyCityLights.forEach(function(light:FlxSprite)
|
||||
{
|
||||
light.visible = false;
|
||||
});
|
||||
|
||||
curLight = FlxG.random.int(0, phillyCityLights.length - 1);
|
||||
|
||||
phillyCityLights.members[curLight].visible = true;
|
||||
}
|
||||
|
||||
if (beat % 8 == 4 && FlxG.random.bool(30) && !trainMoving && trainCooldown > 8)
|
||||
{
|
||||
trainCooldown = FlxG.random.int(-4, 0);
|
||||
trainStart();
|
||||
}
|
||||
|
||||
case 'limo':
|
||||
grpLimoDancers.forEach(function(dancer:BackgroundDancer)
|
||||
{
|
||||
dancer.dance();
|
||||
});
|
||||
|
||||
if (FlxG.random.bool(10) && fastCarCanDrive) fastCarDrive();
|
||||
|
||||
case 'mall':
|
||||
upperBoppers.animation.play('bop', true);
|
||||
bottomBoppers.animation.play('bop', true);
|
||||
santa.animation.play('idle', true);
|
||||
|
||||
case 'school': bgGirls.dance();
|
||||
|
||||
case 'tank':
|
||||
tankWatchtower.dance();
|
||||
foregroundSprites.forEach(function(spr:BGSprite)
|
||||
{
|
||||
spr.dance();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Same as above
|
||||
public function stepHit(step:Int, bf:Character, dad:Character, gf:Character)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Other
|
||||
|
||||
// Philly Stuff
|
||||
var trainMoving:Bool = false;
|
||||
var trainFrameTiming:Float = 0;
|
||||
var trainCars:Int = 8;
|
||||
var trainFinishing:Bool = false;
|
||||
var trainCooldown:Int = 0;
|
||||
var startedMoving:Bool = false;
|
||||
var curLight:Int = 0;
|
||||
|
||||
function updateTrainPos(gf:Character):Void
|
||||
{
|
||||
if (trainSound.time >= 4700)
|
||||
{
|
||||
startedMoving = true;
|
||||
gf.playAnim('hairBlow');
|
||||
}
|
||||
|
||||
if (startedMoving)
|
||||
{
|
||||
phillyTrain.x -= 400;
|
||||
|
||||
if (phillyTrain.x < -2000 && !trainFinishing)
|
||||
{
|
||||
phillyTrain.x = -1150;
|
||||
trainCars -= 1;
|
||||
|
||||
if (trainCars <= 0) trainFinishing = true;
|
||||
}
|
||||
if (phillyTrain.x < -4000 && trainFinishing) trainReset(gf);
|
||||
}
|
||||
}
|
||||
|
||||
function trainReset(gf:Character):Void
|
||||
{
|
||||
gf.playAnim('hairFall');
|
||||
phillyTrain.x = FlxG.width + 200;
|
||||
trainMoving = false;
|
||||
trainCars = 8;
|
||||
trainFinishing = false;
|
||||
startedMoving = false;
|
||||
}
|
||||
|
||||
function trainStart():Void
|
||||
{
|
||||
trainMoving = true;
|
||||
trainSound.play(true);
|
||||
}
|
||||
|
||||
// Limo Stuff
|
||||
var fastCarCanDrive:Bool = true;
|
||||
|
||||
function fastCarDrive()
|
||||
{
|
||||
FlxG.sound.play(Paths.soundRandom('carPass', 0, 1), 0.7);
|
||||
|
||||
fastCar.velocity.x = (FlxG.random.int(170, 220) / FlxG.elapsed) * 3;
|
||||
fastCarCanDrive = false;
|
||||
new FlxTimer().start(2, function(tmr:FlxTimer)
|
||||
{
|
||||
resetFastCar();
|
||||
});
|
||||
}
|
||||
|
||||
public function resetFastCar():Void
|
||||
{
|
||||
fastCar.x = -12600;
|
||||
fastCar.y = FlxG.random.int(140, 250);
|
||||
fastCar.velocity.x = 0;
|
||||
fastCarCanDrive = true;
|
||||
}
|
||||
|
||||
// Tank Stuff
|
||||
var tankResetShit:Bool = false;
|
||||
var tankMoving:Bool = false;
|
||||
var tankAngle:Float = FlxG.random.int(-90, 45);
|
||||
var tankSpeed:Float = FlxG.random.float(5, 7);
|
||||
var tankX:Float = 400;
|
||||
|
||||
function moveTank():Void
|
||||
{
|
||||
if (!PlayState.inCutscene)
|
||||
{
|
||||
var daAngleOffset:Float = 1;
|
||||
tankAngle += FlxG.elapsed * tankSpeed;
|
||||
tankGround.angle = tankAngle - 90 + 15;
|
||||
|
||||
tankGround.x = tankX + Math.cos(FlxAngle.asRadians((tankAngle * daAngleOffset) + 180)) * 1500;
|
||||
tankGround.y = 1300 + Math.sin(FlxAngle.asRadians((tankAngle * daAngleOffset) + 180)) * 1100;
|
||||
}
|
||||
}
|
||||
|
||||
override function add(obj:FlxBasic):FlxBasic { return super.add(obj); }
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package game.objects.stages.background;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
|
||||
class BGSprite extends FlxSprite
|
||||
{
|
||||
/**
|
||||
Cool lil utility thing just so that it can easy do antialiasing and scrollfactor bullshit
|
||||
*/
|
||||
public var idleAnim:String;
|
||||
|
||||
public function new(image:String, x:Float = 0, y:Float = 0, parX:Float = 1, parY:Float = 1, ?daAnimations:Array<String>, ?loopingAnim:Bool = false)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
if (daAnimations != null)
|
||||
{
|
||||
frames = Paths.getSparrowAtlas(image);
|
||||
for (anims in daAnimations)
|
||||
{
|
||||
animation.addByPrefix(anims, anims, 24, loopingAnim);
|
||||
animation.play(anims);
|
||||
|
||||
if (idleAnim == null)
|
||||
idleAnim = anims;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
loadGraphic(Paths.image(image));
|
||||
active = false;
|
||||
}
|
||||
|
||||
scrollFactor.set(parX, parY);
|
||||
antialiasing = true;
|
||||
}
|
||||
|
||||
public function dance():Void
|
||||
{
|
||||
if (idleAnim != null)
|
||||
animation.play(idleAnim);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package game.objects.stages.background;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
|
||||
class BackgroundDancer extends FlxSprite
|
||||
{
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
frames = Paths.getSparrowAtlas("limo/limoDancer");
|
||||
animation.addByIndices('danceLeft', 'bg dancer sketch PINK', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
|
||||
animation.addByIndices('danceRight', 'bg dancer sketch PINK', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
|
||||
animation.play('danceLeft');
|
||||
animation.finish();
|
||||
antialiasing = true;
|
||||
}
|
||||
|
||||
var danceDir:Bool = false;
|
||||
|
||||
public function dance():Void
|
||||
{
|
||||
danceDir = !danceDir;
|
||||
var anim:String = danceDir ? 'danceRight' : 'danceLeft';
|
||||
animation.play(anim, true);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package game.objects.stages.background;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
|
||||
class BackgroundGirls extends FlxSprite
|
||||
{
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
// BG fangirls dissuaded
|
||||
frames = Paths.getSparrowAtlas('weeb/bgFreaks');
|
||||
|
||||
animation.addByIndices('danceLeft', 'BG girls group', CoolUtil.numberArray(14), "", 24, false);
|
||||
animation.addByIndices('danceRight', 'BG girls group', CoolUtil.numberArray(30, 15), "", 24, false);
|
||||
|
||||
animation.play('danceLeft');
|
||||
animation.finish();
|
||||
}
|
||||
|
||||
var danceDir:Bool = false;
|
||||
|
||||
public function getScared():Void
|
||||
{
|
||||
animation.addByIndices('danceLeft', 'BG fangirls dissuaded', CoolUtil.numberArray(14), "", 24, false);
|
||||
animation.addByIndices('danceRight', 'BG fangirls dissuaded', CoolUtil.numberArray(30, 15), "", 24, false);
|
||||
dance();
|
||||
animation.finish();
|
||||
}
|
||||
|
||||
public function dance():Void
|
||||
{
|
||||
danceDir = !danceDir;
|
||||
var anim:String = danceDir ? 'danceRight' : 'danceLeft';
|
||||
animation.play(anim, true);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package game.objects.stages.background;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import haxe.display.Display.Package;
|
||||
|
||||
import game.data.backend.Conductor;
|
||||
|
||||
class TankmenBG extends FlxSprite
|
||||
{
|
||||
public static var animationNotes:Array<Dynamic> = [];
|
||||
|
||||
public var strumTime:Float = 0;
|
||||
public var goingRight:Bool = false;
|
||||
public var tankSpeed:Float = 0.7;
|
||||
|
||||
public var endingOffset:Float;
|
||||
|
||||
public function new(x:Float, y:Float, isGoingRight:Bool)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
// makeGraphic(200, 200);
|
||||
|
||||
frames = Paths.getSparrowAtlas('tankmanKilled1');
|
||||
antialiasing = true;
|
||||
animation.addByPrefix('run', 'tankman running', 24, true);
|
||||
animation.addByPrefix('shot', 'John Shot ' + FlxG.random.int(1, 2), 24, false);
|
||||
|
||||
animation.play('run');
|
||||
animation.curAnim.curFrame = FlxG.random.int(0, animation.curAnim.numFrames - 1);
|
||||
|
||||
updateHitbox();
|
||||
|
||||
setGraphicSize(Std.int(width * 0.8));
|
||||
updateHitbox();
|
||||
}
|
||||
|
||||
public function resetShit(x:Float, y:Float, isGoingRight:Bool)
|
||||
{
|
||||
setPosition(x, y);
|
||||
goingRight = isGoingRight;
|
||||
endingOffset = FlxG.random.float(50, 200);
|
||||
tankSpeed = FlxG.random.float(0.6, 1);
|
||||
|
||||
if (goingRight)
|
||||
flipX = true;
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
if (x >= FlxG.width * 1.2 || x <= FlxG.width * -0.5)
|
||||
visible = false;
|
||||
else
|
||||
visible = true;
|
||||
|
||||
if (animation.curAnim.name == 'run')
|
||||
{
|
||||
var endDirection:Float = (FlxG.width * 0.74) + endingOffset;
|
||||
|
||||
if (goingRight)
|
||||
{
|
||||
endDirection = (FlxG.width * 0.02) - endingOffset;
|
||||
|
||||
x = (endDirection + (Conductor.songPosition - strumTime) * tankSpeed);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = (endDirection - (Conductor.songPosition - strumTime) * tankSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
if (Conductor.songPosition > strumTime)
|
||||
{
|
||||
// kill();
|
||||
animation.play('shot');
|
||||
|
||||
if (goingRight)
|
||||
{
|
||||
offset.y = 200;
|
||||
offset.x = 300;
|
||||
}
|
||||
}
|
||||
|
||||
if (animation.curAnim.name == 'shot' && animation.curAnim.curFrame >= animation.curAnim.frames.length - 1)
|
||||
{
|
||||
kill();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package game.state;
|
||||
|
||||
import flixel.FlxG;
|
||||
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;
|
||||
|
||||
import game.objects.*;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package game.state;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
|
||||
import game.state.menus.*;
|
||||
|
||||
class GitarooPause extends MusicBeatState
|
||||
{
|
||||
var replayButton:FlxSprite;
|
||||
var cancelButton:FlxSprite;
|
||||
|
||||
var replaySelect:Bool = false;
|
||||
|
||||
public function new():Void
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
override function create()
|
||||
{
|
||||
if (FlxG.sound.music != null)
|
||||
FlxG.sound.music.stop();
|
||||
|
||||
var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('pauseAlt/pauseBG'));
|
||||
add(bg);
|
||||
|
||||
var bf:FlxSprite = new FlxSprite(0, 30);
|
||||
bf.frames = Paths.getSparrowAtlas('pauseAlt/bfLol');
|
||||
bf.animation.addByPrefix('lol', "funnyThing", 13);
|
||||
bf.animation.play('lol');
|
||||
add(bf);
|
||||
bf.screenCenter(X);
|
||||
|
||||
replayButton = new FlxSprite(FlxG.width * 0.28, FlxG.height * 0.7);
|
||||
replayButton.frames = Paths.getSparrowAtlas('pauseAlt/pauseUI');
|
||||
replayButton.animation.addByPrefix('selected', 'bluereplay', 0, false);
|
||||
replayButton.animation.appendByPrefix('selected', 'yellowreplay');
|
||||
replayButton.animation.play('selected');
|
||||
add(replayButton);
|
||||
|
||||
cancelButton = new FlxSprite(FlxG.width * 0.58, replayButton.y);
|
||||
cancelButton.frames = Paths.getSparrowAtlas('pauseAlt/pauseUI');
|
||||
cancelButton.animation.addByPrefix('selected', 'bluecancel', 0, false);
|
||||
cancelButton.animation.appendByPrefix('selected', 'cancelyellow');
|
||||
cancelButton.animation.play('selected');
|
||||
add(cancelButton);
|
||||
|
||||
changeThing();
|
||||
|
||||
super.create();
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (controls.UI_LEFT_P || controls.UI_RIGHT_P)
|
||||
changeThing();
|
||||
|
||||
if (controls.ACCEPT)
|
||||
{
|
||||
if (replaySelect)
|
||||
{
|
||||
FlxG.switchState(new PlayState());
|
||||
}
|
||||
else
|
||||
{
|
||||
FlxG.switchState(new MainMenuState());
|
||||
}
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
function changeThing():Void
|
||||
{
|
||||
replaySelect = !replaySelect;
|
||||
|
||||
if (replaySelect)
|
||||
{
|
||||
cancelButton.animation.curAnim.curFrame = 0;
|
||||
replayButton.animation.curAnim.curFrame = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
cancelButton.animation.curAnim.curFrame = 1;
|
||||
replayButton.animation.curAnim.curFrame = 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,339 @@
|
|||
package game.state;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxState;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.util.FlxTimer;
|
||||
import haxe.io.Path;
|
||||
import lime.app.Future;
|
||||
import lime.app.Promise;
|
||||
import lime.utils.AssetLibrary;
|
||||
import lime.utils.AssetManifest;
|
||||
import lime.utils.Assets as LimeAssets;
|
||||
import openfl.utils.Assets;
|
||||
|
||||
class LoadingState extends MusicBeatState
|
||||
{
|
||||
inline static var MIN_TIME = 1.0;
|
||||
|
||||
var target:FlxState;
|
||||
var stopMusic = false;
|
||||
var callbacks:MultiCallback;
|
||||
|
||||
var danceLeft = false;
|
||||
|
||||
var loadBar:FlxSprite;
|
||||
var funkay:FlxSprite;
|
||||
|
||||
function new(target:FlxState, stopMusic:Bool)
|
||||
{
|
||||
super();
|
||||
this.target = target;
|
||||
this.stopMusic = stopMusic;
|
||||
}
|
||||
|
||||
override function create()
|
||||
{
|
||||
var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, 0xFFcaff4d);
|
||||
add(bg);
|
||||
|
||||
funkay = new FlxSprite();
|
||||
funkay.loadGraphic(Paths.image('funkay'));
|
||||
funkay.setGraphicSize(0, FlxG.height);
|
||||
funkay.updateHitbox();
|
||||
funkay.antialiasing = true;
|
||||
add(funkay);
|
||||
funkay.scrollFactor.set();
|
||||
funkay.screenCenter();
|
||||
|
||||
loadBar = new FlxSprite(0, FlxG.height - 20).makeGraphic(FlxG.width, 10, 0xFFff16d2);
|
||||
loadBar.screenCenter(X);
|
||||
add(loadBar);
|
||||
|
||||
initSongsManifest().onComplete(function(lib)
|
||||
{
|
||||
callbacks = new MultiCallback(onLoad);
|
||||
var introComplete = callbacks.add("introComplete");
|
||||
checkLoadSong(getSongPath());
|
||||
if (PlayState.SONG.needsVoices)
|
||||
checkLoadSong(getVocalPath());
|
||||
checkLibrary("shared");
|
||||
if (PlayState.storyWeek > 0)
|
||||
checkLibrary("week" + PlayState.storyWeek);
|
||||
else
|
||||
checkLibrary("tutorial");
|
||||
|
||||
var fadeTime = 0.5;
|
||||
FlxG.camera.fade(FlxG.camera.bgColor, fadeTime, true);
|
||||
new FlxTimer().start(fadeTime + MIN_TIME, function(_) introComplete());
|
||||
});
|
||||
}
|
||||
|
||||
function checkLoadSong(path:String)
|
||||
{
|
||||
if (!Assets.cache.hasSound(path))
|
||||
{
|
||||
var library = Assets.getLibrary("songs");
|
||||
var symbolPath = path.split(":").pop();
|
||||
// @:privateAccess
|
||||
// library.types.set(symbolPath, SOUND);
|
||||
// @:privateAccess
|
||||
// library.pathGroups.set(symbolPath, [library.__cacheBreak(symbolPath)]);
|
||||
var callback = callbacks.add("song:" + path);
|
||||
Assets.loadSound(path).onComplete(function(_)
|
||||
{
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function checkLibrary(library:String)
|
||||
{
|
||||
trace(Assets.hasLibrary(library));
|
||||
if (Assets.getLibrary(library) == null)
|
||||
{
|
||||
@:privateAccess
|
||||
if (!LimeAssets.libraryPaths.exists(library))
|
||||
throw "Missing library: " + library;
|
||||
|
||||
var callback = callbacks.add("library:" + library);
|
||||
Assets.loadLibrary(library).onComplete(function(_)
|
||||
{
|
||||
callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
override function beatHit()
|
||||
{
|
||||
super.beatHit();
|
||||
|
||||
// logo.animation.play('bump');
|
||||
danceLeft = !danceLeft;
|
||||
/*
|
||||
if (danceLeft)
|
||||
gfDance.animation.play('danceRight');
|
||||
else
|
||||
gfDance.animation.play('danceLeft'); */
|
||||
}
|
||||
|
||||
var targetShit:Float = 0;
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
funkay.setGraphicSize(Std.int(FlxMath.lerp(FlxG.width * 0.88, funkay.width, 0.9)));
|
||||
funkay.updateHitbox();
|
||||
// funkay.updateHitbox();
|
||||
|
||||
if (controls.ACCEPT)
|
||||
{
|
||||
funkay.setGraphicSize(Std.int(funkay.width + 60));
|
||||
funkay.updateHitbox();
|
||||
// funkay.setGraphicSize(0, Std.int(funkay.height + 50));
|
||||
// funkay.updateHitbox();
|
||||
// funkay.screenCenter();
|
||||
}
|
||||
|
||||
if (callbacks != null)
|
||||
{
|
||||
targetShit = FlxMath.remapToRange(callbacks.numRemaining / callbacks.length, 1, 0, 0, 1);
|
||||
|
||||
loadBar.scale.x = FlxMath.lerp(loadBar.scale.x, targetShit, 0.50);
|
||||
FlxG.watch.addQuick('percentage?', callbacks.numRemaining / callbacks.length);
|
||||
}
|
||||
|
||||
#if debug
|
||||
if (FlxG.keys.justPressed.SPACE)
|
||||
trace('fired: ' + callbacks.getFired() + " unfired:" + callbacks.getUnfired());
|
||||
#end
|
||||
}
|
||||
|
||||
function onLoad()
|
||||
{
|
||||
if (stopMusic && FlxG.sound.music != null)
|
||||
FlxG.sound.music.stop();
|
||||
|
||||
FlxG.switchState(target);
|
||||
}
|
||||
|
||||
static function getSongPath()
|
||||
{
|
||||
return Paths.inst(PlayState.SONG.song);
|
||||
}
|
||||
|
||||
static function getVocalPath()
|
||||
{
|
||||
return Paths.voices(PlayState.SONG.song);
|
||||
}
|
||||
|
||||
inline static public function loadAndSwitchState(target:FlxState, stopMusic = false)
|
||||
{
|
||||
FlxG.switchState(getNextState(target, stopMusic));
|
||||
}
|
||||
|
||||
static function getNextState(target:FlxState, stopMusic = false):FlxState
|
||||
{
|
||||
Paths.setCurrentLevel("week" + PlayState.storyWeek);
|
||||
#if NO_PRELOAD_ALL
|
||||
var loaded = isSoundLoaded(getSongPath())
|
||||
&& (!PlayState.SONG.needsVoices || isSoundLoaded(getVocalPath()))
|
||||
&& isLibraryLoaded("shared");
|
||||
|
||||
if (!loaded)
|
||||
return new LoadingState(target, stopMusic);
|
||||
#end
|
||||
if (stopMusic && FlxG.sound.music != null)
|
||||
FlxG.sound.music.stop();
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
#if NO_PRELOAD_ALL
|
||||
static function isSoundLoaded(path:String):Bool
|
||||
{
|
||||
return Assets.cache.hasSound(path);
|
||||
}
|
||||
|
||||
static function isLibraryLoaded(library:String):Bool
|
||||
{
|
||||
return Assets.getLibrary(library) != null;
|
||||
}
|
||||
#end
|
||||
|
||||
override function destroy()
|
||||
{
|
||||
super.destroy();
|
||||
|
||||
callbacks = null;
|
||||
}
|
||||
|
||||
static function initSongsManifest()
|
||||
{
|
||||
var id = "songs";
|
||||
var promise = new Promise<AssetLibrary>();
|
||||
|
||||
var library = LimeAssets.getLibrary(id);
|
||||
|
||||
if (library != null)
|
||||
{
|
||||
return Future.withValue(library);
|
||||
}
|
||||
|
||||
var path = id;
|
||||
var rootPath = null;
|
||||
|
||||
@:privateAccess
|
||||
var libraryPaths = LimeAssets.libraryPaths;
|
||||
if (libraryPaths.exists(id))
|
||||
{
|
||||
path = libraryPaths[id];
|
||||
rootPath = Path.directory(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (StringTools.endsWith(path, ".bundle"))
|
||||
{
|
||||
rootPath = path;
|
||||
path += "/library.json";
|
||||
}
|
||||
else
|
||||
{
|
||||
rootPath = Path.directory(path);
|
||||
}
|
||||
@:privateAccess
|
||||
path = LimeAssets.__cacheBreak(path);
|
||||
}
|
||||
|
||||
AssetManifest.loadFromFile(path, rootPath).onComplete(function(manifest)
|
||||
{
|
||||
if (manifest == null)
|
||||
{
|
||||
promise.error("Cannot parse asset manifest for library \"" + id + "\"");
|
||||
return;
|
||||
}
|
||||
|
||||
var library = AssetLibrary.fromManifest(manifest);
|
||||
|
||||
if (library == null)
|
||||
{
|
||||
promise.error("Cannot open library \"" + id + "\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
@:privateAccess
|
||||
LimeAssets.libraries.set(id, library);
|
||||
library.onChange.add(LimeAssets.onChange.dispatch);
|
||||
promise.completeWith(Future.withValue(library));
|
||||
}
|
||||
}).onError(function(_)
|
||||
{
|
||||
promise.error("There is no asset library with an ID of \"" + id + "\"");
|
||||
});
|
||||
|
||||
return promise.future;
|
||||
}
|
||||
}
|
||||
|
||||
class MultiCallback
|
||||
{
|
||||
public var callback:Void->Void;
|
||||
public var logId:String = null;
|
||||
public var length(default, null) = 0;
|
||||
public var numRemaining(default, null) = 0;
|
||||
|
||||
var unfired = new Map<String, Void->Void>();
|
||||
var fired = new Array<String>();
|
||||
|
||||
public function new(callback:Void->Void, logId:String = null)
|
||||
{
|
||||
this.callback = callback;
|
||||
this.logId = logId;
|
||||
}
|
||||
|
||||
public function add(id = "untitled")
|
||||
{
|
||||
id = '$length:$id';
|
||||
length++;
|
||||
numRemaining++;
|
||||
var func:Void->Void = null;
|
||||
func = function()
|
||||
{
|
||||
if (unfired.exists(id))
|
||||
{
|
||||
unfired.remove(id);
|
||||
fired.push(id);
|
||||
numRemaining--;
|
||||
|
||||
if (logId != null)
|
||||
log('fired $id, $numRemaining remaining');
|
||||
|
||||
if (numRemaining == 0)
|
||||
{
|
||||
if (logId != null)
|
||||
log('all callbacks fired');
|
||||
callback();
|
||||
}
|
||||
}
|
||||
else
|
||||
log('already fired $id');
|
||||
}
|
||||
unfired[id] = func;
|
||||
return func;
|
||||
}
|
||||
|
||||
inline function log(msg):Void
|
||||
{
|
||||
if (logId != null)
|
||||
trace('$logId: $msg');
|
||||
}
|
||||
|
||||
public function getFired()
|
||||
return fired.copy();
|
||||
|
||||
public function getUnfired()
|
||||
return [for (id in unfired.keys()) id];
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package game.state;
|
||||
|
||||
import game.data.backend.*;
|
||||
import game.data.backend.Conductor.BPMChangeEvent;
|
||||
import game.state.menus.options.controls.*;
|
||||
import game.data.*;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxGame;
|
||||
import flixel.addons.transition.FlxTransitionableState;
|
||||
import flixel.addons.ui.FlxUIState;
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.util.FlxTimer;
|
||||
|
||||
class MusicBeatState extends FlxUIState
|
||||
{
|
||||
private var curStep:Int = 0;
|
||||
private var curBeat:Int = 0;
|
||||
private var controls(get, never):Controls;
|
||||
|
||||
inline function get_controls():Controls
|
||||
return PlayerSettings.player1.controls;
|
||||
|
||||
override function create()
|
||||
{
|
||||
if (transIn != null)
|
||||
trace('reg ' + transIn.region);
|
||||
|
||||
super.create();
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
// everyStep();
|
||||
var oldStep:Int = curStep;
|
||||
|
||||
updateCurStep();
|
||||
updateBeat();
|
||||
|
||||
if (oldStep != curStep && curStep >= 0)
|
||||
stepHit();
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
private function updateBeat():Void
|
||||
{
|
||||
curBeat = Math.floor(curStep / 4);
|
||||
}
|
||||
|
||||
private function updateCurStep():Void
|
||||
{
|
||||
var lastChange:BPMChangeEvent = {
|
||||
stepTime: 0,
|
||||
songTime: 0,
|
||||
bpm: 0
|
||||
}
|
||||
for (i in 0...Conductor.bpmChangeMap.length)
|
||||
{
|
||||
if (Conductor.songPosition >= Conductor.bpmChangeMap[i].songTime)
|
||||
lastChange = Conductor.bpmChangeMap[i];
|
||||
}
|
||||
|
||||
curStep = lastChange.stepTime + Math.floor((Conductor.songPosition - lastChange.songTime) / Conductor.stepCrochet);
|
||||
}
|
||||
|
||||
public function stepHit():Void
|
||||
{
|
||||
if (curStep % 4 == 0)
|
||||
beatHit();
|
||||
}
|
||||
|
||||
public function beatHit():Void
|
||||
{
|
||||
// do literally nothing dumbass
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,105 @@
|
|||
package game.state;
|
||||
|
||||
import flixel.FlxG;
|
||||
import openfl.display.Sprite;
|
||||
import openfl.events.AsyncErrorEvent;
|
||||
import openfl.events.MouseEvent;
|
||||
import openfl.events.NetStatusEvent;
|
||||
import openfl.media.Video;
|
||||
import openfl.net.NetConnection;
|
||||
import openfl.net.NetStream;
|
||||
|
||||
import game.state.menus.*;
|
||||
|
||||
class VideoState extends MusicBeatState
|
||||
{
|
||||
var video:Video;
|
||||
var netStream:NetStream;
|
||||
private var overlay:Sprite;
|
||||
|
||||
public static var seenVideo:Bool = false;
|
||||
|
||||
override function create()
|
||||
{
|
||||
super.create();
|
||||
|
||||
seenVideo = true;
|
||||
|
||||
FlxG.save.data.seenVideo = true;
|
||||
FlxG.save.flush();
|
||||
|
||||
if (FlxG.sound.music != null)
|
||||
FlxG.sound.music.stop();
|
||||
|
||||
video = new Video();
|
||||
FlxG.addChildBelowMouse(video);
|
||||
|
||||
var netConnection = new NetConnection();
|
||||
netConnection.connect(null);
|
||||
|
||||
netStream = new NetStream(netConnection);
|
||||
netStream.client = {onMetaData: client_onMetaData};
|
||||
netStream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, netStream_onAsyncError);
|
||||
netConnection.addEventListener(NetStatusEvent.NET_STATUS, netConnection_onNetStatus);
|
||||
// netStream.addEventListener(NetStatusEvent.NET_STATUS);
|
||||
netStream.play(Paths.file('music/kickstarterTrailer.mp4'));
|
||||
|
||||
overlay = new Sprite();
|
||||
overlay.graphics.beginFill(0, 0.5);
|
||||
overlay.graphics.drawRect(0, 0, 1280, 720);
|
||||
overlay.addEventListener(MouseEvent.MOUSE_DOWN, overlay_onMouseDown);
|
||||
|
||||
overlay.buttonMode = true;
|
||||
// FlxG.stage.addChild(overlay);
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (controls.ACCEPT)
|
||||
finishVid();
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
function finishVid():Void
|
||||
{
|
||||
netStream.dispose();
|
||||
FlxG.removeChild(video);
|
||||
|
||||
TitleState.initialized = false;
|
||||
FlxG.switchState(new TitleState());
|
||||
}
|
||||
|
||||
private function client_onMetaData(metaData:Dynamic)
|
||||
{
|
||||
video.attachNetStream(netStream);
|
||||
|
||||
video.width = video.videoWidth;
|
||||
video.height = video.videoHeight;
|
||||
// video.
|
||||
}
|
||||
|
||||
private function netStream_onAsyncError(event:AsyncErrorEvent):Void
|
||||
{
|
||||
trace("Error loading video");
|
||||
}
|
||||
|
||||
private function netConnection_onNetStatus(event:NetStatusEvent):Void
|
||||
{
|
||||
if (event.info.code == 'NetStream.Play.Complete')
|
||||
{
|
||||
finishVid();
|
||||
}
|
||||
|
||||
trace(event.toString());
|
||||
}
|
||||
|
||||
private function overlay_onMouseDown(event:MouseEvent):Void
|
||||
{
|
||||
netStream.soundTransform.volume = 0.2;
|
||||
netStream.soundTransform.pan = -1;
|
||||
// netStream.play(Paths.file('music/kickstarterTrailer.mp4'));
|
||||
|
||||
FlxG.stage.removeChild(overlay);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,345 @@
|
|||
package game.state.menus;
|
||||
|
||||
#if discord_rpc
|
||||
import game.data.backend.Discord.DiscordClient;
|
||||
#end
|
||||
import flash.text.TextField;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.addons.display.FlxGridOverlay;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.tweens.FlxEase;
|
||||
import flixel.util.FlxColor;
|
||||
import lime.utils.Assets;
|
||||
|
||||
import game.ui.AtlasMenuList.AtlasMenuItem;
|
||||
import game.ui.MenuList.MenuTypedList;
|
||||
import game.ui.*;
|
||||
import game.ui.gameplay.*;
|
||||
import game.data.backend.*;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class FreeplayState extends MusicBeatState
|
||||
{
|
||||
var songs:Array<SongMetadata> = [];
|
||||
|
||||
// var selector:FlxText;
|
||||
var curSelected:Int = 0;
|
||||
var curDifficulty:Int = 1;
|
||||
|
||||
var scoreText:FlxText;
|
||||
var diffText:FlxText;
|
||||
var lerpScore:Float = 0;
|
||||
var intendedScore:Int = 0;
|
||||
|
||||
var coolColors:Array<Int> = [
|
||||
0xff9271fd,
|
||||
0xff9271fd,
|
||||
0xff223344,
|
||||
0xFF941653,
|
||||
0xFFfc96d7,
|
||||
0xFFa0d1ff,
|
||||
0xffff78bf,
|
||||
0xfff6b604
|
||||
];
|
||||
|
||||
private var grpSongs:FlxTypedGroup<Alphabet>;
|
||||
private var curPlaying:Bool = false;
|
||||
|
||||
private var iconArray:Array<HealthIcon> = [];
|
||||
var bg:FlxSprite;
|
||||
var scoreBG:FlxSprite;
|
||||
var difficulty:FlxSprite;
|
||||
var grpArrows:FlxTypedGroup<FlxSprite>;
|
||||
|
||||
override function create()
|
||||
{
|
||||
#if discord_rpc
|
||||
// Updating Discord Rich Presence
|
||||
DiscordClient.changePresence("In the Menus", null);
|
||||
#end
|
||||
|
||||
var isDebug:Bool = false;
|
||||
|
||||
var initSonglist = CoolUtil.coolTextFile(Paths.txt('freeplaySonglist'));
|
||||
|
||||
for (i in 0...initSonglist.length)
|
||||
{
|
||||
songs.push(new SongMetadata(initSonglist[i], 1, 'gf'));
|
||||
}
|
||||
|
||||
if (FlxG.sound.music != null)
|
||||
{
|
||||
if (!FlxG.sound.music.playing)
|
||||
FlxG.sound.playMusic(Paths.music('freakyMenu'));
|
||||
}
|
||||
|
||||
if (StoryMenuState.weekUnlocked[2] || isDebug)
|
||||
addWeek(['Bopeebo', 'Fresh', 'Dadbattle'], 1, ['dad']);
|
||||
|
||||
if (StoryMenuState.weekUnlocked[2] || isDebug)
|
||||
addWeek(['Spookeez', 'South', 'Monster'], 2, ['spooky', 'spooky', 'monster']);
|
||||
|
||||
if (StoryMenuState.weekUnlocked[3] || isDebug)
|
||||
addWeek(['Pico', 'Philly', 'Blammed'], 3, ['pico']);
|
||||
|
||||
if (StoryMenuState.weekUnlocked[4] || isDebug)
|
||||
addWeek(['Satin-Panties', 'High', 'Milf'], 4, ['mom']);
|
||||
|
||||
if (StoryMenuState.weekUnlocked[5] || isDebug)
|
||||
addWeek(['Cocoa', 'Eggnog', 'Winter-Horrorland'], 5, ['parents-christmas', 'parents-christmas', 'monster-christmas']);
|
||||
|
||||
if (StoryMenuState.weekUnlocked[6] || isDebug)
|
||||
addWeek(['Senpai', 'Roses', 'Thorns'], 6, ['senpai', 'senpai', 'spirit']);
|
||||
|
||||
if (StoryMenuState.weekUnlocked[7] || isDebug)
|
||||
addWeek(['Ugh', 'Guns', 'Stress'], 7, ['tankman']);
|
||||
|
||||
addSong('Test', 1, 'bf-pixel');
|
||||
|
||||
// LOAD MUSIC
|
||||
|
||||
// LOAD CHARACTERS
|
||||
|
||||
bg = new FlxSprite().loadGraphic(Paths.image('menuDesat'));
|
||||
add(bg);
|
||||
|
||||
var songListBG:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, 150, FlxColor.BLACK);
|
||||
songListBG.screenCenter(Y);
|
||||
add(songListBG);
|
||||
|
||||
grpSongs = new FlxTypedGroup<Alphabet>();
|
||||
add(grpSongs);
|
||||
|
||||
for (i in 0...songs.length)
|
||||
{
|
||||
var songText:Alphabet = new Alphabet(0, (70 * i) + 30, songs[i].songName, true, false);
|
||||
// songText.isMenuItem = true;
|
||||
// songText.targetY = i;
|
||||
songText.screenCenter(XY);
|
||||
songText.visible = false;
|
||||
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);
|
||||
|
||||
// songText.x += 40;
|
||||
// DONT PUT X IN THE FIRST PARAMETER OF new ALPHABET() !!
|
||||
// songText.screenCenter(X);
|
||||
}
|
||||
|
||||
scoreBG = new FlxSprite(0, songListBG.y + 210).makeGraphic(FlxG.width, 100, 0x99000000);
|
||||
scoreBG.antialiasing = false;
|
||||
scoreBG.screenCenter(X);
|
||||
add(scoreBG);
|
||||
|
||||
scoreText = new FlxText(0, scoreBG.y + 30, 0, "", 40);
|
||||
scoreText.setFormat(Paths.font("vcr.ttf"), 40, FlxColor.WHITE, CENTER);
|
||||
scoreText.screenCenter(X);
|
||||
scoreText.x -= 140;
|
||||
|
||||
diffText = new FlxText(scoreText.x, scoreText.y + 36, 0, "", 24);
|
||||
diffText.font = scoreText.font;
|
||||
// add(diffText);
|
||||
|
||||
var menuUITex = Paths.getSparrowAtlas('campaign_menu_UI_assets');
|
||||
|
||||
difficulty = new FlxSprite(0, scoreBG.y + 140);
|
||||
difficulty.frames = menuUITex;
|
||||
difficulty.animation.addByPrefix('easy', 'EASY');
|
||||
difficulty.animation.addByPrefix('normal', 'NORMAL');
|
||||
difficulty.animation.addByPrefix('hard', 'HARD');
|
||||
difficulty.animation.play('easy');
|
||||
difficulty.screenCenter(X);
|
||||
difficulty.x += 40;
|
||||
add(difficulty);
|
||||
|
||||
grpArrows = new FlxTypedGroup<FlxSprite>();
|
||||
add(grpArrows);
|
||||
|
||||
var arrowNames:Array<String> = ['left', 'right'];
|
||||
for (i in 0...arrowNames.length)
|
||||
{
|
||||
var xmlEndName:String = (i == 0 ? 'left' : 'right');
|
||||
var arrow:FlxSprite = new FlxSprite(0, difficulty.y - 10);
|
||||
arrow.frames = menuUITex;
|
||||
arrow.animation.addByPrefix('idle', 'arrow $xmlEndName');
|
||||
arrow.animation.addByPrefix('press', 'arrow push $xmlEndName', 24, false);
|
||||
arrow.animation.play('idle');
|
||||
grpArrows.ID = i;
|
||||
grpArrows.add(arrow);
|
||||
arrow.x = (i == 0 ? difficulty.x - 180 : difficulty.x + 300);
|
||||
FlxTween.tween(arrow, {x: (i == 0 ? arrow.x + 10 : arrow.x - 10)}, 1, {ease: FlxEase.sineInOut, type: PINGPONG});
|
||||
}
|
||||
|
||||
add(scoreText);
|
||||
|
||||
changeSelection();
|
||||
changeDiff();
|
||||
|
||||
var swag:Alphabet = new Alphabet(1, 0, "swag");
|
||||
|
||||
super.create();
|
||||
}
|
||||
|
||||
public function addSong(songName:String, weekNum:Int, songCharacter:String)
|
||||
{
|
||||
songs.push(new SongMetadata(songName, weekNum, songCharacter));
|
||||
}
|
||||
|
||||
public function addWeek(songs:Array<String>, weekNum:Int, ?songCharacters:Array<String>)
|
||||
{
|
||||
if (songCharacters == null)
|
||||
songCharacters = ['bf'];
|
||||
|
||||
var num:Int = 0;
|
||||
for (song in songs)
|
||||
{
|
||||
addSong(song, weekNum, songCharacters[num]);
|
||||
|
||||
if (songCharacters.length != 1)
|
||||
num++;
|
||||
}
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
if (FlxG.sound.music != null)
|
||||
{
|
||||
if (FlxG.sound.music.volume < 0.7)
|
||||
{
|
||||
FlxG.sound.music.volume += 0.5 * FlxG.elapsed;
|
||||
}
|
||||
}
|
||||
|
||||
if (FlxG.sound.music != null) Conductor.songPosition = FlxG.sound.music.time;
|
||||
|
||||
FlxG.camera.zoom = FlxMath.lerp(1, FlxG.camera.zoom, CoolUtil.boundTo(1 - (elapsed * 4), 0, 1));
|
||||
|
||||
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);
|
||||
|
||||
var upP = controls.UI_UP_P;
|
||||
var downP = controls.UI_DOWN_P;
|
||||
var accepted = controls.ACCEPT;
|
||||
|
||||
if (upP)
|
||||
changeSelection(-1);
|
||||
if (downP)
|
||||
changeSelection(1);
|
||||
|
||||
if (FlxG.mouse.wheel != 0)
|
||||
changeSelection(-Math.round(FlxG.mouse.wheel / 4));
|
||||
|
||||
if (controls.UI_RIGHT)
|
||||
grpArrows.members[1].animation.play('press');
|
||||
else
|
||||
grpArrows.members[1].animation.play('idle');
|
||||
|
||||
if (controls.UI_LEFT)
|
||||
grpArrows.members[0].animation.play('press');
|
||||
else
|
||||
grpArrows.members[0].animation.play('idle');
|
||||
|
||||
if (controls.UI_LEFT_P) {
|
||||
changeDiff(-1);
|
||||
}
|
||||
if (controls.UI_RIGHT_P) {
|
||||
changeDiff(1);
|
||||
}
|
||||
|
||||
if (controls.BACK)
|
||||
{
|
||||
FlxG.sound.play(Paths.sound('cancelMenu'));
|
||||
FlxG.switchState(new MainMenuState());
|
||||
}
|
||||
|
||||
if (accepted)
|
||||
{
|
||||
var poop:String = Highscore.formatSong(songs[curSelected].songName.toLowerCase(), curDifficulty);
|
||||
PlayState.SONG = Song.loadFromJson(poop, songs[curSelected].songName.toLowerCase());
|
||||
PlayState.isStoryMode = false;
|
||||
PlayState.storyDifficulty = curDifficulty;
|
||||
|
||||
PlayState.storyWeek = songs[curSelected].week;
|
||||
trace('CUR WEEK' + PlayState.storyWeek);
|
||||
LoadingState.loadAndSwitchState(new PlayState());
|
||||
}
|
||||
}
|
||||
|
||||
override function beatHit()
|
||||
{
|
||||
if (curBeat % 1 == 0) FlxG.camera.zoom += 0.015;
|
||||
super.beatHit();
|
||||
}
|
||||
|
||||
function changeDiff(change:Int = 0)
|
||||
{
|
||||
curDifficulty += change;
|
||||
|
||||
if (curDifficulty < 0)
|
||||
curDifficulty = 2;
|
||||
if (curDifficulty > 2)
|
||||
curDifficulty = 0;
|
||||
|
||||
intendedScore = Highscore.getScore(songs[curSelected].songName, curDifficulty);
|
||||
|
||||
PlayState.storyDifficulty = curDifficulty;
|
||||
|
||||
difficulty.offset.x = 0;
|
||||
switch (curDifficulty) {case 1: difficulty.offset.x = 70; case 0 | 2: difficulty.offset.x = 20;}
|
||||
difficulty.animation.play(CoolUtil.difficultyString().toLowerCase());
|
||||
}
|
||||
|
||||
function changeSelection(change:Int = 0)
|
||||
{
|
||||
FlxG.sound.play(Paths.sound('scrollMenu'), 0.4);
|
||||
|
||||
curSelected += change;
|
||||
|
||||
if (curSelected < 0)
|
||||
curSelected = songs.length - 1;
|
||||
if (curSelected >= songs.length)
|
||||
curSelected = 0;
|
||||
|
||||
intendedScore = Highscore.getScore(songs[curSelected].songName, curDifficulty);
|
||||
|
||||
#if PRELOAD_ALL
|
||||
var song = Song.loadFromJson(songs[curSelected].songName, songs[curSelected].songName);
|
||||
FlxG.sound.playMusic(Paths.inst(songs[curSelected].songName), 0);
|
||||
Conductor.changeBPM(song.bpm);
|
||||
#end
|
||||
|
||||
for (i in 0...iconArray.length) iconArray[i].visible = false;
|
||||
iconArray[curSelected].visible = true;
|
||||
|
||||
for (item in grpSongs.members) item.visible = false;
|
||||
grpSongs.members[curSelected].visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
class SongMetadata
|
||||
{
|
||||
public var songName:String = "";
|
||||
public var week:Int = 0;
|
||||
public var songCharacter:String = "";
|
||||
|
||||
public function new(song:String, week:Int, songCharacter:String)
|
||||
{
|
||||
this.songName = song;
|
||||
this.week = week;
|
||||
this.songCharacter = songCharacter;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,289 @@
|
|||
package game.state.menus;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxObject;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxState;
|
||||
import flixel.addons.transition.FlxTransitionableState;
|
||||
import flixel.effects.FlxFlicker;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.tweens.FlxEase;
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.util.FlxTimer;
|
||||
import flixel.math.FlxMath;
|
||||
import lime.app.Application;
|
||||
import game.state.*;
|
||||
import game.state.menus.*;
|
||||
import game.state.subState.*;
|
||||
import game.state.menus.options.OptionsState;
|
||||
import game.state.menus.options.PreferencesMenu;
|
||||
import game.ui.AtlasMenuList;
|
||||
import game.ui.MenuList;
|
||||
import game.ui.*;
|
||||
import game.ui.menu.*;
|
||||
import game.data.backend.Conductor;
|
||||
import game.data.backend.SwagCamera;
|
||||
|
||||
using StringTools;
|
||||
|
||||
#if discord_rpc
|
||||
import game.data.backend.Discord.DiscordClient;
|
||||
#end
|
||||
|
||||
class MainMenuState extends MusicBeatState
|
||||
{
|
||||
// var menuItems:MainMenuList;
|
||||
var menuItems:FlxTypedGroup<FlxSprite>;
|
||||
var menuOptions:Array<String> = ['story mode', 'freeplay', 'options'];
|
||||
|
||||
var curSelected:Int = 0;
|
||||
var selected:Bool = false;
|
||||
|
||||
var magenta:FlxSprite;
|
||||
var logo:FlxSprite;
|
||||
|
||||
override function create()
|
||||
{
|
||||
#if discord_rpc
|
||||
// Updating Discord Rich Presence
|
||||
DiscordClient.changePresence("In the Menus", null);
|
||||
#end
|
||||
|
||||
transIn = FlxTransitionableState.defaultTransIn;
|
||||
transOut = FlxTransitionableState.defaultTransOut;
|
||||
|
||||
if (!FlxG.sound.music.playing)
|
||||
{
|
||||
FlxG.sound.playMusic(Paths.music('freakyMenu'));
|
||||
}
|
||||
|
||||
persistentUpdate = persistentDraw = true;
|
||||
|
||||
var bg:FlxSprite = new FlxSprite(Paths.image('menuBG'));
|
||||
bg.scrollFactor.x = 0;
|
||||
bg.scrollFactor.y = 0.17;
|
||||
bg.setGraphicSize(Std.int(bg.width * 1.2));
|
||||
bg.updateHitbox();
|
||||
bg.screenCenter();
|
||||
bg.antialiasing = true;
|
||||
add(bg);
|
||||
|
||||
magenta = new FlxSprite(Paths.image('menuDesat'));
|
||||
magenta.scrollFactor.x = bg.scrollFactor.x;
|
||||
magenta.scrollFactor.y = bg.scrollFactor.y;
|
||||
magenta.setGraphicSize(Std.int(bg.width));
|
||||
magenta.updateHitbox();
|
||||
magenta.x = bg.x;
|
||||
magenta.y = bg.y;
|
||||
magenta.visible = false;
|
||||
magenta.antialiasing = true;
|
||||
magenta.color = 0xFFfd719b;
|
||||
if (PreferencesMenu.preferences.get('flashing-menu')) add(magenta);
|
||||
|
||||
// FUCK YOU FNF LOGO
|
||||
// Actually Kill Yourself
|
||||
logo = new FlxSprite(0, -130).loadGraphic(Paths.image('logo'));
|
||||
logo.screenCenter(X);
|
||||
add(logo);
|
||||
|
||||
menuItems = new FlxTypedGroup<FlxSprite>();
|
||||
add(menuItems);
|
||||
|
||||
// This took forever to get the x value right
|
||||
// the menu options kept having hard sex in front of the fnf logo every time
|
||||
var menItemTex = Paths.getSparrowAtlas('main_menu');
|
||||
for (i in 0...menuOptions.length)
|
||||
{
|
||||
var menuItem:FlxSprite = new FlxSprite(10 + (i * 500) , FlxG.height / 2 + 100);
|
||||
menuItem.frames = menItemTex;
|
||||
menuItem.animation.addByPrefix('idle', menuOptions[i] + ' idle', 24);
|
||||
menuItem.animation.addByPrefix('selected', menuOptions[i] + ' selected', 24);
|
||||
menuItem.animation.play('idle');
|
||||
menuItem.ID = i;
|
||||
// menuItem.screenCenter(Y);
|
||||
menuItems.add(menuItem);
|
||||
menuItem.scale.set(0.7, 0.7);
|
||||
menuItem.updateHitbox();
|
||||
|
||||
if (i == 1) menuItem.y += 130;
|
||||
if (i == 2) menuItem.x -= 100;
|
||||
}
|
||||
|
||||
changeOption();
|
||||
|
||||
var versionShit:FlxText = new FlxText(5, FlxG.height - 32, 0, "FNF v" + Application.current.meta.get('version'), 12);
|
||||
versionShit.scrollFactor.set();
|
||||
versionShit.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
|
||||
add(versionShit);
|
||||
|
||||
versionShit.text += '\nZyflixel Engine Dev Build (HEAVY WIP)';
|
||||
|
||||
super.create();
|
||||
}
|
||||
|
||||
public function openPrompt(prompt:Prompt, onClose:Void->Void)
|
||||
{
|
||||
// menuItems.enabled = false;
|
||||
prompt.closeCallback = function()
|
||||
{
|
||||
// menuItems.enabled = true;
|
||||
if (onClose != null)
|
||||
onClose();
|
||||
}
|
||||
|
||||
openSubState(prompt);
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (FlxG.sound.music.volume < 0.8) FlxG.sound.music.volume += 0.5 * FlxG.elapsed;
|
||||
|
||||
if (FlxG.sound.music != null) Conductor.songPosition = FlxG.sound.music.time;
|
||||
|
||||
FlxG.camera.zoom = FlxMath.lerp(1, FlxG.camera.zoom, CoolUtil.boundTo(1 - (elapsed * 4), 0, 1));
|
||||
|
||||
logo.scale.x = FlxMath.lerp(0.6, logo.scale.x, CoolUtil.boundTo(1 - (elapsed * 9), 0, 1));
|
||||
logo.scale.y = FlxMath.lerp(0.6, logo.scale.y, CoolUtil.boundTo(1 - (elapsed * 9), 0, 1));
|
||||
|
||||
if (!selected)
|
||||
{
|
||||
if (controls.UI_LEFT_P)
|
||||
{
|
||||
FlxG.sound.play(Paths.sound('scrollMenu'));
|
||||
changeOption(-1);
|
||||
}
|
||||
else if (controls.UI_RIGHT_P)
|
||||
{
|
||||
FlxG.sound.play(Paths.sound('scrollMenu'));
|
||||
changeOption(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (controls.BACK)
|
||||
{
|
||||
FlxG.sound.play(Paths.sound('cancelMenu'));
|
||||
FlxG.switchState(new TitleState());
|
||||
}
|
||||
|
||||
if (controls.ACCEPT && !selected)
|
||||
{
|
||||
selected = true;
|
||||
FlxG.sound.play(Paths.sound('confirmMenu'));
|
||||
FlxFlicker.flicker(magenta, 1.1, 0.15, false, true);
|
||||
|
||||
menuItems.forEach(function(spr:FlxSprite)
|
||||
{
|
||||
if (curSelected != spr.ID)
|
||||
{
|
||||
FlxTween.tween(spr, {alpha: 0}, 0.4, {ease: FlxEase.quadOut,
|
||||
onComplete: function(twn:FlxTween)
|
||||
{
|
||||
spr.kill();
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
FlxFlicker.flicker(spr, 1, 0.06, true, false, function(flicker:FlxFlicker)
|
||||
{
|
||||
var options:String = menuOptions[curSelected];
|
||||
|
||||
switch (options)
|
||||
{
|
||||
case 'story mode':
|
||||
FlxG.switchState(new StoryMenuState());
|
||||
case 'freeplay':
|
||||
FlxG.switchState(new FreeplayState());
|
||||
case 'options':
|
||||
FlxG.switchState(new OptionsState());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
override function beatHit()
|
||||
{
|
||||
if (curBeat % 2 == 0) {
|
||||
FlxG.camera.zoom += 0.015;
|
||||
logo.scale.set(0.7, 0.7);
|
||||
}
|
||||
super.beatHit();
|
||||
}
|
||||
|
||||
function changeOption(num:Int = 0)
|
||||
{
|
||||
curSelected += num;
|
||||
if (curSelected < 0)
|
||||
curSelected = menuItems.length - 1;
|
||||
else if (curSelected >= menuItems.length)
|
||||
curSelected = 0;
|
||||
|
||||
menuItems.forEach(function(item:FlxSprite)
|
||||
{
|
||||
item.offset.x = 0;
|
||||
item.animation.play('idle');
|
||||
item.updateHitbox();
|
||||
|
||||
if (item.ID == curSelected)
|
||||
{
|
||||
item.animation.play('selected');
|
||||
switch (item.ID)
|
||||
{
|
||||
case 0: item.offset.x = 100;
|
||||
case 1: item.offset.x = 130;
|
||||
case 2: item.offset.x = 130;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*private class MainMenuList extends MenuTypedList<MainMenuItem>
|
||||
{
|
||||
public var atlas:FlxAtlasFrames;
|
||||
|
||||
public function new()
|
||||
{
|
||||
atlas = Paths.getSparrowAtlas('main_menu');
|
||||
super(Vertical);
|
||||
}
|
||||
|
||||
public function createItem(x = 0.0, y = 0.0, name:String, callback, fireInstantly = false)
|
||||
{
|
||||
var item = new MainMenuItem(x, y, name, atlas, callback);
|
||||
item.fireInstantly = fireInstantly;
|
||||
item.ID = length;
|
||||
|
||||
return addItem(name, item);
|
||||
}
|
||||
|
||||
override function destroy()
|
||||
{
|
||||
super.destroy();
|
||||
atlas = null;
|
||||
}
|
||||
}
|
||||
|
||||
private class MainMenuItem extends AtlasMenuItem
|
||||
{
|
||||
public function new(x = 0.0, y = 0.0, name, atlas, callback)
|
||||
{
|
||||
super(x, y, name, atlas, callback);
|
||||
scrollFactor.set();
|
||||
}
|
||||
|
||||
override function changeAnim(anim:String)
|
||||
{
|
||||
super.changeAnim(anim);
|
||||
// position by center
|
||||
centerOrigin();
|
||||
offset.copyFrom(origin);
|
||||
}
|
||||
}*/
|
|
@ -0,0 +1,451 @@
|
|||
package game.state.menus;
|
||||
|
||||
#if discord_rpc
|
||||
import game.data.backend.Discord.DiscordClient;
|
||||
#end
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.addons.transition.FlxTransitionableState;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.group.FlxGroup;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.util.FlxTimer;
|
||||
import lime.net.curl.CURLCode;
|
||||
|
||||
import game.ui.menu.*;
|
||||
import game.data.backend.Highscore;
|
||||
import game.data.backend.Song;
|
||||
|
||||
|
||||
using StringTools;
|
||||
|
||||
class StoryMenuState extends MusicBeatState
|
||||
{
|
||||
var scoreText:FlxText;
|
||||
|
||||
var weekData:Array<Dynamic> = [
|
||||
['Tutorial'],
|
||||
['Bopeebo', 'Fresh', 'Dadbattle'],
|
||||
['Spookeez', 'South', "Monster"],
|
||||
['Pico', 'Philly', "Blammed"],
|
||||
['Satin-Panties', "High", "Milf"],
|
||||
['Cocoa', 'Eggnog', 'Winter-Horrorland'],
|
||||
['Senpai', 'Roses', 'Thorns'],
|
||||
['Ugh', 'Guns', 'Stress']
|
||||
];
|
||||
var curDifficulty:Int = 1;
|
||||
|
||||
public static var weekUnlocked:Array<Bool> = [true, true, true, true, true, true, true, true];
|
||||
|
||||
var weekCharacters:Array<Dynamic> = [
|
||||
['dad', 'bf', 'gf'],
|
||||
['dad', 'bf', 'gf'],
|
||||
['spooky', 'bf', 'gf'],
|
||||
['pico', 'bf', 'gf'],
|
||||
['mom', 'bf', 'gf'],
|
||||
['parents-christmas', 'bf', 'gf'],
|
||||
['senpai', 'bf', 'gf'],
|
||||
['tankman', 'bf', 'gf']
|
||||
];
|
||||
|
||||
var weekNames:Array<String> = [
|
||||
"",
|
||||
"Daddy Dearest",
|
||||
"Spooky Month",
|
||||
"PICO",
|
||||
"MOMMY MUST MURDER",
|
||||
"RED SNOW",
|
||||
"hating simulator ft. moawling",
|
||||
"TANKMAN"
|
||||
];
|
||||
|
||||
var txtWeekTitle:FlxText;
|
||||
|
||||
var curWeek:Int = 0;
|
||||
|
||||
var txtTracklist:FlxText;
|
||||
|
||||
var grpWeekText:FlxTypedGroup<MenuItem>;
|
||||
var grpWeekCharacters:FlxTypedGroup<MenuCharacter>;
|
||||
|
||||
var grpLocks:FlxTypedGroup<FlxSprite>;
|
||||
|
||||
var difficultySelectors:FlxGroup;
|
||||
var sprDifficulty:FlxSprite;
|
||||
var leftArrow:FlxSprite;
|
||||
var rightArrow:FlxSprite;
|
||||
|
||||
override function create()
|
||||
{
|
||||
transIn = FlxTransitionableState.defaultTransIn;
|
||||
transOut = FlxTransitionableState.defaultTransOut;
|
||||
|
||||
if (FlxG.sound.music != null)
|
||||
{
|
||||
if (!FlxG.sound.music.playing)
|
||||
FlxG.sound.playMusic(Paths.music('freakyMenu'));
|
||||
}
|
||||
|
||||
persistentUpdate = persistentDraw = true;
|
||||
|
||||
scoreText = new FlxText(10, 10, 0, "SCORE: 49324858", 36);
|
||||
scoreText.setFormat("VCR OSD Mono", 32);
|
||||
|
||||
txtWeekTitle = new FlxText(FlxG.width * 0.7, 10, 0, "", 32);
|
||||
txtWeekTitle.setFormat("VCR OSD Mono", 32, FlxColor.WHITE, RIGHT);
|
||||
txtWeekTitle.alpha = 0.7;
|
||||
|
||||
var rankText:FlxText = new FlxText(0, 10);
|
||||
rankText.text = 'RANK: GREAT';
|
||||
rankText.setFormat(Paths.font("vcr.ttf"), 32);
|
||||
rankText.size = scoreText.size;
|
||||
rankText.screenCenter(X);
|
||||
|
||||
var ui_tex = Paths.getSparrowAtlas('campaign_menu_UI_assets');
|
||||
var yellowBG:FlxSprite = new FlxSprite(0, 56).makeGraphic(FlxG.width, 400, 0xFFF9CF51);
|
||||
|
||||
grpWeekText = new FlxTypedGroup<MenuItem>();
|
||||
add(grpWeekText);
|
||||
|
||||
var blackBarThingie:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, 56, FlxColor.BLACK);
|
||||
add(blackBarThingie);
|
||||
|
||||
grpWeekCharacters = new FlxTypedGroup<MenuCharacter>();
|
||||
|
||||
grpLocks = new FlxTypedGroup<FlxSprite>();
|
||||
add(grpLocks);
|
||||
|
||||
trace("Line 70");
|
||||
|
||||
#if discord_rpc
|
||||
// Updating Discord Rich Presence
|
||||
DiscordClient.changePresence("In the Menus", null);
|
||||
#end
|
||||
|
||||
for (i in 0...weekData.length)
|
||||
{
|
||||
var weekThing:MenuItem = new MenuItem(0, yellowBG.y + yellowBG.height + 10, i);
|
||||
weekThing.y += ((weekThing.height + 20) * i);
|
||||
weekThing.targetY = i;
|
||||
grpWeekText.add(weekThing);
|
||||
|
||||
weekThing.screenCenter(X);
|
||||
weekThing.antialiasing = true;
|
||||
// weekThing.updateHitbox();
|
||||
|
||||
// Needs an offset thingie
|
||||
if (!weekUnlocked[i])
|
||||
{
|
||||
var lock:FlxSprite = new FlxSprite(weekThing.width + 10 + weekThing.x);
|
||||
lock.frames = ui_tex;
|
||||
lock.animation.addByPrefix('lock', 'lock');
|
||||
lock.animation.play('lock');
|
||||
lock.ID = i;
|
||||
lock.antialiasing = true;
|
||||
grpLocks.add(lock);
|
||||
}
|
||||
}
|
||||
|
||||
trace("Line 96");
|
||||
|
||||
for (char in 0...3)
|
||||
{
|
||||
var weekCharacterThing:MenuCharacter = new MenuCharacter((FlxG.width * 0.25) * (1 + char) - 150, weekCharacters[curWeek][char]);
|
||||
weekCharacterThing.y += 70;
|
||||
weekCharacterThing.antialiasing = true;
|
||||
switch (weekCharacterThing.character)
|
||||
{
|
||||
case 'dad':
|
||||
weekCharacterThing.setGraphicSize(Std.int(weekCharacterThing.width * 0.5));
|
||||
weekCharacterThing.updateHitbox();
|
||||
|
||||
case 'bf':
|
||||
weekCharacterThing.setGraphicSize(Std.int(weekCharacterThing.width * 0.9));
|
||||
weekCharacterThing.updateHitbox();
|
||||
weekCharacterThing.x -= 80;
|
||||
case 'gf':
|
||||
weekCharacterThing.setGraphicSize(Std.int(weekCharacterThing.width * 0.5));
|
||||
weekCharacterThing.updateHitbox();
|
||||
case 'pico':
|
||||
weekCharacterThing.flipX = true;
|
||||
case 'parents-christmas':
|
||||
weekCharacterThing.setGraphicSize(Std.int(weekCharacterThing.width * 0.9));
|
||||
weekCharacterThing.updateHitbox();
|
||||
}
|
||||
|
||||
grpWeekCharacters.add(weekCharacterThing);
|
||||
}
|
||||
|
||||
difficultySelectors = new FlxGroup();
|
||||
add(difficultySelectors);
|
||||
|
||||
trace("Line 124");
|
||||
|
||||
leftArrow = new FlxSprite(grpWeekText.members[0].x + grpWeekText.members[0].width + 10, grpWeekText.members[0].y + 10);
|
||||
leftArrow.frames = ui_tex;
|
||||
leftArrow.animation.addByPrefix('idle', "arrow left");
|
||||
leftArrow.animation.addByPrefix('press', "arrow push left");
|
||||
leftArrow.animation.play('idle');
|
||||
difficultySelectors.add(leftArrow);
|
||||
|
||||
sprDifficulty = new FlxSprite(leftArrow.x + 130, leftArrow.y);
|
||||
sprDifficulty.frames = ui_tex;
|
||||
sprDifficulty.animation.addByPrefix('easy', 'EASY');
|
||||
sprDifficulty.animation.addByPrefix('normal', 'NORMAL');
|
||||
sprDifficulty.animation.addByPrefix('hard', 'HARD');
|
||||
sprDifficulty.animation.play('easy');
|
||||
changeDifficulty();
|
||||
|
||||
difficultySelectors.add(sprDifficulty);
|
||||
|
||||
rightArrow = new FlxSprite(sprDifficulty.x + sprDifficulty.width + 50, leftArrow.y);
|
||||
rightArrow.frames = ui_tex;
|
||||
rightArrow.animation.addByPrefix('idle', 'arrow right');
|
||||
rightArrow.animation.addByPrefix('press', "arrow push right", 24, false);
|
||||
rightArrow.animation.play('idle');
|
||||
difficultySelectors.add(rightArrow);
|
||||
|
||||
trace("Line 150");
|
||||
|
||||
add(yellowBG);
|
||||
add(grpWeekCharacters);
|
||||
|
||||
txtTracklist = new FlxText(FlxG.width * 0.05, yellowBG.x + yellowBG.height + 100, 0, "Tracks", 32);
|
||||
txtTracklist.alignment = CENTER;
|
||||
txtTracklist.font = rankText.font;
|
||||
txtTracklist.color = 0xFFe55777;
|
||||
add(txtTracklist);
|
||||
// add(rankText);
|
||||
add(scoreText);
|
||||
add(txtWeekTitle);
|
||||
|
||||
updateText();
|
||||
|
||||
trace("Line 165");
|
||||
|
||||
super.create();
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
// scoreText.setFormat('VCR OSD Mono', 32);
|
||||
lerpScore = CoolUtil.coolLerp(lerpScore, intendedScore, 0.5);
|
||||
|
||||
scoreText.text = "WEEK SCORE:" + Math.round(lerpScore);
|
||||
|
||||
txtWeekTitle.text = weekNames[curWeek].toUpperCase();
|
||||
txtWeekTitle.x = FlxG.width - (txtWeekTitle.width + 10);
|
||||
|
||||
// FlxG.watch.addQuick('font', scoreText.font);
|
||||
|
||||
difficultySelectors.visible = weekUnlocked[curWeek];
|
||||
|
||||
grpLocks.forEach(function(lock:FlxSprite)
|
||||
{
|
||||
lock.y = grpWeekText.members[lock.ID].y;
|
||||
});
|
||||
|
||||
if (!movedBack)
|
||||
{
|
||||
if (!selectedWeek)
|
||||
{
|
||||
if (controls.UI_UP_P)
|
||||
{
|
||||
changeWeek(-1);
|
||||
}
|
||||
|
||||
if (controls.UI_DOWN_P)
|
||||
{
|
||||
changeWeek(1);
|
||||
}
|
||||
|
||||
if (controls.UI_RIGHT)
|
||||
rightArrow.animation.play('press')
|
||||
else
|
||||
rightArrow.animation.play('idle');
|
||||
|
||||
if (controls.UI_LEFT)
|
||||
leftArrow.animation.play('press');
|
||||
else
|
||||
leftArrow.animation.play('idle');
|
||||
|
||||
if (controls.UI_RIGHT_P)
|
||||
changeDifficulty(1);
|
||||
if (controls.UI_LEFT_P)
|
||||
changeDifficulty(-1);
|
||||
}
|
||||
|
||||
if (controls.ACCEPT)
|
||||
{
|
||||
selectWeek();
|
||||
}
|
||||
}
|
||||
|
||||
if (controls.BACK && !movedBack && !selectedWeek)
|
||||
{
|
||||
FlxG.sound.play(Paths.sound('cancelMenu'));
|
||||
movedBack = true;
|
||||
FlxG.switchState(new MainMenuState());
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
var movedBack:Bool = false;
|
||||
var selectedWeek:Bool = false;
|
||||
var stopspamming:Bool = false;
|
||||
|
||||
function selectWeek()
|
||||
{
|
||||
if (weekUnlocked[curWeek])
|
||||
{
|
||||
if (stopspamming == false)
|
||||
{
|
||||
FlxG.sound.play(Paths.sound('confirmMenu'));
|
||||
|
||||
grpWeekText.members[curWeek].startFlashing();
|
||||
grpWeekCharacters.members[1].animation.play('bfConfirm');
|
||||
stopspamming = true;
|
||||
}
|
||||
|
||||
PlayState.storyPlaylist = weekData[curWeek];
|
||||
PlayState.isStoryMode = true;
|
||||
selectedWeek = true;
|
||||
|
||||
var diffic = "";
|
||||
|
||||
switch (curDifficulty)
|
||||
{
|
||||
case 0:
|
||||
diffic = '-easy';
|
||||
case 2:
|
||||
diffic = '-hard';
|
||||
}
|
||||
|
||||
PlayState.storyDifficulty = curDifficulty;
|
||||
|
||||
PlayState.SONG = Song.loadFromJson(PlayState.storyPlaylist[0].toLowerCase() + diffic, PlayState.storyPlaylist[0].toLowerCase());
|
||||
PlayState.storyWeek = curWeek;
|
||||
PlayState.campaignScore = 0;
|
||||
new FlxTimer().start(1, function(tmr:FlxTimer)
|
||||
{
|
||||
LoadingState.loadAndSwitchState(new PlayState(), true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function changeDifficulty(change:Int = 0):Void
|
||||
{
|
||||
curDifficulty += change;
|
||||
|
||||
if (curDifficulty < 0)
|
||||
curDifficulty = 2;
|
||||
if (curDifficulty > 2)
|
||||
curDifficulty = 0;
|
||||
|
||||
sprDifficulty.offset.x = 0;
|
||||
|
||||
switch (curDifficulty)
|
||||
{
|
||||
case 0:
|
||||
sprDifficulty.animation.play('easy');
|
||||
sprDifficulty.offset.x = 20;
|
||||
case 1:
|
||||
sprDifficulty.animation.play('normal');
|
||||
sprDifficulty.offset.x = 70;
|
||||
case 2:
|
||||
sprDifficulty.animation.play('hard');
|
||||
sprDifficulty.offset.x = 20;
|
||||
}
|
||||
|
||||
sprDifficulty.alpha = 0;
|
||||
|
||||
// USING THESE WEIRD VALUES SO THAT IT DOESNT FLOAT UP
|
||||
sprDifficulty.y = leftArrow.y - 15;
|
||||
intendedScore = Highscore.getWeekScore(curWeek, curDifficulty);
|
||||
|
||||
FlxTween.tween(sprDifficulty, {y: leftArrow.y + 15, alpha: 1}, 0.07);
|
||||
}
|
||||
|
||||
var lerpScore:Float = 0;
|
||||
var intendedScore:Int = 0;
|
||||
|
||||
function changeWeek(change:Int = 0):Void
|
||||
{
|
||||
curWeek += change;
|
||||
|
||||
if (curWeek >= weekData.length)
|
||||
curWeek = 0;
|
||||
if (curWeek < 0)
|
||||
curWeek = weekData.length - 1;
|
||||
|
||||
var bullShit:Int = 0;
|
||||
|
||||
for (item in grpWeekText.members)
|
||||
{
|
||||
item.targetY = bullShit - curWeek;
|
||||
if (item.targetY == Std.int(0) && weekUnlocked[curWeek])
|
||||
item.alpha = 1;
|
||||
else
|
||||
item.alpha = 0.6;
|
||||
bullShit++;
|
||||
}
|
||||
|
||||
FlxG.sound.play(Paths.sound('scrollMenu'));
|
||||
|
||||
updateText();
|
||||
}
|
||||
|
||||
function updateText()
|
||||
{
|
||||
grpWeekCharacters.members[0].animation.play(weekCharacters[curWeek][0]);
|
||||
grpWeekCharacters.members[1].animation.play(weekCharacters[curWeek][1]);
|
||||
grpWeekCharacters.members[2].animation.play(weekCharacters[curWeek][2]);
|
||||
txtTracklist.text = "Tracks\n";
|
||||
|
||||
switch (grpWeekCharacters.members[0].animation.curAnim.name)
|
||||
{
|
||||
case 'parents-christmas':
|
||||
grpWeekCharacters.members[0].offset.set(200, 200);
|
||||
grpWeekCharacters.members[0].setGraphicSize(Std.int(grpWeekCharacters.members[0].width * 0.99));
|
||||
|
||||
case 'senpai':
|
||||
grpWeekCharacters.members[0].offset.set(130, 0);
|
||||
grpWeekCharacters.members[0].setGraphicSize(Std.int(grpWeekCharacters.members[0].width * 1.4));
|
||||
|
||||
case 'mom':
|
||||
grpWeekCharacters.members[0].offset.set(100, 200);
|
||||
grpWeekCharacters.members[0].setGraphicSize(Std.int(grpWeekCharacters.members[0].width * 1));
|
||||
|
||||
case 'dad':
|
||||
grpWeekCharacters.members[0].offset.set(120, 200);
|
||||
grpWeekCharacters.members[0].setGraphicSize(Std.int(grpWeekCharacters.members[0].width * 1));
|
||||
case 'tankman':
|
||||
grpWeekCharacters.members[0].offset.set(60, -20);
|
||||
grpWeekCharacters.members[0].setGraphicSize(Std.int(grpWeekCharacters.members[0].width * 1));
|
||||
|
||||
default:
|
||||
grpWeekCharacters.members[0].offset.set(100, 100);
|
||||
grpWeekCharacters.members[0].setGraphicSize(Std.int(grpWeekCharacters.members[0].width * 1));
|
||||
// grpWeekCharacters.members[0].updateHitbox();
|
||||
}
|
||||
|
||||
var stringThing:Array<String> = weekData[curWeek];
|
||||
|
||||
for (i in stringThing)
|
||||
{
|
||||
txtTracklist.text += "\n" + i;
|
||||
}
|
||||
|
||||
txtTracklist.text = txtTracklist.text.toUpperCase();
|
||||
|
||||
txtTracklist.screenCenter(X);
|
||||
txtTracklist.x -= FlxG.width * 0.35;
|
||||
|
||||
intendedScore = Highscore.getWeekScore(curWeek, curDifficulty);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,543 @@
|
|||
package game.state.menus;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxGame;
|
||||
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.group.FlxGroup;
|
||||
import flixel.input.gamepad.FlxGamepad;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.system.FlxAssets.FlxGraphicAsset;
|
||||
import flixel.system.FlxAssets;
|
||||
import flixel.tweens.FlxEase;
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.util.FlxTimer;
|
||||
import lime.app.Application;
|
||||
import lime.ui.Window;
|
||||
import openfl.Assets;
|
||||
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 game.objects.shaders.BuildingShaders.BuildingShader;
|
||||
import game.objects.shaders.BuildingShaders;
|
||||
import game.objects.shaders.ColorSwap;
|
||||
import game.state.menus.options.*;
|
||||
import game.state.*;
|
||||
import game.state.subState.*;
|
||||
import game.state.menus.*;
|
||||
import game.state.charting.*;
|
||||
import game.objects.cutscene.*;
|
||||
import game.data.*;
|
||||
import game.data.backend.*;
|
||||
import game.ui.*;
|
||||
|
||||
using StringTools;
|
||||
|
||||
#if discord_rpc
|
||||
import game.data.backend.Discord.DiscordClient;
|
||||
#end
|
||||
#if desktop
|
||||
import sys.FileSystem;
|
||||
import sys.io.File;
|
||||
import sys.thread.Thread;
|
||||
#end
|
||||
|
||||
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;
|
||||
private var overlay:Sprite;
|
||||
|
||||
// Note: If you are adding songs to the game, make sure you add the songs here
|
||||
var gameSongs:Array<String> = [
|
||||
'test', 'tutorial', 'bopeebo', 'fresh', 'dadbattle', 'spookeez', 'south', 'monster',
|
||||
'pico', 'philly', 'blammed', 'satin-panties', 'high', 'milf', 'cocoa', 'eggnog', 'winter-horrorland',
|
||||
'senpai', 'roses', 'thorns', 'ugh', 'guns', 'stress'];
|
||||
|
||||
override public function create():Void
|
||||
{
|
||||
#if polymod
|
||||
// polymod.Polymod.init({modRoot: "mods", dirs: ['introMod'], framework: OPENFL});
|
||||
// FlxG.bitmap.clearCache();
|
||||
#end
|
||||
|
||||
// A Cache State Will Be Added Soon but this is just so that
|
||||
// the game doesn't lag when you go up or down an option in freeplay
|
||||
// when hovering over it for the first time
|
||||
cacheSongs();
|
||||
|
||||
startedIntro = false;
|
||||
|
||||
FlxG.game.focusLostFramerate = 60;
|
||||
|
||||
swagShader = new ColorSwap();
|
||||
alphaShader = new BuildingShaders();
|
||||
|
||||
FlxG.sound.muteKeys = [ZERO];
|
||||
|
||||
curWacky = FlxG.random.getObject(getIntroTextShit());
|
||||
|
||||
// DEBUG BULLSHIT
|
||||
|
||||
super.create();
|
||||
|
||||
FlxG.save.bind('funkin', 'ninjamuffin99');
|
||||
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 CutsceneAnimTestState());
|
||||
#elseif CHARTING
|
||||
FlxG.switchState(new ChartingState());
|
||||
#else
|
||||
new FlxTimer().start(1, function(tmr:FlxTimer)
|
||||
{
|
||||
startIntro();
|
||||
});
|
||||
#end
|
||||
|
||||
#if discord_rpc
|
||||
DiscordClient.initialize();
|
||||
|
||||
Application.current.onExit.add(function(exitCode)
|
||||
{
|
||||
DiscordClient.shutdown();
|
||||
});
|
||||
#end
|
||||
}
|
||||
|
||||
private function client_onMetaData(metaData:Dynamic)
|
||||
{
|
||||
video.attachNetStream(netStream);
|
||||
|
||||
video.width = video.videoWidth;
|
||||
video.height = video.videoHeight;
|
||||
// video.
|
||||
}
|
||||
|
||||
private function netStream_onAsyncError(event:AsyncErrorEvent):Void
|
||||
{
|
||||
trace("Error loading video");
|
||||
}
|
||||
|
||||
private function netConnection_onNetStatus(event:NetStatusEvent):Void
|
||||
{
|
||||
if (event.info.code == 'NetStream.Play.Complete')
|
||||
{
|
||||
// netStream.dispose();
|
||||
// FlxG.stage.removeChild(video);
|
||||
|
||||
startIntro();
|
||||
}
|
||||
|
||||
trace(event.toString());
|
||||
}
|
||||
|
||||
private function overlay_onMouseDown(event:MouseEvent):Void
|
||||
{
|
||||
netStream.soundTransform.volume = 0.2;
|
||||
netStream.soundTransform.pan = -1;
|
||||
// netStream.play(Paths.file('music/kickstarterTrailer.mp4'));
|
||||
|
||||
FlxG.stage.removeChild(overlay);
|
||||
}
|
||||
|
||||
var logoBl:FlxSprite;
|
||||
|
||||
var gfDance:FlxSprite;
|
||||
var danceLeft:Bool = false;
|
||||
var titleText:FlxSprite;
|
||||
|
||||
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);
|
||||
FlxG.sound.music.fadeIn(4, 0, 0.7);
|
||||
}
|
||||
|
||||
Conductor.changeBPM(102);
|
||||
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);
|
||||
logoBl.frames = Paths.getSparrowAtlas('logoBumpin');
|
||||
logoBl.antialiasing = true;
|
||||
logoBl.animation.addByPrefix('bump', 'logo bumpin', 24);
|
||||
logoBl.animation.play('bump');
|
||||
|
||||
logoBl.updateHitbox();
|
||||
|
||||
logoBl.shader = swagShader.shader;
|
||||
// logoBl.shader = alphaShader.shader;
|
||||
|
||||
// trace();
|
||||
// logoBl.screenCenter();
|
||||
// logoBl.color = FlxColor.BLACK;
|
||||
|
||||
gfDance = new FlxSprite(FlxG.width * 0.4, FlxG.height * 0.07);
|
||||
gfDance.frames = Paths.getSparrowAtlas('gfDanceTitle');
|
||||
gfDance.animation.addByIndices('danceLeft', 'gfDance', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
|
||||
gfDance.animation.addByIndices('danceRight', 'gfDance', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
|
||||
gfDance.antialiasing = true;
|
||||
add(gfDance);
|
||||
|
||||
gfDance.shader = swagShader.shader;
|
||||
|
||||
add(logoBl);
|
||||
|
||||
titleText = new FlxSprite(100, FlxG.height * 0.8);
|
||||
titleText.frames = Paths.getSparrowAtlas('titleEnter');
|
||||
titleText.animation.addByPrefix('idle', "Press Enter to Begin", 24);
|
||||
titleText.animation.addByPrefix('press', "ENTER PRESSED", 24);
|
||||
titleText.antialiasing = true;
|
||||
titleText.animation.play('idle');
|
||||
titleText.updateHitbox();
|
||||
// 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});
|
||||
|
||||
credGroup = new FlxGroup();
|
||||
add(credGroup);
|
||||
textGroup = new FlxGroup();
|
||||
|
||||
blackScreen = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
|
||||
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).loadGraphic(Paths.image('newgrounds_logo'));
|
||||
add(ngSpr);
|
||||
ngSpr.visible = false;
|
||||
ngSpr.setGraphicSize(Std.int(ngSpr.width * 0.8));
|
||||
ngSpr.updateHitbox();
|
||||
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)
|
||||
skipIntro();
|
||||
else
|
||||
initialized = true;
|
||||
|
||||
if (FlxG.sound.music != null)
|
||||
FlxG.sound.music.onComplete = function() FlxG.switchState(new VideoState());
|
||||
|
||||
startedIntro = true;
|
||||
// credGroup.add(credTextShit);
|
||||
}
|
||||
|
||||
function getIntroTextShit():Array<Array<String>>
|
||||
{
|
||||
var fullText:String = Assets.getText(Paths.txt('introText'));
|
||||
|
||||
var firstArray:Array<String> = fullText.split('\n');
|
||||
var swagGoodArray:Array<Array<String>> = [];
|
||||
|
||||
for (i in firstArray)
|
||||
{
|
||||
swagGoodArray.push(i.split('--'));
|
||||
}
|
||||
|
||||
return swagGoodArray;
|
||||
}
|
||||
|
||||
var transitioning:Bool = false;
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
#if debug
|
||||
if (FlxG.keys.justPressed.EIGHT)
|
||||
FlxG.switchState(new CutsceneAnimTestState());
|
||||
#end
|
||||
|
||||
if (FlxG.sound.music != null) Conductor.songPosition = FlxG.sound.music.time;
|
||||
if (FlxG.keys.justPressed.F) FlxG.fullscreen = !FlxG.fullscreen;
|
||||
|
||||
FlxG.camera.zoom = FlxMath.lerp(1, FlxG.camera.zoom, CoolUtil.boundTo(1 - (elapsed * 4), 0, 1));
|
||||
|
||||
var pressedEnter:Bool = FlxG.keys.justPressed.ENTER;
|
||||
|
||||
#if mobile
|
||||
for (touch in FlxG.touches.list)
|
||||
{
|
||||
if (touch.justPressed)
|
||||
pressedEnter = true;
|
||||
}
|
||||
#end
|
||||
|
||||
var gamepad:FlxGamepad = FlxG.gamepads.lastActive;
|
||||
|
||||
if (gamepad != null)
|
||||
{
|
||||
if (gamepad.justPressed.START)
|
||||
pressedEnter = true;
|
||||
|
||||
#if switch
|
||||
if (gamepad.justPressed.B)
|
||||
pressedEnter = true;
|
||||
#end
|
||||
}
|
||||
|
||||
if (pressedEnter && !transitioning && skippedIntro)
|
||||
{
|
||||
if (FlxG.sound.music != null)
|
||||
FlxG.sound.music.onComplete = null;
|
||||
// netStream.play(Paths.file('music/kickstarterTrailer.mp4'));
|
||||
// NGio.unlockMedal(60960);
|
||||
|
||||
// If it's Friday according to da clock
|
||||
if (Date.now().getDay() == 5)
|
||||
// NGio.unlockMedal(61034);
|
||||
|
||||
titleText.animation.play('press');
|
||||
|
||||
FlxG.camera.flash(FlxColor.WHITE, 1);
|
||||
FlxG.sound.play(Paths.sound('confirmMenu'), 0.7);
|
||||
|
||||
transitioning = true;
|
||||
// FlxG.sound.music.stop();
|
||||
|
||||
FlxG.switchState(new MainMenuState());
|
||||
// FlxG.sound.play(Paths.music('titleShoot'), 0.7);
|
||||
}
|
||||
|
||||
if (pressedEnter && !skippedIntro && initialized) skipIntro();
|
||||
|
||||
if (controls.UI_LEFT) swagShader.update(-elapsed * 0.1);
|
||||
|
||||
if (controls.UI_RIGHT) swagShader.update(elapsed * 0.1);
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
function createCoolText(textArray:Array<String>)
|
||||
{
|
||||
for (i in 0...textArray.length)
|
||||
{
|
||||
var money:Alphabet = new Alphabet(0, 0, textArray[i], true, false);
|
||||
money.screenCenter(X);
|
||||
money.y += (i * 60) + 200;
|
||||
credGroup.add(money);
|
||||
textGroup.add(money);
|
||||
}
|
||||
}
|
||||
|
||||
function addMoreText(text:String)
|
||||
{
|
||||
var coolText:Alphabet = new Alphabet(0, 0, text, true, false);
|
||||
coolText.screenCenter(X);
|
||||
coolText.y += (textGroup.length * 60) + 200;
|
||||
credGroup.add(coolText);
|
||||
textGroup.add(coolText);
|
||||
}
|
||||
|
||||
function deleteCoolText()
|
||||
{
|
||||
while (textGroup.members.length > 0)
|
||||
{
|
||||
credGroup.remove(textGroup.members[0], true);
|
||||
textGroup.remove(textGroup.members[0], true);
|
||||
}
|
||||
}
|
||||
|
||||
var isRainbow:Bool = false;
|
||||
|
||||
override function beatHit()
|
||||
{
|
||||
super.beatHit();
|
||||
|
||||
if (!startedIntro)
|
||||
return;
|
||||
|
||||
if (curBeat % 1 == 0) FlxG.camera.zoom += 0.015;
|
||||
|
||||
if (skippedIntro)
|
||||
{
|
||||
logoBl.animation.play('bump', true);
|
||||
|
||||
danceLeft = !danceLeft;
|
||||
var anim:String = danceLeft ? 'danceRight' : 'danceLeft';
|
||||
gfDance.animation.play(anim);
|
||||
}
|
||||
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)
|
||||
{
|
||||
remove(ngSpr);
|
||||
|
||||
FlxG.camera.flash(FlxColor.WHITE, 4);
|
||||
remove(credGroup);
|
||||
skippedIntro = true;
|
||||
}
|
||||
}
|
||||
|
||||
function cacheSongs()
|
||||
{
|
||||
for (songs in gameSongs)
|
||||
{
|
||||
if (Assets.exists(Paths.inst(songs)))
|
||||
{
|
||||
FlxG.sound.cache(Paths.inst(songs));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package game.state.menus.options;
|
||||
|
||||
class Options
|
||||
{
|
||||
public static var masterVolume:Float = 1;
|
||||
}
|
|
@ -0,0 +1,288 @@
|
|||
package game.state.menus.options;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxSubState;
|
||||
import flixel.addons.transition.FlxTransitionableState;
|
||||
import flixel.group.FlxGroup;
|
||||
import flixel.util.FlxSignal;
|
||||
|
||||
import game.state.subState.*;
|
||||
import game.state.menus.options.controls.*;
|
||||
import game.data.PlayerSettings;
|
||||
import game.ui.TextMenuList;
|
||||
import game.ui.ModMenu;
|
||||
|
||||
// typedef OptionsState = OptionsMenu_old;
|
||||
// class OptionsState_new extends MusicBeatState
|
||||
class OptionsState extends MusicBeatState
|
||||
{
|
||||
var pages = new Map<PageName, Page>();
|
||||
var currentName:PageName = Options;
|
||||
var currentPage(get, never):Page;
|
||||
|
||||
inline function get_currentPage()
|
||||
return pages[currentName];
|
||||
|
||||
override function create()
|
||||
{
|
||||
var menuBG = new FlxSprite().loadGraphic(Paths.image('menuDesat'));
|
||||
menuBG.color = 0xFFea71fd;
|
||||
menuBG.setGraphicSize(Std.int(menuBG.width * 1.1));
|
||||
menuBG.updateHitbox();
|
||||
menuBG.screenCenter();
|
||||
menuBG.scrollFactor.set(0, 0);
|
||||
add(menuBG);
|
||||
|
||||
var options = addPage(Options, new OptionsMenu(false));
|
||||
var preferences = addPage(Preferences, new PreferencesMenu());
|
||||
var controls = addPage(Controls, new ControlsMenu());
|
||||
// var colors = addPage(Colors, new ColorsMenu());
|
||||
|
||||
#if cpp
|
||||
var mods = addPage(Mods, new ModMenu());
|
||||
#end
|
||||
|
||||
if (options.hasMultipleOptions())
|
||||
{
|
||||
options.onExit.add(exitToMainMenu);
|
||||
controls.onExit.add(switchPage.bind(Options));
|
||||
// colors.onExit.add(switchPage.bind(Options));
|
||||
preferences.onExit.add(switchPage.bind(Options));
|
||||
|
||||
#if cpp
|
||||
mods.onExit.add(switchPage.bind(Options));
|
||||
#end
|
||||
}
|
||||
else
|
||||
{
|
||||
// No need to show Options page
|
||||
controls.onExit.add(exitToMainMenu);
|
||||
setPage(Controls);
|
||||
}
|
||||
|
||||
// disable for intro transition
|
||||
currentPage.enabled = false;
|
||||
super.create();
|
||||
}
|
||||
|
||||
function addPage<T:Page>(name:PageName, page:T)
|
||||
{
|
||||
page.onSwitch.add(switchPage);
|
||||
pages[name] = page;
|
||||
add(page);
|
||||
page.exists = currentName == name;
|
||||
return page;
|
||||
}
|
||||
|
||||
function setPage(name:PageName)
|
||||
{
|
||||
if (pages.exists(currentName))
|
||||
currentPage.exists = false;
|
||||
|
||||
currentName = name;
|
||||
|
||||
if (pages.exists(currentName))
|
||||
currentPage.exists = true;
|
||||
}
|
||||
|
||||
override function finishTransIn()
|
||||
{
|
||||
super.finishTransIn();
|
||||
|
||||
currentPage.enabled = true;
|
||||
}
|
||||
|
||||
function switchPage(name:PageName)
|
||||
{
|
||||
// Todo animate?
|
||||
setPage(name);
|
||||
}
|
||||
|
||||
function exitToMainMenu()
|
||||
{
|
||||
currentPage.enabled = false;
|
||||
// Todo animate?
|
||||
FlxG.switchState(new MainMenuState());
|
||||
}
|
||||
}
|
||||
|
||||
class Page extends FlxGroup
|
||||
{
|
||||
public var onSwitch(default, null) = new FlxTypedSignal<PageName->Void>();
|
||||
public var onExit(default, null) = new FlxSignal();
|
||||
|
||||
public var enabled(default, set) = true;
|
||||
public var canExit = true;
|
||||
|
||||
var controls(get, never):Controls;
|
||||
|
||||
inline function get_controls()
|
||||
return PlayerSettings.player1.controls;
|
||||
|
||||
var subState:FlxSubState;
|
||||
|
||||
inline function switchPage(name:PageName)
|
||||
{
|
||||
onSwitch.dispatch(name);
|
||||
}
|
||||
|
||||
inline function exit()
|
||||
{
|
||||
onExit.dispatch();
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
if (enabled)
|
||||
updateEnabled(elapsed);
|
||||
}
|
||||
|
||||
function updateEnabled(elapsed:Float)
|
||||
{
|
||||
if (canExit && controls.BACK)
|
||||
{
|
||||
FlxG.sound.play(Paths.sound('cancelMenu'));
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
function set_enabled(value:Bool)
|
||||
{
|
||||
return this.enabled = value;
|
||||
}
|
||||
|
||||
function openPrompt(prompt:Prompt, onClose:Void->Void)
|
||||
{
|
||||
enabled = false;
|
||||
prompt.closeCallback = function()
|
||||
{
|
||||
enabled = true;
|
||||
if (onClose != null)
|
||||
onClose();
|
||||
}
|
||||
|
||||
FlxG.state.openSubState(prompt);
|
||||
}
|
||||
|
||||
override function destroy()
|
||||
{
|
||||
super.destroy();
|
||||
onSwitch.removeAll();
|
||||
}
|
||||
}
|
||||
|
||||
class OptionsMenu extends Page
|
||||
{
|
||||
var items:TextMenuList;
|
||||
|
||||
public function new(showDonate:Bool)
|
||||
{
|
||||
super();
|
||||
|
||||
add(items = new TextMenuList());
|
||||
createItem('preferences', function() switchPage(Preferences));
|
||||
createItem("controls", function() switchPage(Controls));
|
||||
// createItem('colors', function() switchPage(Colors));
|
||||
#if cpp
|
||||
createItem('mods', function() switchPage(Mods));
|
||||
#end
|
||||
|
||||
#if CAN_OPEN_LINKS
|
||||
if (showDonate)
|
||||
{
|
||||
var hasPopupBlocker = #if web true #else false #end;
|
||||
createItem('donate', selectDonate, hasPopupBlocker);
|
||||
}
|
||||
#end
|
||||
#if newgrounds
|
||||
/*if (NGio.isLoggedIn)
|
||||
createItem("logout", selectLogout);
|
||||
else
|
||||
createItem("login", selectLogin);*/
|
||||
#end
|
||||
createItem("exit", exit);
|
||||
}
|
||||
|
||||
function createItem(name:String, callback:Void->Void, fireInstantly = false)
|
||||
{
|
||||
var item = items.createItem(0, 100 + items.length * 100, name, Bold, callback);
|
||||
item.fireInstantly = fireInstantly;
|
||||
item.screenCenter(X);
|
||||
return item;
|
||||
}
|
||||
|
||||
override function set_enabled(value:Bool)
|
||||
{
|
||||
items.enabled = value;
|
||||
return super.set_enabled(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* True if this page has multiple options, excluding the exit option.
|
||||
* If false, there's no reason to ever show this page.
|
||||
*/
|
||||
public function hasMultipleOptions():Bool
|
||||
{
|
||||
return items.length > 2;
|
||||
}
|
||||
|
||||
#if CAN_OPEN_LINKS
|
||||
function selectDonate()
|
||||
{
|
||||
#if linux
|
||||
Sys.command('/usr/bin/xdg-open', ["https://ninja-muffin24.itch.io/funkin", "&"]);
|
||||
#else
|
||||
FlxG.openURL('https://ninja-muffin24.itch.io/funkin');
|
||||
#end
|
||||
}
|
||||
#end
|
||||
|
||||
#if newgrounds
|
||||
/*function selectLogin()
|
||||
{
|
||||
openNgPrompt(NgPrompt.showLogin());
|
||||
}
|
||||
|
||||
function selectLogout()
|
||||
{
|
||||
openNgPrompt(NgPrompt.showLogout());
|
||||
}
|
||||
|
||||
public function openNgPrompt(prompt:Prompt, ?onClose:Void->Void)
|
||||
{
|
||||
var onPromptClose = checkLoginStatus;
|
||||
if (onClose != null)
|
||||
{
|
||||
onPromptClose = function()
|
||||
{
|
||||
checkLoginStatus();
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
|
||||
openPrompt(prompt, onPromptClose);
|
||||
}
|
||||
|
||||
function checkLoginStatus()
|
||||
{
|
||||
// this shit don't work!! wtf!!!!
|
||||
var prevLoggedIn = items.has("logout");
|
||||
if (prevLoggedIn && !NGio.isLoggedIn)
|
||||
items.resetItem("logout", "login", selectLogin);
|
||||
else if (!prevLoggedIn && NGio.isLoggedIn)
|
||||
items.resetItem("login", "logout", selectLogout);
|
||||
}*/
|
||||
#end
|
||||
}
|
||||
|
||||
enum PageName
|
||||
{
|
||||
Options;
|
||||
Controls;
|
||||
Colors;
|
||||
Mods;
|
||||
Preferences;
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
package game.state.menus.options;
|
||||
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxObject;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.group.FlxGroup;
|
||||
import flixel.util.FlxColor;
|
||||
import game.ui.AtlasText.AtlasFont;
|
||||
import game.ui.TextMenuList;
|
||||
import game.ui.TextMenuList.TextMenuItem;
|
||||
import game.data.backend.SwagCamera;
|
||||
import game.state.menus.options.*;
|
||||
|
||||
class PreferencesMenu extends OptionsState.Page
|
||||
{
|
||||
public static var preferences:Map<String, Dynamic> = new Map();
|
||||
|
||||
var items:TextMenuList;
|
||||
|
||||
var checkboxes:Array<CheckboxThingie> = [];
|
||||
var menuCamera:FlxCamera;
|
||||
var camFollow:FlxObject;
|
||||
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
|
||||
menuCamera = new SwagCamera();
|
||||
FlxG.cameras.add(menuCamera, false);
|
||||
menuCamera.bgColor = 0x0;
|
||||
camera = menuCamera;
|
||||
|
||||
add(items = new TextMenuList());
|
||||
|
||||
createPrefItem('naughtyness', 'censor-naughty', true);
|
||||
createPrefItem('downscroll', 'downscroll', false);
|
||||
createPrefItem('flashing menu', 'flashing-menu', true);
|
||||
createPrefItem('Camera Zooming on Beat', 'camera-zoom', true);
|
||||
createPrefItem('FPS Counter', 'fps-counter', true);
|
||||
createPrefItem('Auto Pause', 'auto-pause', false);
|
||||
|
||||
camFollow = new FlxObject(FlxG.width / 2, 0, 140, 70);
|
||||
if (items != null)
|
||||
camFollow.y = items.selectedItem.y;
|
||||
|
||||
menuCamera.follow(camFollow, null, 0.06);
|
||||
var margin = 160;
|
||||
menuCamera.deadzone.set(0, margin, menuCamera.width, 40);
|
||||
menuCamera.minScrollY = 0;
|
||||
|
||||
items.onChange.add(function(selected)
|
||||
{
|
||||
camFollow.y = selected.y;
|
||||
});
|
||||
}
|
||||
|
||||
public static function getPref(pref:String):Dynamic
|
||||
{
|
||||
return preferences.get(pref);
|
||||
}
|
||||
|
||||
// easy shorthand?
|
||||
public static function setPref(pref:String, value:Dynamic):Void
|
||||
{
|
||||
preferences.set(pref, value);
|
||||
}
|
||||
|
||||
public static function initPrefs():Void
|
||||
{
|
||||
preferenceCheck('censor-naughty', true);
|
||||
preferenceCheck('downscroll', false);
|
||||
preferenceCheck('flashing-menu', true);
|
||||
preferenceCheck('camera-zoom', true);
|
||||
preferenceCheck('fps-counter', true);
|
||||
preferenceCheck('auto-pause', false);
|
||||
preferenceCheck('master-volume', 1);
|
||||
|
||||
#if muted
|
||||
setPref('master-volume', 0);
|
||||
FlxG.sound.muted = true;
|
||||
#end
|
||||
|
||||
if (!getPref('fps-counter'))
|
||||
FlxG.stage.removeChild(Main.fpsCounter);
|
||||
|
||||
FlxG.autoPause = getPref('auto-pause');
|
||||
}
|
||||
|
||||
private function createPrefItem(prefName:String, prefString:String, prefValue:Dynamic):Void
|
||||
{
|
||||
items.createItem(120, (120 * items.length) + 30, prefName, AtlasFont.Bold, function()
|
||||
{
|
||||
preferenceCheck(prefString, prefValue);
|
||||
|
||||
switch (Type.typeof(prefValue).getName())
|
||||
{
|
||||
case 'TBool':
|
||||
prefToggle(prefString);
|
||||
|
||||
default:
|
||||
trace('swag');
|
||||
}
|
||||
});
|
||||
|
||||
switch (Type.typeof(prefValue).getName())
|
||||
{
|
||||
case 'TBool':
|
||||
createCheckbox(prefString);
|
||||
|
||||
default:
|
||||
trace('swag');
|
||||
}
|
||||
|
||||
trace(Type.typeof(prefValue).getName());
|
||||
}
|
||||
|
||||
function createCheckbox(prefString:String)
|
||||
{
|
||||
var checkbox:CheckboxThingie = new CheckboxThingie(0, 120 * (items.length - 1), preferences.get(prefString));
|
||||
checkboxes.push(checkbox);
|
||||
add(checkbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assumes that the preference has already been checked/set?
|
||||
*/
|
||||
private function prefToggle(prefName:String)
|
||||
{
|
||||
var daSwap:Bool = preferences.get(prefName);
|
||||
daSwap = !daSwap;
|
||||
preferences.set(prefName, daSwap);
|
||||
checkboxes[items.selectedIndex].daValue = daSwap;
|
||||
trace('toggled? ' + preferences.get(prefName));
|
||||
|
||||
switch (prefName)
|
||||
{
|
||||
case 'fps-counter':
|
||||
if (getPref('fps-counter'))
|
||||
FlxG.stage.addChild(Main.fpsCounter);
|
||||
else
|
||||
FlxG.stage.removeChild(Main.fpsCounter);
|
||||
case 'auto-pause':
|
||||
FlxG.autoPause = getPref('auto-pause');
|
||||
}
|
||||
|
||||
if (prefName == 'fps-counter') {}
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
// menuCamera.followLerp = CoolUtil.camLerpShit(0.05);
|
||||
|
||||
items.forEach(function(daItem:TextMenuItem)
|
||||
{
|
||||
if (items.selectedItem == daItem)
|
||||
daItem.x = 150;
|
||||
else
|
||||
daItem.x = 120;
|
||||
});
|
||||
}
|
||||
|
||||
private static function preferenceCheck(prefString:String, prefValue:Dynamic):Void
|
||||
{
|
||||
if (preferences.get(prefString) == null)
|
||||
{
|
||||
preferences.set(prefString, prefValue);
|
||||
trace('set preference!');
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('found preference: ' + preferences.get(prefString));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CheckboxThingie extends FlxSprite
|
||||
{
|
||||
public var daValue(default, set):Bool;
|
||||
|
||||
public function new(x:Float, y:Float, daValue:Bool = false)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
frames = Paths.getSparrowAtlas('checkboxThingie');
|
||||
animation.addByPrefix('static', 'Check Box unselected', 24, false);
|
||||
animation.addByPrefix('checked', 'Check Box selecting animation', 24, false);
|
||||
|
||||
antialiasing = true;
|
||||
|
||||
setGraphicSize(Std.int(width * 0.7));
|
||||
updateHitbox();
|
||||
|
||||
this.daValue = daValue;
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
switch (animation.curAnim.name)
|
||||
{
|
||||
case 'static':
|
||||
offset.set();
|
||||
case 'checked':
|
||||
offset.set(17, 70);
|
||||
}
|
||||
}
|
||||
|
||||
function set_daValue(value:Bool):Bool
|
||||
{
|
||||
if (value)
|
||||
animation.play('checked', true);
|
||||
else
|
||||
animation.play('static');
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,692 @@
|
|||
package game.state.menus.options.controls;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.input.FlxInput;
|
||||
import flixel.input.actions.FlxAction;
|
||||
import flixel.input.actions.FlxActionInput;
|
||||
import flixel.input.actions.FlxActionInputDigital;
|
||||
import flixel.input.actions.FlxActionManager;
|
||||
import flixel.input.actions.FlxActionSet;
|
||||
import flixel.input.gamepad.FlxGamepadButton;
|
||||
import flixel.input.gamepad.FlxGamepadInputID;
|
||||
import flixel.input.keyboard.FlxKey;
|
||||
|
||||
/**
|
||||
* Since, in many cases multiple actions should use similar keys, we don't want the
|
||||
* rebinding UI to list every action. ActionBinders are what the user percieves as
|
||||
* an input so, for instance, they can't set jump-press and jump-release to different keys.
|
||||
*/
|
||||
enum Control
|
||||
{
|
||||
// List notes in order from left to right on gameplay screen.
|
||||
NOTE_LEFT;
|
||||
NOTE_DOWN;
|
||||
NOTE_UP;
|
||||
NOTE_RIGHT;
|
||||
UI_UP;
|
||||
UI_LEFT;
|
||||
UI_RIGHT;
|
||||
UI_DOWN;
|
||||
RESET;
|
||||
ACCEPT;
|
||||
BACK;
|
||||
PAUSE;
|
||||
#if CAN_CHEAT
|
||||
CHEAT;
|
||||
#end
|
||||
}
|
||||
|
||||
@:enum
|
||||
abstract Action(String) to String from String
|
||||
{
|
||||
var UI_UP = "ui_up";
|
||||
var UI_LEFT = "ui_left";
|
||||
var UI_RIGHT = "ui_right";
|
||||
var UI_DOWN = "ui_down";
|
||||
var UI_UP_P = "ui_up-press";
|
||||
var UI_LEFT_P = "ui_left-press";
|
||||
var UI_RIGHT_P = "ui_right-press";
|
||||
var UI_DOWN_P = "ui_down-press";
|
||||
var UI_UP_R = "ui_up-release";
|
||||
var UI_LEFT_R = "ui_left-release";
|
||||
var UI_RIGHT_R = "ui_right-release";
|
||||
var UI_DOWN_R = "ui_down-release";
|
||||
var NOTE_UP = "note_up";
|
||||
var NOTE_LEFT = "note_left";
|
||||
var NOTE_RIGHT = "note_right";
|
||||
var NOTE_DOWN = "note_down";
|
||||
var NOTE_UP_P = "note_up-press";
|
||||
var NOTE_LEFT_P = "note_left-press";
|
||||
var NOTE_RIGHT_P = "note_right-press";
|
||||
var NOTE_DOWN_P = "note_down-press";
|
||||
var NOTE_UP_R = "note_up-release";
|
||||
var NOTE_LEFT_R = "note_left-release";
|
||||
var NOTE_RIGHT_R = "note_right-release";
|
||||
var NOTE_DOWN_R = "note_down-release";
|
||||
var ACCEPT = "accept";
|
||||
var BACK = "back";
|
||||
var PAUSE = "pause";
|
||||
var RESET = "reset";
|
||||
#if CAN_CHEAT
|
||||
var CHEAT = "cheat";
|
||||
#end
|
||||
}
|
||||
|
||||
enum Device
|
||||
{
|
||||
Keys;
|
||||
Gamepad(id:Int);
|
||||
}
|
||||
|
||||
enum KeyboardScheme
|
||||
{
|
||||
Solo;
|
||||
Duo(first:Bool);
|
||||
None;
|
||||
Custom;
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of actions that a player would invoke via some input device.
|
||||
* Uses FlxActions to funnel various inputs to a single action.
|
||||
*/
|
||||
class Controls extends FlxActionSet
|
||||
{
|
||||
var _ui_up = new FlxActionDigital(Action.UI_UP);
|
||||
var _ui_left = new FlxActionDigital(Action.UI_LEFT);
|
||||
var _ui_right = new FlxActionDigital(Action.UI_RIGHT);
|
||||
var _ui_down = new FlxActionDigital(Action.UI_DOWN);
|
||||
var _ui_upP = new FlxActionDigital(Action.UI_UP_P);
|
||||
var _ui_leftP = new FlxActionDigital(Action.UI_LEFT_P);
|
||||
var _ui_rightP = new FlxActionDigital(Action.UI_RIGHT_P);
|
||||
var _ui_downP = new FlxActionDigital(Action.UI_DOWN_P);
|
||||
var _ui_upR = new FlxActionDigital(Action.UI_UP_R);
|
||||
var _ui_leftR = new FlxActionDigital(Action.UI_LEFT_R);
|
||||
var _ui_rightR = new FlxActionDigital(Action.UI_RIGHT_R);
|
||||
var _ui_downR = new FlxActionDigital(Action.UI_DOWN_R);
|
||||
var _note_up = new FlxActionDigital(Action.NOTE_UP);
|
||||
var _note_left = new FlxActionDigital(Action.NOTE_LEFT);
|
||||
var _note_right = new FlxActionDigital(Action.NOTE_RIGHT);
|
||||
var _note_down = new FlxActionDigital(Action.NOTE_DOWN);
|
||||
var _note_upP = new FlxActionDigital(Action.NOTE_UP_P);
|
||||
var _note_leftP = new FlxActionDigital(Action.NOTE_LEFT_P);
|
||||
var _note_rightP = new FlxActionDigital(Action.NOTE_RIGHT_P);
|
||||
var _note_downP = new FlxActionDigital(Action.NOTE_DOWN_P);
|
||||
var _note_upR = new FlxActionDigital(Action.NOTE_UP_R);
|
||||
var _note_leftR = new FlxActionDigital(Action.NOTE_LEFT_R);
|
||||
var _note_rightR = new FlxActionDigital(Action.NOTE_RIGHT_R);
|
||||
var _note_downR = new FlxActionDigital(Action.NOTE_DOWN_R);
|
||||
var _accept = new FlxActionDigital(Action.ACCEPT);
|
||||
var _back = new FlxActionDigital(Action.BACK);
|
||||
var _pause = new FlxActionDigital(Action.PAUSE);
|
||||
var _reset = new FlxActionDigital(Action.RESET);
|
||||
#if CAN_CHEAT
|
||||
var _cheat = new FlxActionDigital(Action.CHEAT);
|
||||
#end
|
||||
|
||||
var byName:Map<String, FlxActionDigital> = new Map<String, FlxActionDigital>();
|
||||
|
||||
public var gamepadsAdded:Array<Int> = [];
|
||||
public var keyboardScheme = KeyboardScheme.None;
|
||||
|
||||
public var UI_UP (get, never):Bool; inline function get_UI_UP () return _ui_up .check();
|
||||
public var UI_LEFT (get, never):Bool; inline function get_UI_LEFT () return _ui_left .check();
|
||||
public var UI_RIGHT(get, never):Bool; inline function get_UI_RIGHT() return _ui_right.check();
|
||||
public var UI_DOWN (get, never):Bool; inline function get_UI_DOWN () return _ui_down .check();
|
||||
|
||||
public var UI_UP_P (get, never):Bool; inline function get_UI_UP_P () return _ui_upP .check();
|
||||
public var UI_LEFT_P (get, never):Bool; inline function get_UI_LEFT_P () return _ui_leftP .check();
|
||||
public var UI_RIGHT_P(get, never):Bool; inline function get_UI_RIGHT_P() return _ui_rightP.check();
|
||||
public var UI_DOWN_P (get, never):Bool; inline function get_UI_DOWN_P () return _ui_downP .check();
|
||||
|
||||
public var UI_UP_R (get, never):Bool; inline function get_UI_UP_R () return _ui_upR .check();
|
||||
public var UI_LEFT_R (get, never):Bool; inline function get_UI_LEFT_R () return _ui_leftR .check();
|
||||
public var UI_RIGHT_R(get, never):Bool; inline function get_UI_RIGHT_R() return _ui_rightR.check();
|
||||
public var UI_DOWN_R (get, never):Bool; inline function get_UI_DOWN_R () return _ui_downR .check();
|
||||
|
||||
public var NOTE_UP (get, never):Bool; inline function get_NOTE_UP () return _note_up .check();
|
||||
public var NOTE_LEFT (get, never):Bool; inline function get_NOTE_LEFT () return _note_left .check();
|
||||
public var NOTE_RIGHT(get, never):Bool; inline function get_NOTE_RIGHT() return _note_right.check();
|
||||
public var NOTE_DOWN (get, never):Bool; inline function get_NOTE_DOWN () return _note_down .check();
|
||||
|
||||
public var NOTE_UP_P (get, never):Bool; inline function get_NOTE_UP_P () return _note_upP .check();
|
||||
public var NOTE_LEFT_P (get, never):Bool; inline function get_NOTE_LEFT_P () return _note_leftP .check();
|
||||
public var NOTE_RIGHT_P(get, never):Bool; inline function get_NOTE_RIGHT_P() return _note_rightP.check();
|
||||
public var NOTE_DOWN_P (get, never):Bool; inline function get_NOTE_DOWN_P () return _note_downP .check();
|
||||
|
||||
public var NOTE_UP_R (get, never):Bool; inline function get_NOTE_UP_R () return _note_upR .check();
|
||||
public var NOTE_LEFT_R (get, never):Bool; inline function get_NOTE_LEFT_R () return _note_leftR .check();
|
||||
public var NOTE_RIGHT_R(get, never):Bool; inline function get_NOTE_RIGHT_R() return _note_rightR.check();
|
||||
public var NOTE_DOWN_R (get, never):Bool; inline function get_NOTE_DOWN_R () return _note_downR .check();
|
||||
|
||||
public var ACCEPT(get, never):Bool; inline function get_ACCEPT() return _accept.check();
|
||||
public var BACK (get, never):Bool; inline function get_BACK () return _back .check();
|
||||
public var PAUSE (get, never):Bool; inline function get_PAUSE () return _pause .check();
|
||||
public var RESET (get, never):Bool; inline function get_RESET () return _reset .check();
|
||||
#if CAN_CHEAT
|
||||
public var CHEAT (get, never):Bool; inline function get_CHEAT () return _cheat.check ();
|
||||
#end
|
||||
|
||||
public function new(name, scheme:KeyboardScheme = null)
|
||||
{
|
||||
super(name);
|
||||
|
||||
add(_ui_up);
|
||||
add(_ui_left);
|
||||
add(_ui_right);
|
||||
add(_ui_down);
|
||||
add(_ui_upP);
|
||||
add(_ui_leftP);
|
||||
add(_ui_rightP);
|
||||
add(_ui_downP);
|
||||
add(_ui_upR);
|
||||
add(_ui_leftR);
|
||||
add(_ui_rightR);
|
||||
add(_ui_downR);
|
||||
add(_note_up);
|
||||
add(_note_left);
|
||||
add(_note_right);
|
||||
add(_note_down);
|
||||
add(_note_upP);
|
||||
add(_note_leftP);
|
||||
add(_note_rightP);
|
||||
add(_note_downP);
|
||||
add(_note_upR);
|
||||
add(_note_leftR);
|
||||
add(_note_rightR);
|
||||
add(_note_downR);
|
||||
add(_accept);
|
||||
add(_back);
|
||||
add(_pause);
|
||||
add(_reset);
|
||||
#if CAN_CHEAT
|
||||
add(_cheat);
|
||||
#end
|
||||
|
||||
for (action in digitalActions)
|
||||
byName[action.name] = action;
|
||||
|
||||
if (scheme == null)
|
||||
scheme = None;
|
||||
|
||||
setKeyboardScheme(scheme, false);
|
||||
}
|
||||
|
||||
override function update()
|
||||
{
|
||||
super.update();
|
||||
}
|
||||
|
||||
// inline
|
||||
public function checkByName(name:Action):Bool
|
||||
{
|
||||
#if debug
|
||||
if (!byName.exists(name))
|
||||
throw 'Invalid name: $name';
|
||||
#end
|
||||
return byName[name].check();
|
||||
}
|
||||
|
||||
public function getDialogueName(action:FlxActionDigital):String
|
||||
{
|
||||
var input = action.inputs[0];
|
||||
return switch input.device
|
||||
{
|
||||
case KEYBOARD: return '[${(input.inputID : FlxKey)}]';
|
||||
case GAMEPAD: return '(${(input.inputID : FlxGamepadInputID)})';
|
||||
case device: throw 'unhandled device: $device';
|
||||
}
|
||||
}
|
||||
|
||||
public function getDialogueNameFromToken(token:String):String
|
||||
{
|
||||
return getDialogueName(getActionFromControl(Control.createByName(token.toUpperCase())));
|
||||
}
|
||||
|
||||
function getActionFromControl(control:Control):FlxActionDigital
|
||||
{
|
||||
return switch (control)
|
||||
{
|
||||
case UI_UP: _ui_up;
|
||||
case UI_DOWN: _ui_down;
|
||||
case UI_LEFT: _ui_left;
|
||||
case UI_RIGHT: _ui_right;
|
||||
case NOTE_UP: _note_up;
|
||||
case NOTE_DOWN: _note_down;
|
||||
case NOTE_LEFT: _note_left;
|
||||
case NOTE_RIGHT: _note_right;
|
||||
case ACCEPT: _accept;
|
||||
case BACK: _back;
|
||||
case PAUSE: _pause;
|
||||
case RESET: _reset;
|
||||
#if CAN_CHEAT
|
||||
case CHEAT: _cheat;
|
||||
#end
|
||||
}
|
||||
}
|
||||
|
||||
static function init():Void
|
||||
{
|
||||
var actions = new FlxActionManager();
|
||||
FlxG.inputs.add(actions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls a function passing each action bound by the specified control
|
||||
* @param control
|
||||
* @param func
|
||||
* @return ->Void)
|
||||
*/
|
||||
function forEachBound(control:Control, func:FlxActionDigital->FlxInputState->Void)
|
||||
{
|
||||
switch (control)
|
||||
{
|
||||
case UI_UP:
|
||||
func(_ui_up, PRESSED);
|
||||
func(_ui_upP, JUST_PRESSED);
|
||||
func(_ui_upR, JUST_RELEASED);
|
||||
case UI_LEFT:
|
||||
func(_ui_left, PRESSED);
|
||||
func(_ui_leftP, JUST_PRESSED);
|
||||
func(_ui_leftR, JUST_RELEASED);
|
||||
case UI_RIGHT:
|
||||
func(_ui_right, PRESSED);
|
||||
func(_ui_rightP, JUST_PRESSED);
|
||||
func(_ui_rightR, JUST_RELEASED);
|
||||
case UI_DOWN:
|
||||
func(_ui_down, PRESSED);
|
||||
func(_ui_downP, JUST_PRESSED);
|
||||
func(_ui_downR, JUST_RELEASED);
|
||||
case NOTE_UP:
|
||||
func(_note_up, PRESSED);
|
||||
func(_note_upP, JUST_PRESSED);
|
||||
func(_note_upR, JUST_RELEASED);
|
||||
case NOTE_LEFT:
|
||||
func(_note_left, PRESSED);
|
||||
func(_note_leftP, JUST_PRESSED);
|
||||
func(_note_leftR, JUST_RELEASED);
|
||||
case NOTE_RIGHT:
|
||||
func(_note_right, PRESSED);
|
||||
func(_note_rightP, JUST_PRESSED);
|
||||
func(_note_rightR, JUST_RELEASED);
|
||||
case NOTE_DOWN:
|
||||
func(_note_down, PRESSED);
|
||||
func(_note_downP, JUST_PRESSED);
|
||||
func(_note_downR, JUST_RELEASED);
|
||||
case ACCEPT:
|
||||
func(_accept, JUST_PRESSED);
|
||||
case BACK:
|
||||
func(_back, JUST_PRESSED);
|
||||
case PAUSE:
|
||||
func(_pause, JUST_PRESSED);
|
||||
case RESET:
|
||||
func(_reset, JUST_PRESSED);
|
||||
#if CAN_CHEAT
|
||||
case CHEAT:
|
||||
func(_cheat, JUST_PRESSED);
|
||||
#end
|
||||
}
|
||||
}
|
||||
|
||||
public function replaceBinding(control:Control, device:Device, toAdd:Int, toRemove:Int)
|
||||
{
|
||||
if (toAdd == toRemove)
|
||||
return;
|
||||
|
||||
switch (device)
|
||||
{
|
||||
case Keys:
|
||||
forEachBound(control, function(action, _) replaceKey(action, toAdd, toRemove));
|
||||
|
||||
case Gamepad(id):
|
||||
forEachBound(control, function(action, _) replaceButton(action, id, toAdd, toRemove));
|
||||
}
|
||||
}
|
||||
|
||||
function replaceKey(action:FlxActionDigital, toAdd:Int, toRemove:Int)
|
||||
{
|
||||
for (i in 0...action.inputs.length)
|
||||
{
|
||||
var input = action.inputs[i];
|
||||
if (input.device == KEYBOARD && input.inputID == toRemove)
|
||||
{
|
||||
@:privateAccess
|
||||
action.inputs[i].inputID = toAdd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function replaceButton(action:FlxActionDigital, deviceID:Int, toAdd:Int, toRemove:Int)
|
||||
{
|
||||
for (i in 0...action.inputs.length)
|
||||
{
|
||||
var input = action.inputs[i];
|
||||
if (isGamepad(input, deviceID) && input.inputID == toRemove)
|
||||
{
|
||||
@:privateAccess
|
||||
action.inputs[i].inputID = toAdd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function copyFrom(controls:Controls, ?device:Device)
|
||||
{
|
||||
for (name in controls.byName.keys())
|
||||
{
|
||||
var action = controls.byName[name];
|
||||
for (input in action.inputs)
|
||||
{
|
||||
if (device == null || isDevice(input, device))
|
||||
byName[name].add(cast input);
|
||||
}
|
||||
}
|
||||
|
||||
switch (device)
|
||||
{
|
||||
case null:
|
||||
// add all
|
||||
for (gamepad in controls.gamepadsAdded)
|
||||
if (gamepadsAdded.indexOf(gamepad) == -1)
|
||||
gamepadsAdded.push(gamepad);
|
||||
|
||||
mergeKeyboardScheme(controls.keyboardScheme);
|
||||
|
||||
case Gamepad(id):
|
||||
gamepadsAdded.push(id);
|
||||
case Keys:
|
||||
mergeKeyboardScheme(controls.keyboardScheme);
|
||||
}
|
||||
}
|
||||
|
||||
inline public function copyTo(controls:Controls, ?device:Device)
|
||||
{
|
||||
controls.copyFrom(this, device);
|
||||
}
|
||||
|
||||
function mergeKeyboardScheme(scheme:KeyboardScheme):Void
|
||||
{
|
||||
if (scheme != None)
|
||||
{
|
||||
switch (keyboardScheme)
|
||||
{
|
||||
case None:
|
||||
keyboardScheme = scheme;
|
||||
default:
|
||||
keyboardScheme = Custom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all actions that pertain to the binder to trigger when the supplied keys are used.
|
||||
* If binder is a literal you can inline this
|
||||
*/
|
||||
public function bindKeys(control:Control, keys:Array<FlxKey>)
|
||||
{
|
||||
forEachBound(control, function(action, state) addKeys(action, keys, state));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all actions that pertain to the binder to trigger when the supplied keys are used.
|
||||
* If binder is a literal you can inline this
|
||||
*/
|
||||
public function unbindKeys(control:Control, keys:Array<FlxKey>)
|
||||
{
|
||||
forEachBound(control, function(action, _) removeKeys(action, keys));
|
||||
}
|
||||
|
||||
inline static function addKeys(action:FlxActionDigital, keys:Array<FlxKey>, state:FlxInputState)
|
||||
{
|
||||
for (key in keys)
|
||||
action.addKey(key, state);
|
||||
}
|
||||
|
||||
static function removeKeys(action:FlxActionDigital, keys:Array<FlxKey>)
|
||||
{
|
||||
var i = action.inputs.length;
|
||||
while (i-- > 0)
|
||||
{
|
||||
var input = action.inputs[i];
|
||||
if (input.device == KEYBOARD && keys.indexOf(cast input.inputID) != -1)
|
||||
action.remove(input);
|
||||
}
|
||||
}
|
||||
|
||||
public function setKeyboardScheme(scheme:KeyboardScheme, reset = true)
|
||||
{
|
||||
if (reset)
|
||||
removeKeyboard();
|
||||
|
||||
keyboardScheme = scheme;
|
||||
|
||||
switch (scheme)
|
||||
{
|
||||
case Solo:
|
||||
bindKeys(Control.UI_UP, [W, FlxKey.UP]);
|
||||
bindKeys(Control.UI_DOWN, [S, FlxKey.DOWN]);
|
||||
bindKeys(Control.UI_LEFT, [A, FlxKey.LEFT]);
|
||||
bindKeys(Control.UI_RIGHT, [D, FlxKey.RIGHT]);
|
||||
bindKeys(Control.NOTE_UP, [W, FlxKey.UP]);
|
||||
bindKeys(Control.NOTE_DOWN, [S, FlxKey.DOWN]);
|
||||
bindKeys(Control.NOTE_LEFT, [A, FlxKey.LEFT]);
|
||||
bindKeys(Control.NOTE_RIGHT, [D, FlxKey.RIGHT]);
|
||||
bindKeys(Control.ACCEPT, [Z, SPACE, ENTER]);
|
||||
bindKeys(Control.BACK, [X, BACKSPACE, ESCAPE]);
|
||||
bindKeys(Control.PAUSE, [P, ENTER, ESCAPE]);
|
||||
bindKeys(Control.RESET, [R]);
|
||||
case Duo(true):
|
||||
bindKeys(Control.UI_UP, [W]);
|
||||
bindKeys(Control.UI_DOWN, [S]);
|
||||
bindKeys(Control.UI_LEFT, [A]);
|
||||
bindKeys(Control.UI_RIGHT, [D]);
|
||||
bindKeys(Control.NOTE_UP, [W]);
|
||||
bindKeys(Control.NOTE_DOWN, [S]);
|
||||
bindKeys(Control.NOTE_LEFT, [A]);
|
||||
bindKeys(Control.NOTE_RIGHT, [D]);
|
||||
bindKeys(Control.ACCEPT, [G, Z]);
|
||||
bindKeys(Control.BACK, [H, X]);
|
||||
bindKeys(Control.PAUSE, [ONE]);
|
||||
bindKeys(Control.RESET, [R]);
|
||||
case Duo(false):
|
||||
bindKeys(Control.UI_UP, [FlxKey.UP]);
|
||||
bindKeys(Control.UI_DOWN, [FlxKey.DOWN]);
|
||||
bindKeys(Control.UI_LEFT, [FlxKey.LEFT]);
|
||||
bindKeys(Control.UI_RIGHT, [FlxKey.RIGHT]);
|
||||
bindKeys(Control.NOTE_UP, [FlxKey.UP]);
|
||||
bindKeys(Control.NOTE_DOWN, [FlxKey.DOWN]);
|
||||
bindKeys(Control.NOTE_LEFT, [FlxKey.LEFT]);
|
||||
bindKeys(Control.NOTE_RIGHT, [FlxKey.RIGHT]);
|
||||
bindKeys(Control.ACCEPT, [O]);
|
||||
bindKeys(Control.BACK, [P]);
|
||||
bindKeys(Control.PAUSE, [ENTER]);
|
||||
bindKeys(Control.RESET, [BACKSPACE]);
|
||||
case None: // nothing
|
||||
case Custom: // nothing
|
||||
}
|
||||
}
|
||||
|
||||
function removeKeyboard()
|
||||
{
|
||||
for (action in this.digitalActions)
|
||||
{
|
||||
var i = action.inputs.length;
|
||||
while (i-- > 0)
|
||||
{
|
||||
var input = action.inputs[i];
|
||||
if (input.device == KEYBOARD)
|
||||
action.remove(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function addGamepadWithSaveData(id:Int, ?padData:Dynamic):Void
|
||||
{
|
||||
gamepadsAdded.push(id);
|
||||
|
||||
fromSaveData(padData, Gamepad(id));
|
||||
}
|
||||
|
||||
inline function addGamepadLiteral(id:Int, ?buttonMap:Map<Control, Array<FlxGamepadInputID>>):Void
|
||||
{
|
||||
gamepadsAdded.push(id);
|
||||
|
||||
for (control in buttonMap.keys())
|
||||
bindButtons(control, id, buttonMap[control]);
|
||||
}
|
||||
|
||||
public function removeGamepad(deviceID:Int = FlxInputDeviceID.ALL):Void
|
||||
{
|
||||
for (action in this.digitalActions)
|
||||
{
|
||||
var i = action.inputs.length;
|
||||
while (i-- > 0)
|
||||
{
|
||||
var input = action.inputs[i];
|
||||
if (isGamepad(input, deviceID))
|
||||
action.remove(input);
|
||||
}
|
||||
}
|
||||
|
||||
gamepadsAdded.remove(deviceID);
|
||||
}
|
||||
|
||||
public function addDefaultGamepad(id):Void
|
||||
{
|
||||
addGamepadLiteral(id, [
|
||||
|
||||
Control.ACCEPT => [#if switch B #else A #end],
|
||||
Control.BACK => [#if switch A #else B #end, FlxGamepadInputID.BACK],
|
||||
Control.UI_UP => [DPAD_UP, LEFT_STICK_DIGITAL_UP],
|
||||
Control.UI_DOWN => [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN],
|
||||
Control.UI_LEFT => [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT],
|
||||
Control.UI_RIGHT => [DPAD_RIGHT, LEFT_STICK_DIGITAL_RIGHT],
|
||||
// don't swap A/B or X/Y for switch on these. A is always the bottom face button
|
||||
Control.NOTE_UP => [DPAD_UP, Y, LEFT_STICK_DIGITAL_UP, RIGHT_STICK_DIGITAL_UP],
|
||||
Control.NOTE_DOWN => [DPAD_DOWN, A, LEFT_STICK_DIGITAL_DOWN, RIGHT_STICK_DIGITAL_DOWN],
|
||||
Control.NOTE_LEFT => [DPAD_LEFT, X, LEFT_STICK_DIGITAL_LEFT, RIGHT_STICK_DIGITAL_LEFT],
|
||||
Control.NOTE_RIGHT => [DPAD_RIGHT, B, LEFT_STICK_DIGITAL_RIGHT, RIGHT_STICK_DIGITAL_RIGHT],
|
||||
Control.PAUSE => [START],
|
||||
Control.RESET => [Y]
|
||||
#if CAN_CHEAT
|
||||
,Control.CHEAT => [X]
|
||||
#end
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all actions that pertain to the binder to trigger when the supplied keys are used.
|
||||
* If binder is a literal you can inline this
|
||||
*/
|
||||
public function bindButtons(control:Control, id, buttons)
|
||||
{
|
||||
forEachBound(control, function(action, state) addButtons(action, buttons, state, id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all actions that pertain to the binder to trigger when the supplied keys are used.
|
||||
* If binder is a literal you can inline this
|
||||
*/
|
||||
public function unbindButtons(control:Control, gamepadID:Int, buttons)
|
||||
{
|
||||
forEachBound(control, function(action, _) removeButtons(action, gamepadID, buttons));
|
||||
}
|
||||
|
||||
inline static function addButtons(action:FlxActionDigital, buttons:Array<FlxGamepadInputID>, state, id)
|
||||
{
|
||||
for (button in buttons)
|
||||
action.addGamepad(button, state, id);
|
||||
}
|
||||
|
||||
static function removeButtons(action:FlxActionDigital, gamepadID:Int, buttons:Array<FlxGamepadInputID>)
|
||||
{
|
||||
var i = action.inputs.length;
|
||||
while (i-- > 0)
|
||||
{
|
||||
var input = action.inputs[i];
|
||||
if (isGamepad(input, gamepadID) && buttons.indexOf(cast input.inputID) != -1)
|
||||
action.remove(input);
|
||||
}
|
||||
}
|
||||
|
||||
public function getInputsFor(control:Control, device:Device, ?list:Array<Int>):Array<Int>
|
||||
{
|
||||
if (list == null)
|
||||
list = [];
|
||||
|
||||
switch (device)
|
||||
{
|
||||
case Keys:
|
||||
for (input in getActionFromControl(control).inputs)
|
||||
{
|
||||
if (input.device == KEYBOARD)
|
||||
list.push(input.inputID);
|
||||
}
|
||||
case Gamepad(id):
|
||||
for (input in getActionFromControl(control).inputs)
|
||||
{
|
||||
if (isGamepad(input, id))
|
||||
list.push(input.inputID);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public function removeDevice(device:Device)
|
||||
{
|
||||
switch (device)
|
||||
{
|
||||
case Keys:
|
||||
setKeyboardScheme(None);
|
||||
case Gamepad(id):
|
||||
removeGamepad(id);
|
||||
}
|
||||
}
|
||||
|
||||
public function fromSaveData(data:Dynamic, device:Device)
|
||||
{
|
||||
for (control in Control.createAll())
|
||||
{
|
||||
var inputs:Array<Int> = Reflect.field(data, control.getName());
|
||||
if (inputs != null)
|
||||
{
|
||||
switch(device)
|
||||
{
|
||||
case Keys: bindKeys(control, inputs.copy());
|
||||
case Gamepad(id): bindButtons(control, id, inputs.copy());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function createSaveData(device:Device):Dynamic
|
||||
{
|
||||
var isEmpty = true;
|
||||
var data = {};
|
||||
for (control in Control.createAll())
|
||||
{
|
||||
var inputs = getInputsFor(control, device);
|
||||
isEmpty = isEmpty && inputs.length == 0;
|
||||
|
||||
Reflect.setField(data, control.getName(), inputs);
|
||||
}
|
||||
|
||||
return isEmpty ? null : data;
|
||||
}
|
||||
|
||||
static function isDevice(input:FlxActionInput, device:Device)
|
||||
{
|
||||
return switch device
|
||||
{
|
||||
case Keys: input.device == KEYBOARD;
|
||||
case Gamepad(id): isGamepad(input, id);
|
||||
}
|
||||
}
|
||||
|
||||
inline static function isGamepad(input:FlxActionInput, deviceID:Int)
|
||||
{
|
||||
return input.device == GAMEPAD && (deviceID == FlxInputDeviceID.ALL || input.deviceID == deviceID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
typedef SaveInputLists = {?keys:Array<Int>, ?pad:Array<Int>};
|
|
@ -0,0 +1,361 @@
|
|||
package game.state.menus.options.controls;
|
||||
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxObject;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.group.FlxGroup;
|
||||
import flixel.input.actions.FlxActionInput;
|
||||
import flixel.input.gamepad.FlxGamepadInputID;
|
||||
import flixel.input.keyboard.FlxKey;
|
||||
import game.data.PlayerSettings;
|
||||
import game.data.format.InputFormatter;
|
||||
import game.state.subState.Prompt;
|
||||
import game.ui.AtlasText;
|
||||
import game.ui.MenuList;
|
||||
import game.ui.TextMenuList;
|
||||
import game.ui.TextMenuList.TextMenuItem;
|
||||
import game.state.subState.Prompt;
|
||||
import game.state.menus.options.OptionsState.Page;
|
||||
import game.state.menus.options.controls.Controls.Device;
|
||||
import game.state.menus.options.controls.Controls.Control;
|
||||
|
||||
class ControlsMenu extends OptionsState.Page
|
||||
{
|
||||
inline static public var COLUMNS = 2;
|
||||
static var controlList = Control.createAll();
|
||||
/*
|
||||
* Defines groups of controls that cannot share inputs, like left and right. Say, if ACCEPT is Z, Back is X,
|
||||
* if the player sets Back to Z it also set ACCEPT to X. This prevents the player from setting the controls in
|
||||
* a way the prevents them from changing more controls or exiting the menu.
|
||||
*/
|
||||
static var controlGroups:Array<Array<Control>> = [
|
||||
[NOTE_UP, NOTE_DOWN, NOTE_LEFT, NOTE_RIGHT],
|
||||
[UI_UP, UI_DOWN, UI_LEFT, UI_RIGHT, ACCEPT, BACK]
|
||||
];
|
||||
|
||||
var itemGroups:Array<Array<InputItem>> = [for (i in 0...controlGroups.length) []];
|
||||
|
||||
var controlGrid:MenuTypedList<InputItem>;
|
||||
var deviceList:TextMenuList;
|
||||
var menuCamera:FlxCamera;
|
||||
var prompt:Prompt;
|
||||
var camFollow:FlxObject;
|
||||
var labels:FlxTypedGroup<AtlasText>;
|
||||
|
||||
var currentDevice:Device = Keys;
|
||||
var deviceListSelected = false;
|
||||
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
|
||||
menuCamera = new FlxCamera();
|
||||
FlxG.cameras.add(menuCamera, false);
|
||||
menuCamera.bgColor = 0x0;
|
||||
camera = menuCamera;
|
||||
|
||||
labels = new FlxTypedGroup<AtlasText>();
|
||||
var headers = new FlxTypedGroup<AtlasText>();
|
||||
controlGrid = new MenuTypedList(Columns(COLUMNS), Vertical);
|
||||
|
||||
add(labels);
|
||||
add(headers);
|
||||
add(controlGrid);
|
||||
|
||||
if (FlxG.gamepads.numActiveGamepads > 0)
|
||||
{
|
||||
var devicesBg = new FlxSprite();
|
||||
devicesBg.makeGraphic(FlxG.width, 100, 0xFFfafd6d);
|
||||
add(devicesBg);
|
||||
deviceList = new TextMenuList(Horizontal, None);
|
||||
add(deviceList);
|
||||
deviceListSelected = true;
|
||||
|
||||
var item;
|
||||
|
||||
item = deviceList.createItem("Keyboard", Bold, selectDevice.bind(Keys));
|
||||
item.x = FlxG.width / 2 - item.width - 30;
|
||||
item.y = (devicesBg.height - item.height) / 2;
|
||||
|
||||
item = deviceList.createItem("Gamepad", Bold, selectDevice.bind(Gamepad(FlxG.gamepads.firstActive.id)));
|
||||
item.x = FlxG.width / 2 + 30;
|
||||
item.y = (devicesBg.height - item.height) / 2;
|
||||
}
|
||||
|
||||
// FlxG.debugger.drawDebug = true;
|
||||
var y = deviceList == null ? 30 : 120;
|
||||
var spacer = 70;
|
||||
var currentHeader:String = null;
|
||||
// list order is determined by enum order
|
||||
for (i in 0...controlList.length)
|
||||
{
|
||||
var control = controlList[i];
|
||||
var name = control.getName();
|
||||
if (currentHeader != "UI_" && name.indexOf("UI_") == 0)
|
||||
{
|
||||
currentHeader = "UI_";
|
||||
headers.add(new BoldText(0, y, "UI")).screenCenter(X);
|
||||
y += spacer;
|
||||
}
|
||||
else if (currentHeader != "NOTE_" && name.indexOf("NOTE_") == 0)
|
||||
{
|
||||
currentHeader = "NOTE_";
|
||||
headers.add(new BoldText(0, y, "NOTES")).screenCenter(X);
|
||||
y += spacer;
|
||||
}
|
||||
|
||||
if (currentHeader != null && name.indexOf(currentHeader) == 0)
|
||||
name = name.substr(currentHeader.length);
|
||||
|
||||
var label = labels.add(new BoldText(150, y, name));
|
||||
label.alpha = 0.6;
|
||||
for (i in 0...COLUMNS)
|
||||
createItem(label.x + 400 + i * 300, y, control, i);
|
||||
|
||||
y += spacer;
|
||||
}
|
||||
|
||||
camFollow = new FlxObject(FlxG.width / 2, 0, 70, 70);
|
||||
if (deviceList != null)
|
||||
{
|
||||
camFollow.y = deviceList.selectedItem.y;
|
||||
controlGrid.selectedItem.idle();
|
||||
controlGrid.enabled = false;
|
||||
}
|
||||
else
|
||||
camFollow.y = controlGrid.selectedItem.y;
|
||||
|
||||
menuCamera.follow(camFollow, null, 0.06);
|
||||
var margin = 100;
|
||||
menuCamera.deadzone.set(0, margin, menuCamera.width, menuCamera.height - margin * 2);
|
||||
menuCamera.minScrollY = 0;
|
||||
controlGrid.onChange.add(function(selected)
|
||||
{
|
||||
camFollow.y = selected.y;
|
||||
|
||||
labels.forEach((label) -> label.alpha = 0.6);
|
||||
labels.members[Std.int(controlGrid.selectedIndex / COLUMNS)].alpha = 1.0;
|
||||
});
|
||||
|
||||
prompt = new Prompt("\nPress any key to rebind\n\n\n\n Escape to cancel", None);
|
||||
prompt.create();
|
||||
prompt.createBgFromMargin(100, 0xFFfafd6d);
|
||||
prompt.back.scrollFactor.set(0, 0);
|
||||
prompt.exists = false;
|
||||
add(prompt);
|
||||
}
|
||||
|
||||
function createItem(x = 0.0, y = 0.0, control:Control, index:Int)
|
||||
{
|
||||
var item = new InputItem(x, y, currentDevice, control, index, onSelect);
|
||||
for (i in 0...controlGroups.length)
|
||||
{
|
||||
if (controlGroups[i].contains(control))
|
||||
itemGroups[i].push(item);
|
||||
}
|
||||
|
||||
return controlGrid.addItem(item.name, item);
|
||||
}
|
||||
|
||||
function onSelect():Void
|
||||
{
|
||||
controlGrid.enabled = false;
|
||||
canExit = false;
|
||||
prompt.exists = true;
|
||||
}
|
||||
|
||||
function goToDeviceList()
|
||||
{
|
||||
controlGrid.selectedItem.idle();
|
||||
labels.members[Std.int(controlGrid.selectedIndex / COLUMNS)].alpha = 0.6;
|
||||
controlGrid.enabled = false;
|
||||
deviceList.enabled = true;
|
||||
canExit = true;
|
||||
camFollow.y = deviceList.selectedItem.y;
|
||||
deviceListSelected = true;
|
||||
}
|
||||
|
||||
function selectDevice(device:Device)
|
||||
{
|
||||
currentDevice = device;
|
||||
|
||||
for (item in controlGrid.members)
|
||||
item.updateDevice(currentDevice);
|
||||
|
||||
var inputName = device == Keys ? "key" : "button";
|
||||
var cancel = device == Keys ? "Escape" : "Back";
|
||||
// todo: alignment
|
||||
if (device == Keys)
|
||||
prompt.setText('\nPress any key to rebind\n\n\n\n $cancel to cancel');
|
||||
else
|
||||
prompt.setText('\nPress any button\n to rebind\n\n\n $cancel to cancel');
|
||||
|
||||
controlGrid.selectedItem.select();
|
||||
labels.members[Std.int(controlGrid.selectedIndex / COLUMNS)].alpha = 1.0;
|
||||
controlGrid.enabled = true;
|
||||
deviceList.enabled = false;
|
||||
deviceListSelected = false;
|
||||
canExit = false;
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
var controls = PlayerSettings.player1.controls;
|
||||
if (controlGrid.enabled && deviceList != null && deviceListSelected == false && controls.BACK)
|
||||
goToDeviceList();
|
||||
|
||||
if (prompt.exists)
|
||||
{
|
||||
switch (currentDevice)
|
||||
{
|
||||
case Keys:
|
||||
{
|
||||
// check released otherwise bugs can happen when you change the BACK key
|
||||
var key = FlxG.keys.firstJustReleased();
|
||||
if (key != NONE)
|
||||
{
|
||||
if (key != ESCAPE)
|
||||
onInputSelect(key);
|
||||
closePrompt();
|
||||
}
|
||||
}
|
||||
case Gamepad(id):
|
||||
{
|
||||
var button = FlxG.gamepads.getByID(id).firstJustReleasedID();
|
||||
if (button != NONE)
|
||||
{
|
||||
if (button != BACK)
|
||||
onInputSelect(button);
|
||||
closePrompt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onInputSelect(input:Int)
|
||||
{
|
||||
var item = controlGrid.selectedItem;
|
||||
|
||||
// check if that key is already set for this
|
||||
var column0 = Math.floor(controlGrid.selectedIndex / 2) * 2;
|
||||
for (i in 0...COLUMNS)
|
||||
{
|
||||
if (controlGrid.members[column0 + i].input == input)
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if items in the same group already have the new input
|
||||
for (group in itemGroups)
|
||||
{
|
||||
if (group.contains(item))
|
||||
{
|
||||
for (otherItem in group)
|
||||
{
|
||||
if (otherItem != item && otherItem.input == input)
|
||||
{
|
||||
// replace that input with this items old input.
|
||||
PlayerSettings.player1.controls.replaceBinding(otherItem.control, currentDevice, item.input, otherItem.input);
|
||||
// Don't use resetItem() since items share names/labels
|
||||
otherItem.input = item.input;
|
||||
otherItem.label.text = item.label.text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlayerSettings.player1.controls.replaceBinding(item.control, currentDevice, input, item.input);
|
||||
// Don't use resetItem() since items share names/labels
|
||||
item.input = input;
|
||||
item.label.text = item.getLabel(input);
|
||||
|
||||
PlayerSettings.player1.saveControls();
|
||||
}
|
||||
|
||||
function closePrompt()
|
||||
{
|
||||
prompt.exists = false;
|
||||
controlGrid.enabled = true;
|
||||
if (deviceList == null)
|
||||
canExit = true;
|
||||
}
|
||||
|
||||
override function destroy()
|
||||
{
|
||||
super.destroy();
|
||||
|
||||
itemGroups = null;
|
||||
|
||||
if (FlxG.cameras.list.contains(menuCamera))
|
||||
FlxG.cameras.remove(menuCamera);
|
||||
}
|
||||
|
||||
override function set_enabled(value:Bool)
|
||||
{
|
||||
if (value == false)
|
||||
{
|
||||
controlGrid.enabled = false;
|
||||
if (deviceList != null)
|
||||
deviceList.enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
controlGrid.enabled = !deviceListSelected;
|
||||
if (deviceList != null)
|
||||
deviceList.enabled = deviceListSelected;
|
||||
}
|
||||
return super.set_enabled(value);
|
||||
}
|
||||
}
|
||||
|
||||
class InputItem extends TextMenuItem
|
||||
{
|
||||
public var device(default, null):Device = Keys;
|
||||
public var control:Control;
|
||||
public var input:Int = -1;
|
||||
public var index:Int = -1;
|
||||
|
||||
public function new(x = 0.0, y = 0.0, device, control, index, ?callback)
|
||||
{
|
||||
this.device = device;
|
||||
this.control = control;
|
||||
this.index = index;
|
||||
this.input = getInput();
|
||||
|
||||
super(x, y, getLabel(input), Default, callback);
|
||||
}
|
||||
|
||||
public function updateDevice(device:Device)
|
||||
{
|
||||
if (this.device != device)
|
||||
{
|
||||
this.device = device;
|
||||
input = getInput();
|
||||
label.text = getLabel(input);
|
||||
}
|
||||
}
|
||||
|
||||
function getInput()
|
||||
{
|
||||
var list = PlayerSettings.player1.controls.getInputsFor(control, device);
|
||||
if (list.length > index)
|
||||
{
|
||||
if (list[index] != FlxKey.ESCAPE || list[index] != FlxGamepadInputID.BACK)
|
||||
return list[index];
|
||||
|
||||
if (list.length > ControlsMenu.COLUMNS)
|
||||
// Escape isn't mappable, show a third option, instead.
|
||||
return list[ControlsMenu.COLUMNS];
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public function getLabel(input:Int)
|
||||
{
|
||||
return input == -1 ? "---" : InputFormatter.format(input, device);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
package game.state.subState;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxObject;
|
||||
import flixel.FlxSubState;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.util.FlxTimer;
|
||||
import haxe.display.Display.Package;
|
||||
import game.data.backend.Conductor;
|
||||
import game.data.debug.*;
|
||||
import game.objects.*;
|
||||
import game.state.menus.options.PreferencesMenu;
|
||||
import game.state.*;
|
||||
import game.state.menus.*;
|
||||
|
||||
class GameOverSubstate extends MusicBeatSubstate
|
||||
{
|
||||
var bf:Boyfriend;
|
||||
var camFollow:FlxObject;
|
||||
|
||||
var stageSuffix:String = "";
|
||||
var randomGameover:Int = 1;
|
||||
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
var daStage = PlayState.curStage;
|
||||
var daBf:String = '';
|
||||
switch (daStage)
|
||||
{
|
||||
case 'school' | 'schoolEvil':
|
||||
stageSuffix = '-pixel';
|
||||
daBf = 'bf-pixel-dead';
|
||||
default:
|
||||
daBf = 'bf';
|
||||
}
|
||||
|
||||
var daSong = PlayState.SONG.song.toLowerCase();
|
||||
|
||||
switch (daSong)
|
||||
{
|
||||
case 'stress':
|
||||
daBf = 'bf-holding-gf-dead';
|
||||
}
|
||||
|
||||
super();
|
||||
|
||||
Conductor.songPosition = 0;
|
||||
|
||||
bf = new Boyfriend(x, y, daBf);
|
||||
add(bf);
|
||||
|
||||
camFollow = new FlxObject(bf.getGraphicMidpoint().x, bf.getGraphicMidpoint().y, 1, 1);
|
||||
add(camFollow);
|
||||
|
||||
FlxG.sound.play(Paths.sound('fnf_loss_sfx' + stageSuffix));
|
||||
Conductor.changeBPM(100);
|
||||
|
||||
// FlxG.camera.followLerp = 1;
|
||||
// FlxG.camera.focusOn(FlxPoint.get(FlxG.width / 2, FlxG.height / 2));
|
||||
FlxG.camera.scroll.set();
|
||||
FlxG.camera.target = null;
|
||||
|
||||
bf.playAnim('firstDeath');
|
||||
|
||||
var randomCensor:Array<Int> = [];
|
||||
|
||||
if (PreferencesMenu.getPref('censor-naughty'))
|
||||
randomCensor = [1, 3, 8, 13, 17, 21];
|
||||
|
||||
randomGameover = FlxG.random.int(1, 25, randomCensor);
|
||||
}
|
||||
|
||||
var playingDeathSound:Bool = false;
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
// makes the lerp non-dependant on the framerate
|
||||
// FlxG.camera.followLerp = CoolUtil.camLerpShit(0.01);
|
||||
|
||||
super.update(elapsed);
|
||||
|
||||
if (controls.ACCEPT)
|
||||
{
|
||||
endBullshit();
|
||||
}
|
||||
|
||||
if (controls.BACK)
|
||||
{
|
||||
PlayState.deathCounter = 0;
|
||||
PlayState.seenCutscene = false;
|
||||
FlxG.sound.music.stop();
|
||||
|
||||
if (PlayState.isStoryMode)
|
||||
FlxG.switchState(new StoryMenuState());
|
||||
else
|
||||
FlxG.switchState(new FreeplayState());
|
||||
}
|
||||
|
||||
#if debug
|
||||
if (FlxG.keys.justPressed.EIGHT)
|
||||
FlxG.switchState(new AnimationDebug(bf.curCharacter));
|
||||
#end
|
||||
|
||||
if (bf.animation.curAnim.name == 'firstDeath' && bf.animation.curAnim.curFrame == 12)
|
||||
{
|
||||
FlxG.camera.follow(camFollow, LOCKON, 0.01);
|
||||
}
|
||||
|
||||
switch (PlayState.storyWeek)
|
||||
{
|
||||
case 7:
|
||||
if (bf.animation.curAnim.name == 'firstDeath' && bf.animation.curAnim.finished && !playingDeathSound)
|
||||
{
|
||||
playingDeathSound = true;
|
||||
|
||||
bf.startedDeath = true;
|
||||
coolStartDeath(0.2);
|
||||
|
||||
FlxG.sound.play(Paths.sound('jeffGameover/jeffGameover-' + randomGameover), 1, false, null, true, function()
|
||||
{
|
||||
if (!isEnding)
|
||||
FlxG.sound.music.fadeIn(4, 0.2, 1);
|
||||
});
|
||||
}
|
||||
default:
|
||||
if (bf.animation.curAnim.name == 'firstDeath' && bf.animation.curAnim.finished)
|
||||
{
|
||||
bf.startedDeath = true;
|
||||
coolStartDeath();
|
||||
}
|
||||
}
|
||||
|
||||
if (FlxG.sound.music.playing)
|
||||
{
|
||||
Conductor.songPosition = FlxG.sound.music.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');
|
||||
}
|
||||
|
||||
var isEnding:Bool = false;
|
||||
|
||||
function endBullshit():Void
|
||||
{
|
||||
if (!isEnding)
|
||||
{
|
||||
isEnding = true;
|
||||
bf.playAnim('deathConfirm', true);
|
||||
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());
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package game.state.subState;
|
||||
|
||||
import game.data.PlayerSettings;
|
||||
import game.data.backend.Conductor;
|
||||
import game.data.backend.Conductor.BPMChangeEvent;
|
||||
import game.state.menus.options.controls.Controls;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSubState;
|
||||
|
||||
class MusicBeatSubstate extends FlxSubState
|
||||
{
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
private var curStep:Int = 0;
|
||||
private var curBeat:Int = 0;
|
||||
private var controls(get, never):Controls;
|
||||
|
||||
inline function get_controls():Controls
|
||||
return PlayerSettings.player1.controls;
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
//everyStep();
|
||||
var oldStep:Int = curStep;
|
||||
|
||||
updateCurStep();
|
||||
curBeat = Math.floor(curStep / 4);
|
||||
|
||||
if (oldStep != curStep && curStep >= 0)
|
||||
stepHit();
|
||||
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
private function updateCurStep():Void
|
||||
{
|
||||
var lastChange:BPMChangeEvent = {
|
||||
stepTime: 0,
|
||||
songTime: 0,
|
||||
bpm: 0
|
||||
}
|
||||
for (i in 0...Conductor.bpmChangeMap.length)
|
||||
{
|
||||
if (Conductor.songPosition > Conductor.bpmChangeMap[i].songTime)
|
||||
lastChange = Conductor.bpmChangeMap[i];
|
||||
}
|
||||
|
||||
curStep = lastChange.stepTime + Math.floor((Conductor.songPosition - lastChange.songTime) / Conductor.stepCrochet);
|
||||
}
|
||||
|
||||
public function stepHit():Void
|
||||
{
|
||||
if (curStep % 4 == 0)
|
||||
beatHit();
|
||||
}
|
||||
|
||||
public function beatHit():Void
|
||||
{
|
||||
//do literally nothing dumbass
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package game.state.subState;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxSubState;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.util.FlxColor;
|
||||
import lime.app.Application;
|
||||
|
||||
import game.state.MusicBeatState;
|
||||
import game.state.menus.MainMenuState;
|
||||
|
||||
class OutdatedSubState extends MusicBeatState
|
||||
{
|
||||
public static var leftState:Bool = false;
|
||||
|
||||
override function create()
|
||||
{
|
||||
super.create();
|
||||
var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
|
||||
add(bg);
|
||||
var ver = "v" + Application.current.meta.get('version');
|
||||
var txt:FlxText = new FlxText(0, 0, FlxG.width,
|
||||
"HEY! You're running an outdated version of the game!\nCurrent version is "
|
||||
+ ver
|
||||
+ " while the most recent version is "
|
||||
+ NGio.GAME_VER
|
||||
+ "! Press Space to go to itch.io, or ESCAPE to ignore this!!",
|
||||
32);
|
||||
txt.setFormat("VCR OSD Mono", 32, FlxColor.WHITE, CENTER);
|
||||
txt.screenCenter();
|
||||
add(txt);
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (controls.ACCEPT)
|
||||
{
|
||||
FlxG.openURL("https://ninja-muffin24.itch.io/funkin");
|
||||
}
|
||||
if (controls.BACK)
|
||||
{
|
||||
leftState = true;
|
||||
FlxG.switchState(new MainMenuState());
|
||||
}
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
package game.state.subState;
|
||||
|
||||
import game.state.menus.options.controls.Controls.Control;
|
||||
import game.state.menus.*;
|
||||
import game.data.backend.*;
|
||||
import game.ui.Alphabet;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxSubState;
|
||||
import flixel.addons.transition.FlxTransitionableState;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.input.keyboard.FlxKey;
|
||||
import flixel.system.FlxSound;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.tweens.FlxEase;
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.util.FlxColor;
|
||||
|
||||
class PauseSubState extends MusicBeatSubstate
|
||||
{
|
||||
var grpMenuShit:FlxTypedGroup<Alphabet>;
|
||||
|
||||
var pauseOG:Array<String> = [
|
||||
'Resume',
|
||||
'Restart Song',
|
||||
'Change Difficulty',
|
||||
'Toggle Practice Mode',
|
||||
'Exit to menu'
|
||||
];
|
||||
var difficultyChoices:Array<String> = ['EASY', 'NORMAL', 'HARD', 'BACK'];
|
||||
|
||||
var menuItems:Array<String> = [];
|
||||
var curSelected:Int = 0;
|
||||
|
||||
var pauseMusic:FlxSound;
|
||||
|
||||
var practiceText:FlxText;
|
||||
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
super();
|
||||
|
||||
menuItems = pauseOG;
|
||||
|
||||
pauseMusic = new FlxSound().loadEmbedded(Paths.music('breakfast'), true, true);
|
||||
pauseMusic.volume = 0;
|
||||
pauseMusic.play(false, FlxG.random.int(0, Std.int(pauseMusic.length / 2)));
|
||||
|
||||
FlxG.sound.list.add(pauseMusic);
|
||||
|
||||
var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
|
||||
bg.alpha = 0;
|
||||
bg.scrollFactor.set();
|
||||
add(bg);
|
||||
|
||||
var levelInfo:FlxText = new FlxText(20, 15, 0, "", 32);
|
||||
levelInfo.text += PlayState.SONG.song;
|
||||
levelInfo.scrollFactor.set();
|
||||
levelInfo.setFormat(Paths.font("vcr.ttf"), 32);
|
||||
levelInfo.updateHitbox();
|
||||
add(levelInfo);
|
||||
|
||||
var levelDifficulty:FlxText = new FlxText(20, 15 + 32, 0, "", 32);
|
||||
levelDifficulty.text += CoolUtil.difficultyString();
|
||||
levelDifficulty.scrollFactor.set();
|
||||
levelDifficulty.setFormat(Paths.font('vcr.ttf'), 32);
|
||||
levelDifficulty.updateHitbox();
|
||||
add(levelDifficulty);
|
||||
|
||||
var deathCounter:FlxText = new FlxText(20, 15 + 64, 0, "", 32);
|
||||
deathCounter.text = "Blue balled: " + PlayState.deathCounter;
|
||||
deathCounter.scrollFactor.set();
|
||||
deathCounter.setFormat(Paths.font('vcr.ttf'), 32);
|
||||
deathCounter.updateHitbox();
|
||||
add(deathCounter);
|
||||
|
||||
practiceText = new FlxText(20, 15 + 64 + 32, 0, "PRACTICE MODE", 32);
|
||||
practiceText.scrollFactor.set();
|
||||
practiceText.setFormat(Paths.font('vcr.ttf'), 32);
|
||||
practiceText.updateHitbox();
|
||||
practiceText.x = FlxG.width - (practiceText.width + 20);
|
||||
practiceText.visible = PlayState.practiceMode;
|
||||
add(practiceText);
|
||||
|
||||
levelDifficulty.alpha = 0;
|
||||
levelInfo.alpha = 0;
|
||||
deathCounter.alpha = 0;
|
||||
|
||||
levelInfo.x = FlxG.width - (levelInfo.width + 20);
|
||||
levelDifficulty.x = FlxG.width - (levelDifficulty.width + 20);
|
||||
deathCounter.x = FlxG.width - (deathCounter.width + 20);
|
||||
|
||||
FlxTween.tween(bg, {alpha: 0.6}, 0.4, {ease: FlxEase.quartInOut});
|
||||
FlxTween.tween(levelInfo, {alpha: 1, y: 20}, 0.4, {ease: FlxEase.quartInOut, startDelay: 0.3});
|
||||
FlxTween.tween(levelDifficulty, {alpha: 1, y: levelDifficulty.y + 5}, 0.4, {ease: FlxEase.quartInOut, startDelay: 0.5});
|
||||
FlxTween.tween(deathCounter, {alpha: 1, y: deathCounter.y + 5}, 0.4, {ease: FlxEase.quartInOut, startDelay: 0.7});
|
||||
|
||||
grpMenuShit = new FlxTypedGroup<Alphabet>();
|
||||
add(grpMenuShit);
|
||||
|
||||
regenMenu();
|
||||
|
||||
// cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]];
|
||||
}
|
||||
|
||||
private function regenMenu():Void
|
||||
{
|
||||
while (grpMenuShit.members.length > 0)
|
||||
{
|
||||
grpMenuShit.remove(grpMenuShit.members[0], true);
|
||||
}
|
||||
|
||||
for (i in 0...menuItems.length)
|
||||
{
|
||||
var songText:Alphabet = new Alphabet(0, (70 * i) + 30, menuItems[i], true, false);
|
||||
songText.isMenuItem = true;
|
||||
songText.targetY = i;
|
||||
grpMenuShit.add(songText);
|
||||
}
|
||||
|
||||
curSelected = 0;
|
||||
changeSelection();
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (pauseMusic.volume < 0.5)
|
||||
pauseMusic.volume += 0.01 * elapsed;
|
||||
|
||||
super.update(elapsed);
|
||||
|
||||
var upP = controls.UI_UP_P;
|
||||
var downP = controls.UI_DOWN_P;
|
||||
var accepted = controls.ACCEPT;
|
||||
|
||||
if (upP)
|
||||
{
|
||||
changeSelection(-1);
|
||||
}
|
||||
if (downP)
|
||||
{
|
||||
changeSelection(1);
|
||||
}
|
||||
|
||||
if (accepted)
|
||||
{
|
||||
var daSelected:String = menuItems[curSelected];
|
||||
|
||||
switch (daSelected)
|
||||
{
|
||||
case "Resume":
|
||||
close();
|
||||
case "EASY" | 'NORMAL' | "HARD":
|
||||
PlayState.SONG = Song.loadFromJson(Highscore.formatSong(PlayState.SONG.song.toLowerCase(), curSelected),
|
||||
PlayState.SONG.song.toLowerCase());
|
||||
|
||||
PlayState.storyDifficulty = curSelected;
|
||||
|
||||
FlxG.resetState();
|
||||
|
||||
case 'Toggle Practice Mode':
|
||||
PlayState.practiceMode = !PlayState.practiceMode;
|
||||
practiceText.visible = PlayState.practiceMode;
|
||||
|
||||
case 'Change Difficulty':
|
||||
menuItems = difficultyChoices;
|
||||
regenMenu();
|
||||
case 'BACK':
|
||||
menuItems = pauseOG;
|
||||
regenMenu();
|
||||
case "Restart Song":
|
||||
FlxG.resetState();
|
||||
case "Exit to menu":
|
||||
PlayState.seenCutscene = false;
|
||||
PlayState.deathCounter = 0;
|
||||
if (PlayState.isStoryMode)
|
||||
FlxG.switchState(new StoryMenuState());
|
||||
else
|
||||
FlxG.switchState(new FreeplayState());
|
||||
}
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.J)
|
||||
{
|
||||
// for reference later!
|
||||
// PlayerSettings.player1.controls.replaceBinding(Control.LEFT, Keys, FlxKey.J, null);
|
||||
}
|
||||
}
|
||||
|
||||
override function destroy()
|
||||
{
|
||||
pauseMusic.destroy();
|
||||
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
function changeSelection(change:Int = 0):Void
|
||||
{
|
||||
FlxG.sound.play(Paths.sound('scrollMenu'), 0.4);
|
||||
|
||||
curSelected += change;
|
||||
|
||||
if (curSelected < 0)
|
||||
curSelected = menuItems.length - 1;
|
||||
if (curSelected >= menuItems.length)
|
||||
curSelected = 0;
|
||||
|
||||
var bullShit:Int = 0;
|
||||
|
||||
for (item in grpMenuShit.members)
|
||||
{
|
||||
item.targetY = bullShit - curSelected;
|
||||
bullShit++;
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
package game.state.subState;
|
||||
|
||||
import game.ui.*;
|
||||
import game.ui.AtlasText.BoldText;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.util.FlxColor;
|
||||
|
||||
class Prompt extends flixel.FlxSubState
|
||||
{
|
||||
inline static var MARGIN = 100;
|
||||
|
||||
public var onYes:Void->Void;
|
||||
public var onNo:Void->Void;
|
||||
public var buttons:TextMenuList;
|
||||
public var field:AtlasText;
|
||||
public var back:FlxSprite;
|
||||
|
||||
var style:ButtonStyle;
|
||||
|
||||
public function new (text:String, style:ButtonStyle = Ok)
|
||||
{
|
||||
this.style = style;
|
||||
super(0x80000000);
|
||||
|
||||
buttons = new TextMenuList(Horizontal);
|
||||
|
||||
field = new BoldText(text);
|
||||
field.scrollFactor.set(0, 0);
|
||||
}
|
||||
|
||||
override function create()
|
||||
{
|
||||
super.create();
|
||||
|
||||
field.y = MARGIN;
|
||||
field.screenCenter(X);
|
||||
add(field);
|
||||
|
||||
createButtons();
|
||||
add(buttons);
|
||||
}
|
||||
|
||||
public function createBg(width:Int, height:Int, color = 0xFF808080)
|
||||
{
|
||||
back = new FlxSprite();
|
||||
back.makeGraphic(width, height, color, false, "prompt-bg");
|
||||
back.screenCenter(XY);
|
||||
add(back);
|
||||
members.unshift(members.pop());// bring to front
|
||||
}
|
||||
|
||||
|
||||
public function createBgFromMargin(margin = MARGIN, color = 0xFF808080)
|
||||
{
|
||||
createBg(Std.int(FlxG.width - margin * 2), Std.int(FlxG.height - margin * 2), color);
|
||||
}
|
||||
|
||||
public function setButtons(style:ButtonStyle)
|
||||
{
|
||||
if (this.style != style)
|
||||
{
|
||||
this.style = style;
|
||||
createButtons();
|
||||
}
|
||||
}
|
||||
|
||||
function createButtons()
|
||||
{
|
||||
// destroy previous buttons
|
||||
while(buttons.members.length > 0)
|
||||
{
|
||||
buttons.remove(buttons.members[0], true).destroy();
|
||||
}
|
||||
|
||||
switch(style)
|
||||
{
|
||||
case Yes_No : createButtonsHelper("yes", "no");
|
||||
case Ok : createButtonsHelper("ok");
|
||||
case Custom(yes, no): createButtonsHelper(yes, no);
|
||||
case None : buttons.exists = false;
|
||||
};
|
||||
}
|
||||
|
||||
function createButtonsHelper(yes:String, ?no:String)
|
||||
{
|
||||
buttons.exists = true;
|
||||
// pass anonymous functions rather than the current callbacks, in case they change later
|
||||
var yesButton = buttons.createItem(yes, function() onYes());
|
||||
yesButton.screenCenter(X);
|
||||
yesButton.y = FlxG.height - yesButton.height - MARGIN;
|
||||
yesButton.scrollFactor.set(0, 0);
|
||||
if (no != null)
|
||||
{
|
||||
// place right
|
||||
yesButton.x = FlxG.width - yesButton.width - MARGIN;
|
||||
|
||||
var noButton = buttons.createItem(no, function() onNo());
|
||||
noButton.x = MARGIN;
|
||||
noButton.y = FlxG.height - noButton.height - MARGIN;
|
||||
noButton.scrollFactor.set(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public function setText(text:String)
|
||||
{
|
||||
field.text = text;
|
||||
field.screenCenter(X);
|
||||
}
|
||||
}
|
||||
|
||||
enum ButtonStyle
|
||||
{
|
||||
Ok;
|
||||
Yes_No;
|
||||
Custom(yes:String, no:Null<String>);//Todo: more than 2
|
||||
None;
|
||||
}
|
|
@ -0,0 +1,310 @@
|
|||
package game.ui;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.group.FlxSpriteGroup;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.util.FlxTimer;
|
||||
|
||||
using StringTools;
|
||||
|
||||
/**
|
||||
* Loosley based on FlxTypeText lolol
|
||||
*/
|
||||
class Alphabet extends FlxSpriteGroup
|
||||
{
|
||||
public var delay:Float = 0.05;
|
||||
public var paused:Bool = false;
|
||||
|
||||
// for menu shit
|
||||
public var targetY:Float = 0;
|
||||
public var targetX:Float = 0;
|
||||
public var isMenuItem:Bool = false;
|
||||
|
||||
public var text:String = "";
|
||||
|
||||
var _finalText:String = "";
|
||||
var _curText:String = "";
|
||||
|
||||
public var widthOfWords:Float = FlxG.width;
|
||||
|
||||
var yMulti:Float = 1;
|
||||
|
||||
// custom shit
|
||||
// amp, backslash, question mark, apostrophy, comma, angry faic, period
|
||||
var lastSprite:AlphaCharacter;
|
||||
var xPosResetted:Bool = false;
|
||||
var lastWasSpace:Bool = false;
|
||||
|
||||
var splitWords:Array<String> = [];
|
||||
|
||||
var isBold:Bool = false;
|
||||
|
||||
public function new(x:Float = 0.0, y:Float = 0.0, text:String = "", ?bold:Bool = false, typed:Bool = false)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
_finalText = text;
|
||||
this.text = text;
|
||||
isBold = bold;
|
||||
|
||||
if (text != "")
|
||||
{
|
||||
if (typed)
|
||||
{
|
||||
startTypedText();
|
||||
}
|
||||
else
|
||||
{
|
||||
addText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function addText()
|
||||
{
|
||||
doSplitWords();
|
||||
|
||||
var xPos:Float = 0;
|
||||
for (character in splitWords)
|
||||
{
|
||||
// if (character.fastCodeAt() == " ")
|
||||
// {
|
||||
// }
|
||||
|
||||
if (character == " " || character == "-")
|
||||
{
|
||||
lastWasSpace = true;
|
||||
}
|
||||
|
||||
if (AlphaCharacter.alphabet.indexOf(character.toLowerCase()) != -1)
|
||||
// if (AlphaCharacter.alphabet.contains(character.toLowerCase()))
|
||||
{
|
||||
if (lastSprite != null)
|
||||
{
|
||||
xPos = lastSprite.x + lastSprite.width;
|
||||
}
|
||||
|
||||
if (lastWasSpace)
|
||||
{
|
||||
xPos += 40;
|
||||
lastWasSpace = false;
|
||||
}
|
||||
|
||||
// var letter:AlphaCharacter = new AlphaCharacter(30 * loopNum, 0);
|
||||
var letter:AlphaCharacter = new AlphaCharacter(xPos, 0);
|
||||
|
||||
if (isBold)
|
||||
letter.createBold(character);
|
||||
else
|
||||
{
|
||||
letter.createLetter(character);
|
||||
}
|
||||
|
||||
add(letter);
|
||||
|
||||
lastSprite = letter;
|
||||
}
|
||||
|
||||
// loopNum += 1;
|
||||
}
|
||||
}
|
||||
|
||||
function doSplitWords():Void
|
||||
{
|
||||
splitWords = _finalText.split("");
|
||||
}
|
||||
|
||||
public var personTalking:String = 'gf';
|
||||
|
||||
public function startTypedText():Void
|
||||
{
|
||||
_finalText = text;
|
||||
doSplitWords();
|
||||
|
||||
// trace(arrayShit);
|
||||
|
||||
var loopNum:Int = 0;
|
||||
|
||||
var xPos:Float = 0;
|
||||
var curRow:Int = 0;
|
||||
|
||||
new FlxTimer().start(0.05, function(tmr:FlxTimer)
|
||||
{
|
||||
// trace(_finalText.fastCodeAt(loopNum) + " " + _finalText.charAt(loopNum));
|
||||
if (_finalText.fastCodeAt(loopNum) == "\n".code)
|
||||
{
|
||||
yMulti += 1;
|
||||
xPosResetted = true;
|
||||
xPos = 0;
|
||||
curRow += 1;
|
||||
}
|
||||
|
||||
if (splitWords[loopNum] == " ")
|
||||
{
|
||||
lastWasSpace = true;
|
||||
}
|
||||
|
||||
#if (haxe >= "4.0.0")
|
||||
var isNumber:Bool = AlphaCharacter.numbers.contains(splitWords[loopNum]);
|
||||
var isSymbol:Bool = AlphaCharacter.symbols.contains(splitWords[loopNum]);
|
||||
#else
|
||||
var isNumber:Bool = AlphaCharacter.numbers.indexOf(splitWords[loopNum]) != -1;
|
||||
var isSymbol:Bool = AlphaCharacter.symbols.indexOf(splitWords[loopNum]) != -1;
|
||||
#end
|
||||
|
||||
if (AlphaCharacter.alphabet.indexOf(splitWords[loopNum].toLowerCase()) != -1 || isNumber || isSymbol)
|
||||
// if (AlphaCharacter.alphabet.contains(splitWords[loopNum].toLowerCase()) || isNumber || isSymbol)
|
||||
|
||||
{
|
||||
if (lastSprite != null && !xPosResetted)
|
||||
{
|
||||
lastSprite.updateHitbox();
|
||||
xPos += lastSprite.width + 3;
|
||||
// if (isBold)
|
||||
// xPos -= 80;
|
||||
}
|
||||
else
|
||||
{
|
||||
xPosResetted = false;
|
||||
}
|
||||
|
||||
if (lastWasSpace)
|
||||
{
|
||||
xPos += 20;
|
||||
lastWasSpace = false;
|
||||
}
|
||||
// trace(_finalText.fastCodeAt(loopNum) + " " + _finalText.charAt(loopNum));
|
||||
|
||||
// var letter:AlphaCharacter = new AlphaCharacter(30 * loopNum, 0);
|
||||
var letter:AlphaCharacter = new AlphaCharacter(xPos, 55 * yMulti);
|
||||
letter.row = curRow;
|
||||
if (isBold)
|
||||
{
|
||||
letter.createBold(splitWords[loopNum]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isNumber)
|
||||
{
|
||||
letter.createNumber(splitWords[loopNum]);
|
||||
}
|
||||
else if (isSymbol)
|
||||
{
|
||||
letter.createSymbol(splitWords[loopNum]);
|
||||
}
|
||||
else
|
||||
{
|
||||
letter.createLetter(splitWords[loopNum]);
|
||||
}
|
||||
|
||||
letter.x += 90;
|
||||
}
|
||||
|
||||
if (FlxG.random.bool(40))
|
||||
{
|
||||
var daSound:String = "GF_";
|
||||
FlxG.sound.play(Paths.soundRandom(daSound, 1, 4));
|
||||
}
|
||||
|
||||
add(letter);
|
||||
|
||||
lastSprite = letter;
|
||||
}
|
||||
|
||||
loopNum += 1;
|
||||
|
||||
tmr.time = FlxG.random.float(0.04, 0.09);
|
||||
}, splitWords.length);
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (isMenuItem)
|
||||
{
|
||||
var scaledY = FlxMath.remapToRange(targetY, 0, 1, 0, 1.3);
|
||||
|
||||
y = CoolUtil.coolLerp(y, (scaledY * 120) + (FlxG.height * 0.48), 0.16);
|
||||
x = CoolUtil.coolLerp(x, (targetY * 20) + 90, 0.16);
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
class AlphaCharacter extends FlxSprite
|
||||
{
|
||||
public static var alphabet:String = "abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
public static var numbers:String = "1234567890";
|
||||
|
||||
public static var symbols:String = "|~#$%()*+-:;<=>@[]^_.,'!?";
|
||||
|
||||
public var row:Int = 0;
|
||||
|
||||
public function new(x:Float, y:Float)
|
||||
{
|
||||
super(x, y);
|
||||
var tex = Paths.getSparrowAtlas('alphabet');
|
||||
frames = tex;
|
||||
|
||||
antialiasing = true;
|
||||
}
|
||||
|
||||
public function createBold(letter:String)
|
||||
{
|
||||
animation.addByPrefix(letter, letter.toUpperCase() + " bold", 24);
|
||||
animation.play(letter);
|
||||
updateHitbox();
|
||||
}
|
||||
|
||||
public function createLetter(letter:String):Void
|
||||
{
|
||||
var letterCase:String = "lowercase";
|
||||
if (letter.toLowerCase() != letter)
|
||||
{
|
||||
letterCase = 'capital';
|
||||
}
|
||||
|
||||
animation.addByPrefix(letter, letter + " " + letterCase, 24);
|
||||
animation.play(letter);
|
||||
updateHitbox();
|
||||
|
||||
FlxG.log.add('the row' + row);
|
||||
|
||||
y = (110 - height);
|
||||
y += row * 60;
|
||||
}
|
||||
|
||||
public function createNumber(letter:String):Void
|
||||
{
|
||||
animation.addByPrefix(letter, letter, 24);
|
||||
animation.play(letter);
|
||||
|
||||
updateHitbox();
|
||||
}
|
||||
|
||||
public function createSymbol(letter:String)
|
||||
{
|
||||
switch (letter)
|
||||
{
|
||||
case '.':
|
||||
animation.addByPrefix(letter, 'period', 24);
|
||||
animation.play(letter);
|
||||
y += 50;
|
||||
case "'":
|
||||
animation.addByPrefix(letter, 'apostraphie', 24);
|
||||
animation.play(letter);
|
||||
y -= 0;
|
||||
case "?":
|
||||
animation.addByPrefix(letter, 'question mark', 24);
|
||||
animation.play(letter);
|
||||
case "!":
|
||||
animation.addByPrefix(letter, 'exclamation point', 24);
|
||||
animation.play(letter);
|
||||
}
|
||||
|
||||
updateHitbox();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package game.ui;
|
||||
|
||||
import game.ui.MenuList;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
|
||||
typedef AtlasAsset = flixel.util.typeLimit.OneOfTwo<String, FlxAtlasFrames>;
|
||||
|
||||
class AtlasMenuList extends MenuTypedList<AtlasMenuItem>
|
||||
{
|
||||
public var atlas:FlxAtlasFrames;
|
||||
|
||||
public function new (atlas, navControls:NavControls = Vertical, ?wrapMode)
|
||||
{
|
||||
super(navControls, wrapMode);
|
||||
|
||||
if (Std.isOfType(atlas, String))
|
||||
this.atlas = Paths.getSparrowAtlas(cast atlas);
|
||||
else
|
||||
this.atlas = cast atlas;
|
||||
}
|
||||
|
||||
public function createItem(x = 0.0, y = 0.0, name, callback, fireInstantly = false)
|
||||
{
|
||||
var item = new AtlasMenuItem(x, y, name, atlas, callback);
|
||||
item.fireInstantly = fireInstantly;
|
||||
return addItem(name, item);
|
||||
}
|
||||
|
||||
override function destroy()
|
||||
{
|
||||
super.destroy();
|
||||
atlas = null;
|
||||
}
|
||||
}
|
||||
|
||||
class AtlasMenuItem extends MenuItem
|
||||
{
|
||||
var atlas:FlxAtlasFrames;
|
||||
public function new (x = 0.0, y = 0.0, name:String, atlas:FlxAtlasFrames, callback)
|
||||
{
|
||||
this.atlas = atlas;
|
||||
super(x, y, name, callback);
|
||||
}
|
||||
|
||||
override function setData(name:String, ?callback:Void->Void)
|
||||
{
|
||||
frames = atlas;
|
||||
animation.addByPrefix('idle', '$name idle', 24);
|
||||
animation.addByPrefix('selected', '$name selected', 24);
|
||||
|
||||
super.setData(name, callback);
|
||||
}
|
||||
|
||||
function changeAnim(animName:String)
|
||||
{
|
||||
animation.play(animName);
|
||||
updateHitbox();
|
||||
}
|
||||
|
||||
override function idle()
|
||||
{
|
||||
changeAnim('idle');
|
||||
}
|
||||
|
||||
override function select()
|
||||
{
|
||||
changeAnim('selected');
|
||||
}
|
||||
|
||||
override function get_selected()
|
||||
{
|
||||
return animation.curAnim != null && animation.curAnim.name == "selected";
|
||||
}
|
||||
|
||||
override function destroy()
|
||||
{
|
||||
super.destroy();
|
||||
atlas = null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,262 @@
|
|||
package game.ui;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import flixel.group.FlxSpriteGroup;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.util.FlxStringUtil;
|
||||
|
||||
@:forward
|
||||
abstract BoldText(AtlasText) from AtlasText to AtlasText
|
||||
{
|
||||
inline public function new (x = 0.0, y = 0.0, text:String)
|
||||
{
|
||||
this = new AtlasText(x, y, text, Bold);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alphabet.hx has a ton of bugs and does a bunch of stuff I don't need, fuck that class
|
||||
*/
|
||||
class AtlasText extends FlxTypedSpriteGroup<AtlasChar>
|
||||
{
|
||||
static var fonts = new Map<AtlasFont, AtlasFontData>();
|
||||
static var casesAllowed = new Map<AtlasFont, Case>();
|
||||
public var text(default, set):String = "";
|
||||
|
||||
var font:AtlasFontData;
|
||||
|
||||
public var atlas(get, never):FlxAtlasFrames;
|
||||
inline function get_atlas() return font.atlas;
|
||||
public var caseAllowed(get, never):Case;
|
||||
inline function get_caseAllowed() return font.caseAllowed;
|
||||
public var maxHeight(get, never):Float;
|
||||
inline function get_maxHeight() return font.maxHeight;
|
||||
|
||||
public function new (x = 0.0, y = 0.0, text:String, fontName:AtlasFont = Default)
|
||||
{
|
||||
if (!fonts.exists(fontName))
|
||||
fonts[fontName] = new AtlasFontData(fontName);
|
||||
font = fonts[fontName];
|
||||
|
||||
super(x, y);
|
||||
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
function set_text(value:String)
|
||||
{
|
||||
if (value == null)
|
||||
value = "";
|
||||
|
||||
var caseValue = restrictCase(value);
|
||||
var caseText = restrictCase(this.text);
|
||||
|
||||
this.text = value;
|
||||
if (caseText == caseValue)
|
||||
return value; // cancel redraw
|
||||
|
||||
if (caseValue.indexOf(caseText) == 0)
|
||||
{
|
||||
// new text is just old text with additions at the end, append the difference
|
||||
appendTextCased(caseValue.substr(caseText.length));
|
||||
return this.text;
|
||||
}
|
||||
|
||||
value = caseValue;
|
||||
|
||||
group.kill();
|
||||
|
||||
if (value == "")
|
||||
return this.text;
|
||||
|
||||
appendTextCased(caseValue);
|
||||
return this.text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new characters, without needing to redraw the previous characters
|
||||
* @param text The text to add.
|
||||
* @throws String if `text` is null.
|
||||
*/
|
||||
public function appendText(text:String)
|
||||
{
|
||||
if (text == null)
|
||||
throw "cannot append null";
|
||||
|
||||
if (text == "")
|
||||
return;
|
||||
|
||||
this.text = this.text + text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts all characters to fit the font's `allowedCase`.
|
||||
* @param text
|
||||
*/
|
||||
function restrictCase(text:String)
|
||||
{
|
||||
return switch(caseAllowed)
|
||||
{
|
||||
case Both: text;
|
||||
case Upper: text.toUpperCase();
|
||||
case Lower: text.toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new text on top of the existing text. Helper for other methods; DOESN'T CHANGE `this.text`.
|
||||
* @param text The text to add, assumed to match the font's `caseAllowed`.
|
||||
*/
|
||||
function appendTextCased(text:String)
|
||||
{
|
||||
var charCount = group.countLiving();
|
||||
var xPos:Float = 0;
|
||||
var yPos:Float = 0;
|
||||
// `countLiving` returns -1 if group is empty
|
||||
if (charCount == -1)
|
||||
charCount = 0;
|
||||
else if (charCount > 0)
|
||||
{
|
||||
var lastChar = group.members[charCount - 1];
|
||||
xPos = lastChar.x + lastChar.width - x;
|
||||
yPos = lastChar.y + lastChar.height - maxHeight - y;
|
||||
}
|
||||
|
||||
var splitValues = text.split("");
|
||||
for (i in 0...splitValues.length)
|
||||
{
|
||||
switch(splitValues[i])
|
||||
{
|
||||
case " ":
|
||||
{
|
||||
xPos += 40;
|
||||
}
|
||||
case "\n":
|
||||
{
|
||||
xPos = 0;
|
||||
yPos += maxHeight;
|
||||
}
|
||||
case char:
|
||||
{
|
||||
var charSprite:AtlasChar;
|
||||
if (group.members.length <= charCount)
|
||||
charSprite = new AtlasChar(atlas, char);
|
||||
else
|
||||
{
|
||||
charSprite = group.members[charCount];
|
||||
charSprite.revive();
|
||||
charSprite.char = char;
|
||||
charSprite.alpha = 1;//gets multiplied when added
|
||||
}
|
||||
charSprite.x = xPos;
|
||||
charSprite.y = yPos + maxHeight - charSprite.height;
|
||||
add(charSprite);
|
||||
|
||||
xPos += charSprite.width;
|
||||
charCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override function toString()
|
||||
{
|
||||
return "InputItem, " + FlxStringUtil.getDebugString(
|
||||
[ LabelValuePair.weak("x", x)
|
||||
, LabelValuePair.weak("y", y)
|
||||
, LabelValuePair.weak("text", text)
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AtlasChar extends FlxSprite
|
||||
{
|
||||
public var char(default, set):String;
|
||||
public function new(x = 0.0, y = 0.0, atlas:FlxAtlasFrames, char:String)
|
||||
{
|
||||
super(x, y);
|
||||
frames = atlas;
|
||||
this.char = char;
|
||||
antialiasing = true;
|
||||
}
|
||||
|
||||
function set_char(value:String)
|
||||
{
|
||||
if (this.char != value)
|
||||
{
|
||||
var prefix = getAnimPrefix(value);
|
||||
animation.addByPrefix("anim", prefix, 24);
|
||||
animation.play("anim");
|
||||
updateHitbox();
|
||||
}
|
||||
|
||||
return this.char = value;
|
||||
}
|
||||
|
||||
function getAnimPrefix(char:String)
|
||||
{
|
||||
return switch (char)
|
||||
{
|
||||
case '-': '-dash-';
|
||||
case '.': '-period-';
|
||||
case ",": '-comma-';
|
||||
case "'": '-apostraphie-';
|
||||
case "?": '-question mark-';
|
||||
case "!": '-exclamation point-';
|
||||
case "\\": '-back slash-';
|
||||
case "/": '-forward slash-';
|
||||
case "*": '-multiply x-';
|
||||
case "“": '-start quote-';
|
||||
case "”": '-end quote-';
|
||||
default: char;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class AtlasFontData
|
||||
{
|
||||
static public var upperChar = ~/^[A-Z]\d+$/;
|
||||
static public var lowerChar = ~/^[a-z]\d+$/;
|
||||
|
||||
public var atlas:FlxAtlasFrames;
|
||||
public var maxHeight:Float = 0.0;
|
||||
public var caseAllowed:Case = Both;
|
||||
|
||||
public function new (name:AtlasFont)
|
||||
{
|
||||
atlas = Paths.getSparrowAtlas("fonts/" + name.getName().toLowerCase());
|
||||
atlas.parent.destroyOnNoUse = false;
|
||||
atlas.parent.persist = true;
|
||||
|
||||
var containsUpper = false;
|
||||
var containsLower = false;
|
||||
|
||||
for (frame in atlas.frames)
|
||||
{
|
||||
maxHeight = Math.max(maxHeight, frame.frame.height);
|
||||
|
||||
if (!containsUpper)
|
||||
containsUpper = upperChar.match(frame.name);
|
||||
|
||||
if (!containsLower)
|
||||
containsLower = lowerChar.match(frame.name);
|
||||
}
|
||||
|
||||
if (containsUpper != containsLower)
|
||||
caseAllowed = containsUpper ? Upper : Lower;
|
||||
}
|
||||
}
|
||||
|
||||
enum Case
|
||||
{
|
||||
Both;
|
||||
Upper;
|
||||
Lower;
|
||||
}
|
||||
|
||||
enum AtlasFont
|
||||
{
|
||||
Default;
|
||||
Bold;
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package game.ui;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.addons.effects.chainable.FlxEffectSprite;
|
||||
import flixel.addons.effects.chainable.FlxOutlineEffect;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.util.FlxColor;
|
||||
|
||||
class ColorsMenu extends ui.OptionsState.Page
|
||||
{
|
||||
var curSelected:Int = 0;
|
||||
|
||||
var grpNotes:FlxTypedGroup<Note>;
|
||||
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
|
||||
grpNotes = new FlxTypedGroup<Note>();
|
||||
add(grpNotes);
|
||||
|
||||
for (i in 0...4)
|
||||
{
|
||||
var note:Note = new Note(0, i);
|
||||
|
||||
note.x = (100 * i) + i;
|
||||
note.screenCenter(Y);
|
||||
|
||||
var _effectSpr:FlxEffectSprite = new FlxEffectSprite(note, [new FlxOutlineEffect(FlxOutlineMode.FAST, FlxColor.WHITE, 4, 1)]);
|
||||
add(_effectSpr);
|
||||
_effectSpr.y = 0;
|
||||
_effectSpr.x = i * 130;
|
||||
_effectSpr.antialiasing = true;
|
||||
_effectSpr.scale.x = _effectSpr.scale.y = 0.7;
|
||||
// _effectSpr.setGraphicSize();
|
||||
_effectSpr.height = note.height;
|
||||
_effectSpr.width = note.width;
|
||||
|
||||
// _effectSpr.updateHitbox();
|
||||
|
||||
grpNotes.add(note);
|
||||
}
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (controls.UI_RIGHT_P)
|
||||
curSelected += 1;
|
||||
if (controls.UI_LEFT_P)
|
||||
curSelected -= 1;
|
||||
|
||||
if (curSelected < 0)
|
||||
curSelected = grpNotes.members.length - 1;
|
||||
if (curSelected >= grpNotes.members.length)
|
||||
curSelected = 0;
|
||||
|
||||
if (controls.UI_UP)
|
||||
{
|
||||
grpNotes.members[curSelected].colorSwap.update(elapsed * 0.3);
|
||||
Note.arrowColors[curSelected] += elapsed * 0.3;
|
||||
}
|
||||
|
||||
if (controls.UI_DOWN)
|
||||
{
|
||||
grpNotes.members[curSelected].colorSwap.update(-elapsed * 0.3);
|
||||
Note.arrowColors[curSelected] += -elapsed * 0.3;
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,369 @@
|
|||
package game.ui;
|
||||
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.effects.FlxFlicker;
|
||||
import flixel.group.FlxGroup;
|
||||
import flixel.util.FlxSignal;
|
||||
|
||||
import game.data.PlayerSettings;
|
||||
|
||||
class MenuTypedList<T:MenuItem> extends FlxTypedGroup<T>
|
||||
{
|
||||
public var selectedIndex(default, null) = 0;
|
||||
public var selectedItem(get, never):T;
|
||||
/** Called when a new item is highlighted */
|
||||
public var onChange(default, null) = new FlxTypedSignal<T->Void>();
|
||||
/** Called when an item is accepted */
|
||||
public var onAcceptPress(default, null) = new FlxTypedSignal<T->Void>();
|
||||
/** The navigation control scheme to use */
|
||||
public var navControls:NavControls;
|
||||
/** Set to false to disable nav control */
|
||||
public var enabled:Bool = true;
|
||||
/** */
|
||||
public var wrapMode:WrapMode = Both;
|
||||
|
||||
var byName = new Map<String, T>();
|
||||
/** Set to true, internally to disable controls, without affecting vars like `enabled` */
|
||||
public var busy(default, null):Bool = false;
|
||||
// bit awkward because BACK is also a menu control and this doesn't affect that
|
||||
|
||||
public function new (navControls:NavControls = Vertical, ?wrapMode:WrapMode)
|
||||
{
|
||||
this.navControls = navControls;
|
||||
|
||||
if (wrapMode != null)
|
||||
this.wrapMode = wrapMode;
|
||||
else
|
||||
this.wrapMode = switch (navControls)
|
||||
{
|
||||
case Horizontal: Horizontal;
|
||||
case Vertical: Vertical;
|
||||
default: Both;
|
||||
}
|
||||
super();
|
||||
}
|
||||
|
||||
public function addItem(name:String, item:T):T
|
||||
{
|
||||
if (length == selectedIndex)
|
||||
item.select();
|
||||
|
||||
byName[name] = item;
|
||||
return add(item);
|
||||
}
|
||||
|
||||
public function resetItem(oldName:String, newName:String, ?callback:Void->Void):T
|
||||
{
|
||||
if (!byName.exists(oldName))
|
||||
throw "No item named:" + oldName;
|
||||
|
||||
var item = byName[oldName];
|
||||
byName.remove(oldName);
|
||||
byName[newName] = item;
|
||||
item.setItem(newName, callback);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
if (enabled && !busy)
|
||||
updateControls();
|
||||
}
|
||||
|
||||
inline function updateControls()
|
||||
{
|
||||
var controls = PlayerSettings.player1.controls;
|
||||
|
||||
var wrapX = wrapMode.match(Horizontal | Both);
|
||||
var wrapY = wrapMode.match(Vertical | Both);
|
||||
var newIndex = switch(navControls)
|
||||
{
|
||||
case Vertical : navList(controls.UI_UP_P , controls.UI_DOWN_P, wrapY);
|
||||
case Horizontal : navList(controls.UI_LEFT_P, controls.UI_RIGHT_P, wrapX);
|
||||
case Both : navList(controls.UI_LEFT_P || controls.UI_UP_P, controls.UI_RIGHT_P || controls.UI_DOWN_P, !wrapMode.match(None));
|
||||
|
||||
case Columns(num): navGrid(num, controls.UI_LEFT_P, controls.UI_RIGHT_P, wrapX, controls.UI_UP_P , controls.UI_DOWN_P , wrapY);
|
||||
case Rows (num): navGrid(num, controls.UI_UP_P , controls.UI_DOWN_P , wrapY, controls.UI_LEFT_P, controls.UI_RIGHT_P, wrapX);
|
||||
}
|
||||
|
||||
if (newIndex != selectedIndex)
|
||||
{
|
||||
FlxG.sound.play(Paths.sound('scrollMenu'));
|
||||
selectItem(newIndex);
|
||||
}
|
||||
|
||||
//Todo: bypass popup blocker on firefox
|
||||
if (controls.ACCEPT)
|
||||
accept();
|
||||
}
|
||||
|
||||
function navAxis(index:Int, size:Int, prev:Bool, next:Bool, allowWrap:Bool):Int
|
||||
{
|
||||
if (prev == next)
|
||||
return index;
|
||||
|
||||
if (prev)
|
||||
{
|
||||
if (index > 0)
|
||||
index--;
|
||||
else if (allowWrap)
|
||||
index = size - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index < size - 1)
|
||||
index++;
|
||||
else if (allowWrap)
|
||||
index = 0;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls navigation on a linear list of items such as Vertical.
|
||||
* @param prev
|
||||
* @param next
|
||||
* @param allowWrap
|
||||
*/
|
||||
inline function navList(prev:Bool, next:Bool, allowWrap:Bool)
|
||||
{
|
||||
return navAxis(selectedIndex, length, prev, next, allowWrap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls navigation on a grid
|
||||
* @param latSize The size of the fixed axis of the grid, or the "lateral axis"
|
||||
* @param latPrev Whether the 'prev' key is pressed along the fixed-lengthed axis. eg: "left" in Column mode
|
||||
* @param latNext Whether the 'next' key is pressed along the fixed-lengthed axis. eg: "right" in Column mode
|
||||
* @param prev Whether the 'prev' key is pressed along the variable-lengthed axis. eg: "up" in Column mode
|
||||
* @param next Whether the 'next' key is pressed along the variable-lengthed axis. eg: "down" in Column mode
|
||||
* @param allowWrap unused
|
||||
*/
|
||||
function navGrid(latSize:Int, latPrev:Bool, latNext:Bool, latAllowWrap:Bool, prev:Bool, next:Bool, allowWrap:Bool):Int
|
||||
{
|
||||
// The grid lenth along the variable-length axis
|
||||
var size = Math.ceil(length / latSize);
|
||||
// The selected position along the variable-length axis
|
||||
var index = Math.floor(selectedIndex / latSize);
|
||||
// The selected position along the fixed axis
|
||||
var latIndex = selectedIndex % latSize;
|
||||
|
||||
latIndex = navAxis(latIndex, latSize, latPrev, latNext, latAllowWrap);
|
||||
index = navAxis(index, size, prev, next, allowWrap);
|
||||
|
||||
return Std.int(Math.min(length - 1, index * latSize + latIndex));
|
||||
}
|
||||
|
||||
public function accept()
|
||||
{
|
||||
var selected = members[selectedIndex];
|
||||
onAcceptPress.dispatch(selected);
|
||||
|
||||
if (selected.fireInstantly)
|
||||
selected.callback();
|
||||
else
|
||||
{
|
||||
busy = true;
|
||||
FlxG.sound.play(Paths.sound('confirmMenu'));
|
||||
FlxFlicker.flicker(selected, 1, 0.06, true, false, function(_)
|
||||
{
|
||||
busy = false;
|
||||
selected.callback();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public function selectItem(index:Int)
|
||||
{
|
||||
members[selectedIndex].idle();
|
||||
|
||||
selectedIndex = index;
|
||||
|
||||
var selected = members[selectedIndex];
|
||||
selected.select();
|
||||
onChange.dispatch(selected);
|
||||
}
|
||||
|
||||
public function has(name:String)
|
||||
{
|
||||
return byName.exists(name);
|
||||
}
|
||||
|
||||
public function getItem(name:String)
|
||||
{
|
||||
return byName[name];
|
||||
}
|
||||
|
||||
override function destroy()
|
||||
{
|
||||
super.destroy();
|
||||
byName.clear();
|
||||
onChange.removeAll();
|
||||
onAcceptPress.removeAll();
|
||||
}
|
||||
|
||||
inline function get_selectedItem():T
|
||||
{
|
||||
return members[selectedIndex];
|
||||
}
|
||||
}
|
||||
|
||||
class MenuItem extends FlxSprite
|
||||
{
|
||||
public var callback:Void->Void;
|
||||
public var name:String;
|
||||
/**
|
||||
* Set to true for things like opening URLs otherwise, it may it get blocked.
|
||||
*/
|
||||
public var fireInstantly = false;
|
||||
public var selected(get, never):Bool;
|
||||
function get_selected() return alpha == 1.0;
|
||||
|
||||
public function new (x = 0.0, y = 0.0, name:String, callback)
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
antialiasing = true;
|
||||
setData(name, callback);
|
||||
idle();
|
||||
}
|
||||
|
||||
function setData(name:String, ?callback:Void->Void)
|
||||
{
|
||||
this.name = name;
|
||||
|
||||
if (callback != null)
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls setData and resets/redraws the state of the item
|
||||
* @param name the label.
|
||||
* @param callback Unchanged if null.
|
||||
*/
|
||||
public function setItem(name:String, ?callback:Void->Void)
|
||||
{
|
||||
setData(name, callback);
|
||||
|
||||
if (selected)
|
||||
select();
|
||||
else
|
||||
idle();
|
||||
}
|
||||
|
||||
public function idle()
|
||||
{
|
||||
alpha = 0.6;
|
||||
}
|
||||
|
||||
public function select()
|
||||
{
|
||||
alpha = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
class MenuTypedItem<T:FlxSprite> extends MenuItem
|
||||
{
|
||||
public var label(default, set):T;
|
||||
|
||||
public function new (x = 0.0, y = 0.0, label:T, name:String, callback)
|
||||
{
|
||||
super(x, y, name, callback);
|
||||
// set label after super otherwise setters fuck up
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this when you only want to show the label
|
||||
*/
|
||||
function setEmptyBackground()
|
||||
{
|
||||
var oldWidth = width;
|
||||
var oldHeight = height;
|
||||
makeGraphic(1, 1, 0x0);
|
||||
width = oldWidth;
|
||||
height = oldHeight;
|
||||
}
|
||||
|
||||
function set_label(value:T)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
value.x = x;
|
||||
value.y = y;
|
||||
value.alpha = alpha;
|
||||
}
|
||||
return this.label = value;
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
if (label != null)
|
||||
label.update(elapsed);
|
||||
}
|
||||
|
||||
override function draw()
|
||||
{
|
||||
super.draw();
|
||||
if (label != null)
|
||||
{
|
||||
label.cameras = cameras;
|
||||
label.scrollFactor.copyFrom(scrollFactor);
|
||||
label.draw();
|
||||
}
|
||||
}
|
||||
|
||||
override function set_alpha(value:Float):Float
|
||||
{
|
||||
super.set_alpha(value);
|
||||
|
||||
if (label != null)
|
||||
label.alpha = alpha;
|
||||
|
||||
return alpha;
|
||||
}
|
||||
|
||||
override function set_x(value:Float):Float
|
||||
{
|
||||
super.set_x(value);
|
||||
|
||||
if (label != null)
|
||||
label.x = x;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
override function set_y(Value:Float):Float
|
||||
{
|
||||
super.set_y(Value);
|
||||
|
||||
if (label != null)
|
||||
label.y = y;
|
||||
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
enum NavControls
|
||||
{
|
||||
Horizontal;
|
||||
Vertical;
|
||||
Both;
|
||||
Columns(num:Int);
|
||||
Rows(num:Int);
|
||||
}
|
||||
|
||||
enum WrapMode
|
||||
{
|
||||
Horizontal;
|
||||
Vertical;
|
||||
Both;
|
||||
None;
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
package game.ui;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.util.FlxColor;
|
||||
#if cpp
|
||||
import polymod.Polymod;
|
||||
import sys.FileSystem;
|
||||
#end
|
||||
import game.state.menus.options.OptionsState;
|
||||
import game.state.menus.options.OptionsState.Page;
|
||||
|
||||
class ModMenu extends OptionsState.Page
|
||||
{
|
||||
var grpMods:FlxTypedGroup<ModMenuItem>;
|
||||
var enabledMods:Array<String> = [];
|
||||
var modFolders:Array<String> = [];
|
||||
|
||||
var curSelected:Int = 0;
|
||||
|
||||
public function new():Void
|
||||
{
|
||||
super();
|
||||
|
||||
grpMods = new FlxTypedGroup<ModMenuItem>();
|
||||
add(grpMods);
|
||||
|
||||
refreshModList();
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (FlxG.keys.justPressed.R)
|
||||
refreshModList();
|
||||
|
||||
selections();
|
||||
|
||||
if (controls.UI_UP_P)
|
||||
selections(-1);
|
||||
if (controls.UI_DOWN_P)
|
||||
selections(1);
|
||||
|
||||
if (FlxG.keys.justPressed.SPACE)
|
||||
grpMods.members[curSelected].modEnabled = !grpMods.members[curSelected].modEnabled;
|
||||
|
||||
if (FlxG.keys.justPressed.I && curSelected != 0)
|
||||
{
|
||||
var oldOne = grpMods.members[curSelected - 1];
|
||||
grpMods.members[curSelected - 1] = grpMods.members[curSelected];
|
||||
grpMods.members[curSelected] = oldOne;
|
||||
selections(-1);
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.K && curSelected < grpMods.members.length - 1)
|
||||
{
|
||||
var oldOne = grpMods.members[curSelected + 1];
|
||||
grpMods.members[curSelected + 1] = grpMods.members[curSelected];
|
||||
grpMods.members[curSelected] = oldOne;
|
||||
selections(1);
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
private function selections(change:Int = 0):Void
|
||||
{
|
||||
curSelected += change;
|
||||
|
||||
if (curSelected >= modFolders.length)
|
||||
curSelected = 0;
|
||||
if (curSelected < 0)
|
||||
curSelected = modFolders.length - 1;
|
||||
|
||||
for (txt in 0...grpMods.length)
|
||||
{
|
||||
if (txt == curSelected)
|
||||
{
|
||||
grpMods.members[txt].color = FlxColor.YELLOW;
|
||||
}
|
||||
else
|
||||
grpMods.members[txt].color = FlxColor.WHITE;
|
||||
}
|
||||
|
||||
organizeByY();
|
||||
}
|
||||
|
||||
inline static var MOD_PATH = "./mods";
|
||||
private function refreshModList():Void
|
||||
{
|
||||
while (grpMods.members.length > 0)
|
||||
{
|
||||
grpMods.remove(grpMods.members[0], true);
|
||||
}
|
||||
|
||||
#if desktop
|
||||
var modList = [];
|
||||
modFolders = [];
|
||||
|
||||
trace("mods path:" + FileSystem.absolutePath(MOD_PATH));
|
||||
if (!FileSystem.exists(MOD_PATH))
|
||||
{
|
||||
FlxG.log.warn("missing mods folder, expected: " + FileSystem.absolutePath(MOD_PATH));
|
||||
return;
|
||||
}
|
||||
|
||||
for (file in FileSystem.readDirectory(MOD_PATH))
|
||||
{
|
||||
if (FileSystem.isDirectory(MOD_PATH + file))
|
||||
modFolders.push(file);
|
||||
}
|
||||
|
||||
enabledMods = [];
|
||||
|
||||
modList = Polymod.scan(MOD_PATH);
|
||||
|
||||
trace(modList);
|
||||
|
||||
var loopNum:Int = 0;
|
||||
for (i in modFolders)
|
||||
{
|
||||
var txt:ModMenuItem = new ModMenuItem(0, 10 + (40 * loopNum), 0, i, 32);
|
||||
txt.text = i;
|
||||
grpMods.add(txt);
|
||||
|
||||
loopNum++;
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
private function organizeByY():Void
|
||||
{
|
||||
for (i in 0...grpMods.length)
|
||||
{
|
||||
grpMods.members[i].y = 10 + (40 * i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ModMenuItem extends FlxText
|
||||
{
|
||||
public var modEnabled:Bool = false;
|
||||
public var daMod:String;
|
||||
|
||||
public function new(x:Float, y:Float, w:Float, str:String, size:Int)
|
||||
{
|
||||
super(x, y, w, str, size);
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (modEnabled)
|
||||
alpha = 1;
|
||||
else
|
||||
alpha = 0.5;
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package game.ui;
|
||||
|
||||
import game.ui.AtlasText.AtlasFont;
|
||||
import game.ui.MenuList.MenuTypedItem;
|
||||
import game.ui.MenuList.MenuTypedList;
|
||||
import game.ui.MenuList.NavControls;
|
||||
|
||||
class TextMenuList extends MenuTypedList<TextMenuItem>
|
||||
{
|
||||
public function new(navControls:NavControls = Vertical, ?wrapMode)
|
||||
{
|
||||
super(navControls, wrapMode);
|
||||
}
|
||||
|
||||
public function createItem(x = 0.0, y = 0.0, name:String, font:AtlasFont = Bold, callback, fireInstantly = false)
|
||||
{
|
||||
var item = new TextMenuItem(x, y, name, font, callback);
|
||||
item.fireInstantly = fireInstantly;
|
||||
return addItem(name, item);
|
||||
}
|
||||
}
|
||||
|
||||
class TextMenuItem extends TextTypedMenuItem<AtlasText>
|
||||
{
|
||||
public function new(x = 0.0, y = 0.0, name:String, font:AtlasFont = Bold, callback)
|
||||
{
|
||||
super(x, y, new AtlasText(0, 0, name, font), name, callback);
|
||||
setEmptyBackground();
|
||||
}
|
||||
}
|
||||
|
||||
class TextTypedMenuItem<T:AtlasText> extends MenuTypedItem<T>
|
||||
{
|
||||
public function new(x = 0.0, y = 0.0, label:T, name:String, callback)
|
||||
{
|
||||
super(x, y, label, name, callback);
|
||||
}
|
||||
|
||||
override function setItem(name:String, ?callback:Void->Void)
|
||||
{
|
||||
if (label != null)
|
||||
{
|
||||
label.text = name;
|
||||
label.alpha = alpha;
|
||||
width = label.width;
|
||||
height = label.height;
|
||||
}
|
||||
|
||||
super.setItem(name, callback);
|
||||
}
|
||||
|
||||
override function set_label(value:T):T
|
||||
{
|
||||
super.set_label(value);
|
||||
setItem(name, callback);
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,277 @@
|
|||
package game.ui.gameplay;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.addons.text.FlxTypeText;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.group.FlxSpriteGroup;
|
||||
import flixel.input.FlxKeyManager;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.util.FlxTimer;
|
||||
|
||||
import game.state.*;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class DialogueBox extends FlxSpriteGroup
|
||||
{
|
||||
var box:FlxSprite;
|
||||
|
||||
var curCharacter:String = '';
|
||||
|
||||
var dialogue:Alphabet;
|
||||
var dialogueList:Array<String> = [];
|
||||
|
||||
// SECOND DIALOGUE FOR THE PIXEL SHIT INSTEAD???
|
||||
var swagDialogue:FlxTypeText;
|
||||
|
||||
var dropText:FlxText;
|
||||
|
||||
public var finishThing:Void->Void;
|
||||
|
||||
var portraitLeft:FlxSprite;
|
||||
var portraitRight:FlxSprite;
|
||||
|
||||
var handSelect:FlxSprite;
|
||||
var bgFade:FlxSprite;
|
||||
|
||||
public function new(talkingRight:Bool = true, ?dialogueList:Array<String>)
|
||||
{
|
||||
super();
|
||||
|
||||
switch (PlayState.SONG.song.toLowerCase())
|
||||
{
|
||||
case 'senpai':
|
||||
FlxG.sound.playMusic(Paths.music('Lunchbox'), 0);
|
||||
FlxG.sound.music.fadeIn(1, 0, 0.8);
|
||||
case 'thorns':
|
||||
FlxG.sound.playMusic(Paths.music('LunchboxScary'), 0);
|
||||
FlxG.sound.music.fadeIn(1, 0, 0.8);
|
||||
}
|
||||
|
||||
bgFade = new FlxSprite(-200, -200).makeGraphic(Std.int(FlxG.width * 1.3), Std.int(FlxG.height * 1.3), 0xFFB3DFd8);
|
||||
bgFade.scrollFactor.set();
|
||||
bgFade.alpha = 0;
|
||||
add(bgFade);
|
||||
|
||||
new FlxTimer().start(0.83, function(tmr:FlxTimer)
|
||||
{
|
||||
bgFade.alpha += (1 / 5) * 0.7;
|
||||
if (bgFade.alpha > 0.7)
|
||||
bgFade.alpha = 0.7;
|
||||
}, 5);
|
||||
|
||||
portraitLeft = new FlxSprite(-20, 40);
|
||||
portraitLeft.frames = Paths.getSparrowAtlas('weeb/senpaiPortrait');
|
||||
portraitLeft.animation.addByPrefix('enter', 'Senpai Portrait Enter', 24, false);
|
||||
portraitLeft.setGraphicSize(Std.int(portraitLeft.width * PlayState.daPixelZoom * 0.9));
|
||||
portraitLeft.updateHitbox();
|
||||
portraitLeft.scrollFactor.set();
|
||||
add(portraitLeft);
|
||||
portraitLeft.visible = false;
|
||||
|
||||
portraitRight = new FlxSprite(0, 40);
|
||||
portraitRight.frames = Paths.getSparrowAtlas('weeb/bfPortrait');
|
||||
portraitRight.animation.addByPrefix('enter', 'Boyfriend portrait enter', 24, false);
|
||||
portraitRight.setGraphicSize(Std.int(portraitRight.width * PlayState.daPixelZoom * 0.9));
|
||||
portraitRight.updateHitbox();
|
||||
portraitRight.scrollFactor.set();
|
||||
add(portraitRight);
|
||||
portraitRight.visible = false;
|
||||
|
||||
box = new FlxSprite(-20, 45);
|
||||
|
||||
var hasDialog = false;
|
||||
switch (PlayState.SONG.song.toLowerCase())
|
||||
{
|
||||
case 'senpai':
|
||||
hasDialog = true;
|
||||
box.frames = Paths.getSparrowAtlas('weeb/pixelUI/dialogueBox-pixel');
|
||||
box.animation.addByPrefix('normalOpen', 'Text Box Appear', 24, false);
|
||||
box.animation.addByIndices('normal', 'Text Box Appear', [4], "", 24);
|
||||
case 'roses':
|
||||
hasDialog = true;
|
||||
FlxG.sound.play(Paths.sound('ANGRY_TEXT_BOX'));
|
||||
|
||||
box.frames = Paths.getSparrowAtlas('weeb/pixelUI/dialogueBox-senpaiMad');
|
||||
box.animation.addByPrefix('normalOpen', 'SENPAI ANGRY IMPACT SPEECH', 24, false);
|
||||
box.animation.addByIndices('normal', 'SENPAI ANGRY IMPACT SPEECH', [4], "", 24);
|
||||
|
||||
case 'thorns':
|
||||
hasDialog = true;
|
||||
box.frames = Paths.getSparrowAtlas('weeb/pixelUI/dialogueBox-evil');
|
||||
box.animation.addByPrefix('normalOpen', 'Spirit Textbox spawn', 24, false);
|
||||
box.animation.addByIndices('normal', 'Spirit Textbox spawn', [11], "", 24);
|
||||
|
||||
var face:FlxSprite = new FlxSprite(320, 170).loadGraphic(Paths.image('weeb/spiritFaceForward'));
|
||||
face.setGraphicSize(Std.int(face.width * 6));
|
||||
add(face);
|
||||
}
|
||||
|
||||
this.dialogueList = dialogueList;
|
||||
|
||||
if (!hasDialog)
|
||||
return;
|
||||
|
||||
box.animation.play('normalOpen');
|
||||
box.setGraphicSize(Std.int(box.width * PlayState.daPixelZoom * 0.9));
|
||||
box.updateHitbox();
|
||||
add(box);
|
||||
|
||||
box.screenCenter(X);
|
||||
portraitLeft.screenCenter(X);
|
||||
|
||||
handSelect = new FlxSprite(1042, 590).loadGraphic(Paths.image('weeb/pixelUI/hand_textbox'));
|
||||
handSelect.setGraphicSize(Std.int(handSelect.width * PlayState.daPixelZoom * 0.9));
|
||||
handSelect.updateHitbox();
|
||||
handSelect.visible = false;
|
||||
add(handSelect);
|
||||
|
||||
|
||||
if (!talkingRight)
|
||||
{
|
||||
// box.flipX = true;
|
||||
}
|
||||
|
||||
dropText = new FlxText(242, 502, Std.int(FlxG.width * 0.6), "", 32);
|
||||
dropText.font = 'Pixel Arial 11 Bold';
|
||||
dropText.color = 0xFFD89494;
|
||||
add(dropText);
|
||||
|
||||
swagDialogue = new FlxTypeText(240, 500, Std.int(FlxG.width * 0.6), "", 32);
|
||||
swagDialogue.font = 'Pixel Arial 11 Bold';
|
||||
swagDialogue.color = 0xFF3F2021;
|
||||
swagDialogue.sounds = [FlxG.sound.load(Paths.sound('pixelText'), 0.6)];
|
||||
add(swagDialogue);
|
||||
|
||||
dialogue = new Alphabet(0, 80, "", false, true);
|
||||
// dialogue.x = 90;
|
||||
// add(dialogue);
|
||||
}
|
||||
|
||||
var dialogueOpened:Bool = false;
|
||||
var dialogueStarted:Bool = false;
|
||||
var dialogueEnded:Bool = false;
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
// HARD CODING CUZ IM STUPDI
|
||||
if (PlayState.SONG.song.toLowerCase() == 'roses')
|
||||
portraitLeft.visible = false;
|
||||
if (PlayState.SONG.song.toLowerCase() == 'thorns')
|
||||
{
|
||||
portraitLeft.color = FlxColor.BLACK;
|
||||
swagDialogue.color = FlxColor.WHITE;
|
||||
dropText.color = FlxColor.BLACK;
|
||||
}
|
||||
|
||||
dropText.text = swagDialogue.text;
|
||||
|
||||
if (box.animation.curAnim != null)
|
||||
{
|
||||
if (box.animation.curAnim.name == 'normalOpen' && box.animation.curAnim.finished)
|
||||
{
|
||||
box.animation.play('normal');
|
||||
dialogueOpened = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (dialogueOpened && !dialogueStarted)
|
||||
{
|
||||
startDialogue();
|
||||
dialogueStarted = true;
|
||||
}
|
||||
|
||||
if (FlxG.keys.justPressed.ANY && dialogueEnded)
|
||||
{
|
||||
remove(dialogue);
|
||||
|
||||
FlxG.sound.play(Paths.sound('clickText'), 0.8);
|
||||
|
||||
if (dialogueList[1] == null && dialogueList[0] != null)
|
||||
{
|
||||
if (!isEnding)
|
||||
{
|
||||
isEnding = true;
|
||||
|
||||
if (PlayState.SONG.song.toLowerCase() == 'senpai' || PlayState.SONG.song.toLowerCase() == 'thorns')
|
||||
FlxG.sound.music.fadeOut(2.2, 0);
|
||||
|
||||
new FlxTimer().start(0.2, function(tmr:FlxTimer)
|
||||
{
|
||||
box.alpha -= 1 / 5;
|
||||
bgFade.alpha -= 1 / 5 * 0.7;
|
||||
portraitLeft.visible = false;
|
||||
portraitRight.visible = false;
|
||||
swagDialogue.alpha -= 1 / 5;
|
||||
handSelect.alpha -= 1 / 5;
|
||||
dropText.alpha = swagDialogue.alpha;
|
||||
}, 5);
|
||||
|
||||
new FlxTimer().start(1.2, function(tmr:FlxTimer)
|
||||
{
|
||||
finishThing();
|
||||
kill();
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dialogueList.remove(dialogueList[0]);
|
||||
startDialogue();
|
||||
}
|
||||
}
|
||||
else if (FlxG.keys.justPressed.ANY && dialogueStarted)
|
||||
swagDialogue.skip();
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
var isEnding:Bool = false;
|
||||
|
||||
function startDialogue():Void
|
||||
{
|
||||
cleanDialog();
|
||||
// var theDialog:Alphabet = new Alphabet(0, 70, dialogueList[0], false, true);
|
||||
// dialogue = theDialog;
|
||||
// add(theDialog);
|
||||
|
||||
// swagDialogue.text = ;
|
||||
swagDialogue.resetText(dialogueList[0]);
|
||||
swagDialogue.start(0.04);
|
||||
swagDialogue.completeCallback = function()
|
||||
{
|
||||
trace("dialogue finish");
|
||||
handSelect.visible = true;
|
||||
dialogueEnded = true;
|
||||
};
|
||||
handSelect.visible = false;
|
||||
dialogueEnded = false;
|
||||
|
||||
switch (curCharacter)
|
||||
{
|
||||
case 'dad':
|
||||
portraitRight.visible = false;
|
||||
if (!portraitLeft.visible)
|
||||
{
|
||||
portraitLeft.visible = true;
|
||||
portraitLeft.animation.play('enter');
|
||||
}
|
||||
case 'bf':
|
||||
portraitLeft.visible = false;
|
||||
if (!portraitRight.visible)
|
||||
{
|
||||
portraitRight.visible = true;
|
||||
portraitRight.animation.play('enter');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function cleanDialog():Void
|
||||
{
|
||||
var splitName:Array<String> = dialogueList[0].split(":");
|
||||
curCharacter = splitName[1];
|
||||
dialogueList[0] = dialogueList[0].substr(splitName[1].length + 2).trim();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
package game.ui.gameplay;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxBasic;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.text.FlxText;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.ui.FlxBar;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
|
||||
import game.state.PlayState;
|
||||
import game.state.menus.options.PreferencesMenu;
|
||||
|
||||
using StringTools;
|
||||
|
||||
/*
|
||||
Class For The Games UI.
|
||||
|
||||
Yet another Forever Engine Moment
|
||||
|
||||
- Zyflx
|
||||
*/
|
||||
|
||||
class GameUI extends FlxTypedGroup<FlxBasic>
|
||||
{
|
||||
var scoreTxt:FlxText;
|
||||
var watermark:FlxText;
|
||||
|
||||
var healthBarBG:FlxSprite;
|
||||
|
||||
var healthBar:FlxBar;
|
||||
|
||||
var iconP1:HealthIcon;
|
||||
var iconP2:HealthIcon;
|
||||
|
||||
var Song = PlayState.SONG.song;
|
||||
|
||||
// var health = PlayState.health;
|
||||
|
||||
// Accuracy Shit
|
||||
var notesHit:Float = 0.0;
|
||||
var notesPlayed:Int = 0;
|
||||
var accuracy:Float;
|
||||
var rankStr:String = 'N/A';
|
||||
|
||||
var rankArray:Array<Dynamic> = [
|
||||
[100, 'SS'],
|
||||
[95, 'S'],
|
||||
[90, 'A'],
|
||||
[85, 'B'],
|
||||
[80, 'C'],
|
||||
[75, 'D'],
|
||||
[70, 'E'],
|
||||
[65, 'F']
|
||||
];
|
||||
|
||||
public var ratingMap:Map<String, Float> = [
|
||||
'sick' => 1,
|
||||
'good' => 0.67,
|
||||
'bad' => 0.34,
|
||||
'shit' => 0
|
||||
];
|
||||
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
|
||||
healthBarBG = new FlxSprite(0, FlxG.height * 0.9).loadGraphic(Paths.image('healthBar'));
|
||||
healthBarBG.screenCenter(X);
|
||||
healthBarBG.scrollFactor.set();
|
||||
add(healthBarBG);
|
||||
|
||||
if (PreferencesMenu.getPref('downscroll')) 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), PlayState,
|
||||
'health', 0, 2);
|
||||
healthBar.scrollFactor.set();
|
||||
healthBar.createFilledBar(0xFFFF0000, 0xFF66FF33);
|
||||
add(healthBar);
|
||||
|
||||
iconP1 = new HealthIcon(PlayState.SONG.player1, true);
|
||||
iconP1.y = healthBar.y - (iconP1.height / 2);
|
||||
add(iconP1);
|
||||
|
||||
iconP2 = new HealthIcon(PlayState.SONG.player2, false);
|
||||
iconP2.y = healthBar.y - (iconP2.height / 2);
|
||||
add(iconP2);
|
||||
|
||||
scoreTxt = new FlxText(0, healthBarBG.y + 40, FlxG.width, "", 20);
|
||||
scoreTxt.setFormat(Paths.font("vcr.ttf"), 20, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
|
||||
scoreTxt.scrollFactor.set();
|
||||
scoreTxt.borderSize = 1.2;
|
||||
add(scoreTxt);
|
||||
|
||||
updateScoreTxt();
|
||||
|
||||
var songName = Song.replace('-', " ");
|
||||
var diffName = CoolUtil.difficultyString();
|
||||
watermark = new FlxText(0, (PreferencesMenu.getPref('downscroll') ? FlxG.height - 40 : 10), 0, '', 30);
|
||||
watermark.setFormat(Paths.font('vcr.ttf'), 30, FlxColor.WHITE);
|
||||
watermark.setBorderStyle(OUTLINE, FlxColor.BLACK, 1.4);
|
||||
watermark.text = '~ $songName - ($diffName) ~';
|
||||
watermark.screenCenter(X);
|
||||
add(watermark);
|
||||
}
|
||||
|
||||
override public function update(elapsed:Float)
|
||||
{
|
||||
// healthBar.percent = health;
|
||||
|
||||
if (FlxG.keys.justPressed.NINE) iconP1.swapOldIcon();
|
||||
|
||||
iconP1.scale.set(FlxMath.lerp(1, iconP1.scale.x, CoolUtil.boundTo(1 - (elapsed * 11), 0, 1)), FlxMath.lerp(1, iconP1.scale.y, CoolUtil.boundTo(1 - (elapsed * 11), 0, 1)));
|
||||
iconP2.scale.set(FlxMath.lerp(1, iconP2.scale.x, CoolUtil.boundTo(1 - (elapsed * 11), 0, 1)), FlxMath.lerp(1, iconP2.scale.y, CoolUtil.boundTo(1 - (elapsed * 11), 0, 1)));
|
||||
|
||||
iconP1.updateHitbox();
|
||||
iconP2.updateHitbox();
|
||||
|
||||
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.animation.curAnim.curFrame = (healthBar.percent < 20 ? 1 : 0);
|
||||
iconP2.animation.curAnim.curFrame = (healthBar.percent > 80 ? 1 : 0);
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
public function updateScoreTxt()
|
||||
{
|
||||
var acc:Float = Math.floor(accuracy * 10000) / 100;
|
||||
updateRank(acc);
|
||||
|
||||
scoreTxt.text = 'Score: ' + PlayState.songScore + ' - Misses: ' + PlayState.songMisses +
|
||||
' - Accuracy: [$acc% | $rankStr]';
|
||||
}
|
||||
|
||||
// Accuracy Shit Part 2
|
||||
public function updateAcc(rating:Float, ?isMiss:Bool = false)
|
||||
{
|
||||
if (!isMiss) notesHit += rating;
|
||||
notesPlayed++;
|
||||
accuracy = Math.min(1, Math.max(0, notesHit / notesPlayed));
|
||||
updateScoreTxt();
|
||||
}
|
||||
|
||||
function updateRank(accuracy:Float)
|
||||
{
|
||||
for (i in 0...rankArray.length)
|
||||
{
|
||||
if (rankArray[i][0] <= accuracy)
|
||||
{
|
||||
rankStr = rankArray[i][1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function iconBeat()
|
||||
{
|
||||
iconP1.setGraphicSize(Std.int(iconP1.width + 30));
|
||||
iconP2.setGraphicSize(Std.int(iconP2.width + 30));
|
||||
|
||||
iconP1.updateHitbox();
|
||||
iconP2.updateHitbox();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package game.ui.gameplay;
|
||||
|
||||
import game.state.PlayState;
|
||||
import flixel.FlxSprite;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class HealthIcon extends FlxSprite
|
||||
{
|
||||
/**
|
||||
* Used for FreeplayState! If you use it elsewhere, prob gonna annoying
|
||||
*/
|
||||
public var sprTracker:FlxSprite;
|
||||
|
||||
var char:String = '';
|
||||
var isPlayer:Bool = false;
|
||||
|
||||
public function new(char:String = 'bf', isPlayer:Bool = false)
|
||||
{
|
||||
super();
|
||||
|
||||
this.isPlayer = isPlayer;
|
||||
|
||||
changeIcon(char);
|
||||
antialiasing = true;
|
||||
scrollFactor.set();
|
||||
}
|
||||
|
||||
public var isOldIcon:Bool = false;
|
||||
|
||||
public function swapOldIcon():Void
|
||||
{
|
||||
isOldIcon = !isOldIcon;
|
||||
|
||||
if (isOldIcon)
|
||||
changeIcon('bf-old');
|
||||
else
|
||||
changeIcon(PlayState.SONG.player1);
|
||||
}
|
||||
|
||||
public function changeIcon(newChar:String):Void
|
||||
{
|
||||
if (newChar != 'bf-pixel' && newChar != 'bf-old')
|
||||
newChar = newChar.split('-')[0].trim();
|
||||
|
||||
if (newChar != char)
|
||||
{
|
||||
if (animation.getByName(newChar) == null)
|
||||
{
|
||||
loadGraphic(Paths.image('icons/icon-' + newChar), true, 150, 150);
|
||||
animation.add(newChar, [0, 1], 0, false, isPlayer);
|
||||
}
|
||||
animation.play(newChar);
|
||||
char = newChar;
|
||||
}
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
if (sprTracker != null)
|
||||
setPosition(sprTracker.x + sprTracker.width + 10, sprTracker.y - 30);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,241 @@
|
|||
package game.ui.gameplay.note;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.util.FlxTimer;
|
||||
import game.objects.shaders.ColorSwap;
|
||||
import game.state.menus.options.PreferencesMenu;
|
||||
import game.state.PlayState;
|
||||
import game.data.backend.Conductor;
|
||||
|
||||
using StringTools;
|
||||
|
||||
#if polymod
|
||||
import polymod.format.ParseRules.TargetSignatureElement;
|
||||
#end
|
||||
|
||||
class Note extends FlxSprite
|
||||
{
|
||||
public var strumTime:Float = 0;
|
||||
|
||||
public var mustPress:Bool = false;
|
||||
public var noteData:Int = 0;
|
||||
public var canBeHit:Bool = false;
|
||||
public var tooLate:Bool = false;
|
||||
public var wasGoodHit:Bool = false;
|
||||
public var prevNote:Note;
|
||||
|
||||
private var willMiss:Bool = false;
|
||||
|
||||
public var altNote:Bool = false;
|
||||
public var invisNote:Bool = false;
|
||||
|
||||
public var sustainLength:Float = 0;
|
||||
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;
|
||||
public static var GREEN_NOTE:Int = 2;
|
||||
public static var BLUE_NOTE:Int = 1;
|
||||
public static var RED_NOTE:Int = 3;
|
||||
|
||||
public static var arrowColors:Array<Float> = [1, 1, 1, 1];
|
||||
|
||||
public function new(strumTime:Float, noteData:Int, ?prevNote:Note, ?sustainNote:Bool = false)
|
||||
{
|
||||
super();
|
||||
|
||||
if (prevNote == null)
|
||||
prevNote = this;
|
||||
|
||||
this.prevNote = prevNote;
|
||||
isSustainNote = sustainNote;
|
||||
|
||||
x += 98.5;
|
||||
// MAKE SURE ITS DEFINITELY OFF SCREEN?
|
||||
y -= 2000;
|
||||
this.strumTime = strumTime;
|
||||
|
||||
this.noteData = noteData;
|
||||
|
||||
if (PlayState.isPixel)
|
||||
{
|
||||
loadGraphic(Paths.image('weeb/pixelUI/arrows-pixels'), true, 17, 17);
|
||||
|
||||
animation.add('greenScroll', [6]);
|
||||
animation.add('redScroll', [7]);
|
||||
animation.add('blueScroll', [5]);
|
||||
animation.add('purpleScroll', [4]);
|
||||
|
||||
if (isSustainNote)
|
||||
{
|
||||
loadGraphic(Paths.image('weeb/pixelUI/arrowEnds'), true, 7, 6);
|
||||
|
||||
animation.add('purpleholdend', [4]);
|
||||
animation.add('greenholdend', [6]);
|
||||
animation.add('redholdend', [7]);
|
||||
animation.add('blueholdend', [5]);
|
||||
|
||||
animation.add('purplehold', [0]);
|
||||
animation.add('greenhold', [2]);
|
||||
animation.add('redhold', [3]);
|
||||
animation.add('bluehold', [1]);
|
||||
}
|
||||
|
||||
setGraphicSize(Std.int(width * PlayState.daPixelZoom));
|
||||
updateHitbox();
|
||||
}
|
||||
else
|
||||
{
|
||||
frames = Paths.getSparrowAtlas('NOTE_assets');
|
||||
|
||||
animation.addByPrefix('greenScroll', 'green instance');
|
||||
animation.addByPrefix('redScroll', 'red instance');
|
||||
animation.addByPrefix('blueScroll', 'blue instance');
|
||||
animation.addByPrefix('purpleScroll', 'purple instance');
|
||||
|
||||
animation.addByPrefix('purpleholdend', 'pruple end hold');
|
||||
animation.addByPrefix('greenholdend', 'green hold end');
|
||||
animation.addByPrefix('redholdend', 'red hold end');
|
||||
animation.addByPrefix('blueholdend', 'blue hold end');
|
||||
|
||||
animation.addByPrefix('purplehold', 'purple hold piece');
|
||||
animation.addByPrefix('greenhold', 'green hold piece');
|
||||
animation.addByPrefix('redhold', 'red hold piece');
|
||||
animation.addByPrefix('bluehold', 'blue hold piece');
|
||||
|
||||
setGraphicSize(Std.int(width * 0.7));
|
||||
updateHitbox();
|
||||
antialiasing = true;
|
||||
|
||||
// colorSwap.colorToReplace = 0xFFF9393F;
|
||||
// colorSwap.newColor = 0xFF00FF00;
|
||||
|
||||
// color = FlxG.random.color();
|
||||
// color.saturation *= 4;
|
||||
// replaceColor(0xFFC1C1C1, FlxColor.RED);
|
||||
}
|
||||
|
||||
colorSwap = new ColorSwap();
|
||||
shader = colorSwap.shader;
|
||||
updateColors();
|
||||
|
||||
switch (noteData)
|
||||
{
|
||||
case 0:
|
||||
x += swagWidth * 0;
|
||||
animation.play('purpleScroll');
|
||||
case 1:
|
||||
x += swagWidth * 1;
|
||||
animation.play('blueScroll');
|
||||
case 2:
|
||||
x += swagWidth * 2;
|
||||
animation.play('greenScroll');
|
||||
case 3:
|
||||
x += swagWidth * 3;
|
||||
animation.play('redScroll');
|
||||
}
|
||||
|
||||
// trace(prevNote);
|
||||
|
||||
if (isSustainNote && prevNote != null)
|
||||
{
|
||||
noteScore * 0.2;
|
||||
alpha = 0.6;
|
||||
|
||||
if (PreferencesMenu.getPref('downscroll'))
|
||||
angle = 180;
|
||||
|
||||
x += width / 2;
|
||||
|
||||
switch (noteData)
|
||||
{
|
||||
case 2:
|
||||
animation.play('greenholdend');
|
||||
case 3:
|
||||
animation.play('redholdend');
|
||||
case 1:
|
||||
animation.play('blueholdend');
|
||||
case 0:
|
||||
animation.play('purpleholdend');
|
||||
}
|
||||
|
||||
updateHitbox();
|
||||
|
||||
x -= width / 2;
|
||||
|
||||
if (PlayState.isPixel) x += 30;
|
||||
|
||||
if (prevNote.isSustainNote)
|
||||
{
|
||||
switch (prevNote.noteData)
|
||||
{
|
||||
case 0:
|
||||
prevNote.animation.play('purplehold');
|
||||
case 1:
|
||||
prevNote.animation.play('bluehold');
|
||||
case 2:
|
||||
prevNote.animation.play('greenhold');
|
||||
case 3:
|
||||
prevNote.animation.play('redhold');
|
||||
}
|
||||
|
||||
prevNote.scale.y *= Conductor.stepCrochet / 100 * 1.5 * PlayState.SONG.speed;
|
||||
prevNote.updateHitbox();
|
||||
// prevNote.setGraphicSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function updateColors():Void
|
||||
{
|
||||
colorSwap.update(arrowColors[noteData]);
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
if (mustPress)
|
||||
{
|
||||
// miss on the NEXT frame so lag doesnt make u miss notes
|
||||
if (willMiss && !wasGoodHit)
|
||||
{
|
||||
tooLate = true;
|
||||
canBeHit = false;
|
||||
}
|
||||
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))
|
||||
canBeHit = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
canBeHit = true;
|
||||
willMiss = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
canBeHit = false;
|
||||
|
||||
if (strumTime <= Conductor.songPosition)
|
||||
wasGoodHit = true;
|
||||
}
|
||||
|
||||
if (tooLate)
|
||||
{
|
||||
if (alpha > 0.3)
|
||||
alpha = 0.3;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package game.ui.gameplay.note;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
|
||||
class NoteSplash extends FlxSprite
|
||||
{
|
||||
public function new(x:Float, y:Float, noteData:Int = 0):Void
|
||||
{
|
||||
super(x, y);
|
||||
|
||||
frames = Paths.getSparrowAtlas('noteSplashes');
|
||||
|
||||
animation.addByPrefix('note1-0', 'note impact 1 blue', 24, false);
|
||||
animation.addByPrefix('note2-0', 'note impact 1 green', 24, false);
|
||||
animation.addByPrefix('note0-0', 'note impact 1 purple', 24, false);
|
||||
animation.addByPrefix('note3-0', 'note impact 1 red', 24, false);
|
||||
animation.addByPrefix('note1-1', 'note impact 2 blue', 24, false);
|
||||
animation.addByPrefix('note2-1', 'note impact 2 green', 24, false);
|
||||
animation.addByPrefix('note0-1', 'note impact 2 purple', 24, false);
|
||||
animation.addByPrefix('note3-1', 'note impact 2 red', 24, false);
|
||||
|
||||
setupNoteSplash(x, y, noteData);
|
||||
|
||||
// alpha = 0.75;
|
||||
}
|
||||
|
||||
public function setupNoteSplash(x:Float, y:Float, noteData:Int = 0)
|
||||
{
|
||||
setPosition(x, y);
|
||||
alpha = 0.6;
|
||||
|
||||
animation.play('note' + noteData + '-' + FlxG.random.int(0, 1), true);
|
||||
animation.curAnim.frameRate = 24 + FlxG.random.int(-2, 2);
|
||||
updateHitbox();
|
||||
|
||||
offset.set(width * 0.3, height * 0.3);
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (animation.curAnim.finished) kill();
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
package game.ui.gameplay.note;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import game.state.PlayState;
|
||||
|
||||
class StaticNote extends FlxSprite
|
||||
{
|
||||
public var animReset:Float = 0;
|
||||
|
||||
public function new(x:Float, y:Float, data:Int, player:Int)
|
||||
{
|
||||
super(x, y);
|
||||
loadStaticArrow(data);
|
||||
scrollFactor.set();
|
||||
}
|
||||
|
||||
function loadStaticArrow(data:Int)
|
||||
{
|
||||
if (PlayState.isPixel)
|
||||
{
|
||||
loadGraphic(Paths.image('weeb/pixelUI/arrows-pixels'), true, 17, 17);
|
||||
animation.add('green', [6]);
|
||||
animation.add('red', [7]);
|
||||
animation.add('blue', [5]);
|
||||
animation.add('purplel', [4]);
|
||||
|
||||
setGraphicSize(Std.int(width * PlayState.daPixelZoom));
|
||||
updateHitbox();
|
||||
antialiasing = false;
|
||||
|
||||
switch (Math.abs(data) % 4)
|
||||
{
|
||||
case 0:
|
||||
x += Note.swagWidth * 0;
|
||||
animation.add('static', [0]);
|
||||
animation.add('pressed', [4, 8], 12, false);
|
||||
animation.add('confirm', [12, 16], 24, false);
|
||||
case 1:
|
||||
x += Note.swagWidth * 1;
|
||||
animation.add('static', [1]);
|
||||
animation.add('pressed', [5, 9], 12, false);
|
||||
animation.add('confirm', [13, 17], 24, false);
|
||||
case 2:
|
||||
x += Note.swagWidth * 2;
|
||||
animation.add('static', [2]);
|
||||
animation.add('pressed', [6, 10], 12, false);
|
||||
animation.add('confirm', [14, 18], 12, false);
|
||||
case 3:
|
||||
x += Note.swagWidth * 3;
|
||||
animation.add('static', [3]);
|
||||
animation.add('pressed', [7, 11], 12, false);
|
||||
animation.add('confirm', [15, 19], 24, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
frames = Paths.getSparrowAtlas('NOTE_assets');
|
||||
animation.addByPrefix('green', 'arrowUP');
|
||||
animation.addByPrefix('blue', 'arrowDOWN');
|
||||
animation.addByPrefix('purple', 'arrowLEFT');
|
||||
animation.addByPrefix('red', 'arrowRIGHT');
|
||||
|
||||
antialiasing = true;
|
||||
setGraphicSize(Std.int(width * 0.7));
|
||||
|
||||
switch (Math.abs(data) % 4)
|
||||
{
|
||||
case 0:
|
||||
x += Note.swagWidth * 0;
|
||||
animation.addByPrefix('static', 'arrow static instance 1');
|
||||
animation.addByPrefix('pressed', 'left press', 24, false);
|
||||
animation.addByPrefix('confirm', 'left confirm', 24, false);
|
||||
case 1:
|
||||
x += Note.swagWidth * 1;
|
||||
animation.addByPrefix('static', 'arrow static instance 2');
|
||||
animation.addByPrefix('pressed', 'down press', 24, false);
|
||||
animation.addByPrefix('confirm', 'down confirm', 24, false);
|
||||
case 2:
|
||||
x += Note.swagWidth * 2;
|
||||
animation.addByPrefix('static', 'arrow static instance 4');
|
||||
animation.addByPrefix('pressed', 'up press', 24, false);
|
||||
animation.addByPrefix('confirm', 'up confirm', 24, false);
|
||||
case 3:
|
||||
x += Note.swagWidth * 3;
|
||||
animation.addByPrefix('static', 'arrow static instance 3');
|
||||
animation.addByPrefix('pressed', 'right press', 24, false);
|
||||
animation.addByPrefix('confirm', 'right confirm', 24, false);
|
||||
}
|
||||
}
|
||||
updateHitbox();
|
||||
playStrumAnim('static', true);
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
if (animReset > 0) {
|
||||
animReset -= elapsed;
|
||||
if (animReset <= 0) {
|
||||
playStrumAnim('static', true);
|
||||
animReset = 0;
|
||||
}
|
||||
}
|
||||
super.update(elapsed);
|
||||
}
|
||||
|
||||
public function playStrumAnim(anim:String, ?forced:Bool = false):Void
|
||||
{
|
||||
animation.play(anim, forced);
|
||||
|
||||
if (anim == 'confirm' && !PlayState.isPixel)
|
||||
{
|
||||
centerOffsets();
|
||||
offset.x -= 13;
|
||||
offset.y -= 13;
|
||||
}
|
||||
else
|
||||
centerOffsets();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package game.ui.menu;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
|
||||
class MenuCharacter extends FlxSprite
|
||||
{
|
||||
public var character:String;
|
||||
|
||||
public function new(x:Float, character:String = 'bf')
|
||||
{
|
||||
super(x);
|
||||
|
||||
this.character = character;
|
||||
|
||||
var tex = Paths.getSparrowAtlas('campaign_menu_UI_characters');
|
||||
frames = tex;
|
||||
|
||||
animation.addByPrefix('bf', "BF idle dance white", 24);
|
||||
animation.addByPrefix('bfConfirm', 'BF HEY!!', 24, false);
|
||||
animation.addByPrefix('gf', "GF Dancing Beat WHITE", 24);
|
||||
animation.addByPrefix('dad', "Dad idle dance BLACK LINE", 24);
|
||||
animation.addByPrefix('spooky', "spooky dance idle BLACK LINES", 24);
|
||||
animation.addByPrefix('pico', "Pico Idle Dance", 24);
|
||||
animation.addByPrefix('mom', "Mom Idle BLACK LINES", 24);
|
||||
animation.addByPrefix('parents-christmas', "Parent Christmas Idle", 24);
|
||||
animation.addByPrefix('senpai', "SENPAI idle Black Lines", 24);
|
||||
animation.addByPrefix('tankman', "Tankman Menu BLACK", 24);
|
||||
// Parent Christmas Idle
|
||||
|
||||
animation.play(character);
|
||||
updateHitbox();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package game.ui.menu;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.graphics.frames.FlxAtlasFrames;
|
||||
import flixel.group.FlxSpriteGroup;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.util.FlxColor;
|
||||
|
||||
class MenuItem extends FlxSpriteGroup
|
||||
{
|
||||
public var targetY:Float = 0;
|
||||
public var week:FlxSprite;
|
||||
public var flashingInt:Int = 0;
|
||||
|
||||
public function new(x:Float, y:Float, weekNum:Int = 0)
|
||||
{
|
||||
super(x, y);
|
||||
week = new FlxSprite().loadGraphic(Paths.image('storymenu/week' + weekNum));
|
||||
add(week);
|
||||
}
|
||||
|
||||
private var isFlashing:Bool = false;
|
||||
|
||||
public function startFlashing():Void
|
||||
{
|
||||
isFlashing = true;
|
||||
}
|
||||
|
||||
// if it runs at 60fps, fake framerate will be 6
|
||||
// if it runs at 144 fps, fake framerate will be like 14, and will update the graphic every 0.016666 * 3 seconds still???
|
||||
// so it runs basically every so many seconds, not dependant on framerate??
|
||||
// I'm still learning how math works thanks whoever is reading this lol
|
||||
var fakeFramerate:Int = Math.round((1 / FlxG.elapsed) / 10);
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
y = CoolUtil.coolLerp(y, (targetY * 120) + 480, 0.17);
|
||||
|
||||
if (isFlashing)
|
||||
flashingInt += 1;
|
||||
|
||||
if (flashingInt % fakeFramerate >= Math.floor(fakeFramerate / 2))
|
||||
week.color = 0xFF33ffff;
|
||||
else
|
||||
week.color = FlxColor.WHITE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package;
|
||||
|
||||
import flixel.FlxSubState;
|
||||
|
||||
class ButtonRemapSubstate extends FlxSubState
|
||||
{
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package;
|
||||
|
||||
import flixel.util.FlxStringUtil;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class ChartParser
|
||||
{
|
||||
static public function parse(songName:String, section:Int):Array<Dynamic>
|
||||
{
|
||||
var IMG_WIDTH:Int = 8;
|
||||
var regex:EReg = new EReg("[ \t]*((\r\n)|\r|\n)[ \t]*", "g");
|
||||
|
||||
var csvData = FlxStringUtil.imageToCSV(Paths.file('data/' + songName + '/' + songName + '_section' + section + '.png'));
|
||||
|
||||
var lines:Array<String> = regex.split(csvData);
|
||||
var rows:Array<String> = lines.filter(function(line) return line != "");
|
||||
csvData.replace("\n", ',');
|
||||
|
||||
var heightInTiles = rows.length;
|
||||
var widthInTiles = 0;
|
||||
|
||||
var row:Int = 0;
|
||||
|
||||
// LMAOOOO STOLE ALL THIS FROM FLXBASETILEMAP LOLOL
|
||||
|
||||
var dopeArray:Array<Int> = [];
|
||||
while (row < heightInTiles)
|
||||
{
|
||||
var rowString = rows[row];
|
||||
if (rowString.endsWith(","))
|
||||
rowString = rowString.substr(0, rowString.length - 1);
|
||||
var columns = rowString.split(",");
|
||||
|
||||
if (columns.length == 0)
|
||||
{
|
||||
heightInTiles--;
|
||||
continue;
|
||||
}
|
||||
if (widthInTiles == 0)
|
||||
{
|
||||
widthInTiles = columns.length;
|
||||
}
|
||||
|
||||
var column = 0;
|
||||
var pushedInColumn:Bool = false;
|
||||
while (column < widthInTiles)
|
||||
{
|
||||
// the current tile to be added:
|
||||
var columnString = columns[column];
|
||||
var curTile = Std.parseInt(columnString);
|
||||
|
||||
if (curTile == null)
|
||||
throw 'String in row $row, column $column is not a valid integer: "$columnString"';
|
||||
|
||||
if (curTile == 1)
|
||||
{
|
||||
if (column < 4)
|
||||
dopeArray.push(column + 1);
|
||||
else
|
||||
{
|
||||
var tempCol = (column + 1) * -1;
|
||||
tempCol += 4;
|
||||
dopeArray.push(tempCol);
|
||||
}
|
||||
|
||||
pushedInColumn = true;
|
||||
}
|
||||
|
||||
column++;
|
||||
}
|
||||
|
||||
if (!pushedInColumn)
|
||||
dopeArray.push(0);
|
||||
|
||||
row++;
|
||||
}
|
||||
return dopeArray;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxSubState;
|
||||
|
||||
class ControlsSubState extends FlxSubState
|
||||
{
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package;
|
||||
|
||||
import flixel.FlxG;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.FlxState;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.text.FlxText;
|
||||
|
||||
class LatencyState extends FlxState
|
||||
{
|
||||
var offsetText:FlxText;
|
||||
var noteGrp:FlxTypedGroup<Note>;
|
||||
var strumLine:FlxSprite;
|
||||
|
||||
override function create()
|
||||
{
|
||||
FlxG.sound.playMusic(Paths.sound('soundTest'));
|
||||
|
||||
noteGrp = new FlxTypedGroup<Note>();
|
||||
add(noteGrp);
|
||||
|
||||
for (i in 0...32)
|
||||
{
|
||||
var note:Note = new Note(Conductor.crochet * i, 1);
|
||||
noteGrp.add(note);
|
||||
}
|
||||
|
||||
offsetText = new FlxText();
|
||||
offsetText.screenCenter();
|
||||
add(offsetText);
|
||||
|
||||
strumLine = new FlxSprite(FlxG.width / 2, 100).makeGraphic(FlxG.width, 5);
|
||||
add(strumLine);
|
||||
|
||||
Conductor.changeBPM(120);
|
||||
|
||||
super.create();
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
offsetText.text = "Offset: " + Conductor.offset + "ms";
|
||||
|
||||
Conductor.songPosition = FlxG.sound.music.time - Conductor.offset;
|
||||
|
||||
var multiply:Float = 1;
|
||||
|
||||
if (FlxG.keys.pressed.SHIFT)
|
||||
multiply = 10;
|
||||
|
||||
if (FlxG.keys.justPressed.RIGHT)
|
||||
Conductor.offset += 1 * multiply;
|
||||
if (FlxG.keys.justPressed.LEFT)
|
||||
Conductor.offset -= 1 * multiply;
|
||||
|
||||
if (FlxG.keys.justPressed.SPACE)
|
||||
{
|
||||
FlxG.sound.music.stop();
|
||||
|
||||
FlxG.resetState();
|
||||
}
|
||||
|
||||
noteGrp.forEach(function(daNote:Note)
|
||||
{
|
||||
daNote.y = (strumLine.y - (Conductor.songPosition - daNote.strumTime) * 0.45);
|
||||
daNote.x = strumLine.x + 30;
|
||||
|
||||
if (daNote.y < strumLine.y)
|
||||
daNote.kill();
|
||||
});
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,332 @@
|
|||
import h2d.Tweenie.TType;
|
||||
|
||||
//praise delahee, i'll figure out what this shit means later!
|
||||
|
||||
enum TVVar{
|
||||
TVVVolume;
|
||||
TVVPan;
|
||||
}
|
||||
|
||||
@:publicFields
|
||||
class TweenV {
|
||||
static var GUID = 0;
|
||||
var uid = 0;
|
||||
|
||||
var man : SndTV;
|
||||
var parent : Snd;
|
||||
var n : Float;
|
||||
var ln : Float;
|
||||
var speed : Float;
|
||||
var from : Float;
|
||||
var to : Float;
|
||||
var type : TType;
|
||||
var plays : Int; // -1 = infini, 1 et plus = nombre d'exécutions (1 par défaut)
|
||||
var varType : TVVar;
|
||||
var onUpdate : Null<TweenV->Void>;
|
||||
var onEnd : Null<TweenV->Void>;
|
||||
var isDebug = false;
|
||||
|
||||
public inline function new (
|
||||
parent:Snd ,
|
||||
n:Float ,
|
||||
ln:Float ,
|
||||
varType:TVVar,
|
||||
speed:Float ,
|
||||
from:Float ,
|
||||
to:Float ,
|
||||
type:h2d.Tweenie.TType ,
|
||||
plays ,
|
||||
onUpdate ,
|
||||
onEnd
|
||||
) {
|
||||
this.parent = parent ;
|
||||
this.n = n ;
|
||||
this.ln = ln ;
|
||||
this.varType = varType ;
|
||||
this.speed = speed ;
|
||||
this.from = from ;
|
||||
this.to = to ;
|
||||
this.type = type ;
|
||||
this.plays = plays ;
|
||||
this.onUpdate = onUpdate ;
|
||||
this.onEnd = onEnd ;
|
||||
}
|
||||
|
||||
public inline function reset(
|
||||
parent:Snd ,
|
||||
n:Float ,
|
||||
ln:Float ,
|
||||
varType:TVVar,
|
||||
speed:Float ,
|
||||
from:Float ,
|
||||
to:Float ,
|
||||
type:TType ,
|
||||
plays:Int ,
|
||||
onUpdate ,
|
||||
onEnd
|
||||
) {
|
||||
this.parent = parent ;
|
||||
this.n = n ;
|
||||
this.ln = ln ;
|
||||
this.speed = speed ;
|
||||
this.from = from ;
|
||||
this.to = to ;
|
||||
this.type = type ;
|
||||
this.plays = plays ;
|
||||
this.onUpdate = onUpdate ;
|
||||
this.onEnd = onEnd ;
|
||||
this.varType = varType ;
|
||||
isDebug = false;
|
||||
uid = GUID++;
|
||||
}
|
||||
|
||||
public function clear(){
|
||||
n = 0.0;
|
||||
ln = 0.0;
|
||||
speed = 0.0;
|
||||
plays = 0;
|
||||
from = 0.0;
|
||||
to = 0.0;
|
||||
parent = null;
|
||||
onEnd = null;
|
||||
onUpdate = null;
|
||||
isDebug = false;
|
||||
uid = GUID++;
|
||||
}
|
||||
|
||||
|
||||
public
|
||||
inline
|
||||
function apply( val ) {
|
||||
switch(varType){
|
||||
case TVVVolume: {
|
||||
parent.volume = val;
|
||||
#if debug
|
||||
if( isDebug )
|
||||
trace("tv:" + val);
|
||||
#end
|
||||
}
|
||||
case TVVPan: parent.pan = val;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public inline function kill( withCbk = true ) {
|
||||
if ( withCbk )
|
||||
man.terminateTween( this );
|
||||
else
|
||||
man.forceTerminateTween( this) ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* tween order is not respected
|
||||
*/
|
||||
class SndTV {
|
||||
static var DEFAULT_DURATION = DateTools.seconds(1);
|
||||
public var fps = 60.0;
|
||||
public var isDebug = false;
|
||||
|
||||
var tlist : hxd.Stack<TweenV>;
|
||||
|
||||
public function new() {
|
||||
tlist = new hxd.Stack<TweenV>();
|
||||
tlist.reserve(8);
|
||||
}
|
||||
|
||||
function onError(e) {
|
||||
trace(e);
|
||||
}
|
||||
|
||||
public function count() {
|
||||
return tlist.length;
|
||||
}
|
||||
|
||||
public inline function create(parent:Snd, vartype:TVVar, to:Float, ?tp:h2d.Tweenie.TType, ?duration_ms:Float) : TweenV{
|
||||
return create_(parent, vartype, to, tp, duration_ms);
|
||||
}
|
||||
|
||||
public function exists(p:Snd) {
|
||||
for (t in tlist)
|
||||
if (t.parent == p )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public var pool : hxd.Stack<TweenV> = new hxd.Stack();
|
||||
|
||||
function create_(p:Snd, vartype:TVVar,to:Float, ?tp:h2d.Tweenie.TType, ?duration_ms:Float) : TweenV{
|
||||
if ( duration_ms==null )
|
||||
duration_ms = DEFAULT_DURATION;
|
||||
|
||||
#if debug
|
||||
if ( p == null ) trace("tween2 creation failed to:"+to+" tp:"+tp);
|
||||
#end
|
||||
|
||||
if ( tp==null ) tp = TEase;
|
||||
|
||||
{
|
||||
// on supprime les tweens précédents appliqués à la même variable
|
||||
for(t in tlist.backWardIterator())
|
||||
if(t.parent==p && t.varType == vartype) {
|
||||
forceTerminateTween(t);
|
||||
}
|
||||
}
|
||||
|
||||
var from = switch( vartype ){
|
||||
case TVVVolume : p.volume;
|
||||
case TVVPan : p.pan;
|
||||
}
|
||||
var t : TweenV;
|
||||
if (pool.length == 0){
|
||||
t = new TweenV(
|
||||
p,
|
||||
0.0,
|
||||
0.0,
|
||||
vartype,
|
||||
1 / ( duration_ms*fps/1000 ), // une seconde
|
||||
from,
|
||||
to,
|
||||
tp,
|
||||
1,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
else {
|
||||
t = pool.pop();
|
||||
t.reset(
|
||||
p,
|
||||
0.0,
|
||||
0.0,
|
||||
vartype,
|
||||
1 / ( duration_ms*fps/1000 ), // une seconde
|
||||
from,
|
||||
to,
|
||||
tp,
|
||||
1,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
if( t.from==t.to )
|
||||
t.ln = 1; // tweening inutile : mais on s'assure ainsi qu'un update() et un end() seront bien appelés
|
||||
|
||||
t.man = this;
|
||||
tlist.push(t);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
public static inline
|
||||
function fastPow2(n:Float):Float {
|
||||
return n*n;
|
||||
}
|
||||
|
||||
public static inline
|
||||
function fastPow3(n:Float):Float {
|
||||
return n*n*n;
|
||||
}
|
||||
|
||||
public static inline
|
||||
function bezier(t:Float, p0:Float, p1:Float,p2:Float, p3:Float) {
|
||||
return
|
||||
fastPow3(1-t)*p0 +
|
||||
3*( t*fastPow2(1-t)*p1 + fastPow2(t)*(1-t)*p2 ) +
|
||||
fastPow3(t)*p3;
|
||||
}
|
||||
|
||||
// suppression du tween sans aucun appel aux callbacks onUpdate, onUpdateT et onEnd (!)
|
||||
public function killWithoutCallbacks(parent:Snd) {
|
||||
for (t in tlist.backWardIterator())
|
||||
if (t.parent==parent ){
|
||||
forceTerminateTween(t);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function terminate(parent:Snd) {
|
||||
for (t in tlist.backWardIterator())
|
||||
if (t.parent==parent){
|
||||
forceTerminateTween(t);
|
||||
}
|
||||
}
|
||||
|
||||
public function forceTerminateTween(t:TweenV) {
|
||||
var tOk = tlist.remove(t);
|
||||
if( tOk ){
|
||||
t.clear();
|
||||
pool.push(t);
|
||||
}
|
||||
}
|
||||
|
||||
public function terminateTween(t:TweenV, ?fl_allowLoop=false) {
|
||||
var v = t.from + (t.to - t.from) * h2d.Tweenie.interp(t.type, 1);
|
||||
t.apply(v);
|
||||
onUpdate(t, 1);
|
||||
|
||||
var ouid = t.uid;
|
||||
|
||||
onEnd(t);
|
||||
|
||||
if( ouid == t.uid ){
|
||||
if( fl_allowLoop && (t.plays==-1 || t.plays>1) ) {
|
||||
if( t.plays!=-1 )
|
||||
t.plays--;
|
||||
t.n = t.ln = 0;
|
||||
}
|
||||
else {
|
||||
forceTerminateTween(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function terminateAll() {
|
||||
for(t in tlist)
|
||||
t.ln = 1;
|
||||
update();
|
||||
}
|
||||
|
||||
inline
|
||||
function onUpdate(t:TweenV, n:Float) {
|
||||
if ( t.onUpdate!=null )
|
||||
t.onUpdate(t);
|
||||
}
|
||||
|
||||
inline
|
||||
function onEnd(t:TweenV) {
|
||||
if ( t.onEnd!=null )
|
||||
t.onEnd(t);
|
||||
}
|
||||
|
||||
public function update(?tmod = 1.0) {
|
||||
if ( tlist.length > 0 ) {
|
||||
for (t in tlist.backWardIterator() ) {
|
||||
var dist = t.to-t.from;
|
||||
if (t.type==TRand)
|
||||
t.ln+=if(Std.random(100)<33) t.speed * tmod else 0;
|
||||
else
|
||||
t.ln += t.speed * tmod;
|
||||
|
||||
t.n = h2d.Tweenie.interp(t.type, t.ln);
|
||||
|
||||
if ( t.ln<1 ) {
|
||||
// en cours...
|
||||
var val = t.from + t.n*dist;
|
||||
|
||||
t.apply(val);
|
||||
|
||||
onUpdate(t, t.ln);
|
||||
}
|
||||
else // fini !
|
||||
{
|
||||
terminateTween(t, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
import Paths;
|
Loading…
Reference in New Issue