mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-26 17:46:08 -05:00
Merge pull request #627 from FunkinCrew/pixel-perfect
more retro week 6 stuff
This commit is contained in:
commit
9b64d08944
10 changed files with 277 additions and 16 deletions
2
assets
2
assets
|
@ -1 +1 @@
|
|||
Subproject commit 4b95075255baeaba3585fabff7052c257856fafe
|
||||
Subproject commit 225e248f148a92500a6fe90e4f10e4cd2acee782
|
106
source/funkin/effects/RetroCameraFade.hx
Normal file
106
source/funkin/effects/RetroCameraFade.hx
Normal file
|
@ -0,0 +1,106 @@
|
|||
package funkin.effects;
|
||||
|
||||
import flixel.util.FlxTimer;
|
||||
import flixel.FlxCamera;
|
||||
import openfl.filters.ColorMatrixFilter;
|
||||
|
||||
class RetroCameraFade
|
||||
{
|
||||
// im lazy, but we only use this for week 6
|
||||
// and also sorta yoinked for djflixel, lol !
|
||||
public static function fadeWhite(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void
|
||||
{
|
||||
var steps:Int = 0;
|
||||
var stepsTotal:Int = camSteps;
|
||||
|
||||
new FlxTimer().start(time / stepsTotal, _ -> {
|
||||
var V:Float = (1 / stepsTotal) * steps;
|
||||
if (steps == stepsTotal) V = 1;
|
||||
|
||||
var matrix = [
|
||||
1, 0, 0, 0, V * 255,
|
||||
0, 1, 0, 0, V * 255,
|
||||
0, 0, 1, 0, V * 255,
|
||||
0, 0, 0, 1, 0
|
||||
];
|
||||
camera.filters = [new ColorMatrixFilter(matrix)];
|
||||
steps++;
|
||||
}, stepsTotal + 1);
|
||||
}
|
||||
|
||||
public static function fadeFromWhite(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void
|
||||
{
|
||||
var steps:Int = camSteps;
|
||||
var stepsTotal:Int = camSteps;
|
||||
|
||||
var matrixDerp = [
|
||||
1, 0, 0, 0, 1.0 * 255,
|
||||
0, 1, 0, 0, 1.0 * 255,
|
||||
0, 0, 1, 0, 1.0 * 255,
|
||||
0, 0, 0, 1, 0
|
||||
];
|
||||
camera.filters = [new ColorMatrixFilter(matrixDerp)];
|
||||
|
||||
new FlxTimer().start(time / stepsTotal, _ -> {
|
||||
var V:Float = (1 / stepsTotal) * steps;
|
||||
if (steps == stepsTotal) V = 1;
|
||||
|
||||
var matrix = [
|
||||
1, 0, 0, 0, V * 255,
|
||||
0, 1, 0, 0, V * 255,
|
||||
0, 0, 1, 0, V * 255,
|
||||
0, 0, 0, 1, 0
|
||||
];
|
||||
camera.filters = [new ColorMatrixFilter(matrix)];
|
||||
steps--;
|
||||
}, camSteps);
|
||||
}
|
||||
|
||||
public static function fadeToBlack(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void
|
||||
{
|
||||
var steps:Int = 0;
|
||||
var stepsTotal:Int = camSteps;
|
||||
|
||||
new FlxTimer().start(time / stepsTotal, _ -> {
|
||||
var V:Float = (1 / stepsTotal) * steps;
|
||||
if (steps == stepsTotal) V = 1;
|
||||
|
||||
var matrix = [
|
||||
1, 0, 0, 0, -V * 255,
|
||||
0, 1, 0, 0, -V * 255,
|
||||
0, 0, 1, 0, -V * 255,
|
||||
0, 0, 0, 1, 0
|
||||
];
|
||||
camera.filters = [new ColorMatrixFilter(matrix)];
|
||||
steps++;
|
||||
}, camSteps);
|
||||
}
|
||||
|
||||
public static function fadeBlack(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void
|
||||
{
|
||||
var steps:Int = camSteps;
|
||||
var stepsTotal:Int = camSteps;
|
||||
|
||||
var matrixDerp = [
|
||||
1, 0, 0, 0, -1.0 * 255,
|
||||
0, 1, 0, 0, -1.0 * 255,
|
||||
0, 0, 1, 0, -1.0 * 255,
|
||||
0, 0, 0, 1, 0
|
||||
];
|
||||
camera.filters = [new ColorMatrixFilter(matrixDerp)];
|
||||
|
||||
new FlxTimer().start(time / stepsTotal, _ -> {
|
||||
var V:Float = (1 / stepsTotal) * steps;
|
||||
if (steps == stepsTotal) V = 1;
|
||||
|
||||
var matrix = [
|
||||
1, 0, 0, 0, -V * 255,
|
||||
0, 1, 0, 0, -V * 255,
|
||||
0, 0, 1, 0, -V * 255,
|
||||
0, 0, 0, 1, 0
|
||||
];
|
||||
camera.filters = [new ColorMatrixFilter(matrix)];
|
||||
steps--;
|
||||
}, camSteps + 1);
|
||||
}
|
||||
}
|
|
@ -7,6 +7,10 @@ import flixel.tweens.FlxTween;
|
|||
import openfl.display3D.textures.TextureBase;
|
||||
import funkin.graphics.framebuffer.FixedBitmapData;
|
||||
import openfl.display.BitmapData;
|
||||
import flixel.math.FlxRect;
|
||||
import flixel.math.FlxPoint;
|
||||
import flixel.graphics.frames.FlxFrame;
|
||||
import flixel.FlxCamera;
|
||||
|
||||
/**
|
||||
* An FlxSprite with additional functionality.
|
||||
|
@ -269,6 +273,103 @@ class FunkinSprite extends FlxSprite
|
|||
return result;
|
||||
}
|
||||
|
||||
@:access(flixel.FlxCamera)
|
||||
override function getBoundingBox(camera:FlxCamera):FlxRect
|
||||
{
|
||||
getScreenPosition(_point, camera);
|
||||
|
||||
_rect.set(_point.x, _point.y, width, height);
|
||||
_rect = camera.transformRect(_rect);
|
||||
|
||||
if (isPixelPerfectRender(camera))
|
||||
{
|
||||
_rect.width = _rect.width / this.scale.x;
|
||||
_rect.height = _rect.height / this.scale.y;
|
||||
_rect.x = _rect.x / this.scale.x;
|
||||
_rect.y = _rect.y / this.scale.y;
|
||||
_rect.floor();
|
||||
_rect.x = _rect.x * this.scale.x;
|
||||
_rect.y = _rect.y * this.scale.y;
|
||||
_rect.width = _rect.width * this.scale.x;
|
||||
_rect.height = _rect.height * this.scale.y;
|
||||
}
|
||||
|
||||
return _rect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the screen position of this object.
|
||||
*
|
||||
* @param result Optional arg for the returning point
|
||||
* @param camera The desired "screen" coordinate space. If `null`, `FlxG.camera` is used.
|
||||
* @return The screen position of this object.
|
||||
*/
|
||||
public override function getScreenPosition(?result:FlxPoint, ?camera:FlxCamera):FlxPoint
|
||||
{
|
||||
if (result == null) result = FlxPoint.get();
|
||||
|
||||
if (camera == null) camera = FlxG.camera;
|
||||
|
||||
result.set(x, y);
|
||||
if (pixelPerfectPosition)
|
||||
{
|
||||
_rect.width = _rect.width / this.scale.x;
|
||||
_rect.height = _rect.height / this.scale.y;
|
||||
_rect.x = _rect.x / this.scale.x;
|
||||
_rect.y = _rect.y / this.scale.y;
|
||||
_rect.round();
|
||||
_rect.x = _rect.x * this.scale.x;
|
||||
_rect.y = _rect.y * this.scale.y;
|
||||
_rect.width = _rect.width * this.scale.x;
|
||||
_rect.height = _rect.height * this.scale.y;
|
||||
}
|
||||
|
||||
return result.subtract(camera.scroll.x * scrollFactor.x, camera.scroll.y * scrollFactor.y);
|
||||
}
|
||||
|
||||
override function drawSimple(camera:FlxCamera):Void
|
||||
{
|
||||
getScreenPosition(_point, camera).subtractPoint(offset);
|
||||
if (isPixelPerfectRender(camera))
|
||||
{
|
||||
_point.x = _point.x / this.scale.x;
|
||||
_point.y = _point.y / this.scale.y;
|
||||
_point.round();
|
||||
|
||||
_point.x = _point.x * this.scale.x;
|
||||
_point.y = _point.y * this.scale.y;
|
||||
}
|
||||
|
||||
_point.copyToFlash(_flashPoint);
|
||||
camera.copyPixels(_frame, framePixels, _flashRect, _flashPoint, colorTransform, blend, antialiasing);
|
||||
}
|
||||
|
||||
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 (bakedRotationAngle <= 0)
|
||||
{
|
||||
updateTrig();
|
||||
|
||||
if (angle != 0) _matrix.rotateWithTrig(_cosAngle, _sinAngle);
|
||||
}
|
||||
|
||||
getScreenPosition(_point, camera).subtractPoint(offset);
|
||||
_point.add(origin.x, origin.y);
|
||||
_matrix.translate(_point.x, _point.y);
|
||||
|
||||
if (isPixelPerfectRender(camera))
|
||||
{
|
||||
_matrix.tx = Math.round(_matrix.tx / this.scale.x) * this.scale.x;
|
||||
_matrix.ty = Math.round(_matrix.ty / this.scale.y) * this.scale.y;
|
||||
}
|
||||
|
||||
camera.drawPixels(_frame, framePixels, _matrix, colorTransform, blend, antialiasing, shader);
|
||||
}
|
||||
|
||||
public override function destroy():Void
|
||||
{
|
||||
frames = null;
|
||||
|
|
|
@ -9,6 +9,7 @@ import funkin.modding.module.ModuleHandler;
|
|||
import funkin.modding.events.ScriptEvent;
|
||||
import funkin.modding.events.ScriptEvent.CountdownScriptEvent;
|
||||
import flixel.util.FlxTimer;
|
||||
import funkin.util.EaseUtil;
|
||||
import funkin.audio.FunkinSound;
|
||||
|
||||
class Countdown
|
||||
|
@ -117,7 +118,7 @@ class Countdown
|
|||
*
|
||||
* If you want to call this from a module, it's better to use the event system and cancel the onCountdownStep event.
|
||||
*/
|
||||
public static function pauseCountdown()
|
||||
public static function pauseCountdown():Void
|
||||
{
|
||||
if (countdownTimer != null && !countdownTimer.finished)
|
||||
{
|
||||
|
@ -130,7 +131,7 @@ class Countdown
|
|||
*
|
||||
* If you want to call this from a module, it's better to use the event system and cancel the onCountdownStep event.
|
||||
*/
|
||||
public static function resumeCountdown()
|
||||
public static function resumeCountdown():Void
|
||||
{
|
||||
if (countdownTimer != null && !countdownTimer.finished)
|
||||
{
|
||||
|
@ -143,7 +144,7 @@ class Countdown
|
|||
*
|
||||
* If you want to call this from a module, it's better to use the event system and cancel the onCountdownStart event.
|
||||
*/
|
||||
public static function stopCountdown()
|
||||
public static function stopCountdown():Void
|
||||
{
|
||||
if (countdownTimer != null)
|
||||
{
|
||||
|
@ -156,7 +157,7 @@ class Countdown
|
|||
/**
|
||||
* Stops the current countdown, then starts the song for you.
|
||||
*/
|
||||
public static function skipCountdown()
|
||||
public static function skipCountdown():Void
|
||||
{
|
||||
stopCountdown();
|
||||
// This will trigger PlayState.startSong()
|
||||
|
@ -185,8 +186,11 @@ class Countdown
|
|||
{
|
||||
var spritePath:String = null;
|
||||
|
||||
var fadeEase = FlxEase.cubeInOut;
|
||||
|
||||
if (isPixelStyle)
|
||||
{
|
||||
fadeEase = EaseUtil.stepped(8);
|
||||
switch (index)
|
||||
{
|
||||
case TWO:
|
||||
|
@ -227,7 +231,7 @@ class Countdown
|
|||
countdownSprite.screenCenter();
|
||||
|
||||
// Fade sprite in, then out, then destroy it.
|
||||
FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100, alpha: 0}, Conductor.instance.beatLengthMs / 1000,
|
||||
FlxTween.tween(countdownSprite, {y: countdownSprite.y += 100}, Conductor.instance.beatLengthMs / 1000,
|
||||
{
|
||||
ease: FlxEase.cubeInOut,
|
||||
onComplete: function(twn:FlxTween) {
|
||||
|
@ -235,6 +239,11 @@ class Countdown
|
|||
}
|
||||
});
|
||||
|
||||
FlxTween.tween(countdownSprite, {alpha: 0}, Conductor.instance.beatLengthMs / 1000,
|
||||
{
|
||||
ease: fadeEase
|
||||
});
|
||||
|
||||
PlayState.instance.add(countdownSprite);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import funkin.ui.MusicBeatSubState;
|
|||
import funkin.ui.story.StoryMenuState;
|
||||
import funkin.util.MathUtil;
|
||||
import openfl.utils.Assets;
|
||||
import funkin.effects.RetroCameraFade;
|
||||
|
||||
/**
|
||||
* A substate which renders over the PlayState when the player dies.
|
||||
|
@ -332,9 +333,12 @@ class GameOverSubState extends MusicBeatSubState
|
|||
// After the animation finishes...
|
||||
new FlxTimer().start(0.7, function(tmr:FlxTimer) {
|
||||
// ...fade out the graphics. Then after that happens...
|
||||
FlxG.camera.fade(FlxColor.BLACK, 2, false, function() {
|
||||
|
||||
var resetPlaying = function(pixel:Bool = false) {
|
||||
// ...close the GameOverSubState.
|
||||
FlxG.camera.fade(FlxColor.BLACK, 1, true, null, true);
|
||||
if (pixel) RetroCameraFade.fadeBlack(FlxG.camera, 10, 1);
|
||||
else
|
||||
FlxG.camera.fade(FlxColor.BLACK, 1, true, null, true);
|
||||
PlayState.instance.needsReset = true;
|
||||
|
||||
if (PlayState.instance.isMinimalMode || boyfriend == null) {}
|
||||
|
@ -351,7 +355,22 @@ class GameOverSubState extends MusicBeatSubState
|
|||
|
||||
// Close the substate.
|
||||
close();
|
||||
});
|
||||
};
|
||||
|
||||
if (musicSuffix == '-pixel')
|
||||
{
|
||||
RetroCameraFade.fadeToBlack(FlxG.camera, 10, 2);
|
||||
new FlxTimer().start(2, _ -> {
|
||||
FlxG.camera.filters = [];
|
||||
resetPlaying(true);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
FlxG.camera.fade(FlxColor.BLACK, 2, false, function() {
|
||||
resetPlaying();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ class MultiSparrowCharacter extends BaseCharacter
|
|||
{
|
||||
this.isPixel = true;
|
||||
this.antialiasing = false;
|
||||
pixelPerfectRender = true;
|
||||
pixelPerfectPosition = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -43,6 +43,8 @@ class PackerCharacter extends BaseCharacter
|
|||
{
|
||||
this.isPixel = true;
|
||||
this.antialiasing = false;
|
||||
pixelPerfectRender = true;
|
||||
pixelPerfectPosition = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -46,6 +46,8 @@ class SparrowCharacter extends BaseCharacter
|
|||
{
|
||||
this.isPixel = true;
|
||||
this.antialiasing = false;
|
||||
pixelPerfectRender = true;
|
||||
pixelPerfectPosition = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -7,8 +7,9 @@ import flixel.util.FlxDirection;
|
|||
import funkin.graphics.FunkinSprite;
|
||||
import funkin.play.PlayState;
|
||||
import funkin.util.TimerUtil;
|
||||
import funkin.util.EaseUtil;
|
||||
|
||||
class PopUpStuff extends FlxTypedGroup<FlxSprite>
|
||||
class PopUpStuff extends FlxTypedGroup<FunkinSprite>
|
||||
{
|
||||
public var offsets:Array<Int> = [0, 0];
|
||||
|
||||
|
@ -17,7 +18,7 @@ class PopUpStuff extends FlxTypedGroup<FlxSprite>
|
|||
super();
|
||||
}
|
||||
|
||||
public function displayRating(daRating:String)
|
||||
public function displayRating(daRating:String):Void
|
||||
{
|
||||
var perfStart:Float = TimerUtil.start();
|
||||
|
||||
|
@ -40,10 +41,15 @@ class PopUpStuff extends FlxTypedGroup<FlxSprite>
|
|||
|
||||
add(rating);
|
||||
|
||||
var fadeEase = null;
|
||||
|
||||
if (PlayState.instance.currentStageId.startsWith('school'))
|
||||
{
|
||||
rating.setGraphicSize(Std.int(rating.width * Constants.PIXEL_ART_SCALE * 0.7));
|
||||
rating.antialiasing = false;
|
||||
rating.pixelPerfectRender = true;
|
||||
rating.pixelPerfectPosition = true;
|
||||
fadeEase = EaseUtil.stepped(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -61,7 +67,8 @@ class PopUpStuff extends FlxTypedGroup<FlxSprite>
|
|||
remove(rating, true);
|
||||
rating.destroy();
|
||||
},
|
||||
startDelay: Conductor.instance.beatLengthMs * 0.001
|
||||
startDelay: Conductor.instance.beatLengthMs * 0.001,
|
||||
ease: fadeEase
|
||||
});
|
||||
|
||||
trace('displayRating took: ${TimerUtil.seconds(perfStart)}');
|
||||
|
@ -92,10 +99,15 @@ class PopUpStuff extends FlxTypedGroup<FlxSprite>
|
|||
|
||||
// add(comboSpr);
|
||||
|
||||
var fadeEase = null;
|
||||
|
||||
if (PlayState.instance.currentStageId.startsWith('school'))
|
||||
{
|
||||
comboSpr.setGraphicSize(Std.int(comboSpr.width * Constants.PIXEL_ART_SCALE * 0.7));
|
||||
comboSpr.setGraphicSize(Std.int(comboSpr.width * Constants.PIXEL_ART_SCALE * 1));
|
||||
comboSpr.antialiasing = false;
|
||||
comboSpr.pixelPerfectRender = true;
|
||||
comboSpr.pixelPerfectPosition = true;
|
||||
fadeEase = EaseUtil.stepped(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -110,7 +122,8 @@ class PopUpStuff extends FlxTypedGroup<FlxSprite>
|
|||
remove(comboSpr, true);
|
||||
comboSpr.destroy();
|
||||
},
|
||||
startDelay: Conductor.instance.beatLengthMs * 0.001
|
||||
startDelay: Conductor.instance.beatLengthMs * 0.001,
|
||||
ease: fadeEase
|
||||
});
|
||||
|
||||
var seperatedScore:Array<Int> = [];
|
||||
|
@ -133,8 +146,10 @@ class PopUpStuff extends FlxTypedGroup<FlxSprite>
|
|||
|
||||
if (PlayState.instance.currentStageId.startsWith('school'))
|
||||
{
|
||||
numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 0.7));
|
||||
numScore.setGraphicSize(Std.int(numScore.width * Constants.PIXEL_ART_SCALE * 1));
|
||||
numScore.antialiasing = false;
|
||||
numScore.pixelPerfectRender = true;
|
||||
numScore.pixelPerfectPosition = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -156,7 +171,8 @@ class PopUpStuff extends FlxTypedGroup<FlxSprite>
|
|||
remove(numScore, true);
|
||||
numScore.destroy();
|
||||
},
|
||||
startDelay: Conductor.instance.beatLengthMs * 0.002
|
||||
startDelay: Conductor.instance.beatLengthMs * 0.002,
|
||||
ease: fadeEase
|
||||
});
|
||||
|
||||
daLoop++;
|
||||
|
|
|
@ -249,6 +249,10 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass implements
|
|||
// If pixel, disable antialiasing.
|
||||
propSprite.antialiasing = !dataProp.isPixel;
|
||||
|
||||
// If pixel, we render it pixel perfect so there's less "mixels"
|
||||
propSprite.pixelPerfectRender = dataProp.isPixel;
|
||||
propSprite.pixelPerfectPosition = dataProp.isPixel;
|
||||
|
||||
propSprite.scrollFactor.x = dataProp.scroll[0];
|
||||
propSprite.scrollFactor.y = dataProp.scroll[1];
|
||||
|
||||
|
|
Loading…
Reference in a new issue