allocen allocen - 1 month ago 21
AngularJS Question

Replicate an ingame inventory on the web

i'm trying to replicate an inventory from a mmorpg online game called CABAL on the web, the game's inventory looks like this:

enter image description here

Basically, inventory has 4 tabs each with 8x8, so on every tab there are a 64 totals of cells and in total 256, though, the index starts from 0 to 63 on each tab and the total from 0 to 255.
As you can see some items occupies 1:1 (rowspan:colspan) some 2:2, some can even be 2:6 for example an armoursuit, anyway the point is that i tried here replicate as best as i could, though i managed to make 1 tab only.

function createCells(rows, cols) {
var cells = {},
x = 0,
startRow = 0,
endRow = 0;

for (var i = 0; i < rows; i++) {
cells[i] = {};
for (var j = 0; j < cols; j++) {
cells[i][j] = { id: "e" + x };

if (angular.isDefined(items[x])) {
cells[i][j] = items[x];
if (items[x].colspan > 1 && items[x].rowspan > 1) {
startRow = x % rows;
endRow = parseInt(x / cols, 10) + items[x].rowspan;
console.log(j);
console.log("Start column " + startRow + " end rowspan " + endRow + " x = " + x);
}
// console.log();
// if (j >= 5 && j <= 8) {
// x += j;
// }
}

if (!angular.equals(cells[i][j], {})) {
console.log(cells[i][j]);
}


x++;
}
}

return cells;
}


So what that issue is that if an item occupies rowspan and colspan bigger than 1 it pushes the other cells after and i need them removed (e7, e14, e15, e39, e46, e47, e54, e55, e62, e63). I need that loops do to calcs automatically based on the items rowspan and colspan that are inventory. The items that are in var items are a sample of the api response so 3, 6, 12, 240, 105 are items for tab 1.

So anyone can help me further? I'm stucked for days on this. Thanks.

Answer

If you don't mind a small approach change, you could try this out:

  • Before making cells, loop through all your items
  • For each item, identify the row and col combinations that will be blocked

Now, you have a map of all blocked (i.e.: not empty) cells. In the createCells loop, you can use this map to determine if you need a place holder. There are now three cases for each cell:

  • It's the exact slot an item goes in: add an item
  • It's a slot that is blocked by an item: do nothing
  • It's not related to an item: insert placeholder

Here's how I did it:

function createCells(rows, cols) {
  var cells = {};

  // Create an object that holds all cell codes blocked by an item
  var itemMap = Object.keys(items).reduce(function(map, key) {
    var item = items[key],
      cStart = item.slot % cols,
      rStart = Math.floor(item.slot / cols)
    for (var c = 0; c < item.colspan; c += 1) {
      for (var r = 0; r < item.rowspan; r += 1) {
        map[(r + rStart) + ";" + (c + cStart)] = item;
      }
    }
    return map;
  }, {});

  var currentNr;
  for (var i = 0; i < rows; i++) {
    cells[i] = {};

    for (var j = 0; j < cols; j++) {
      currentNr = i * cols + j;

      // If there's an item with this slot, place it
      if (items[currentNr]) {
        // Add item
        cells[i][j] = items[currentNr];

      } else if (itemMap[i + ";" + j]) { // The item isn't in the exact spot, but blocks it
        // Block square, do nothing
      } else {
        // Add empty square
        cells[i][j] = {
          id: "e" + currentNr
        }
      }
    }
  }
  return cells;
}

In a working fiddle: http://jsfiddle.net/q1ba3x4h/