Por exemplo, eu tenho uma classe de jogo e mantém uma int
que rastreia a vida do jogador. Eu tenho uma condicional
if ( mLives < 1 ) {
// Do some work.
}
No entanto, esta condição continua disparando e o trabalho é feito repetidamente. Por exemplo, quero definir um cronômetro para sair do jogo em 5 segundos. Atualmente, ele continuará definindo para 5 segundos a cada quadro e o jogo nunca termina.
Este é apenas um exemplo, e eu tenho o mesmo problema em várias áreas do meu jogo. Quero verificar se há alguma condição e, em seguida, fazer algo uma vez e apenas uma vez e depois não verificar ou executar o código na instrução if novamente. Algumas soluções possíveis que vêm à mente está tendo um bool
para cada condição e definir os bool
Quando os fogos de condição. No entanto, na prática, isso fica muito confuso ao lidar com muitasbools
, pois eles precisam ser armazenados como campos de classe ou estaticamente dentro do próprio método.
Qual é a solução adequada para isso (não no meu exemplo, mas no domínio do problema)? Como você faria isso em um jogo?
Respostas:
Eu acho que você pode resolver esse problema simplesmente exercendo um controle mais cuidadoso sobre seus possíveis caminhos de código. Por exemplo, no caso em que você está verificando se o número de vidas do jogador caiu abaixo de um, por que não verificar apenas quando o jogador perde uma vida, em vez de cada quadro?
Por sua vez, isso pressupõe que isso
subtractPlayerLife
seria chamado apenas em ocasiões específicas, o que talvez resultasse de condições que você deve verificar em todos os quadros (colisões, talvez).Controlando cuidadosamente a forma como seu código é executado, você pode evitar soluções confusas, como booleanos estáticos, além de reduzir, pouco a pouco, a quantidade de código executado em um único quadro.
Se há algo que parece impossível de refatorar e você realmente precisa apenas verificar uma vez, então
enum
booleanos estatais (como um ) ou estáticos são o caminho a percorrer. Para evitar declarar a estática, você pode usar o seguinte truque:que faria o seguinte código:
imprimir
something
esomething else
apenas uma vez. Não produz o código mais bonito, mas funciona. Também tenho certeza de que há maneiras de aprimorá-lo, talvez garantindo melhor nomes de variáveis exclusivos. Isso#define
funcionará apenas uma vez durante o tempo de execução. Não há como redefini-lo e não há como salvá-lo.Apesar do truque, eu recomendo controlar melhor o fluxo de código primeiro e usá-lo
#define
como último recurso ou apenas para fins de depuração.fonte
Isso soa como o caso clássico de usar o padrão de estado. Em um estado, você verifica sua condição para vidas <1. Se essa condição se tornar verdadeira, você fará a transição para um estado de atraso. Esse estado de atraso aguarda a duração especificada e depois faz a transição para o estado de saída.
Na abordagem mais trivial:
Você pode considerar o uso de uma classe State juntamente com um StateManager / StateMachine para lidar com a alteração / envio / transição entre estados, em vez de uma instrução switch.
Você pode tornar sua solução de gerenciamento de estado tão sofisticada quanto desejar, incluindo vários estados ativos, um único estado pai ativo com muitos estados filhos ativos usando alguma hierarquia etc. A solução padrão de estado tornará seu código muito mais reutilizável e mais fácil de manter e seguir.
fonte
Se você está preocupado com o desempenho, o desempenho da verificação várias vezes geralmente não é significativo; idem por ter condições de bool.
Se você estiver interessado em outra coisa, poderá usar algo semelhante ao padrão de design nulo para resolver esse problema.
Nesse caso, vamos supor que você queira chamar um método
foo
se o jogador não tiver vidas restantes. Você implementaria isso como duas classes, uma que chamafoo
e outra que não faz nada. Vamos chamá-losDoNothing
eCallFoo
assim:Este é um exemplo um pouco "bruto"; os pontos principais são:
FooClass
quais pode serDoNothing
ouCallFoo
. Pode ser uma classe base, classe abstrata ou interface.execute
método dessa classe.DoNothing
instância).CallFoo
instância).Isso é essencialmente como uma mistura de estratégia e padrões nulos.
fonte
if
verificação para aFooClass
própria instância, para que seja executada apenas uma vez e o mesmo para instanciaçãoCallFoo
.