Atualmente, tenho um jogo simples do tipo Tetris e me deparei com um problema que não consigo resolver.
Ao contrário de Tetris, onde há uma única forma em queda, tenho várias formas potencialmente interligadas que precisam cair; Eu preciso calcular suas posições finais. Considere o seguinte:
Para calcular a posição final da forma verde, simplesmente digitalizo para baixo cada quadrado até atingir outro quadrado ou a borda do quadro. Feito
Para várias formas simples, eu caminho até o quadro. Assim, o vermelho não precisa ser movido, a laranja diminui em um, o verde diminui em três. Feito
Não sei como tratar as formas verdes e vermelhas entrelaçadas. Usando a lógica do número 2, acabaríamos "presos" flutuando no ar. Se eu procurar a forma verde, encontro o vermelho e, portanto, não me movo, e vice-versa para o vermelho. A solução pode ser tratar as duas formas como uma.
Semelhante ao item 3, nesse cenário eu também poderia obter sucesso tratando os objetos como um.
Ao contrário dos nºs 3 e 4, eu não poderia tratar a forma como uma, pois a forma laranja acabaria flutuando um quadrado muito alto ...
Outra variação do problema # 6.
Pode haver outros cenários nos quais tenho muitas formas que se entrelaçam em cenários cada vez mais complexos, mas acho que o exposto acima cobre as partes mais fundamentais do problema.
Sinto que há uma solução elegante que ainda tenho que encontrar / pensar e ficaria muito grato por qualquer insight, idéias ou recursos.
SOLUÇÃO
A solução que eu encontrei é realmente elegante, com base na resposta de @ user35958 abaixo, criei a seguinte função recursiva (pseudo-código)
function stop(square1, square2){
// Skip if we're already stopped
if(square1.stopped){
return;
}
// Are we comparing squares?
if(!square2){
// We are NOT comparing squares, simply stop.
square1.stopped = true;
} else {
// Stop IF
// square1 is directly above square2
// square1 is connected to square2 (part of the same complex shape)
if(square1.x == square2.x && square1.y == (square2.y+1) || isConnected(square1, square2)){
square1.stopped = true;
}
}
// If we're now stopped, we must recurse to our neighbours
stop(square1, squareAbove);
stop(square1, squareBelow);
stop(square1, squareRight);
stop(square1, squareDown);
}
GIF animado mostrando cada passo da solução
Para resumir:
- Ao "parar" um quadrado, também paramos:
- QUALQUER quadrado acima dele. SEMPRE.
- Praça vizinha à qual estamos conectados (ou seja, a mesma forma).
- Paramos toda a linha inferior e a função se repete através dos quadrados.
- Repetimos até que todos os quadrados sejam parados.
- Então nós animamos.