Search code examples
windowsloopsstatehaxehaxeflixel

how do i make FlxAsyncLoop work for making a progress bar in HaxeFlixel?


so, i tried to make an async loop for my game (to make a progress bar) and the game crashes when the state loads...

i tried to change the loops position so they don't collide and all of the code is from the FlxAsyncLoop demo but with other variables and some other changes.

here's the code:

import flixel.FlxCamera;
import flixel.FlxG;
import flixel.FlxObject;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.addons.util.FlxAsyncLoop;
import flixel.group.FlxGroup;
import flixel.math.FlxPoint;
import flixel.math.FlxVelocity;
import flixel.text.FlxText;
import flixel.ui.FlxBar;
import flixel.util.FlxColor;

class PlayState extends FlxState
{
public static var player:FlxSprite;

var ground:FlxSprite;
var axe:FlxSprite;
var wood:FlxSprite;
var base:FlxSprite;
var txt:FlxText;

var playerPos:FlxPoint;

var enemy:FlxSprite;

var move = false;

var progressR:FlxGroup;
var progressE:FlxGroup;

var resourceGroup:FlxGroup;
var enemyGroup:FlxGroup;

var maxItems:Int = 100;

var bar1:FlxBar;
var bartxt1:FlxText;
var bar2:FlxBar;
var bartxt2:FlxText;

var loopR:FlxAsyncLoop;
var loopE:FlxAsyncLoop;

public function addR()
{
    var wood = new FlxSprite(FlxG.random.int(100, 2500), FlxG.random.int(100, 1800));
    wood.makeGraphic(40, 100, FlxColor.BROWN);
    add(wood);

    bar1.value = (resourceGroup.members.length / maxItems) * 100;
    bartxt1.text = "Loading resources... " + resourceGroup.members.length + " / " + maxItems;
    bartxt1.screenCenter();
}

public function addE()
{
    var enemy = new FlxSprite(FlxG.random.int(300, 2500), FlxG.random.int(300, 1800));
    enemy.makeGraphic(32, 32, FlxColor.RED);
    add(enemy);

    bar2.value = (enemyGroup.members.length / maxItems) * 100;
    bartxt2.text = "Loading enemys... " + enemyGroup.members.length + " / " + maxItems;
    bartxt2.screenCenter();
}

override public function create()
{
    super.create();

    resourceGroup = new FlxGroup(maxItems);
    enemyGroup = new FlxGroup(maxItems);

    loopR = new FlxAsyncLoop(maxItems, addR);
    loopE = new FlxAsyncLoop(maxItems, addE);

    FlxG.camera.zoom = 0.5;

    playerPos = FlxPoint.get();

    ground = new FlxSprite(0, 0);
    ground.makeGraphic(2500, 1800, FlxColor.GREEN);
    add(ground);

    player = new FlxSprite(100, 100);
    player.loadGraphic(AssetPaths.n1__png);

    axe = new FlxSprite(player.x + 60, player.y);
    axe.loadGraphic(AssetPaths.axeR__png);

    camera = new FlxCamera(0, 0, 2500, 1800);
    camera.bgColor = FlxColor.TRANSPARENT;
    camera.setScrollBoundsRect(0, 0, ground.width, ground.height);
    FlxG.cameras.reset(camera);
    camera.target = player;

    if (FlxG.collide(wood, player))
        FlxObject.separate(wood, player);

    if (FlxG.collide(wood, enemy))
        FlxObject.separate(wood, enemy);

    if (FlxG.collide(enemy, player))
        FlxObject.separate(enemy, player);

    progressR = new FlxGroup();

    bar1 = new FlxBar(0, 0, LEFT_TO_RIGHT, FlxG.width, 50, null, "", 0, 100, true);
    bar1.value = 0;
    bar1.screenCenter();
    progressR.add(bar1);

    bartxt1 = new FlxText(0, 0, FlxG.width, "Loading resources... 0 / " + maxItems);
    bartxt1.setFormat(null, 28, FlxColor.WHITE, CENTER, OUTLINE);
    bartxt1.screenCenter();
    progressR.add(bartxt1);

    progressE = new FlxGroup();

    bar2 = new FlxBar(0, 0, LEFT_TO_RIGHT, FlxG.width, 50, null, "", 0, 100, true);
    bar2.value = 0;
    bar2.screenCenter();
    progressE.add(bar2);

    bartxt2 = new FlxText(0, 0, FlxG.width, "Loading enemys... 0 / " + maxItems);
    bartxt2.setFormat(null, 28, FlxColor.WHITE, CENTER, OUTLINE);
    bartxt2.screenCenter();
    progressE.add(bartxt2);

    resourceGroup.visible = false;
    resourceGroup.active = false;
    enemyGroup.visible = false;
    enemyGroup.active = false;

    add(progressR);
    add(progressE);
    add(resourceGroup);
    add(enemyGroup);
    add(loopR);
}

override public function update(elapsed:Float)
{
    super.update(elapsed);

    if (FlxG.keys.pressed.LEFT && move)
    {
        player.x -= 5;
        axe.loadGraphic(AssetPaths.axeL__png);
    }

    if (FlxG.keys.pressed.RIGHT && move)
    {
        player.x += 5;
        axe.loadGraphic(AssetPaths.axeR__png);
    }

    if (FlxG.keys.pressed.UP && move)
    {
        player.y -= 5;
    }

    if (FlxG.keys.pressed.DOWN && move)
    {
        player.y += 5;
    }

    axe.x = player.x + 60;
    axe.y = player.y;

    playerPos = FlxPoint.get();
    playerPos = player.getMidpoint();

    FlxVelocity.moveTowardsPoint(enemy, playerPos, 70);

    if (!loopR.started)
    {
        loopR.start();
    }
    else
    {
        if (loopR.finished)
        {
            resourceGroup.visible = true;
            progressR.visible = false;
            resourceGroup.active = true;
            progressR.active = false;

            loopR.kill();
            loopR.destroy();

            add(loopE);
            loopE.start();
        }
    }

    if (loopE.finished)
    {
        move = true;
        add(player);
        add(axe);

        enemyGroup.visible = true;
        progressE.visible = false;
        enemyGroup.active = true;
        progressE.active = false;

        loopE.kill();
        loopE.destroy();
    }
}

}

i'm showing everything because of the functions and other things that can make this problem

(my english is bad sorry if i miss something...)


Solution

  • Without knowing the exact error, I suspect that the problem is when you call

    if (FlxG.collide(wood, player))
        FlxObject.separate(wood, player);
    
    if (FlxG.collide(wood, enemy))
        FlxObject.separate(wood, enemy);
    
    if (FlxG.collide(enemy, player))
        FlxObject.separate(enemy, player);
    

    Inside your create function - wood and enemy are declared in other functions and do not exist there.

    There are a couple of things I would do differently here:

    (Note: I didn't TEST this code, so there may still be problems, but this might help get you pointed in the right direction...)

    class PlayState extends FlxState
    {
        public static var player:FlxSprite;
    
        var ground:FlxSprite;
        var axe:FlxSprite;
    
        var base:FlxSprite;
        var txt:FlxText;
    
        var playerPos:FlxPoint;
    
        var move:Bool = false;
    
        var progressR:FlxGroup;
        var progressE:FlxGroup;
    
        var resourceGroup:FlxTypedGroup<FlxSprite>;
        var enemyGroup:FlxTypedGroup<FlxSprite>;
    
        var maxItems:Int = 100;
    
        var bar1:FlxBar;
        var bartxt1:FlxText;
        var bar2:FlxBar;
        var bartxt2:FlxText;
    
        var loopR:FlxAsyncLoop;
        var loopE:FlxAsyncLoop;
    
        public function addR()
        {
            var wood = new FlxSprite(FlxG.random.int(100, 2500), FlxG.random.int(100, 1800));
            wood.makeGraphic(40, 100, FlxColor.BROWN);
            resourceGroup.add(wood);
    
            bar1.value = (resourceGroup.members.length / maxItems) * 100;
            bartxt1.text = "Loading resources... " + resourceGroup.members.length + " / " + maxItems;
            bartxt1.screenCenter();
    
            FlxG.collide(player, resourceGroup) // should not need to call `seperate` - it's automatic when using `collide` vs `overlap`
        }
    
        public function addE()
        {
            var enemy = new FlxSprite(FlxG.random.int(300, 2500), FlxG.random.int(300, 1800));
            enemy.makeGraphic(32, 32, FlxColor.RED);
            enemyGroup.add(enemy);
    
            FlxG.collide(enemyGroup, resourceGroup)
    
            FlxG.collide(player, resourceGroup)
    
            bar2.value = (enemyGroup.members.length / maxItems) * 100;
            bartxt2.text = "Loading enemys... " + enemyGroup.members.length + " / " + maxItems;
            bartxt2.screenCenter();
        }
    
        override public function create()
        {
            super.create();
    
            resourceGroup = new FlxTypedGroup<FlxSprite>(maxItems);
            enemyGroup = new FlxTypedGroup<FlxSprite>(maxItems);
    
            loopR = new FlxAsyncLoop(maxItems, addR);
            loopE = new FlxAsyncLoop(maxItems, addE);
    
            FlxG.camera.zoom = 0.5;
    
            playerPos = FlxPoint.get();
    
            ground = new FlxSprite(0, 0);
            ground.makeGraphic(2500, 1800, FlxColor.GREEN);
            add(ground);
    
            player = new FlxSprite(100, 100);
            player.loadGraphic(AssetPaths.n1__png);
    
            axe = new FlxSprite(player.x + 60, player.y);
            axe.loadGraphic(AssetPaths.axeR__png);
    
            camera = new FlxCamera(0, 0, 2500, 1800);
            camera.bgColor = FlxColor.TRANSPARENT;
            camera.setScrollBoundsRect(0, 0, ground.width, ground.height);
            FlxG.cameras.reset(camera);
            camera.target = player;
    
            progressR = new FlxGroup();
    
            bar1 = new FlxBar(0, 0, LEFT_TO_RIGHT, FlxG.width, 50, null, "", 0, 100, true);
            bar1.value = 0;
            bar1.screenCenter();
            progressR.add(bar1);
    
            bartxt1 = new FlxText(0, 0, FlxG.width, "Loading resources... 0 / " + maxItems);
            bartxt1.setFormat(null, 28, FlxColor.WHITE, CENTER, OUTLINE);
            bartxt1.screenCenter();
            progressR.add(bartxt1);
    
            progressE = new FlxGroup();
    
            bar2 = new FlxBar(0, 0, LEFT_TO_RIGHT, FlxG.width, 50, null, "", 0, 100, true);
            bar2.value = 0;
            bar2.screenCenter();
            progressE.add(bar2);
    
            bartxt2 = new FlxText(0, 0, FlxG.width, "Loading enemys... 0 / " + maxItems);
            bartxt2.setFormat(null, 28, FlxColor.WHITE, CENTER, OUTLINE);
            bartxt2.screenCenter();
            progressE.add(bartxt2);
    
            resourceGroup.visible = false;
            resourceGroup.active = false;
            enemyGroup.visible = false;
            enemyGroup.active = false;
    
            add(progressR);
            add(progressE);
            add(resourceGroup);
            add(enemyGroup);
            add(loopR);
        }
    
        public function gamePlay(elapsed:Float):Void
        {
            if (FlxG.keys.pressed.LEFT && move)
            {
                player.x -= 5; // why +/- position and not .velocity?
    
                // THIS is probably not right - you want to use a sprite sheet with animations and call axe.play("left") or something...
                axe.loadGraphic(AssetPaths.axeL__png);
            }
    
            if (FlxG.keys.pressed.RIGHT && move)
            {
                player.x += 5;
                axe.loadGraphic(AssetPaths.axeR__png);
            }
    
            if (FlxG.keys.pressed.UP && move)
            {
                player.y -= 5;
            }
    
            if (FlxG.keys.pressed.DOWN && move)
            {
                player.y += 5;
            }
    
            axe.x = player.x + 60;
            axe.y = player.y;
    
            playerPos = FlxPoint.get();
            playerPos = player.getMidpoint();
    
            for (e in enemyGroup)
            {
                FlxVelocity.moveTowardsPoint(e, playerPos, 70);
            }
        }
    
        public function loading(elapsed:Float):Void
        {
            if (!loopR.started)
            {
                loopR.start();
            }
            else if (loopR.finished)
            {
                resourceGroup.visible = true;
                progressR.visible = false;
                resourceGroup.active = true;
                progressR.active = false;
    
                loopR.kill();
                loopR.destroy();
    
                add(loopE);
                loopE.start();
            }
            else if (loopE.finished)
            {
                move = true;
                add(player);
                add(axe);
    
                enemyGroup.visible = true;
                progressE.visible = false;
                enemyGroup.active = true;
                progressE.active = false;
    
                loopE.kill();
                loopE.destroy();
            }
        }
    
        override public function update(elapsed:Float)
        {
            super.update(elapsed);
    
            if (!move)
            {
                loading(elapsed);
            }
            else
            {
                gamePlay(elapsed);
            }
        }
    }