mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2024-11-04 13:54:22 +00:00
Additional fixes for health icons and camera positioning.
This commit is contained in:
parent
3634346072
commit
4b7744f4e3
|
@ -1,14 +1,10 @@
|
|||
package funkin;
|
||||
|
||||
import funkin.util.Constants;
|
||||
import funkin.modding.events.ScriptEvent.UpdateScriptEvent;
|
||||
import funkin.modding.module.ModuleHandler;
|
||||
import funkin.NGio;
|
||||
import flixel.addons.transition.FlxTransitionableState;
|
||||
import flixel.effects.FlxFlicker;
|
||||
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.input.touch.FlxTouch;
|
||||
|
@ -18,14 +14,19 @@ import flixel.tweens.FlxTween;
|
|||
import flixel.ui.FlxButton;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.util.FlxTimer;
|
||||
import lime.app.Application;
|
||||
import openfl.filters.ShaderFilter;
|
||||
import funkin.modding.events.ScriptEvent.UpdateScriptEvent;
|
||||
import funkin.modding.module.ModuleHandler;
|
||||
import funkin.NGio;
|
||||
import funkin.shaderslmfao.ScreenWipeShader;
|
||||
import funkin.ui.AtlasMenuList;
|
||||
import funkin.ui.MenuList;
|
||||
import funkin.ui.OptionsState;
|
||||
import funkin.ui.PreferencesMenu;
|
||||
import funkin.ui.Prompt;
|
||||
import funkin.util.Constants;
|
||||
import funkin.util.WindowUtil;
|
||||
import lime.app.Application;
|
||||
import openfl.filters.ShaderFilter;
|
||||
|
||||
using StringTools;
|
||||
|
||||
|
@ -185,17 +186,7 @@ class MainMenuState extends MusicBeatState
|
|||
#if CAN_OPEN_LINKS
|
||||
function selectDonate()
|
||||
{
|
||||
#if linux
|
||||
// Sys.command('/usr/bin/xdg-open', ["https://ninja-muffin24.itch.io/funkin", "&"]);
|
||||
Sys.command('/usr/bin/xdg-open', [
|
||||
"https://www.kickstarter.com/projects/funkin/friday-night-funkin-the-full-ass-game/",
|
||||
"&"
|
||||
]);
|
||||
#else
|
||||
// FlxG.openURL('https://ninja-muffin24.itch.io/funkin');
|
||||
|
||||
FlxG.openURL('https://www.kickstarter.com/projects/funkin/friday-night-funkin-the-full-ass-game/');
|
||||
#end
|
||||
WindowUtil.openURL(Constants.URL_KICKSTARTER);
|
||||
}
|
||||
#end
|
||||
|
||||
|
|
|
@ -95,10 +95,14 @@ class MusicBeatState extends FlxUIState
|
|||
|
||||
function debug_refreshModules()
|
||||
{
|
||||
// Forcibly clear scripts so that scripts can be edited.
|
||||
ModuleHandler.clearModuleCache();
|
||||
|
||||
// Forcibly reload scripts so that scripted stages can be edited.
|
||||
polymod.hscript.PolymodScriptClass.clearScriptClasses();
|
||||
|
||||
// Forcibly reload Polymod so it finds any new files.
|
||||
polymod.Polymod.reload();
|
||||
|
||||
// Reload scripted classes so stages and modules will update.
|
||||
polymod.hscript.PolymodScriptClass.registerAllScriptClasses();
|
||||
|
||||
// Reload the stages in cache. This might cause a lag spike but who cares this is a debug utility.
|
||||
|
@ -106,7 +110,7 @@ class MusicBeatState extends FlxUIState
|
|||
CharacterDataParser.loadCharacterCache();
|
||||
ModuleHandler.loadModuleCache();
|
||||
|
||||
// Create a new instance of the current state class.
|
||||
// Restart the current state, so old data is cleared.
|
||||
FlxG.resetState();
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ class StoryMenuState extends MusicBeatState
|
|||
['mom', 'bf', 'gf'],
|
||||
['parents-christmas', 'bf', 'gf'],
|
||||
['senpai', 'bf', 'gf'],
|
||||
['tankman', 'bf', 'gf']
|
||||
['tankman', 'bf', 'gf'],
|
||||
];
|
||||
|
||||
var weekNames:Array<String> = [
|
||||
|
|
|
@ -27,7 +27,7 @@ typedef AnimationData =
|
|||
* Offset the character's position by this amount when playing this animation.
|
||||
* @default [0, 0]
|
||||
*/
|
||||
var offsets:Null<Array<Int>>;
|
||||
var offsets:Null<Array<Float>>;
|
||||
|
||||
/**
|
||||
* Whether the animation should loop when it finishes.
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package funkin.play;
|
||||
|
||||
import funkin.play.character.CharacterData.CharacterDataParser;
|
||||
import flixel.math.FlxMath;
|
||||
import flixel.FlxSprite;
|
||||
import flixel.math.FlxPoint;
|
||||
import funkin.play.character.CharacterData.CharacterDataParser;
|
||||
import openfl.utils.Assets;
|
||||
|
||||
/**
|
||||
|
@ -31,10 +33,25 @@ class HealthIcon extends FlxSprite
|
|||
|
||||
/**
|
||||
* Whether this health icon should automatically update its state based on the character's health.
|
||||
* You can set this to false if you want to manually forc
|
||||
* Note that turning this off means you have to manually do the following:
|
||||
* - Bumping the icon on the beat.
|
||||
* - Switching between winning/losing/idle animations.
|
||||
* - Repositioning the icon as health changes.
|
||||
*/
|
||||
public var autoUpdate:Bool = true;
|
||||
|
||||
/**
|
||||
* Since the `scale` of the sprite dynamically changes over time,
|
||||
* this value allows you to set a relative scale for the icon.
|
||||
* @default 1x scale
|
||||
*/
|
||||
public var size:FlxPoint = new FlxPoint(1, 1);
|
||||
|
||||
/**
|
||||
* Apply the "bump" animation once every X steps.
|
||||
*/
|
||||
public var bumpEvery:Int = 4;
|
||||
|
||||
/**
|
||||
* The player the health icon is attached to.
|
||||
*/
|
||||
|
@ -46,6 +63,11 @@ class HealthIcon extends FlxSprite
|
|||
*/
|
||||
var isPixel:Bool = false;
|
||||
|
||||
/**
|
||||
* Whether this is a legacy icon or not.
|
||||
*/
|
||||
var isLegacyStyle:Bool = false;
|
||||
|
||||
/**
|
||||
* At this amount of health, play the Winning animation instead of the idle.
|
||||
*/
|
||||
|
@ -127,10 +149,57 @@ class HealthIcon extends FlxSprite
|
|||
switch (playerId)
|
||||
{
|
||||
case 0: // Boyfriend
|
||||
// Update the animation based on the current state.
|
||||
updateHealthIcon(PlayState.instance.health);
|
||||
// Update the position to match the health bar.
|
||||
this.x = PlayState.instance.healthBar.x
|
||||
+ (PlayState.instance.healthBar.width * (FlxMath.remapToRange(PlayState.instance.healthBar.value, 0, 2, 100, 0) * 0.01));
|
||||
case 1: // Dad
|
||||
// Update the animation based on the current state.
|
||||
updateHealthIcon(MAXIMUM_HEALTH - PlayState.instance.health);
|
||||
// Update the position to match the health bar.
|
||||
this.x = PlayState.instance.healthBar.x
|
||||
+ (PlayState.instance.healthBar.width * (FlxMath.remapToRange(PlayState.instance.healthBar.value, 0, 2, 100, 0) * 0.01))
|
||||
- (this.width);
|
||||
}
|
||||
|
||||
// Lerp the health icon back to its normal size,
|
||||
// while maintaining aspect ratio.
|
||||
if (this.width > this.height)
|
||||
{
|
||||
// Apply linear interpolation while accounting for frame rate.
|
||||
var targetSize = Std.int(CoolUtil.coolLerp(this.width, 150 * this.size.x, 0.15));
|
||||
|
||||
setGraphicSize(targetSize, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
var targetSize = Std.int(CoolUtil.coolLerp(this.height, 150 * this.size.y, 0.15));
|
||||
|
||||
setGraphicSize(0, targetSize);
|
||||
}
|
||||
this.updateHitbox();
|
||||
}
|
||||
}
|
||||
|
||||
public function onStepHit(curStep:Int)
|
||||
{
|
||||
if (curStep % bumpEvery == 0 && isLegacyStyle)
|
||||
{
|
||||
// Make the health icons bump (the update function causes them to lerp back down).
|
||||
if (this.width > this.height)
|
||||
{
|
||||
var targetSize = Std.int(CoolUtil.coolLerp(this.width + 30, 150, 0.15));
|
||||
|
||||
setGraphicSize(targetSize, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
var targetSize = Std.int(CoolUtil.coolLerp(this.height + 30, 150, 0.15));
|
||||
|
||||
setGraphicSize(0, targetSize);
|
||||
}
|
||||
this.updateHitbox();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,6 +238,10 @@ class HealthIcon extends FlxSprite
|
|||
case FROM_LOSING | FROM_WINNING:
|
||||
if (isAnimationFinished())
|
||||
playAnimation(IDLE);
|
||||
case "":
|
||||
playAnimation(IDLE);
|
||||
default:
|
||||
playAnimation(IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,7 +273,7 @@ class HealthIcon extends FlxSprite
|
|||
|
||||
function correctCharacterId(charId:String):String
|
||||
{
|
||||
if (!Assets.exists(Paths.image('icons/icon-' + charId)))
|
||||
if (!Assets.exists(Paths.image('icons/icon-$charId')))
|
||||
{
|
||||
FlxG.log.warn('No icon for character: $charId : using default placeholder face instead!');
|
||||
return "face";
|
||||
|
@ -211,7 +284,7 @@ class HealthIcon extends FlxSprite
|
|||
|
||||
function isNewSpritesheet(charId:String):Bool
|
||||
{
|
||||
return Assets.exists(Paths.xml('icons/icon-' + characterId));
|
||||
return Assets.exists(Paths.file('images/icons/icon-$characterId.xml'));
|
||||
}
|
||||
|
||||
function fetchIsPixel(charId:String):Bool
|
||||
|
@ -235,7 +308,9 @@ class HealthIcon extends FlxSprite
|
|||
|
||||
isPixel = fetchIsPixel(charId);
|
||||
|
||||
if (isNewSpritesheet(charId))
|
||||
isLegacyStyle = !isNewSpritesheet(charId);
|
||||
|
||||
if (!isLegacyStyle)
|
||||
{
|
||||
frames = Paths.getSparrowAtlas('icons/icon-$charId');
|
||||
|
||||
|
@ -290,11 +365,17 @@ class HealthIcon extends FlxSprite
|
|||
{
|
||||
// Attempt to play the animation
|
||||
if (hasAnimation(name))
|
||||
{
|
||||
this.animation.play(name, restart, false, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Play the fallback animation if the requested animation was not found
|
||||
if (fallback != null && hasAnimation(fallback))
|
||||
{
|
||||
this.animation.play(fallback, restart, false, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we don't have an animation, we're done.
|
||||
}
|
||||
|
|
|
@ -185,7 +185,7 @@ class PlayState extends MusicBeatState implements IHook
|
|||
* The bar which displays the player's health.
|
||||
* Dynamically updated based on the value of `healthLerp` (which is based on `health`).
|
||||
*/
|
||||
private var healthBar:FlxBar;
|
||||
public var healthBar:FlxBar;
|
||||
|
||||
/**
|
||||
* The background image used for the health bar.
|
||||
|
@ -193,6 +193,16 @@ class PlayState extends MusicBeatState implements IHook
|
|||
*/
|
||||
public var healthBarBG:FlxSprite;
|
||||
|
||||
/**
|
||||
* The health icon representing the player.
|
||||
*/
|
||||
public var iconP1:HealthIcon;
|
||||
|
||||
/**
|
||||
* The health icon representing the opponent.
|
||||
*/
|
||||
public var iconP2:HealthIcon;
|
||||
|
||||
/**
|
||||
* The sprite group containing active player's strumline notes.
|
||||
*/
|
||||
|
@ -247,8 +257,6 @@ class PlayState extends MusicBeatState implements IHook
|
|||
private var combo:Int = 0;
|
||||
private var generatedMusic:Bool = false;
|
||||
private var startingSong:Bool = false;
|
||||
private var iconP1:HealthIcon;
|
||||
private var iconP2:HealthIcon;
|
||||
|
||||
var dialogue:Array<String>;
|
||||
var talking:Bool = true;
|
||||
|
@ -275,8 +283,9 @@ class PlayState extends MusicBeatState implements IHook
|
|||
|
||||
instance = this;
|
||||
|
||||
// TEMP: For testing
|
||||
cameraFollowPoint.makeGraphic(8, 8, 0xFFFF00FF);
|
||||
// Displays the camera follow point as a sprite for debug purposes.
|
||||
// TODO: Put this on a toggle?
|
||||
cameraFollowPoint.makeGraphic(8, 8, 0xFF00FF00);
|
||||
cameraFollowPoint.zIndex = 1000000;
|
||||
|
||||
// Reduce physics accuracy (who cares!!!) to improve animation quality.
|
||||
|
@ -326,6 +335,18 @@ class PlayState extends MusicBeatState implements IHook
|
|||
|
||||
// Once the song is loaded, we can continue and initialize the stage.
|
||||
|
||||
var healthBarYPos:Float = PreferencesMenu.getPref('downscroll') ? FlxG.height * 0.1 : FlxG.height * 0.9;
|
||||
healthBarBG = new FlxSprite(0, healthBarYPos).loadGraphic(Paths.image('healthBar'));
|
||||
healthBarBG.screenCenter(X);
|
||||
healthBarBG.scrollFactor.set(0, 0);
|
||||
add(healthBarBG);
|
||||
|
||||
healthBar = new FlxBar(healthBarBG.x + 4, healthBarBG.y + 4, RIGHT_TO_LEFT, Std.int(healthBarBG.width - 8), Std.int(healthBarBG.height - 8), this,
|
||||
'healthLerp', 0, 2);
|
||||
healthBar.scrollFactor.set();
|
||||
healthBar.createFilledBar(Constants.HEALTH_BAR_RED, Constants.HEALTH_BAR_GREEN);
|
||||
add(healthBar);
|
||||
|
||||
initStage();
|
||||
initCharacters();
|
||||
#if discord_rpc
|
||||
|
@ -357,31 +378,11 @@ class PlayState extends MusicBeatState implements IHook
|
|||
|
||||
FlxG.worldBounds.set(0, 0, FlxG.width, FlxG.height);
|
||||
|
||||
var healthBarYPos:Float = PreferencesMenu.getPref('downscroll') ? FlxG.height * 0.1 : FlxG.height * 0.9;
|
||||
healthBarBG = new FlxSprite(0, healthBarYPos).loadGraphic(Paths.image('healthBar'));
|
||||
healthBarBG.screenCenter(X);
|
||||
healthBarBG.scrollFactor.set(0, 0);
|
||||
add(healthBarBG);
|
||||
|
||||
healthBar = new FlxBar(healthBarBG.x + 4, healthBarBG.y + 4, RIGHT_TO_LEFT, Std.int(healthBarBG.width - 8), Std.int(healthBarBG.height - 8), this,
|
||||
'healthLerp', 0, 2);
|
||||
healthBar.scrollFactor.set();
|
||||
healthBar.createFilledBar(Constants.HEALTH_BAR_RED, Constants.HEALTH_BAR_GREEN);
|
||||
add(healthBar);
|
||||
|
||||
scoreText = new FlxText(healthBarBG.x + healthBarBG.width - 190, healthBarBG.y + 30, 0, "", 20);
|
||||
scoreText.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
|
||||
scoreText.scrollFactor.set();
|
||||
add(scoreText);
|
||||
|
||||
iconP1 = new HealthIcon(currentSong.player1, 0);
|
||||
iconP1.y = healthBar.y - (iconP1.height / 2);
|
||||
add(iconP1);
|
||||
|
||||
iconP2 = new HealthIcon(currentSong.player2, 1);
|
||||
iconP2.y = healthBar.y - (iconP2.height / 2);
|
||||
add(iconP2);
|
||||
|
||||
// Attach the groups to the HUD camera so they are rendered independent of the stage.
|
||||
grpNoteSplashes.cameras = [camHUD];
|
||||
activeNotes.cameras = [camHUD];
|
||||
|
@ -475,6 +476,9 @@ class PlayState extends MusicBeatState implements IHook
|
|||
currentStageId = 'schoolEvil';
|
||||
case 'guns' | 'stress' | 'ugh':
|
||||
currentStageId = 'tankmanBattlefield';
|
||||
case 'experimental-phase' | 'perfection':
|
||||
// SERIOUSLY REVAMP THE CHART FORMAT ALREADY
|
||||
currentStageId = "breakout";
|
||||
default:
|
||||
currentStageId = "mainStage";
|
||||
}
|
||||
|
@ -484,6 +488,14 @@ class PlayState extends MusicBeatState implements IHook
|
|||
|
||||
function initCharacters()
|
||||
{
|
||||
iconP1 = new HealthIcon(currentSong.player1, 0);
|
||||
iconP1.y = healthBar.y - (iconP1.height / 2);
|
||||
add(iconP1);
|
||||
|
||||
iconP2 = new HealthIcon(currentSong.player2, 1);
|
||||
iconP2.y = healthBar.y - (iconP2.height / 2);
|
||||
add(iconP2);
|
||||
|
||||
//
|
||||
// GIRLFRIEND
|
||||
//
|
||||
|
@ -501,6 +513,9 @@ class PlayState extends MusicBeatState implements IHook
|
|||
gfVersion = 'gf-pixel';
|
||||
case 'tankmanBattlefield':
|
||||
gfVersion = 'gf-tankmen';
|
||||
case 'breakout':
|
||||
// SERIOUSLY PUT THIS SHIT IN THE CHART
|
||||
gfVersion = '';
|
||||
}
|
||||
|
||||
if (currentSong.player1 == "pico")
|
||||
|
@ -585,8 +600,8 @@ class PlayState extends MusicBeatState implements IHook
|
|||
{
|
||||
// We're using Eric's stage handler.
|
||||
// Characters get added to the stage, not the main scene.
|
||||
currentStage.addCharacter(boyfriend, BF);
|
||||
currentStage.addCharacter(girlfriend, GF);
|
||||
currentStage.addCharacter(boyfriend, BF);
|
||||
currentStage.addCharacter(dad, DAD);
|
||||
|
||||
// Redo z-indexes.
|
||||
|
@ -1048,17 +1063,6 @@ class PlayState extends MusicBeatState implements IHook
|
|||
if (FlxG.keys.justPressed.NINE)
|
||||
iconP1.toggleOldIcon();
|
||||
|
||||
iconP1.setGraphicSize(Std.int(CoolUtil.coolLerp(iconP1.width, 150, 0.15)));
|
||||
iconP2.setGraphicSize(Std.int(CoolUtil.coolLerp(iconP2.width, 150, 0.15)));
|
||||
|
||||
iconP1.updateHitbox();
|
||||
iconP2.updateHitbox();
|
||||
|
||||
var iconOffset:Int = 26;
|
||||
|
||||
iconP1.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.value, 0, 2, 100, 0) * 0.01) - iconOffset);
|
||||
iconP2.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.value, 0, 2, 100, 0) * 0.01)) - (iconP2.width - iconOffset);
|
||||
|
||||
if (health > 2)
|
||||
health = 2;
|
||||
|
||||
|
@ -1293,7 +1297,7 @@ class PlayState extends MusicBeatState implements IHook
|
|||
function killCombo():Void
|
||||
{
|
||||
// Girlfriend gets sad if you combo break after hitting 5 notes.
|
||||
if (currentStage.getGirlfriend() != null)
|
||||
if (currentStage != null && currentStage.getGirlfriend() != null)
|
||||
if (combo > 5 && currentStage.getGirlfriend().hasAnimation('sad'))
|
||||
currentStage.getGirlfriend().playAnimation('sad');
|
||||
|
||||
|
@ -1727,6 +1731,9 @@ class PlayState extends MusicBeatState implements IHook
|
|||
resyncVocals();
|
||||
}
|
||||
|
||||
iconP1.onStepHit(curStep);
|
||||
iconP2.onStepHit(curStep);
|
||||
|
||||
dispatchEvent(new SongTimeScriptEvent(ScriptEvent.SONG_STEP_HIT, curBeat, curStep));
|
||||
}
|
||||
|
||||
|
@ -1765,12 +1772,6 @@ class PlayState extends MusicBeatState implements IHook
|
|||
}
|
||||
}
|
||||
|
||||
// Make the health icons bump (the update function causes them to lerp back down).
|
||||
iconP1.setGraphicSize(Std.int(iconP1.width + 30));
|
||||
iconP2.setGraphicSize(Std.int(iconP2.width + 30));
|
||||
iconP1.updateHitbox();
|
||||
iconP2.updateHitbox();
|
||||
|
||||
// Make the characters dance on the beat
|
||||
danceOnBeat();
|
||||
|
||||
|
|
|
@ -61,21 +61,21 @@ class BaseCharacter extends Bopper
|
|||
*/
|
||||
public var cameraFocusPoint(default, null):FlxPoint = new FlxPoint(0, 0);
|
||||
|
||||
override function set_animOffset(value:Array<Float>)
|
||||
override function set_animOffsets(value:Array<Float>)
|
||||
{
|
||||
if (animOffset == null)
|
||||
animOffset = [0, 0];
|
||||
if (animOffset == value)
|
||||
if (animOffsets == null)
|
||||
animOffsets = [0, 0];
|
||||
if (animOffsets == value)
|
||||
return value;
|
||||
|
||||
var xDiff = animOffset[0] - value[0];
|
||||
var yDiff = animOffset[1] - value[1];
|
||||
var xDiff = animOffsets[0] - value[0];
|
||||
var yDiff = animOffsets[1] - value[1];
|
||||
|
||||
// Call the super function so that camera focus point is not affected.
|
||||
super.set_x(this.x + xDiff);
|
||||
super.set_y(this.y + yDiff);
|
||||
|
||||
return animOffset = value;
|
||||
return animOffsets = value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,6 +122,7 @@ class BaseCharacter extends Bopper
|
|||
{
|
||||
this.characterName = _data.name;
|
||||
this.singTimeCrochet = _data.singTime;
|
||||
this.globalOffsets = _data.offsets;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,12 +140,43 @@ class BaseCharacter extends Bopper
|
|||
this.updateHitbox();
|
||||
}
|
||||
|
||||
/**
|
||||
* The per-character camera offset.
|
||||
*/
|
||||
var characterCameraOffsets(get, null):Array<Float>;
|
||||
|
||||
function get_characterCameraOffsets():Array<Float>
|
||||
{
|
||||
return _data.cameraOffsets;
|
||||
}
|
||||
|
||||
override function onCreate(event:ScriptEvent):Void
|
||||
{
|
||||
this.cameraFocusPoint = new FlxPoint(this.x + this.width / 2 + _data.cameraOffset[0], this.y + this.height / 2 + _data.cameraOffset[0]);
|
||||
// Camera focus point
|
||||
var charCenterX = this.x + this.width / 2;
|
||||
var charCenterY = this.y + this.height / 2;
|
||||
this.cameraFocusPoint = new FlxPoint(charCenterX + _data.cameraOffsets[0], charCenterY + _data.cameraOffsets[1]);
|
||||
super.onCreate(event);
|
||||
}
|
||||
|
||||
public function initHealthIcon(isOpponent:Bool):Void
|
||||
{
|
||||
if (!isOpponent)
|
||||
{
|
||||
PlayState.instance.iconP1.characterId = _data.healthIcon.id;
|
||||
PlayState.instance.iconP1.size.set(_data.healthIcon.scale, _data.healthIcon.scale);
|
||||
PlayState.instance.iconP1.offset.x = _data.healthIcon.offsets[0];
|
||||
PlayState.instance.iconP1.offset.y = _data.healthIcon.offsets[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayState.instance.iconP2.characterId = _data.healthIcon.id;
|
||||
PlayState.instance.iconP2.size.set(_data.healthIcon.scale, _data.healthIcon.scale);
|
||||
PlayState.instance.iconP2.offset.x = _data.healthIcon.offsets[0];
|
||||
PlayState.instance.iconP2.offset.y = _data.healthIcon.offsets[1];
|
||||
}
|
||||
}
|
||||
|
||||
public override function onUpdate(event:UpdateScriptEvent):Void
|
||||
{
|
||||
super.onUpdate(event);
|
||||
|
|
|
@ -290,11 +290,11 @@ class CharacterDataParser
|
|||
static final DEFAULT_ISPIXEL:Bool = false;
|
||||
static final DEFAULT_LOOP:Bool = false;
|
||||
static final DEFAULT_NAME:String = "Untitled Character";
|
||||
static final DEFAULT_OFFSETS:Array<Int> = [0, 0];
|
||||
static final DEFAULT_OFFSETS:Array<Float> = [0, 0];
|
||||
static final DEFAULT_HEALTHICON_OFFSETS:Array<Int> = [0, 25];
|
||||
static final DEFAULT_RENDERTYPE:CharacterRenderType = CharacterRenderType.SPARROW;
|
||||
static final DEFAULT_SCALE:Float = 1;
|
||||
static final DEFAULT_SCROLL:Array<Float> = [0, 0];
|
||||
static final DEFAULT_CAMERAOFFSET:Array<Float> = [0, 0];
|
||||
static final DEFAULT_STARTINGANIM:String = "idle";
|
||||
|
||||
/**
|
||||
|
@ -341,6 +341,40 @@ class CharacterDataParser
|
|||
return null;
|
||||
}
|
||||
|
||||
if (input.offsets == null)
|
||||
{
|
||||
input.offsets = DEFAULT_OFFSETS;
|
||||
}
|
||||
|
||||
if (input.cameraOffsets == null)
|
||||
{
|
||||
input.cameraOffsets = DEFAULT_OFFSETS;
|
||||
}
|
||||
|
||||
if (input.healthIcon == null)
|
||||
{
|
||||
input.healthIcon = {
|
||||
id: null,
|
||||
scale: null,
|
||||
offsets: null
|
||||
};
|
||||
}
|
||||
|
||||
if (input.healthIcon.id == null)
|
||||
{
|
||||
input.healthIcon.id = id;
|
||||
}
|
||||
|
||||
if (input.healthIcon.scale == null)
|
||||
{
|
||||
input.healthIcon.scale = DEFAULT_SCALE;
|
||||
}
|
||||
|
||||
if (input.healthIcon.offsets == null)
|
||||
{
|
||||
input.healthIcon.offsets = DEFAULT_OFFSETS;
|
||||
}
|
||||
|
||||
if (input.startingAnimation == null)
|
||||
{
|
||||
input.startingAnimation = DEFAULT_STARTINGANIM;
|
||||
|
@ -351,11 +385,6 @@ class CharacterDataParser
|
|||
input.scale = DEFAULT_SCALE;
|
||||
}
|
||||
|
||||
if (input.cameraOffset == null)
|
||||
{
|
||||
input.cameraOffset = DEFAULT_CAMERAOFFSET;
|
||||
}
|
||||
|
||||
if (input.isPixel == null)
|
||||
{
|
||||
input.isPixel = DEFAULT_ISPIXEL;
|
||||
|
@ -467,12 +496,23 @@ typedef CharacterData =
|
|||
*/
|
||||
var scale:Null<Float>;
|
||||
|
||||
/**
|
||||
* Optional data about the health icon for the character.
|
||||
*/
|
||||
var healthIcon:Null<HealthIconData>;
|
||||
|
||||
/**
|
||||
* The global offset to the character's position, in pixels.
|
||||
* @default [0, 0]
|
||||
*/
|
||||
var offsets:Null<Array<Float>>;
|
||||
|
||||
/**
|
||||
* The amount to offset the camera by while focusing on this character.
|
||||
* Default value focuses on the character directly.
|
||||
* @default [0, 0]
|
||||
*/
|
||||
var cameraOffset:Array<Float>;
|
||||
var cameraOffsets:Array<Float>;
|
||||
|
||||
/**
|
||||
* Setting this to true disables anti-aliasing for the character.
|
||||
|
@ -510,3 +550,23 @@ typedef CharacterData =
|
|||
*/
|
||||
var startingAnimation:Null<String>;
|
||||
};
|
||||
|
||||
typedef HealthIconData =
|
||||
{
|
||||
/**
|
||||
* The ID to use for the health icon.
|
||||
* @default The character's ID
|
||||
*/
|
||||
var id:Null<String>;
|
||||
|
||||
/**
|
||||
* The scale of the health icon.
|
||||
*/
|
||||
var scale:Null<Float>;
|
||||
|
||||
/**
|
||||
* The offset of the health icon, in pixels.
|
||||
* @default [0, 25]
|
||||
*/
|
||||
var offsets:Null<Array<Float>>;
|
||||
}
|
||||
|
|
|
@ -47,22 +47,27 @@ class Bopper extends FlxSprite implements IPlayStateScriptedClass
|
|||
return value;
|
||||
}
|
||||
|
||||
private var animOffset(default, set):Array<Float> = [0, 0];
|
||||
/**
|
||||
* The offset of the character relative to the position specified by the stage.
|
||||
*/
|
||||
public var globalOffsets(default, null):Array<Float> = [0, 0];
|
||||
|
||||
function set_animOffset(value:Array<Float>)
|
||||
private var animOffsets(default, set):Array<Float> = [0, 0];
|
||||
|
||||
function set_animOffsets(value:Array<Float>)
|
||||
{
|
||||
if (animOffset == null)
|
||||
animOffset = [0, 0];
|
||||
if (animOffset == value)
|
||||
if (animOffsets == null)
|
||||
animOffsets = [0, 0];
|
||||
if (animOffsets == value)
|
||||
return value;
|
||||
|
||||
var xDiff = animOffset[0] - value[0];
|
||||
var yDiff = animOffset[1] - value[1];
|
||||
var xDiff = animOffsets[0] - value[0];
|
||||
var yDiff = animOffsets[1] - value[1];
|
||||
|
||||
this.x += xDiff;
|
||||
this.y += yDiff;
|
||||
|
||||
return animOffset = value;
|
||||
return animOffsets = value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -192,11 +197,11 @@ class Bopper extends FlxSprite implements IPlayStateScriptedClass
|
|||
var offsets = animationOffsets.get(name);
|
||||
if (offsets != null)
|
||||
{
|
||||
this.animOffset = offsets;
|
||||
this.animOffsets = [offsets[0] + globalOffsets[0], offsets[1] + globalOffsets[1]];
|
||||
}
|
||||
else
|
||||
{
|
||||
this.animOffset = [0, 0];
|
||||
this.animOffsets = globalOffsets;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,7 +210,7 @@ class Bopper extends FlxSprite implements IPlayStateScriptedClass
|
|||
return this.animation.finished;
|
||||
}
|
||||
|
||||
public function setAnimationOffsets(name:String, xOffset:Int, yOffset:Int):Void
|
||||
public function setAnimationOffsets(name:String, xOffset:Float, yOffset:Float):Void
|
||||
{
|
||||
animationOffsets.set(name, [xOffset, yOffset]);
|
||||
applyAnimationOffsets(name);
|
||||
|
|
|
@ -241,33 +241,70 @@ class Stage extends FlxSpriteGroup implements IHook implements IPlayStateScripte
|
|||
if (character == null)
|
||||
return;
|
||||
|
||||
#if debug
|
||||
// Temporary marker that shows where the character's location is relative to.
|
||||
// Should display at the stage position of the character (before any offsets).
|
||||
// TODO: Make this a toggle? It's useful to turn on from time to time.
|
||||
var debugIcon:FlxSprite = new FlxSprite(0, 0);
|
||||
debugIcon.makeGraphic(8, 8, 0xffff00ff);
|
||||
debugIcon.zIndex = 1000000;
|
||||
#end
|
||||
|
||||
// Apply position and z-index.
|
||||
switch (charType)
|
||||
{
|
||||
case BF:
|
||||
this.characters.set("bf", character);
|
||||
character.zIndex = _data.characters.bf.zIndex;
|
||||
|
||||
// Start with the per-stage character position.
|
||||
// Subtracting the origin ensures characters are positioned relative to their feet.
|
||||
character.x = _data.characters.bf.position[0] - character.characterOrigin.x;
|
||||
character.y = _data.characters.bf.position[1] - character.characterOrigin.y;
|
||||
// Subtracting the global offset allows positioning on a per-character basis.
|
||||
character.x = _data.characters.bf.position[0] - character.characterOrigin.x + character.globalOffsets[0];
|
||||
character.y = _data.characters.bf.position[1] - character.characterOrigin.y + character.globalOffsets[1];
|
||||
|
||||
character.cameraFocusPoint.x += _data.characters.bf.cameraOffsets[0];
|
||||
character.cameraFocusPoint.y += _data.characters.bf.cameraOffsets[1];
|
||||
|
||||
debugIcon.x = _data.characters.bf.position[0];
|
||||
debugIcon.y = _data.characters.bf.position[1];
|
||||
|
||||
character.initHealthIcon(false);
|
||||
case GF:
|
||||
this.characters.set("gf", character);
|
||||
character.zIndex = _data.characters.gf.zIndex;
|
||||
// Subtracting the origin ensures characters are positioned relative to their feet.
|
||||
character.x = _data.characters.gf.position[0] - character.characterOrigin.x;
|
||||
character.y = _data.characters.gf.position[1] - character.characterOrigin.y;
|
||||
|
||||
character.x = _data.characters.gf.position[0] - character.characterOrigin.x + character.globalOffsets[0];
|
||||
character.y = _data.characters.gf.position[1] - character.characterOrigin.y + character.globalOffsets[1];
|
||||
|
||||
character.cameraFocusPoint.x += _data.characters.gf.cameraOffsets[0];
|
||||
character.cameraFocusPoint.y += _data.characters.gf.cameraOffsets[1];
|
||||
|
||||
// Draw the debug icon at the character's feet.
|
||||
debugIcon.x = _data.characters.gf.position[0];
|
||||
debugIcon.y = _data.characters.gf.position[1];
|
||||
case DAD:
|
||||
this.characters.set("dad", character);
|
||||
character.zIndex = _data.characters.dad.zIndex;
|
||||
// Subtracting the origin ensures characters are positioned relative to their feet.
|
||||
character.x = _data.characters.dad.position[0] - character.characterOrigin.x;
|
||||
character.y = _data.characters.dad.position[1] - character.characterOrigin.y;
|
||||
|
||||
character.x = _data.characters.dad.position[0] - character.characterOrigin.x + character.globalOffsets[0];
|
||||
character.y = _data.characters.dad.position[1] - character.characterOrigin.y + character.globalOffsets[1];
|
||||
|
||||
character.cameraFocusPoint.x += _data.characters.dad.cameraOffsets[0];
|
||||
character.cameraFocusPoint.y += _data.characters.dad.cameraOffsets[1];
|
||||
|
||||
// Draw the debug icon at the character's feet.
|
||||
debugIcon.x = _data.characters.dad.position[0];
|
||||
debugIcon.y = _data.characters.dad.position[1];
|
||||
|
||||
character.initHealthIcon(true);
|
||||
default:
|
||||
this.characters.set(character.characterId, character);
|
||||
}
|
||||
|
||||
// Add the character to the scene.
|
||||
this.add(character);
|
||||
this.add(debugIcon);
|
||||
}
|
||||
|
||||
public inline function getGirlfriendPosition():FlxPoint
|
||||
|
|
|
@ -174,7 +174,7 @@ class StageDataParser
|
|||
static final DEFAULT_DANCEEVERY:Int = 0;
|
||||
static final DEFAULT_ISPIXEL:Bool = false;
|
||||
static final DEFAULT_NAME:String = "Untitled Stage";
|
||||
static final DEFAULT_OFFSETS:Array<Int> = [0, 0];
|
||||
static final DEFAULT_OFFSETS:Array<Float> = [0, 0];
|
||||
static final DEFAULT_POSITION:Array<Float> = [0, 0];
|
||||
static final DEFAULT_SCALE:Float = 1.0;
|
||||
static final DEFAULT_SCROLL:Array<Float> = [0, 0];
|
||||
|
@ -183,6 +183,7 @@ class StageDataParser
|
|||
static final DEFAULT_CHARACTER_DATA:StageDataCharacter = {
|
||||
zIndex: DEFAULT_ZINDEX,
|
||||
position: DEFAULT_POSITION,
|
||||
cameraOffsets: DEFAULT_OFFSETS,
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -358,6 +359,10 @@ class StageDataParser
|
|||
{
|
||||
inputCharacter.position = [0, 0];
|
||||
}
|
||||
if (inputCharacter.cameraOffsets == null || inputCharacter.cameraOffsets.length != 2)
|
||||
{
|
||||
inputCharacter.cameraOffsets = [0, 0];
|
||||
}
|
||||
}
|
||||
|
||||
// All good!
|
||||
|
@ -475,5 +480,11 @@ typedef StageDataCharacter =
|
|||
/**
|
||||
* The position to render the character at.
|
||||
*/
|
||||
position:Array<Float>
|
||||
position:Array<Float>,
|
||||
|
||||
/**
|
||||
* The camera offsets to apply when focusing on the character on this stage.
|
||||
* @default [0, 0]
|
||||
*/
|
||||
cameraOffsets:Array<Float>,
|
||||
};
|
||||
|
|
|
@ -31,4 +31,7 @@ class Constants
|
|||
return 'v${Application.current.meta.get('version')}' + VERSION_SUFFIX;
|
||||
}
|
||||
#end
|
||||
|
||||
public static final URL_KICKSTARTER:String = "https://www.kickstarter.com/projects/funkin/friday-night-funkin-the-full-ass-game/";
|
||||
public static final URL_ITCH:String = "https://ninja-muffin24.itch.io/funkin";
|
||||
}
|
||||
|
|
18
source/funkin/util/WindowUtil.hx
Normal file
18
source/funkin/util/WindowUtil.hx
Normal file
|
@ -0,0 +1,18 @@
|
|||
package funkin.util;
|
||||
|
||||
class WindowUtil
|
||||
{
|
||||
public static function openURL(targetUrl:String)
|
||||
{
|
||||
#if CAN_OPEN_LINKS
|
||||
#if linux
|
||||
// Sys.command('/usr/bin/xdg-open', [, "&"]);
|
||||
Sys.command('/usr/bin/xdg-open', [targetUrl, "&"]);
|
||||
#else
|
||||
FlxG.openURL(targetUrl);
|
||||
#end
|
||||
#else
|
||||
trace('Cannot open')
|
||||
#end
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue