Jump to content
Search Community

Managing load order dynamically with multiple priorities

prestont test
Moderator Tag

Recommended Posts

So I am loading a bunch of images (for a game). When the game starts it starts loading images say 4 at a time. Some are higher priority related to others but aren't actually queued until a little later in the load cycle. I can basically give every image a priority of 1 to 10 say (1 being highest) but can't know what order they will be queued in or even what exact will be queued until later (or even after a user action)

 

I now want to setup LoaderMax so that when I get a new image (say priority 3) I can insert it such that any currently pending priority 1, 2 or 3 images load first but then this priority 3 image loads before any queued images of priority lower then 3. What is the best way to arrange my queue's to support this? If I have 10 sub queue's can I add to a early sub queue and will that one take priority?

 

Thanks,

Preston

Link to comment
Share on other sites

I don't have any code examples to show you but in short you will have to manually change the order of the loader's in the cue. prioritize() is great for immediately making a single loader the most import loader, but if you want to very precisely and dynamically change the load order (set varying degrees of priority) its going to take a little work.

 

you may have to do some fancy looping through the children of your cue, assess their priority and then insert them where they need based on your priority scheme and which one was most recently requested. It's totally possible but I don't think it is necessarily easy.

 

by using numChildren you can figure out how may loaders you have.

 

by using getChildAt(index) you can figure out which loader is in which position.

 

by using insert() you can move a loader to any position in the cue

 

here is info on insert() http://www.greensock.com/as/docs/tween/ ... ml#insert() and the other handy LoaderMax methods.

 

---

Link to comment
Share on other sites

I've got another idea for you...I think you're gonna like it...

 

You could nest different priority-based LoaderMax instances inside of a master/parent LoaderMax and populate the children accordingly, but there are a few caveats to keep in mind. Let's visualize it first...

 

var priority0:LoaderMax = new LoaderMax({name:"priority0"});
var priority1:LoaderMax = new LoaderMax({name:"priority1"});
var priority2:LoaderMax = new LoaderMax({name:"priority2"});

var master:LoaderMax = new LoaderMax({name:"master", maxConnections:1});
master.append(priority0);
master.append(priority1);
master.append(priority2);

 

Now we've got things set up in the right order. You can add stuff directly to priority0, priority1, or priority2 anytime. Notice I set maxConnections to 1 on the master - that just means that it should only load one of its children at a time. Since each of its children is a LoaderMax itself, those have independent maxConnections of their own (the default is 2). Setting master's maxConnections to 1 ensures that it doesn't start loading priority0 AND priority1 at the same time (defeating the purpose of our handy-dandy priority concept).

 

But now let's consider a scenario in which master is in the process of loading, and maybe it has already completed priority0 and priority1, so it's working on priority2 when you decide to drop a new loader into priority0. Each time a child completes, LoaderMax looks through its queue from the top and re-checks each child in order to see if they're completed. If they are, it moves on to the next one, and so on. In this case, priority2 would finish loading and then master would say "okay, let me see what I should do next...any children need loading?...OH! Yes, priority0's status is 'ready', so I'll load that one now..."

 

You could implement this nested priority-based LoaderMax setup as long as you manage things properly. In fact, I whipped together a method that pretty much does all the work for you. You create the master LoaderMax and then use a single method to easily dump a new loader in wherever you want...

 

//this is the master/parent LoaderMax that will contain the sub-groups (children)
var master:LoaderMax = new LoaderMax({name:"master", maxConnections:1});

/*
The "priority" parameter determines which child queue the loader gets put into (like priority1, priority2, etc., each of which can contain an unlimited number of children). The "index" parameter determines the position inside that child queue. For example, if you want the loader to go into the first slot (index 0) of the "priority2" child queue, the "priority" would be 2 and "index" would be 0. Leave the index at -1 if you want to insert it at the end of the child queue.  
*/
function queue(loader:LoaderCore, priority:uint, index:int=-1):void {
//this simply ensures that the master LoaderMax is packed correctly up to the priority that's being requested.
while (master.numChildren 		master.append( new LoaderMax({name:"priority" + master.numChildren}) );
}

//find the child LoaderMax named after that priority
var group:LoaderMax = LoaderMax.getLoader("priority" + priority);

if (index == -1) {
	group.append(loader);
} else {
	group.insert(loader, index);
	cancelChildrenAfterIndex(group, index);
}

if (master.status == LoaderStatus.LOADING) {	
	cancelChildrenAfterIndex(master, priority);
	/*
	Notice we don't need to prioritize() anything because we're automatically accomplishing the same thing by canceling lower priority groups (children). This also ensures that higher priority groups are given precedence - they're not interrupted.
	*/
} else {
	master.load();
}
}

/*
You don't typically use this method directly. Instead, the queue() method uses it to cancel the loading of children after a particular index which basically allows us to prioritize on the fly. For example, if child 5 is loading but you just inserted one at index 2, that new one should be prioritized, thus temporarily canceling the loader at index 5 (and all others after 2). 
*/
function cancelChildrenAfterIndex(queue:LoaderMax, index:uint):void {
var children:Array = queue.getChildren();
var i:int = children.length;
while (--i > index) {
	if (children[i].status == LoaderStatus.LOADING) {
		children[i].cancel();
	}
}
}

//so you could create a new ImageLoader and dump it in at the end of the priority 2 queue...
queue( new ImageLoader("1.jpg"), 2, -1);

//and put this ImageLoader at the beginning of the priority 1 group...
queue( new ImageLoader("2.jpg"), 1, 0);

 

Does that make any sense? Hopefully this greatly simplifies your approach. With a few lines of code, you're rockin' a pretty complex priority-based queue system. Let me know if that works out for you (I haven't tested this approach extensively, but I can't see any holes in the logic at this point) (disclaimer: my brain is in a relatively sleep-deprived state)

Link to comment
Share on other sites

  • 2 weeks later...

This looks perfect, thank you. This was actually my first thought for a solution but I wasn't sure it was going to work but I am very glad to hear it will. Will be implementing today so I will let you know how it goes.

 

Thanks,

Preston

Link to comment
Share on other sites

  • 2 weeks later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...