I'm currently working on a JRPG style turn-based game and I read an article about that an action queue is necessary for these types of games, so I wrote one.It basically has 4 methods:.add (add an object to the queue).remove (remove an object from the queue, might be useful if some entity dies mid fight and shouldn't action if it's still in the queue).removeFirst (remove the first object from the queue after it invoked its action function e.g attack, defend, spell etc.).reset (Resets the whole queue to an empty array [], could be useful if the player kills the target and the battle ends, then the queue should also be emptied)The queue looks rather complex in code and the arrays I'm putting these in feel a bit awkward to access. Generally the code feels poorly written and inefficient, which is why I'm asking for a code review.function keys(object) {  return Object.keys(object);}let queue = {  attackQueue: [],  add: function(object) {    let propName = keys(object), array = [], outerArr = [];    for (let i = 0; i < propName.length; i++) {      if (propName[i] === name) {        outerArr.push(object[propName[i]]);      } else if (propName[i] === command || propName[i] === hitChance) {        array.push([propName[i], object[propName[i]]]);      }    }    outerArr.push(array);    queue.attackQueue.push(outerArr);  },  remove: function(object) {    for (let i = 0; i < queue.attackQueue.length; i++) {      if (object.name === queue.attackQueue[i][0]) {        queue.attackQueue.splice([i], 1);      }    }  },  sort: function() {    queue.attackQueue.sort(function(a, b) {      if (a[1][0][1] < b[1][0][1]) {        return 1;      }    })  },  removeFirst: function() {    queue.attackQueue.shift();  },  reset: function() {    queue.attackQueue = [];  }}function executeRound() {  let length = queue.attackQueue.length, arr = queue.attackQueue;  while (queue.attackQueue.length !== 0) {    window[arr[0][1][1][1].toLowerCase()]();  // I used toLowerCase just in case the commands would have been wrote in upperCase    console.log(removed entity  + arr[0][0] +  !);    queue.removeFirst();  }}function attack() {  console.log(attack);}function defend() {  console.log(defend);}// examplelet player1 = {  name: player1,  hitChance: 9000,  command: attack}// add player1 to the queuequeue.add(player1);// execute function executeRoundexecuteRound();console.log(queue.attackQueue) // --> removed entitiy player1 !
Action queue system
javascript;game
Separation of concernsA queue is a well-known data structure for the general purpose of processing things following first-in-first-out logic.Such FIFO logic has a few well-defined essential operations, such as enqueue, dequeue, isEmpty.The posted implementation does much more than expected from a general purpose queue. The add function in particular maps the input objects to different kind of objects before adding them.It would be better to separate the queue data structure from the rest of the logic specific to the game.OOPThe queue is a custom user object, designed by you.It would be good to go further and design a custom object to model the items you add to the action queue. What you currently have, a plain array with another array inside is not very easy to understand or work with.Alternative implementationA queue backed by an array can be implemented like this:var queue = (() => {  var arr = [];  return {    isEmpty: () => arr.length == 0,    add: item => arr.push(item),    remove: () => arr.shift(),    removeAll: filter => arr = arr.filter(x => !filter(x))  };})();Notable points:It implements only essential features: the common features of a queue, and the removeAll method required by your application, but concerning only the internals of the queue, no other objectsThe queue doesn't need to know anything about the objects you put in itThe queue's storage, arr, is inaccessible from the outsideYou also had a sort function in your queue,but you didn't explain why.This is not a common functionality of queues,and it goes directly against the FIFO behavior,so I don't think it belongs here.It's also possible that you need not a queue, but something else.You could put your player plain objects in this queue,without converting them to the nested array structure.If the player plain object in the example is not useful to you,you could define your own data structure,just like you did for your queue implementation.You can convert into that structure before putting in the queue.