1

I have a game board similar to chess (with attacks instead of just moves) where I'm highlighting the possible areas of effect of an attack on a cell by getting relative cells to the hovered cell, like this;

    this.getAOECells = function(startCell, hoveredCell) {
        let possibleCells = [hoveredCell];

        let upCell = hoveredCell.relative(0, -1);
        possibleCells.push(upCell);

        let rightCell = hoveredCell.relative(1, 0);
        possibleCells.push(rightCell);

        let downCell = hoveredCell.relative(0, 1);
        possibleCells.push(downCell);

        let leftCell = hoveredCell.relative(-1, 0);
        possibleCells.push(leftCell);

        return possibleCells;
    };

but it would be much simpler to maintain if I could store it in a visible way like this instead

this.getAOECells = function(startCell, hoveredCell) {

let possibleCells = [
    0, 1, 0
    1, 1, 1
    0, 1, 0
]

return convertToRealCells(possibleCells, startCell, hoveredCell);
};

How can I format the possibleCells array so that this convert function would be practical?

P.S. I'm very new to javascript

Gallaxhar
  • 976
  • 1
  • 15
  • 28

1 Answers1

1

There's absolutely no problem with the first approach, but you can spare a few lines like this:

this.getAOECells = function(startCell, hoveredCell) {
    var possibleCells = [hoveredCell];
    possibleCells.push(hoveredCell.relative(0, -1));
    possibleCells.push(hoveredCell.relative(1, 0));
    possibleCells.push(hoveredCell.relative(0, 1));
    possibleCells.push(hoveredCell.relative(-1, 0));
    return possibleCells;
};

or this:

this.getAOECells = function(startCell, hoveredCell) {
    return [
        hoveredCell,
        hoveredCell.relative(0, -1),
        hoveredCell.relative(1, 0),
        hoveredCell.relative(0, 1),
        hoveredCell.relative(-1, 0)
    ];
};

How can I format the possibleCells array so that this convert function would be practical?

Use a 2D array:

possibleCells = [
    [0, 1, 0],
    [1, 1, 1],
    [0, 1, 0]
];

Example code for convertToRealCells:

//xPos, yPos - where the relativeCells' top left cell's real position is
//width, height - size of relativeCells, maybe there's a better way of getting it...
//twidth, theight - size of the map
function convertToRealCells(relativeCells, xPos, yPos, width, height, twidth, theight) {
        var res = makeArray(twidth, theight, 0);
        for (x = 0; x < width; x++) {
            for (y = 0; y < height; y++) {
                res[x + xPos][y + yPos] = relativeCells[x][y];
            }
        }
        return res;
    }

//https://stackoverflow.com/questions/13808325/creating-a-2d-array-with-specific-length-and-width
function makeArray(w, h, val) {
    var arr = [];
    for(i = 0; i < h; i++) {
        arr[i] = [];
        for(j = 0; j < w; j++) {
            arr[i][j] = val;
        }
    }
    return arr;
}

possibleCells = [
    [0, 1, 0],
    [1, 1, 1],
    [0, 1, 0]
];

console.log(convertToRealCells(possibleCells, 5, 5, 3, 3, 10, 10));

It outputs something like this:

[
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]

you can use it like

this.getAOECells = function(startCell, hoveredCell) {

    let possibleCells = [
        [0, 1, 0],
        [1, 1, 1],
        [0, 1, 0]
    ]

    return convertToRealCells(possibleCells, hoveredCell.x - 1, hoveredCell.y - 1, 3, 3, map.width, map.height);
};

where map.width and map.height are the size of the map and hoveredCell.x and hoveredCell.y are the position of the hovered cell.

You can make possibleCells a global constant if it's always the same and just it's position changes.

EDIT:

The convert to real coordinates method is very ineffective on large maps but it's more understandable especially if you use a complicated pattern.

If you want to go the more visual way without making code ineffective on large maps, do something like this:

//xPos, yPos - where the relativeCells' top left cell's real position is
//width, height - size of relativeCells, maybe there's a better way of getting it...
function convertToRealCells(relativeCells, xPos, yPos, width, height) {
    var res = [];
    for (x = 0; x < width; x++) {
        for (y = 0; y < height; y++) {
            if (relativeCells[x][y] == 1) {
              res.push({
                "x": x + xPos,
                "y": y + yPos
              });
            }
        }
    }
    return res;
}

possibleCells = [
    [0, 1, 0],
    [1, 1, 1],
    [0, 1, 0]
];

console.log(convertToRealCells(possibleCells, 5, 5, 3, 3));

it outputs something like this:

[[object Object] {
  x: 5,
  y: 6
}, [object Object] {
  x: 6,
  y: 5
}, [object Object] {
  x: 6,
  y: 6
}, [object Object] {
  x: 6,
  y: 7
}, [object Object] {
  x: 7,
  y: 6
}]

You can access each element's coordinates like this:

res = convertToRealCells(possibleCells, 5, 5, 3, 3);

for (i = 0; i < res.length; i++) {
  console.log(i + ". x: " + res[i].x + ", y: " + res[i].y);
}
GDavid
  • 128
  • 1
  • 2
  • 12
  • the 0's and 1's array is just so easy to change and spot visually, but it sure does add complexity with the convert function, because I have to get the center of the array as the hovered cell and offset everything by it. I think I will just use the return array solution you gave after your 'or this:' text, i didn't know you could return an array, that is the shortest code so probably the best way for readability in the long run, thank you! – Gallaxhar Mar 11 '18 at 20:17