documentation

This commit is contained in:
Yoshman29
2023-02-06 13:08:15 +01:00
parent 376609153b
commit a9df83d905
20 changed files with 154 additions and 323 deletions
+3
View File
@@ -125,6 +125,9 @@
<!-- Comment this out to use the default OpenFL assets system for the assets/ folder. !-->
<haxedef name="USE_ADAPTED_ASSETS" />
<!-- Comment this out to disable support for custom ndlls. !-->
<haxedef name="NDLLS_SUPPORTED" />
<!-- Comment this out to disable video cutscene support, in case of compilation errors. !-->
<define name="VIDEO_CUTSCENES" unless="web || linux || hl || mac" />
+1 -1
View File
@@ -4,7 +4,7 @@ var tankman:FunkinSprite;
var tankTalk1, distorto:FlxSound;
function create() {
FlxG.camera.zoom = 1;
FlxTween.tween(FlxG.camera, {zoom: 1}, 0.7, {ease: FlxEase.quadInOut});
game.camHUD.visible = false;
tankman = new FunkinSprite(game.dad.x + game.dad.globalOffset.x + 520, game.dad.y + game.dad.globalOffset.y + 225);
+1 -1
View File
@@ -8,7 +8,7 @@ var stressCutscene:FlxSound;
var step:Int = 0;
function create() {
FlxG.camera.zoom = 1;
// FlxTween.tween(FlxG.camera, {zoom: 1}, 0.7, {ease: FlxEase.quadInOut});
game.camHUD.visible = false;
game.persistentUpdate = true;
+1 -1
View File
@@ -4,7 +4,7 @@ var tankman:FunkinSprite;
var tankTalk1, tankTalk2, bfBeep, distorto:FlxSound;
function create() {
FlxG.camera.zoom = 1;
FlxTween.tween(FlxG.camera, {zoom: 1}, 0.7, {ease: FlxEase.quadInOut});
game.camHUD.visible = false;
tankman = new FunkinSprite(game.dad.x + game.dad.globalOffset.x + 520, game.dad.y + game.dad.globalOffset.y + 225);
+1 -1
View File
@@ -1 +1 @@
2219
2223
+3
View File
@@ -1,5 +1,8 @@
package funkin.cutscenes;
/**
* Substate made for cutscenes.
*/
class Cutscene extends MusicBeatSubstate {
var __callback:Void->Void;
var game:PlayState = PlayState.instance;
@@ -7,6 +7,9 @@ import openfl.utils.Assets;
import funkin.cutscenes.dialogue.*;
import haxe.xml.Access;
/**
* Substate made for dialogue cutscenes. To use it in a scripted cutscene, call `startDialogue`.
*/
class DialogueCutscene extends Cutscene {
public var dialoguePath:String;
public var dialogueData:Access;
@@ -4,6 +4,10 @@ import funkin.scripting.DummyScript;
import flixel.addons.transition.FlxTransitionableState;
import funkin.scripting.Script;
/**
* Substate made for scripted cutscenes.
* To add cutscenes to your songs, add a `cutscene.hx` file in your song's directory (ex: `songs/song/cutscene.hx`)
*/
class ScriptedCutscene extends Cutscene {
var script:Script;
+3
View File
@@ -5,6 +5,9 @@ import flixel.FlxG;
import flixel.FlxCamera;
import openfl.utils.Assets;
/**
* Substate made for video cutscenes. To use it in a scripted cutscene, call `startVideo`.
*/
class VideoCutscene extends Cutscene {
var path:String;
var localPath:String;
-197
View File
@@ -1,197 +0,0 @@
package funkin.debug;
import funkin.game.Character;
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;
/**
*DEBUG MODE
*/
class AnimationDebug extends FlxState
{
var bf:Character;
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()
{
if (FlxG.sound.music != null)
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 Character(0, 0, daAnim, true);
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]).y += 1 * multiplier;
if (downP)
char.animOffsets.get(animList[curAnim]).y -= 1 * multiplier;
if (leftP)
char.animOffsets.get(animList[curAnim]).x += 1 * multiplier;
if (rightP)
char.animOffsets.get(animList[curAnim]).x -= 1 * multiplier;
updateTexts();
genBoyOffsets(false);
char.playAnim(animList[curAnim]);
}
super.update(elapsed);
}
}
+27 -13
View File
@@ -193,7 +193,7 @@ class PlayState extends MusicBeatState
/**
* Previous cam follow.
*/
private static var prevCamFollow:FlxObject;
private static var smoothTransitionData:PlayStateTransitionData;
/**
* All of the strum line notes.
@@ -553,8 +553,6 @@ class PlayState extends MusicBeatState
}
var dadMidpoint = dad.getGraphicMidpoint();
var camPos:FlxPoint = new FlxPoint(dadMidpoint.x, dadMidpoint.y);
dadMidpoint.put();
comboGroup = new FlxSpriteGroup(FlxG.width * 0.55, (FlxG.height * 0.5) - 60);
@@ -565,6 +563,9 @@ class PlayState extends MusicBeatState
if (SONG.stage == null || SONG.stage.trim() == "") SONG.stage = "stage";
add(stage = new Stage(SONG.stage));
var camPos:FlxPoint = new FlxPoint(dadMidpoint.x, dadMidpoint.y);
dadMidpoint.put();
switch(SONG.song) {
// case "":
@@ -619,19 +620,19 @@ class PlayState extends MusicBeatState
generateSong(SONG);
if (prevCamFollow != null)
{
camFollow = prevCamFollow;
prevCamFollow = null;
} else {
camFollow = new FlxObject(0, 0, 2, 2);
camFollow.setPosition(camPos.x, camPos.y);
}
camFollow = new FlxObject(0, 0, 2, 2);
camFollow.setPosition(camPos.x, camPos.y);
add(camFollow);
FlxG.camera.follow(camFollow, LOCKON, 0.04);
FlxG.camera.zoom = defaultCamZoom;
FlxG.camera.focusOn(camFollow.getPosition());
if (smoothTransitionData != null && smoothTransitionData.stage == curStage) {
FlxG.camera.scroll.set(smoothTransitionData.camX, smoothTransitionData.camY);
FlxG.camera.zoom = smoothTransitionData.camZoom;
FlxTransitionableState.skipNextTransIn = true;
} else {
FlxG.camera.focusOn(camFollow.getPosition());
}
FlxG.worldBounds.set(0, 0, FlxG.width, FlxG.height);
@@ -1356,9 +1357,15 @@ class PlayState extends MusicBeatState
trace('LOADING NEXT SONG');
trace(PlayState.storyPlaylist[0].toLowerCase(), difficulty);
smoothTransitionData = {
stage: curStage,
camX: FlxG.camera.scroll.x,
camY: FlxG.camera.scroll.y,
camZoom: FlxG.camera.zoom
};
FlxTransitionableState.skipNextTransIn = true;
FlxTransitionableState.skipNextTransOut = true;
prevCamFollow = camFollow;
PlayState.SONG = Song.loadFromJson(PlayState.storyPlaylist[0].toLowerCase(), difficulty);
FlxG.sound.music.stop();
@@ -1705,4 +1712,11 @@ class ComboRating {
this.rating = rating;
this.color = color;
}
}
typedef PlayStateTransitionData = {
var stage:String;
var camX:Float;
var camY:Float;
var camZoom:Float;
}
+8 -1
View File
@@ -8,8 +8,15 @@ import haxe.macro.Context;
import sys.io.File;
#end
/**
* Macro that loads the current build number from `buildnumber.txt`, then make it available as an integer.
*
* `buildnumber.txt` is automatically incremented when the engine is launched with `lime test windows`.
*/
class BuildCounterMacro {
// non functional
/**
* Returns the obtained build number.
*/
public static macro function getBuildNumber():haxe.macro.Expr.ExprOf<Int> {
#if !display
var buildNum:Int = Std.parseInt(File.getContent("buildnumber.txt"));
+4 -1
View File
@@ -1,7 +1,10 @@
package funkin.macros;
#if macro
/**
* Macro that generates all additional fields, making events much easier to code in.
* It adds the `recycle` function, which allows you to "reset" an event's values.
*/
class EventMacro {
public static function build():Array<Field> {
var fields = Context.getBuildFields();
-106
View File
@@ -1,106 +0,0 @@
package funkin.macros;
#if macro
class FlxSpriteProxyMacro {
public static function build() {
return Context.getBuildFields();
/*
//TODO: FIX ALL OF THIS
var parentFields:Array<ClassField> = [];
var parentFieldsNames:Array<String> = [];
var superClass = Context.getLocalClass().get().superClass.t.get();
while(superClass != null) {
for(e in superClass.fields.get()) {
if (!parentFieldsNames.contains(e.name) && !e.kind.match(FMethod(MethInline))) {
parentFields.push(e);
parentFieldsNames.push(e.name);
}
}
if (superClass.superClass != null)
superClass = superClass.superClass.t.get();
else
superClass = null;
}
parentFieldsNames = [];
trace(Context.getLocalType());
var fields:Array<Field> = Context.getBuildFields();
// loop through all parent functions
for(f in parentFields) {
for(field in fields)
if (field.name == f.name)
continue;
switch(f.type) {
case TLazy(lazyFunc):
switch(lazyFunc()) {
case TFun(args, ret):
// its a function / getter / setter! overriding
var overFunc:Function = {
args: [for(a in args) {
value: null,
type: TypeTools.toComplexType(a.t),
opt: a.opt,
name: a.name
}]
};
var funcName = f.name;
var argNames:Array<haxe.macro.Expr> = [];
for(a in args)
argNames.push({
pos: Context.makePosition({
min: 1,
max: 2,
file: "DeezNuts.hx"
}),
expr: EConst(CIdent(a.name))
});
if (ret == null) {
overFunc.expr = macro {
function test(p1) {
trace(p1);
}
if (this.proxy != null) {
this.proxy.$funcName($a{argNames});
return;
}
super.$funcName($a{argNames});
};
} else {
overFunc.expr = macro {
if (this.proxy != null) {
return this.proxy.$funcName($a{argNames});
}
return super.$funcName($a{argNames});
};
}
var field:Field = {
pos: Context.makePosition({
min: 0,
max: 0,
file: "DeezNuts.hx"
}),
name: f.name,
kind: FFun(overFunc),
access: [AOverride, APublic]
};
var p = new Printer();
trace(p.printField(field));
fields.push(field);
default:
// nothing
}
default:
// nothing
}
}
return fields;
*/
}
}
#end
+4
View File
@@ -3,6 +3,10 @@ package funkin.macros;
#if macro
using StringTools;
/**
* Macro used in the options class to add getters for the SOLO keybinds.
*/
class OptionsMacro {
public static function build():Array<Field> {
var fields = Context.getBuildFields();
+3
View File
@@ -5,6 +5,9 @@ import haxe.macro.Context;
import haxe.macro.Compiler;
import haxe.macro.Expr;
/**
* Macros containing additional help functions to expand HScript capabilities.
*/
class ScriptsMacro {
public static function addAdditionalClasses() {
Compiler.include("flixel");
+20
View File
@@ -0,0 +1,20 @@
package funkin.system;
import flixel.FlxGame;
class FunkinGame extends FlxGame {
var skipNextTickUpdate:Bool = false;
public override function switchState() {
super.switchState();
// draw once to put all images in gpu then put the last update time to now to prevent lag spikes or whatever
draw();
_total = ticks = getTicks();
skipNextTickUpdate = true;
}
public override function onEnterFrame(t) {
if (skipNextTickUpdate != (skipNextTickUpdate = false))
_total = ticks = getTicks();
super.onEnterFrame(t);
}
}
+1 -1
View File
@@ -100,7 +100,7 @@ class Main extends Sprite
}
addChild(new FlxGame(gameWidth, gameHeight, null, zoom, framerate, framerate, skipSplash, startFullscreen));
addChild(new FunkinGame(gameWidth, gameHeight, null, zoom, framerate, framerate, skipSplash, startFullscreen));
loadGameSettings();
// FlxG.switchState(new TitleState());
FlxG.switchState(new funkin.menus.BetaWarningState());
+3
View File
@@ -41,6 +41,9 @@ class Paths
static public function video(key:String) {
return getPath('videos/$key.mp4', BINARY, null);
}
static public function ndll(key:String) {
return getPath('ndlls/$key.ndll', BINARY, null);
}
static public function getLibraryPath(file:String, library = "default")
{
+64
View File
@@ -1,5 +1,69 @@
package funkin.utils;
import openfl.utils.Assets;
import lime.app.Application;
/**
* Small util that allows you to load any function from ndlls via `getFunction`.
*
* NDLLs must be in your mod's "ndlls" folder, and must follow this name scheme:
* - `name-windows.ndll` for Windows targeted ndlls
* - `name-linux.ndll` for Linux targeted ndlls
* - `name-mac.ndll` for Mac targeted ndlls
*
* If:
* - The platform does not support NDLLs
* - The NDLL is not found
* - The Function cannot be found in the NDLL
* then an empty function will be returned instead, and a message will be shown in logs.
*/
class NdllUtil {
#if NDLLS_SUPPORTED
#if windows public static final os:String = "windows"; #end
#if linux public static final os:String = "linux"; #end
#if macos public static final os:String = "mac"; #end
#if android public static final os:String = "android"; #end
#end
/**
* Returns an function from a Haxe NDLL.
*
* @param ndll Name of the NDLL.
* @param name Name of the function.
* @param args Number of arguments of that function.
*/
public static function getFunction(ndll:String, name:String, args:Int) {
#if NDLLS_SUPPORTED
return getFunctionFromPath(Paths.ndll('$ndll-$os'), name, args);
#else
Logs.trace('NDLLs are not supported on this platform.', WARNING);
return function() {};
#end
}
/**
* Returns an function from a Haxe NDLL at specified path.
*
* @param ndll Asset path to the NDLL.
* @param name Name of the function.
* @param args Number of arguments of that function.
*/
public static function getFunctionFromPath(ndll:String, name:String, args:Int) {
#if NDLLS_SUPPORTED
if (!Assets.exists(ndll)) {
Logs.trace('Couldn\'t find ndll at ${ndll}.', WARNING);
return function() {};
}
var func = lime.system.CFFI.load(Assets.getPath(ndll), name, args);
if (func == null) {
Logs.trace('Method ${name} in ndll ${ndll} with ${args} args was not found.', ERROR);
return function() {};
}
return func;
#else
Logs.trace('NDLLs are not supported on this platform.', WARNING);
#end
return function() {};
}
}