Ho scritto un gioco RTS (una demo per una sorta di motore di gioco, in realtà) in cui l'interazione di base dell'utente con il gioco consiste nel selezionare un gruppo di soldati e quindi fare clic con il tasto destro sulla mappa per spostarli nella posizione specificata. Questo è in JavaScript e puoi giocarci qui ( codice ).
Ignorando il problema di come i soldati si spostano dalla loro posizione attuale alla loro destinazione, la mia domanda riguarda la determinazione di quale sia la loro destinazione effettiva. Ecco cosa ho provato finora:
- Tentativo 1: dire a tutti i soldati selezionati di spostarsi sulle coordinate su cui ha fatto clic il mouse. Questo ha lo strano comportamento che tutti i soldati si raggrupperanno in modo innaturale attorno al bersaglio.
- Tentativo 2: trova le coordinate medie di tutti i soldati selezionati, quindi trova l'offset da quel punto centrale per ciascun soldato e infine traduci l'offset attorno alle coordinate del mouse. Funziona bene, tranne per il fatto che se i tuoi soldati selezionati sono molto distanti non si avvicinano al bersaglio.
- Tentativo 3: costruisci una griglia attorno alle coordinate del mouse e posiziona ciascun soldato selezionato in una cella della griglia. Se ogni soldato arriva alla cella assegnata, questo funziona alla grande. Tuttavia, i soldati sono assegnati alle celle della griglia nell'ordine in cui sono stati generati, quindi a volte si scontrano (cioè tutti i soldati sul lato destro cercheranno di andare sul lato sinistro) che sembra innaturale.
- Tentativo 4: usa una griglia come prima, ma prima ordina i soldati per posizione in modo che si allineino in modo sensato, cioè se fai clic sotto il gruppo, i soldati nella parte inferiore del gruppo finiranno nella parte inferiore della griglia quando raggiungere la loro destinazione. Funziona piuttosto bene ma a volte ci sono problemi e non sono sicuro del perché.
Ecco la funzione che determina le coordinate di destinazione:
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);
}
}
}
}
Puoi incollare questa funzione nella console JavaScript del tuo browser quando visualizzi la demo e scherzi con essa per cambiare il comportamento dei soldati.
La mia domanda è: esiste un modo migliore per determinare la posizione di destinazione in cui ogni soldato deve spostarsi?