Então, eu estou criando um jogo no qual você pode enviar navios para locais para vender ou comprar recursos como madeira, ferro, ouro etc.
Agora eu queria saber como os recursos devem ser criados no jogo. Eu vim com 2 opções
Crie uma classe para cada recurso:
public class ResourceBase { private int value; // other base properties } public class Gold : ResourceBase { public Gold { this.value = 40 // or whatever } }
Criar instâncias de uma classe Resource
public class Resource { string name; int value; public Resource(string name, int value) { this.name = name; this.value = value; } } // later on... Resource gold = new Resource("Gold",40);
Com a segunda opção, é possível preencher os recursos do jogo a partir de um arquivo resources.json, eu meio que gosto dessa estrutura.
Novas idéias / padrões / estruturas de design são sempre bem-vindos!
EDIT: É um pouco como o aplicativo complementar de Assassins Creed Black Flag. Veja a barra de recursos na imagem abaixo
EDIÇÃO 2: Pesquisei mais sobre o "carregar itens / recursos do arquivo JSON" e encontrei este blog: Poder do JSON no desenvolvimento de jogos - itens . Ele mostra o melhor das opções 1 e 2. Você ainda pode adicionar funcionalidades a cada recurso :)
fonte
enum
vez disso.Respostas:
Siga a segunda abordagem, simplesmente pelo fato de poder introduzir novos tipos ou itens de recursos a qualquer momento, sem precisar reescrever ou atualizar o código ( desenvolvimento orientado a dados ).
Editar:
Para elaborar um pouco mais sobre por que isso é uma boa prática geral, mesmo que você tenha 100% de certeza de que algum valor nunca será alterado.
Vamos dar o exemplo do jogo de console mencionado nos comentários, porque isso fornece uma boa razão para você não codificar nada, a menos que você realmente tenha (ou queira), por exemplo, chaves de criptografia, seu próprio nome, etc.
Ao lançar um jogo em consoles, eles geralmente precisam passar por um processo de revisão, onde o controle de qualidade do fabricante do console testará o jogo, jogará com ele, procurará por problemas etc. Isso é obrigatório e custa muito dinheiro. Acho que li uma vez que um release pode custar entre US $ 30.000 e US $ 50.000 apenas para a certificação.
Agora imagine que você está apostando no lançamento, pagando os US $ 30.000 e aguarde. E de repente você percebe que alguns dos valores do seu jogo estão literalmente quebrados. Digamos que você possa comprar barras de ferro por 50 de ouro e vendê-las por 55 de ouro.
O que você faz? Se você codificou essas coisas, terá que criar uma nova versão de atualização / lançamento, que precisará ser revisada mais uma vez; portanto, na pior das hipóteses, você pagará mais uma vez pela recertificação! Aposto que a Ubisoft não se importará, mas para o seu próprio bolso de desenvolvedor de jogos indie ... ai!
Mas imagine que o jogo apenas verifique ocasionalmente as definições atualizadas do jogo (por exemplo, na forma de um arquivo JSON). Seu jogo pode baixar e usar a versão mais recente a qualquer momento, sem a necessidade de uma nova atualização. Você pode corrigir esse desequilíbrio / exploração / bug a qualquer momento, sem exigir a recertificação ou qualquer outro dinheiro pago. Apenas uma pequena decisão de projeto, você não achou que valesse a pena, apenas economizou uma quantia em dinheiro de 5 dígitos! Isso não é incrível? :)
Só não me interpretem mal. Isso também se aplica a outros tipos de software e plataformas. O download de arquivos de dados atualizados é geralmente muito mais fácil e viável para o usuário padrão, não importa se é um jogo ou algum tipo de aplicativo / ferramenta. Imagine um jogo instalado em Arquivos de Programa no Windows. Seu atualizador precisa de direitos de administrador para modificar qualquer coisa e você não pode modificar os programas em execução. Com o DDD, seu programa apenas baixa os dados e os utiliza. O jogador pode nem perceber que houve uma atualização.
fonte
Uma regra prática é que você use classes diferentes quando os objetos requerem código diferente e instâncias da mesma classe quando os objetos exigem apenas valores diferentes.
Quando os recursos têm uma mecânica de jogo diferente, exclusiva para eles, pode fazer sentido representá-los com classes. Por exemplo, quando você tem plutônio com meia-vida e coelhos que procriam de acordo com a sequência de fibonacci , pode fazer sentido ter uma classe base
Resource
com um métodoUpdate
implementado como no-op e duas classes derivadasHalfLifeResource
eSelfGrowingResource
que substitua esse método para diminuir / aumentar o valor (e talvez também inclua lógica para controlar o que acontece quando você armazena os dois próximos um do outro).Mas quando seus recursos são realmente apenas números estúpidos, não faz sentido implementá-los com algo mais sofisticado do que uma variável simples.
fonte
Gostaria de acrescentar que há duas opções extras:
Interface: você pode considerar se a classe de recurso seria apenas um "armazenamento" para 5 números inteiros e cada outra entidade teria uma lógica diferente em relação aos recursos (por exemplo, gasto / saque do jogador, cidade produz recurso). Nesse caso, você pode não querer uma classe - apenas deseja expor que alguma entidade possui uma variável com a qual outras pessoas podem interagir:
Além disso, isso tem a vantagem de poder saquear uma cidade com exatamente o mesmo código que saquearia a frota inimiga, promovendo a reutilização do código.
A desvantagem é que a implementação dessa interface pode ser tediosa se muitas classes a implementarem, então você pode acabar usando interfaces, mas não para o problema original, resolvendo-o com as opções 1 ou 2:
Instâncias (com enum): em alguns casos, seria desejável usar enum em vez de string ao definir o tipo de recurso:
isso fornecerá um pouco de "segurança", porque seu IDE fornecerá uma lista de todos os recursos válidos ao atribuí-lo após a gravação do ponto
ResourceType = Resource.
. Além disso, existem mais "truques" com enumerações que você pode precisar, como Tipo explícito ou composição / sinalizadores que posso imaginar ser útil ao criar:Quanto ao que é melhor - não existe uma bala de prata, mas pessoalmente eu me inclinaria para qualquer forma de instância, elas podem não ser tão sofisticadas quanto a interface, mas são simples, não desordenam a árvore de herança e são amplamente compreendidas.
fonte
my-great-enum
) para alguma representação em C # da enumeração (MyGreatEnum
).Você deve usar a opção 1, que possui 3 vantagens:
new Gold(50)
resource instanceof Gold
fonte
Se seus recursos não possuem lógica comercial própria ou cenários especiais de como eles interagem com o ambiente, outros recursos (além do comércio que você cobriu) ou o player, a opção dois facilita a adição de novos.
Se você precisar considerar situações como o que aconteceria se você misturasse dois recursos para a elaboração, se os recursos puderem ter propriedades muito diferentes (um balde de água é muito diferente de um pedaço de carvão) ou outras interações econômicas complexas, a abordagem 1 será muito mais flexível para o mecanismo, mas não os dados.
fonte