Last active
August 6, 2019 14:20
-
-
Save Geokureli/cf3168efc9835208ae10b1e459f7c284 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package; | |
| //import utils.Sounds; | |
| import flixel.FlxG; | |
| import flixel.FlxSprite; | |
| import flixel.effects.FlxFlicker; | |
| import flixel.group.FlxGroup; | |
| import flixel.group.FlxGroup.FlxTypedGroup; | |
| import flixel.math.FlxPoint; | |
| import flixel.math.FlxRect; | |
| import flixel.tweens.FlxEase; | |
| import flixel.tweens.FlxTween; | |
| import flixel.util.FlxTimer; | |
| import flixel.addons.display.FlxSliceSprite; | |
| import openfl.geom.Rectangle; | |
| class Main extends openfl.display.Sprite | |
| { | |
| public function new () | |
| { | |
| super(); | |
| addChild(new flixel.FlxGame(160, 160, State, 1, 60, 60, true, false)); | |
| } | |
| } | |
| class State extends flixel.FlxState | |
| { | |
| var scoreBar:ScoreBar; | |
| var numLeft:Int = 0; | |
| override public function create () | |
| { | |
| super.create(); | |
| add(scoreBar = new ScoreBar()); | |
| resetCount(); | |
| var text = new flixel.text.FlxText(0, 80, FlxG.width, "Press SPACE"); | |
| text.alignment = CENTER; | |
| add(text); | |
| } | |
| override function update(elapsed:Float) | |
| { | |
| super.update(elapsed); | |
| if (numLeft > 0 && FlxG.keys.justPressed.SPACE) | |
| { | |
| scoreBar.highlightNext(); | |
| numLeft--; | |
| if (numLeft == 0) | |
| scoreBar.addPoint(resetCount.bind()); | |
| } | |
| } | |
| public function resetCount(?num:Int):Void | |
| { | |
| numLeft = num == null ? FlxG.random.int(2, 22) : num; | |
| scoreBar.setMaxPellets(numLeft); | |
| } | |
| } | |
| class ScoreBar extends FlxGroup | |
| { | |
| public var maxScore(default, null):Int; | |
| public var score(default, set):Int; | |
| var maxPellets:Int; | |
| var pointAnim:FlxSprite; | |
| var pelletsGroup:FlxTypedGroup<Pellet>; | |
| var pelletsGathered = 0; | |
| var pelletsHighlighted = 0; | |
| var animPellet:Pellet; | |
| var back:FlxSprite; | |
| var bar:FlxSprite; | |
| var frame:FlxSprite; | |
| public function new(xMargin = 4, y = 1.0) | |
| { | |
| super(); | |
| maxScore = 8; | |
| bar = new FlxSprite(xMargin, y); | |
| bar.makeGraphic(Std.int(FlxG.width) - xMargin * 2, 8, 0xFF5fcde4, false, "bar_bar"); | |
| bar.origin.x = 0; | |
| back = new FlxSprite(xMargin, y); | |
| back.makeGraphic(bar.graphic.width, bar.graphic.height, 0xFF144491, false, "bar_back"); | |
| back.offset.set(-1, -1); | |
| back.origin.x = 0; | |
| frame = new FlxSprite(xMargin, y, FlxG.bitmap.get("bar_frame")); | |
| if (frame.graphic == null) | |
| { | |
| frame.makeGraphic(Std.int(bar.width), Std.int(bar.height), 0xFFffffff, false, "bar_frame"); | |
| var rect = new Rectangle(0, 1, 0, 6); | |
| for (i in 0...maxScore) | |
| { | |
| rect.left = rect.right + 1; | |
| rect.right = getBarDividerX(i+1); | |
| frame.graphic.bitmap.fillRect(rect, 0); | |
| } | |
| } | |
| score = 0; | |
| pointAnim = new FlxSprite(0, bar.y); | |
| pointAnim.makeGraphic(1, 1, 0xFFffffff); | |
| pointAnim.visible = false; | |
| pointAnim.scale.x = Math.ceil((frame.width - 2) / maxScore); | |
| pointAnim.scale.y = frame.height; | |
| pointAnim.width = Math.abs(pointAnim.scale.x) * pointAnim.frameWidth; | |
| pointAnim.height = Math.abs(pointAnim.scale.y) * pointAnim.frameHeight; | |
| pointAnim.origin.set(); | |
| add(animPellet = Pellet.createEmpty()); | |
| animPellet.highlight(); | |
| animPellet.x = bar.x; | |
| animPellet.y = bar.y; | |
| add(pelletsGroup = new FlxTypedGroup<Pellet>()); | |
| add(back); | |
| add(bar); | |
| add(animPellet); | |
| add(pointAnim); | |
| add(frame); | |
| } | |
| inline function getBarDividerX(index:Int):Int | |
| { | |
| return 1 + Std.int(index * (bar.width - 2) / maxScore); | |
| } | |
| function set_score(value:Int):Int | |
| { | |
| bar.scale.x = getBarDividerX(value) / bar.width; | |
| return this.score = value; | |
| } | |
| public function addPoint(?onComplete:()->Void):Void | |
| { | |
| pointAnim.x = 1 + bar.x + Std.int(score * (bar.width - 2) / maxScore); | |
| var left = pelletsGroup.getFirstAlive(); | |
| var right = pelletsGroup.members[pelletsGroup.countLiving() - 1]; | |
| animPellet.x = left.x; | |
| animPellet.y = left.y; | |
| animPellet.width = left.width; | |
| animPellet.height = left.height; | |
| left.kill(); | |
| // replace with anim | |
| left = animPellet; | |
| members.remove(left); | |
| members.unshift(left); | |
| left.revive(); | |
| var leftStart = left.x; | |
| var rightStart = right.x; | |
| var end = pointAnim.x; | |
| var leftWidthStart = left.width; | |
| var rightWidthStart = right.width; | |
| var endWidth = pointAnim.width + 2; | |
| inline function lerp(start:Float, end:Float, mixer:Float):Int | |
| { | |
| return Math.round(start + (end - start) * mixer); | |
| } | |
| function onTweenUpdate(value:Float):Void | |
| { | |
| // Movbe left and right inward towards the next score slot | |
| if (right.alive) | |
| { | |
| left.x = lerp(leftStart , end, value); | |
| right.x = lerp(rightStart, end, value); | |
| if (leftStart + leftWidthStart <= end + endWidth) | |
| left.width = lerp(leftWidthStart, endWidth, value); | |
| right.width = lerp(rightWidthStart, endWidth, value); | |
| if (right.x < left.x + left.width) | |
| { | |
| killPellets(); | |
| left.width = right.x + right.width - left.x; | |
| } | |
| } | |
| else if (!right.alive) | |
| { | |
| left.x = lerp(leftStart , end, value); | |
| left.width | |
| = lerp(rightWidthStart, endWidth, value) | |
| + lerp(rightStart, end, value) | |
| - left.x; | |
| } | |
| var i = pelletsGroup.members.length; | |
| while (i-- > 0) | |
| { | |
| var pellet = pelletsGroup.members[i]; | |
| if (pellet.on && pellet.alive && pellet != left && pellet != right) | |
| { | |
| if (pellet.x < end + endWidth) | |
| { | |
| if (left.x > pellet.x + pellet.width) | |
| { | |
| pellet.kill(); | |
| continue; | |
| } | |
| if (left.x + left.width > pellet.x + 2) | |
| { | |
| pellet.width = pellet.x + pellet.width - left.x - left.width + 2; | |
| pellet.x = left.x + left.width - 2; | |
| } | |
| } | |
| if (right.alive && pellet.x + pellet.width > end + endWidth) | |
| { | |
| if (right.x < pellet.x) | |
| { | |
| pellet.kill(); | |
| continue; | |
| } | |
| if (right.x < pellet.x + pellet.width - 2) | |
| pellet.width = right.x - pellet.x + 2; | |
| } | |
| } | |
| } | |
| } | |
| function onTweenComplete(_):Void | |
| { | |
| killPellets(); | |
| members.remove(left); | |
| members.push(left); | |
| if (onComplete != null) | |
| onComplete(); | |
| FlxTween.tween( | |
| left, | |
| { y:bar.y, height:bar.height }, | |
| 0.25, | |
| { | |
| ease:FlxEase.backInOut, | |
| onComplete: function(_) | |
| { | |
| score++; | |
| left.kill(); | |
| //Sounds.delay(0.1, CHEER); | |
| FlxFlicker.flicker(pointAnim, 0.5, false); | |
| } | |
| } | |
| ); | |
| } | |
| FlxTween.num(0, 1, 0.25, { onComplete: onTweenComplete, ease:FlxEase.quadIn }, onTweenUpdate); | |
| // play random sound pair | |
| //var ran = FlxG.random.int(1, Sounds.getCount(SCORE_SMOOSH)) - 1; | |
| //Sounds.delay(0.25 - Sounds.getDuration(SCORE_SMOOSH, ran) + 0.05, SCORE_SMOOSH, ran); | |
| //Sounds.delay(0.4, SCORE_LIFT); | |
| } | |
| inline function killPellets():Void | |
| { | |
| pelletsGroup.forEachAlive((pellet)->pellet.kill()); | |
| } | |
| public function setMaxPellets(num:Int, log = true):Void | |
| { | |
| maxPellets = num; | |
| pelletsHighlighted = 0; | |
| pelletsGathered = 0; | |
| pelletsGroup.kill(); | |
| pelletsGroup.exists = true; | |
| pelletsGroup.alive = true; | |
| if (maxPellets == 0) | |
| return; | |
| // | |
| var x = 0; | |
| var fixedWidth = -1; | |
| if (bar.width / maxPellets < 8) | |
| { | |
| // less than 8 px wide force everything to be the same width, | |
| // otherwise it's noticably non-uniform | |
| fixedWidth = Std.int(bar.width / maxPellets); | |
| // recenter | |
| x = Math.round((bar.width - (fixedWidth * maxPellets)) / 2); | |
| } | |
| if (log) | |
| { | |
| var width = fixedWidth; | |
| final fixed = fixedWidth != -1 && Math.floor(bar.width / maxPellets) != Math.floor(bar.width / maxPellets); | |
| if (!fixed) | |
| width = Math.floor(bar.width / maxPellets); | |
| trace('num:$maxPellets' | |
| + ' width(${fixed ? "fixed" : "variable"}):' | |
| + (fixed ? Std.string(width) : Std.string(width) + "-" + Std.string(width+1)) | |
| ); | |
| } | |
| // Staggewr spawn, otherwise all the pellets unfilling causes a bad performance spike | |
| var maxStaggerTime = 0.5; | |
| function spawnNew(timer:FlxTimer) | |
| { | |
| var index = timer.elapsedLoops; | |
| var pellet = pelletsGroup.recycle(Pellet.createEmpty); | |
| pellet.reset | |
| ( bar.x + x | |
| , -pellet.height | |
| , fixedWidth > 0 ? fixedWidth : Std.int(index * bar.width / maxPellets) - x | |
| , pelletsHighlighted > index | |
| ); | |
| x += Std.int(pellet.width); | |
| FlxTween.tween(pellet, { y:bar.y + 9 }, 0.25, { ease:FlxEase.backOut }); | |
| } | |
| new FlxTimer().start(maxStaggerTime / maxPellets, spawnNew, maxPellets); | |
| } | |
| public function highlightNext():Void | |
| { | |
| getFirstUnhilighted(true).highlight(); | |
| } | |
| public function getFirstUnhilighted(iterate = false):Pellet | |
| { | |
| return pelletsGroup.members[iterate ? pelletsHighlighted++ : pelletsHighlighted]; | |
| } | |
| } | |
| @:forward | |
| abstract Pellet(FlxSliceSprite) to FlxSliceSprite | |
| { | |
| inline static var ON = "assets/images/ui/UiPellet_filled.png"; | |
| inline static var OFF = "assets/images/ui/UiPellet.png"; | |
| static public var rect = FlxRect.get(2, 0, 1, 6); | |
| static public var sourceRect = FlxRect.get(0, 0, 6, 6); | |
| public var on(get, never):Bool; | |
| public function new (x = 0, y = 0, width = 6) | |
| { | |
| this = new FlxSliceSprite(OFF, rect, width, sourceRect.height, sourceRect); | |
| this.stretchCenter = true; | |
| reset(x, y, width); | |
| } | |
| inline public function switchGraphic(on:Bool):Void | |
| { | |
| var graphicKey = on ? ON : OFF; | |
| if (graphicKey != this.graphic.assetsKey) | |
| this.loadGraphic(graphicKey); | |
| } | |
| inline public function reset(x = 0.0, y = 0.0, width = 6, on = false):Void | |
| { | |
| switchGraphic(on); | |
| this.x = x; | |
| this.y = y; | |
| this.width = width; | |
| this.height = sourceRect.height; | |
| } | |
| inline public function highlight():Void | |
| { | |
| switchGraphic(true); | |
| } | |
| inline public function get_on() return this.graphic.assetsKey == ON; | |
| static public function create(x = 0, y = 0, width = 6):Pellet | |
| { | |
| return new Pellet(x, y, width); | |
| } | |
| static public function createEmpty():Pellet { return new Pellet(); } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment