• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

GML Speed, deciding order of an array

L

LanderMiskolczi

Guest
So I am trying to make this combat system, where the order, of who goes first, and last are up to how fast the characters Attack Speed is. So right as I have it, the order is random, but what I want is to have the fastest character go first.
Here is the code for the player:
Code:
Create Event:

execute code:

/// Varabiles
hspd = 0;
vspd = 0;
spd = 6;
fric = 1;

// Health
hp = 10;
maxHp = hp;

// Magic
mp = 5;
maxMp = mp;

// Attack
attackSpeed = 3;
attackStrength = 10;

// Armor
physicalArmor = 10;
magicalArmor = 5;

state = sc_movement_state;

Step Event:

execute code:

/// State
script_execute(state);

if (state == sc_your_turn)
{
    if (x != 160)
    {
        x += 8;
    }
}
Here is the enemy code:
Code:
Create Event:

execute code:

/// Varabiles

// Health
hp = 5;
maxHp = hp;

// Magic
mp = 0;
maxMp = mp;

// Attack
attackSpeed = 1;
attackStrength = 1;

// Armor
physicalArmor = 0;
magicalArmor = 0;

state = sc_static_state;

Step Event:

execute code:

/// State
if (state = sc_your_turn)
{
    if (x != 320)
    {
        x -= 8;
    }
}

Draw Event:

execute code:

/// Draw text
draw_self();
draw_text(x, y-32, hp);
draw_text(x+12, y-32, mp);
draw_text(x+24, y-32, attackSpeed);
draw_text(x+36, y-32, attackStrength);
draw_text(x+48, y-32, physicalArmor);
draw_text(x+60, y-32, physicalArmor);
Lastly, here is the object which I use to create the battle system
Code:
Create Event:

execute code:

/// Varabiles
randomize();

field_type = 0;

execute code:

/// Field Create

speedList = ds_list_create();

// Allies
battleField[0] = instance_create(96, 160, ob_player);
battleField[1] = instance_create(96, 224, ob_ally);


battleField[0].state = sc_static_state;

ds_list_add(speedList, battleField[0].attackSpeed);
ds_list_add(speedList, battleField[1].attackSpeed);

// Enemy
sc_list_of_enemys();
var enemyNumber = irandom_range(1, 4);
var enemyType = field_type;

for (i = 0; i < enemyNumber; i++)
{
    var battleNumber = i+2;
    battleField[battleNumber] = instance_create(384, 96+(64*i), enemyId[enemyType, irandom_range(0, array_length_2d(enemyId, enemyType)-1)]);
    ds_list_add(speedList, battleField[battleNumber].attackSpeed);
}

execute code:

/// Decide order of Battle

// Getting the speed Array
battleFieldLength = array_length_1d(battleField)-1;

ds_list_sort(speedList, true);
for (i = 0; i < battleFieldLength; i++)
{
    speedArray[i] = speedList[| i];
}
ds_list_destroy(speedList);

// Setting Battle Order
for (i = 0; i < battleFieldLength; i++)
{
    for (ii = 0; ii < battleFieldLength; ii++)
    {
        if (speedArray[i] == battleField[ii].attackSpeed)
        {
            battleOrder[i] = battleField[ii];
        }
    }
}

battleOrder[0].state = sc_your_turn;
If you need anything to help, just ask please.
Hopefully you can see something I can't
 
D

Danei

Guest
Do all enemies inherently have different attack speeds? It looks to me like you're making a list of the speeds of the present enemies, sorting the list, and then going back and assigning a turn order based on matching the list entries with the enemy's attack speed. If I'm interpreting that right, that'll only be reliable if there are no enemies with the same stat.

Personally I would try to do this with a priority queue, where I add the instance IDs to it directly with priority equal to their stat.
 
L

LanderMiskolczi

Guest
Do all enemies inherently have different attack speeds? It looks to me like you're making a list of the speeds of the present enemies, sorting the list, and then going back and assigning a turn order based on matching the list entries with the enemy's attack speed. If I'm interpreting that right, that'll only be reliable if there are no enemies with the same stat.

Personally I would try to do this with a priority queue, where I add the instance IDs to it directly with priority equal to their stat.
Some do have the same stats and you are correct, that is what I am doing. Idk how to create a queue, or what that really is. Could you send me a tutorial or explain what that might be to me please? Could help alot
 

TheouAegis

Member
Or you open the manual and look up "priority queue". Here's a pointer:
ds_priority_create()

You could still sort an array, though. It's just a lot more work. You could cross-check each entry in the array with their stats and then sort the array. Like I said, it's a lot more work then simply adding the ids to a priority queue, though.

Edit: I started to write up a code, but once I hit line 5, I stopped because it was pointless in GM. lol
 
Last edited:
L

LanderMiskolczi

Guest
Or you open the manual and look up "priority queue". Here's a pointer:
ds_priority_create()
Thank you, and also yeah i've learned a very small amount but from what I can see this is a way better method then what I was trying to do

Edit: Lol your good, thanks for the advice, I see how much more useful it is now, thank you
 
Last edited by a moderator:
L

LanderMiskolczi

Guest
So I tried using the Priority Queue but it still didn't work, I don't know if it was something I did wrong, but now it wont count the player or ally, in the queue, it's just empty
Here is the new creation of the battle field now
Code:
/// Field Create

speedQueues = ds_priority_create();

// Field Create
sc_list_of_enemys();
var allyNumber = 2;
var enemyNumber = irandom_range(1, 4);
var enemyType = field_type;

for (i = 0; i < (enemyNumber + allyNumber); i++)
{
    var battleNumber = i;
    switch (i)
    {
        case 0:
            battleField[i] = instance_create(96, 160, ob_player);
            break;
        
        case 1:
            battleField[i] = instance_create(96, 224, ob_ally);
            break;
        
        default:
            battleField[i] = instance_create(384, -32+(64*i), enemyId[enemyType, irandom_range(0, array_length_2d(enemyId, enemyType)-1)]);
            break;
    }
    
    ds_priority_add(speedQueues, battleField[i], battleField[i].attackSpeed);
}

/// Decide order of Battle
battleFieldLength = array_length_1d(battleField)-1;

// Getting the speed Array
ds_priority_delete_max(speedQueues);

for (i = 0; i < array_length_1d(battleField)-1; i++)
{
    battleOrder[i] = ds_priority_delete_max(speedQueues);
}

ds_priority_destroy(speedQueues);

battleOrder[0].state = sc_your_turn;
 

TheouAegis

Member
Create the priority queue at the very start of the game. You're going to be using it all game, so there's no need to make it so volatile like that. Make sure it's saved to a global variable.
At the start of the battle, call ds_priority_clear().
Create your array. Don't worry about adding anything to the queue at this point, though.
Every time it's someone's turn to attack, check if ds_priority_size() is 0.
If it is, loop through all instances and add their ID-attackSpeed pairs to the queue;
Otherwise, pop the top ID from the queue and let that unit attack.

Do not destroy the queue ever, unless you actually allow the player to go back to the room that created the queue in the first place.
 
Top