Eu escrevi um jogo RTS (na verdade, uma demo para um mecanismo de jogo) em que a interação básica do usuário com o jogo é selecionar um monte de soldados e clicar com o botão direito do mouse no mapa para movê-los para o local especificado. Isso está em JavaScript e você pode brincar com ele aqui ( código ).
Ignorando o problema de como os soldados se deslocam da sua localização atual para o seu destino, minha pergunta é sobre como determinar qual é o seu destino real. Aqui está o que eu tentei até agora:
- Tentativa 1: Diga a todos os soldados selecionados para moverem para as coordenadas em que o mouse clicou. Isso tem o comportamento estranho de que todos os soldados irão se agrupar em torno do alvo de maneira não natural.
- Tentativa 2: encontre as coordenadas médias de todos os soldados selecionados, encontre o deslocamento desse ponto central para cada soldado e, finalmente, traduza esse deslocamento em torno das coordenadas do mouse. Isso funciona bem, exceto que, se os soldados selecionados estiverem afastados, eles não chegarão perto do alvo.
- Tentativa 3: Crie uma grade em torno das coordenadas do mouse e coloque cada soldado selecionado em uma célula da grade. Se cada soldado chegar à sua cela designada, isso funcionará muito bem. No entanto, os soldados são designados para células da grade na ordem em que os soldados foram gerados; portanto, às vezes eles colidem (ou seja, todos os soldados do lado direito tentam ir para o lado esquerdo), o que não parece natural.
- Tentativa 4: Use uma grade como antes, mas primeiro classifique os soldados por local, para que eles se alinhem de forma sensata. Por exemplo, se você clicou abaixo do grupo, os soldados na parte inferior do grupo terminarão na parte inferior da grade quando chegar ao seu destino. Isso funciona muito bem, mas às vezes há falhas e não sei por que.
Aqui está a função que determina as coordenadas de destino:
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);
}
}
}
}
Você pode colar esta função no console JavaScript do seu navegador ao visualizar a demonstração e mexer nela para alterar o comportamento dos soldados.
Minha pergunta é: existe uma maneira melhor de determinar o local de destino de cada soldado para o qual se mudar?