Skip to content

Instantly share code, notes, and snippets.

@Geokureli
Last active August 6, 2019 14:20
Show Gist options
  • Save Geokureli/cf3168efc9835208ae10b1e459f7c284 to your computer and use it in GitHub Desktop.
Save Geokureli/cf3168efc9835208ae10b1e459f7c284 to your computer and use it in GitHub Desktop.
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