Making a queue of units and drawing their position in the queue

inertias

Member
Ok, so sorry for the bizarre title. I hope the title and my explanation is good enough to help you guys understand my issue.

So basically, in my game there are units you can create. They get created at your base and then simply move to the right of the screen until they reach the enemy. I want there to be a "queue" or lineup of units.

The queue corresponds to the order of units you created. So you make 1 unit, it is first in line. You make a second unit, it is second in line, etc.

Only the first unit in the queue can attack. All the other units have to wait until they are first in line to attack. If a unit dies, the queue gets shifted so that the next unit is now able to attack.

Here's an example image of what I need:

Maybe this is not the right approach, but I plan to use a ds_grid to accomplish this. I have a script that creates a ds_grid that simply adds the instance of the unit to the grid and then expands the grid's height by 1. If a unit is destroyed, the ds_grid has its height removed by 1, but I don't know how to shift the ds_grid.

Now I want the unit to draw its place in the queue above its sprite. How would I go about drawing the unit's placement in the ds_grid? I can't just draw the height of the ds_grid because that will just display the same number for ALL units, since the ds_height will be the same for all of them. I need to display their unique position within the ds_grid and have that number be shifted if the unit in front of them dies.

Am I going about this the wrong way? Any idea of how you would implement this? Am I not explaining things well?

Thank you for any help you can provide!
 

NightFrost

Member
You should rather use ds list for that. When you create a new unit, you just ds_list_add() its ID and it goes to the end. When you want to get the unit that attacks you read the first ID stored in the list, CanAttack = ListOfMyUnits[| 0]. There's several ways to go about drawing the queue position. You could add code that updates position info on Units whenever the ds list changes, or you could create a centralized code that draws the numbers instead of the units drawing them. For example if you want to save the information on units, let's say they have QueuePosition variable on them, you'd run this code every time a unit is destroyed:
Code:
var Length = ds_list_size(ListOfMyUnits);
for(var i = 0; i < Length; i++){
    var ThisUnit = listOfMyUnits[| i];
    ThisUnit.QueuePosition = i +1;
}
The position of a newly created unit is simply the current size of the ds list, plus one.

Edit: well you also could just QueuePosition-- for all units when one is destroyed, but I don't like the thought of that. You're just subtracting one from an undetermined value instead of confirming queue position, and crossing fingers that the new number is correct.
 

inertias

Member
You should rather use ds list for that. When you create a new unit, you just ds_list_add() its ID and it goes to the end. When you want to get the unit that attacks you read the first ID stored in the list, CanAttack = ListOfMyUnits[| 0]. There's several ways to go about drawing the queue position. You could add code that updates position info on Units whenever the ds list changes, or you could create a centralized code that draws the numbers instead of the units drawing them. For example if you want to save the information on units, let's say they have QueuePosition variable on them, you'd run this code every time a unit is destroyed:
Code:
var Length = ds_list_size(ListOfMyUnits);
for(var i = 0; i < Length; i++){
    var ThisUnit = listOfMyUnits[| i];
    ThisUnit.QueuePosition = i +1;
}
The position of a newly created unit is simply the current size of the ds list, plus one.

Edit: well you also could just QueuePosition-- for all units when one is destroyed, but I don't like the thought of that. You're just subtracting one from an undetermined value instead of confirming queue position, and crossing fingers that the new number is correct.
Thanks for the suggestion!

So right now I'm still a bit confused as to how this will all work and how to go about doing things. Now I'll provide some code to show you what I have so far (it's not much).

So first, I have a script "scr_unit_queue_add" that simply creates the list and adds the unit to it. I'm not sure if the "instance_number(obj_unit)" is what I want though.
The object in the script "obj_unit_queue" is simply there to initialize the variable "ds_unit_queue" and that's all.

Here's the script code. Very simple atm:
Code:
with(obj_unit_queue) {
   
//create unit queue
if (!ds_exists(ds_unit_queue, ds_type_list)) {
ds_unit_queue = ds_list_create();

    }
   
    else {
       
        //add the instance of the unit to the list
        ds_list_add(ds_unit_queue, instance_number(obj_unit));  

    }
}
and then I have the obj_unit which simply calls the script "scr_unit_queue_add()" in its create event.

Now the draw event in obj_unit is what I need to fix. Right now I don't know how to draw the text over the unit that will display the unit's current position in the queue. Right now all the units that get created have the same number and it isn't increasing when I make more instances of the unit. Right now a "1" displays and that's it. I need each unit to draw their position.

so something like this in the draw event:
Code:
with(obj_unit_queue) {
if (ds_exists(ds_unit_queue, ds_type_list)) {

draw_text(other.x, other.y-100,string(unit_queue_pos));

}
where "unit_queue_pos" is currently not being used because as I said I don't really know how to go about making this variable display the instance's position.

Thanks for the help so far!
 

Lady Glitch

Member
Create a ds_list (Create Event of your spawner/controller object)
Code:
global.ds_unit_queue = ds_list_create();
Add a unit to the queue once spawned (obj_unit Create Event)
Code:
ds_list_add(global.ds_unit_queue, id);
Check the unit's position in the queue (obj_unit Step Event)
Code:
unit_queue_pos = ds_list_find_index(global.ds_unit_queue, id);
Check if the unit is first in the queue (obj_unit)
Code:
if unit_queue_pos = 0
{
    *attack*
}
Remove the unit from the queue once destroyed (obj_unit Destroy Event)
Code:
ds_list_delete(global.ds_unit_queue, unit_queue_pos);
Draw unit position (obj_unit Draw Event)
Code:
draw_text(x, y-100,unit_queue_pos+1);
 
Last edited:
B

Bayesian

Guest
Maybe this is not the right approach, but I plan to use a ds_grid to accomplish this.
You don't need any DSs or arrays to do this

Code:
//GameStart
global.unitNum = 1

//Unit Create
queuePos = global.unitNum
global.unitNum++

//Unit Draw
draw_self()
draw_text(x,y - someOffset, string(queuePos))

//Unit Destroy
with (objUnitParent){
    queuePos--
}
global.unitNum--
 

TheouAegis

Member
Why even queue at all? Don't let them move forward if there is another unit in the way. Don't let them attack until the enemy base is right in front of them. If they can't move because other units are in front of them, then naturally they can't attack either.

The queue is pointless outside of spawning units. If two units are created 5 seconds apart, the second one's just going to miraculously spawn halfway across the screen next to the older unit? Of course not.
 
B

Bayesian

Guest
My understanding was that he has everything working except drawing these numbers above the units.
 

inertias

Member
@Lady Glitch Thanks! This helped a lot.
@Bayesian Thanks for the alternate suggestion
Why even queue at all? Don't let them move forward if there is another unit in the way. Don't let them attack until the enemy base is right in front of them. If they can't move because other units are in front of them, then naturally they can't attack either.

The queue is pointless outside of spawning units. If two units are created 5 seconds apart, the second one's just going to miraculously spawn halfway across the screen next to the older unit? Of course not.
Yeah, I suppose you don't necessarily need the queue, but keep in mind I deliberately left out details about how my game works in order to make the explanation of the problem simpler to understand. I figure the queue is a good idea in case units start overlapping when you're being pushed to your base (units spawn here and will spawn even if the units can't move forward). In order to prevent units from all attacking at once since they're overlapping, the queue will make sure the right units will attack at the right time. This also helps with which units can die, which also depends on their position in the queue.

In all, my initial idea was to go with a queue. Plus, I learned a bit about ds_grids and lists. Since I'm new to coding, this helped a lot.

Edit: So far things are working well! Thanks for the help guys!
 
Top