Я написал RTS-игру (на самом деле демо для своего рода игрового движка), в которой основное взаимодействие пользователя с игрой - выбрать группу солдат, а затем щелкнуть правой кнопкой мыши на карте, чтобы переместить их в указанное место. Это в JavaScript, и вы можете поиграть с ним здесь ( код ).
Игнорируя проблему того, как солдаты перемещаются из своего текущего местоположения в пункт назначения, мой вопрос состоит в том, чтобы определить, каков их фактический пункт назначения. Вот что я пробовал до сих пор:
- Попытка 1: Скажите всем выбранным солдатам, чтобы они двигались к координатам, по которым щелкала мышь. Это имеет странное поведение, что все солдаты сгруппируются вокруг цели неестественно.
- Попытка 2: найдите средние координаты всех выбранных солдат, затем найдите смещение от этой центральной точки для каждого солдата и, наконец, переведите это смещение вокруг координат мыши. Это прекрасно работает, за исключением того, что если выбранные вами солдаты находятся далеко друг от друга, они не приблизятся к цели.
- Попытка 3: Постройте сетку вокруг координат мыши и поместите каждого выбранного солдата в ячейку сетки. Если каждый солдат добирается до назначенной клетки, это прекрасно работает. Однако солдат назначают в ячейки сетки в том порядке, в котором они были созданы, поэтому иногда они сталкиваются (т.е. все солдаты с правой стороны будут пытаться перейти на левую сторону), что выглядит неестественно.
- Попытка 4: используйте сетку, как раньше, но сначала рассортируйте солдат по локации, чтобы они выстроились в линию, то есть, если вы нажмете ниже группы, то солдаты в нижней части группы окажутся в нижней части сетки, когда они достичь их назначения. Это работает довольно хорошо, но иногда случаются глюки, и я не уверен, почему.
Вот функция, которая определяет координаты пункта назначения:
function moveSelectedSoldiersToMouse() {
var w = 0, h = 0, selected = [];
// Get information about the selected soldiers.
myTeam.soldiers.forEach(function(soldier) {
if (soldier.selected) {
selected.push(soldier);
w += soldier.width;
h += soldier.height;
}
});
var numSelected = selected.length, k = -1;
if (!numSelected) return;
// Build a grid of evenly spaced soldiers.
var sqrt = Math.sqrt(numSelected),
rows = Math.ceil(sqrt),
cols = Math.ceil(sqrt),
x = Mouse.Coords.worldX(),
y = Mouse.Coords.worldY(),
iw = Math.ceil(w / numSelected), // grid cell width
ih = Math.ceil(h / numSelected), // grid cell height
wg = iw*1.2, // width of gap between cells
hg = ih*1.2; // height of gap between cells
if ((rows-1)*cols >= numSelected) rows--;
w = iw * cols + wg * (cols-1); // total width of group
h = ih * rows + hg * (rows-1); // total height of group
// Sort by location to avoid soldiers getting in each others' way.
selected.sort(function(a, b) {
// Round to 10's digit; specific locations can be off by a pixel or so
var ax = a.x.round(-1), ay = a.y.round(-1), bx = b.x.round(-1), by = b.y.round(-1);
return ay - by || ax - bx;
});
// Place the grid over the mouse and send soldiers there.
for (var i = 0; i < rows; i++) {
for (var j = 0; j < cols; j++) {
var s = selected[++k];
if (s) {
var mx = x + j * (iw+wg) - w * 0.5 + s.width * 0.5,
my = y + i * (ih+hg) - h * 0.5 + s.height * 0.5;
// Finally, move to the end destination coordinates
s.moveTo(mx, my);
}
}
}
}
Вы можете вставить эту функцию в консоль JavaScript вашего браузера при просмотре демонстрации и возиться с ней, чтобы изменить поведение солдат.
У меня вопрос: есть ли лучший способ определить местоположение цели для каждого солдата, чтобы перейти к?