diff --git a/source/PlayState.hx b/source/PlayState.hx index dca9af201..a0a693645 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -393,61 +393,13 @@ class PlayState extends MusicBeatState loadStage(curStageId); case "cocoa" | 'eggnog': - curStageId = 'mall'; + curStageId = 'mallXmas'; + loadStage(curStageId); - 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 'winter-horrorland': - loadStageOld('mallEvil'); + curStageId = 'mallEvil'; + loadStage(curStageId); + case 'senpai' | 'roses': curStageId = 'school'; @@ -584,7 +536,8 @@ class PlayState extends MusicBeatState var fgTank3:BGSprite = new BGSprite('tank3', 1300, 1200, 3.5, 2.5, ['fg']); foregroundSprites.add(fgTank3); case "darnell": - loadStageOld('phillyStreets'); + curStageId = 'phillyStreets'; + loadStage(curStageId); default: loadStage('mainStage'); } @@ -686,11 +639,6 @@ class PlayState extends MusicBeatState // REPOSITIONING PER STAGE switch (curStageId) { - case 'mall': - boyfriend.x += 200; - case 'mallEvil': - boyfriend.x += 320; - dad.y -= 80; case 'school': boyfriend.x += 200; boyfriend.y += 220; @@ -722,8 +670,6 @@ class PlayState extends MusicBeatState gf.x -= 170; gf.y -= 75; } - case 'phillyStreets': - dad.y = 870 - dad.height; } if (curStage != null) @@ -2848,9 +2794,9 @@ class PlayState extends MusicBeatState if (curBeat % 2 == 0) { - if (!boyfriend.animation.curAnim.name.startsWith("sing")) + if (boyfriend.animation != null && !boyfriend.animation.curAnim.name.startsWith("sing")) boyfriend.playAnim('idle'); - if (!dad.animation.curAnim.name.startsWith("sing")) + if (dad.animation != null && !dad.animation.curAnim.name.startsWith("sing")) dad.dance(); } else if (dad.curCharacter == 'spooky') @@ -2881,11 +2827,6 @@ class PlayState extends MusicBeatState case 'school': bgGirls.dance(); - case 'mall': - upperBoppers.animation.play('bop', true); - bottomBoppers.animation.play('bop', true); - santa.animation.play('idle', true); - case 'tank': tankWatchtower.dance(); } diff --git a/source/play/stage/Bopper.hx b/source/play/stage/Bopper.hx new file mode 100644 index 000000000..910fc85ff --- /dev/null +++ b/source/play/stage/Bopper.hx @@ -0,0 +1,110 @@ +package play.stage; + +import flixel.FlxSprite; + +/** + * A Bopper is a stage prop which plays a dance animation. + * Y'know, a thingie that bops. A bopper. + */ +class Bopper extends FlxSprite +{ + /** + * The bopper plays the dance animation once every `danceEvery` beats. + */ + public var danceEvery:Int = 1; + + /** + * Whether the bopper should dance left and right. + * - If true, alternate playing `danceLeft` and `danceRight`. + * - If false, play `idle` every time. + * + * You can manually set this value, or you can leave it as `null` to determine it automatically. + */ + public var shouldAlternate:Null = null; + + /** + * Set this value to define an additional horizontal offset to this sprite's position. + */ + public var xOffset:Float = 0; + + override function set_x(value:Float):Float + { + this.x = value + this.xOffset; + return value; + } + + /** + * Set this value to define an additional vertical offset to this sprite's position. + */ + public var yOffset:Float = 0; + + override function set_y(value:Float):Float + { + this.y = value + this.yOffset; + return value; + } + + /** + * Whether to play `danceRight` next iteration. + * Only used when `shouldAlternate` is true. + */ + var hasDanced:Bool = false; + + public function new(danceEvery:Int = 1) + { + super(); + this.danceEvery = danceEvery; + } + + function update_shouldAlternate():Void + { + if (this.animation.getByName('danceLeft') != null) + { + this.shouldAlternate = true; + } + } + + /** + * Called once every beat of the song. + */ + public function onBeatHit(curBeat:Int):Void + { + if (curBeat % danceEvery == 0) + { + dance(); + } + } + + /** + * Called every `danceEvery` beats of the song. + */ + public function dance():Void + { + if (this.animation == null) + { + return; + } + + if (shouldAlternate == null) + { + update_shouldAlternate(); + } + + if (shouldAlternate) + { + if (hasDanced) + { + this.animation.play('danceRight'); + } + else + { + this.animation.play('danceLeft'); + } + hasDanced = !hasDanced; + } + else + { + this.animation.play('idle'); + } + } +} diff --git a/source/play/stage/Stage.hx b/source/play/stage/Stage.hx index 0e6737811..a78985a4b 100644 --- a/source/play/stage/Stage.hx +++ b/source/play/stage/Stage.hx @@ -40,7 +40,14 @@ class Stage extends FlxSpriteGroup implements IHook this.stageId = stageId; _data = StageDataParser.parseStageData(this.stageId); - this.stageName = _data.name; + if (_data == null) + { + throw 'Could not find stage data for stageId: $stageId'; + } + else + { + this.stageName = _data.name; + } } /** @@ -79,6 +86,9 @@ class Stage extends FlxSpriteGroup implements IHook { // Initalize static sprite. propSprite.loadGraphic(Paths.image(dataProp.assetPath)); + + // Disables calls to update() for a performance boost. + propSprite.active = false; } if (Std.isOfType(dataProp.scale, Array)) @@ -94,6 +104,9 @@ class Stage extends FlxSpriteGroup implements IHook propSprite.x = dataProp.position[0]; propSprite.y = dataProp.position[1]; + // If pixel, disable antialiasing. + propSprite.antialiasing = !dataProp.isPixel; + propSprite.scrollFactor.x = dataProp.scroll[0]; propSprite.scrollFactor.y = dataProp.scroll[1]; diff --git a/source/play/stage/StageData.hx b/source/play/stage/StageData.hx index d5278f26c..eb3c9b698 100644 --- a/source/play/stage/StageData.hx +++ b/source/play/stage/StageData.hx @@ -76,11 +76,20 @@ class StageDataParser trace(' Instantiating ${unscriptedStageIds.length} non-scripted stages...'); for (stageId in unscriptedStageIds) { - var stage:Stage = new Stage(stageId); - if (stage != null) + var stage:Stage; + try { - trace(' Loaded stage data: ${stage.stageName}'); - stageCache.set(stageId, stage); + stage = new Stage(stageId); + if (stage != null) + { + trace(' Loaded stage data: ${stage.stageName}'); + stageCache.set(stageId, stage); + } + } + catch (e) + { + // Assume error was already logged. + continue; } } @@ -166,6 +175,7 @@ class StageDataParser static final DEFAULT_ZINDEX:Int = 0; static final DEFAULT_DANCEEVERY:Int = 0; static final DEFAULT_SCALE:Float = 1.0; + static final DEFAULT_ISPIXEL:Bool = false; static final DEFAULT_POSITION:Array = [0, 0]; static final DEFAULT_SCROLL:Array = [0, 0]; static final DEFAULT_FRAMEINDICES:Array = []; @@ -233,6 +243,11 @@ class StageDataParser inputProp.zIndex = DEFAULT_ZINDEX; } + if (inputProp.isPixel == null) + { + inputProp.isPixel = DEFAULT_ISPIXEL; + } + if (inputProp.danceEvery == null) { inputProp.danceEvery = DEFAULT_DANCEEVERY; @@ -381,8 +396,16 @@ typedef StageDataProp = */ var zIndex:Null; + /** + * If set to true, anti-aliasing will be forcibly disabled on the sprite. + * This prevents blurry images on pixel-art levels. + * @default false + */ + var isPixel:Null; + /** * Either the scale of the prop as a float, or the [w, h] scale as an array of two floats. + * Pro tip: On pixel-art levels, save the sprite small and set this value to 6 or so to save memory. * @default 1 */ var scale:OneOfTwo>;